From 0cf411b09cf5d8970b873a338a69eae98d5ce5d8 Mon Sep 17 00:00:00 2001 From: Michele Calgaro Date: Sat, 8 Jun 2024 12:56:43 +0900 Subject: Rename text nt* related files to equivalent tq* Signed-off-by: Michele Calgaro --- src/codecs/ntqbig5codec.h | 2 +- src/codecs/ntqeucjpcodec.h | 2 +- src/codecs/ntqeuckrcodec.h | 2 +- src/codecs/ntqgb18030codec.h | 2 +- src/codecs/ntqjiscodec.h | 2 +- src/codecs/ntqrtlcodec.h | 2 +- src/codecs/ntqsjiscodec.h | 2 +- src/codecs/ntqtextcodec.h | 134 - src/codecs/ntqtextcodecfactory.h | 59 - src/codecs/ntqtextcodecplugin.h | 70 - src/codecs/ntqtsciicodec.h | 2 +- src/codecs/ntqutfcodec.h | 2 +- src/codecs/qfontcodecs_p.h | 2 +- src/codecs/qisciicodec_p.h | 2 +- src/codecs/qrtlcodec.cpp | 2 +- src/codecs/qt_codecs.pri | 14 +- src/codecs/qtextcodec.cpp | 3161 --------------- src/codecs/qtextcodecfactory.cpp | 131 - src/codecs/qtextcodecinterface_p.h | 80 - src/codecs/qtextcodecplugin.cpp | 186 - src/codecs/tqtextcodec.cpp | 3161 +++++++++++++++ src/codecs/tqtextcodec.h | 134 + src/codecs/tqtextcodecfactory.cpp | 131 + src/codecs/tqtextcodecfactory.h | 59 + src/codecs/tqtextcodecinterface_p.h | 80 + src/codecs/tqtextcodecplugin.cpp | 186 + src/codecs/tqtextcodecplugin.h | 70 + src/dialogs/qerrormessage.cpp | 2 +- src/dialogs/qprintdialog.cpp | 2 +- src/kernel/ntqnamespace.h | 2 +- src/kernel/ntqt.h | 18 +- src/kernel/qapplication.cpp | 2 +- src/kernel/qapplication_x11.cpp | 2 +- src/kernel/qclipboard_x11.cpp | 2 +- src/kernel/qdragobject.cpp | 2 +- src/kernel/qfont.cpp | 2 +- src/kernel/qfont_x11.cpp | 4 +- src/kernel/qfontengine_p.h | 4 +- src/kernel/qfontengine_x11.cpp | 4 +- src/kernel/qpainter.cpp | 2 +- src/kernel/qpainter_x11.cpp | 8 +- src/kernel/qpsprinter.cpp | 6 +- src/kernel/qpsprinter_p.h | 2 +- src/kernel/qrichtext.cpp | 4 +- src/kernel/qrichtext_p.h | 2 +- src/kernel/qscriptengine.cpp | 2 +- src/kernel/qscriptengine_p.h | 2 +- src/kernel/qscriptengine_x11.cpp | 2 +- src/kernel/qt_kernel.pri | 8 +- src/kernel/qtextengine.cpp | 1180 ------ src/kernel/qtextengine_p.h | 377 -- src/kernel/qtextengine_unix.cpp | 127 - src/kernel/qtextlayout.cpp | 643 --- src/kernel/qtextlayout_p.h | 184 - src/kernel/tqimage.cpp | 2 +- src/kernel/tqtextengine.cpp | 1180 ++++++ src/kernel/tqtextengine_p.h | 377 ++ src/kernel/tqtextengine_unix.cpp | 127 + src/kernel/tqtextlayout.cpp | 643 +++ src/kernel/tqtextlayout_p.h | 184 + src/kernel/tqwidget_x11.cpp | 4 +- src/moc/moc.pro | 4 +- src/network/qdns.cpp | 2 +- src/network/qftp.cpp | 2 +- src/network/qhttp.cpp | 2 +- src/qt.pro | 4 +- src/styles/qsgistyle.cpp | 2 +- src/tools/ntqtextstream.h | 341 -- src/tools/ntqtl.h | 2 +- src/tools/qfeatures.txt | 8 +- src/tools/qsettings.cpp | 2 +- src/tools/qt_tools.pri | 4 +- src/tools/qtextstream.cpp | 2632 ------------ src/tools/tqstring.cpp | 2 +- src/tools/tqtextstream.cpp | 2632 ++++++++++++ src/tools/tqtextstream.h | 341 ++ src/widgets/ntqdockarea.h | 2 +- src/widgets/ntqmainwindow.h | 2 +- src/widgets/ntqmultilineedit.h | 2 +- src/widgets/ntqtextbrowser.h | 107 - src/widgets/ntqtextedit.h | 613 --- src/widgets/ntqtextview.h | 74 - src/widgets/qcheckbox.cpp | 2 +- src/widgets/qiconview.cpp | 2 +- src/widgets/qlineedit.cpp | 2 +- src/widgets/qradiobutton.cpp | 2 +- src/widgets/qsyntaxhighlighter.cpp | 2 +- src/widgets/qt_widgets.pri | 12 +- src/widgets/qtextbrowser.cpp | 555 --- src/widgets/qtextedit.cpp | 7474 ----------------------------------- src/widgets/qtextview.cpp | 103 - src/widgets/tqtextbrowser.cpp | 555 +++ src/widgets/tqtextbrowser.h | 107 + src/widgets/tqtextedit.cpp | 7474 +++++++++++++++++++++++++++++++++++ src/widgets/tqtextedit.h | 613 +++ src/widgets/tqtextview.cpp | 103 + src/widgets/tqtextview.h | 74 + src/xml/qsvgdevice.cpp | 2 +- src/xml/tqdom.cpp | 4 +- src/xml/tqxml.cpp | 2 +- src/xml/tqxml.h | 2 +- 101 files changed, 18331 insertions(+), 18331 deletions(-) delete mode 100644 src/codecs/ntqtextcodec.h delete mode 100644 src/codecs/ntqtextcodecfactory.h delete mode 100644 src/codecs/ntqtextcodecplugin.h delete mode 100644 src/codecs/qtextcodec.cpp delete mode 100644 src/codecs/qtextcodecfactory.cpp delete mode 100644 src/codecs/qtextcodecinterface_p.h delete mode 100644 src/codecs/qtextcodecplugin.cpp create mode 100644 src/codecs/tqtextcodec.cpp create mode 100644 src/codecs/tqtextcodec.h create mode 100644 src/codecs/tqtextcodecfactory.cpp create mode 100644 src/codecs/tqtextcodecfactory.h create mode 100644 src/codecs/tqtextcodecinterface_p.h create mode 100644 src/codecs/tqtextcodecplugin.cpp create mode 100644 src/codecs/tqtextcodecplugin.h delete mode 100644 src/kernel/qtextengine.cpp delete mode 100644 src/kernel/qtextengine_p.h delete mode 100644 src/kernel/qtextengine_unix.cpp delete mode 100644 src/kernel/qtextlayout.cpp delete mode 100644 src/kernel/qtextlayout_p.h create mode 100644 src/kernel/tqtextengine.cpp create mode 100644 src/kernel/tqtextengine_p.h create mode 100644 src/kernel/tqtextengine_unix.cpp create mode 100644 src/kernel/tqtextlayout.cpp create mode 100644 src/kernel/tqtextlayout_p.h delete mode 100644 src/tools/ntqtextstream.h delete mode 100644 src/tools/qtextstream.cpp create mode 100644 src/tools/tqtextstream.cpp create mode 100644 src/tools/tqtextstream.h delete mode 100644 src/widgets/ntqtextbrowser.h delete mode 100644 src/widgets/ntqtextedit.h delete mode 100644 src/widgets/ntqtextview.h delete mode 100644 src/widgets/qtextbrowser.cpp delete mode 100644 src/widgets/qtextedit.cpp delete mode 100644 src/widgets/qtextview.cpp create mode 100644 src/widgets/tqtextbrowser.cpp create mode 100644 src/widgets/tqtextbrowser.h create mode 100644 src/widgets/tqtextedit.cpp create mode 100644 src/widgets/tqtextedit.h create mode 100644 src/widgets/tqtextview.cpp create mode 100644 src/widgets/tqtextview.h (limited to 'src') diff --git a/src/codecs/ntqbig5codec.h b/src/codecs/ntqbig5codec.h index 73039967f..d2f1f7c84 100644 --- a/src/codecs/ntqbig5codec.h +++ b/src/codecs/ntqbig5codec.h @@ -46,7 +46,7 @@ #define TQBIG5CODEC_H #ifndef QT_H -#include "ntqtextcodec.h" +#include "tqtextcodec.h" #endif // QT_H #ifndef TQT_NO_BIG_CODECS diff --git a/src/codecs/ntqeucjpcodec.h b/src/codecs/ntqeucjpcodec.h index 6ccbcddb2..39b768665 100644 --- a/src/codecs/ntqeucjpcodec.h +++ b/src/codecs/ntqeucjpcodec.h @@ -71,7 +71,7 @@ #define TQEUCJPCODEC_H #ifndef QT_H -#include "ntqtextcodec.h" +#include "tqtextcodec.h" #include "ntqjpunicode.h" #endif // QT_H diff --git a/src/codecs/ntqeuckrcodec.h b/src/codecs/ntqeuckrcodec.h index fcd97a964..513c85f0b 100644 --- a/src/codecs/ntqeuckrcodec.h +++ b/src/codecs/ntqeuckrcodec.h @@ -67,7 +67,7 @@ #define TQEUCKRCODEC_H #ifndef QT_H -#include "ntqtextcodec.h" +#include "tqtextcodec.h" #endif // QT_H #ifndef TQT_NO_BIG_CODECS diff --git a/src/codecs/ntqgb18030codec.h b/src/codecs/ntqgb18030codec.h index 676a08a18..c28c6222d 100644 --- a/src/codecs/ntqgb18030codec.h +++ b/src/codecs/ntqgb18030codec.h @@ -42,7 +42,7 @@ #define TQGB18030CODEC_H #ifndef QT_H -#include "ntqtextcodec.h" +#include "tqtextcodec.h" #endif // QT_H diff --git a/src/codecs/ntqjiscodec.h b/src/codecs/ntqjiscodec.h index b96d0aec2..3e914f489 100644 --- a/src/codecs/ntqjiscodec.h +++ b/src/codecs/ntqjiscodec.h @@ -71,7 +71,7 @@ #define TQJISCODEC_H #ifndef QT_H -#include "ntqtextcodec.h" +#include "tqtextcodec.h" #include "ntqjpunicode.h" #endif // QT_H diff --git a/src/codecs/ntqrtlcodec.h b/src/codecs/ntqrtlcodec.h index f40161250..bbd990df6 100644 --- a/src/codecs/ntqrtlcodec.h +++ b/src/codecs/ntqrtlcodec.h @@ -42,7 +42,7 @@ #define TQRTLCODEC_H #ifndef QT_H -#include "ntqtextcodec.h" +#include "tqtextcodec.h" #endif // QT_H #ifndef TQT_NO_CODEC_HEBREW diff --git a/src/codecs/ntqsjiscodec.h b/src/codecs/ntqsjiscodec.h index a1acc053e..8a5f83aae 100644 --- a/src/codecs/ntqsjiscodec.h +++ b/src/codecs/ntqsjiscodec.h @@ -71,7 +71,7 @@ #define TQSJISCODEC_H #ifndef QT_H -#include "ntqtextcodec.h" +#include "tqtextcodec.h" #include "ntqjpunicode.h" #endif // QT_H diff --git a/src/codecs/ntqtextcodec.h b/src/codecs/ntqtextcodec.h deleted file mode 100644 index f5554d261..000000000 --- a/src/codecs/ntqtextcodec.h +++ /dev/null @@ -1,134 +0,0 @@ -/**************************************************************************** -** -** Definition of TQTextCodec class -** -** Created : 981015 -** -** Copyright (C) 1998-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 TQTEXTCODEC_H -#define TQTEXTCODEC_H - -#ifndef QT_H -#include "tqstring.h" -#endif // QT_H - -#ifndef TQT_NO_TEXTCODEC - -class TQTextCodec; -class TQIODevice; -class TQFont; - -class TQ_EXPORT TQTextEncoder { -public: - virtual ~TQTextEncoder(); - virtual TQCString fromUnicode(const TQString& uc, int& lenInOut) = 0; -}; - -class TQ_EXPORT TQTextDecoder { -public: - virtual ~TQTextDecoder(); - virtual TQString toUnicode(const char* chars, int len) = 0; -}; - -class TQ_EXPORT TQTextCodec { -public: - virtual ~TQTextCodec(); - -#ifndef TQT_NO_CODECS - static TQTextCodec* loadCharmap(TQIODevice*); - static TQTextCodec* loadCharmapFile(TQString filename); -#endif //TQT_NO_CODECS - static TQTextCodec* codecForMib(int mib); - static TQTextCodec* codecForName(const char* hint, int accuracy=0); - static TQTextCodec* codecForContent(const char* chars, int len); - static TQTextCodec* codecForIndex(int i); - static TQTextCodec* codecForLocale(); - static void setCodecForLocale(TQTextCodec *c); - - static TQTextCodec* codecForTr(); - static void setCodecForTr(TQTextCodec *c); - static TQTextCodec* codecForCStrings(); - static void setCodecForCStrings(TQTextCodec *c); - - static void deleteAllCodecs(); - - static const char* locale(); - - virtual const char* name() const = 0; - virtual const char* mimeName() const; - virtual int mibEnum() const = 0; - - virtual TQTextDecoder* makeDecoder() const; - virtual TQTextEncoder* makeEncoder() const; - - virtual TQString toUnicode(const char* chars, int len) const; - virtual TQCString fromUnicode(const TQString& uc, int& lenInOut) const; - - TQCString fromUnicode(const TQString& uc) const; - TQString toUnicode(const TQByteArray&, int len) const; - TQString toUnicode(const TQByteArray&) const; - TQString toUnicode(const TQCString&, int len) const; - TQString toUnicode(const TQCString&) const; - TQString toUnicode(const char* chars) const; - virtual bool canEncode( TQChar ) const; - virtual bool canEncode( const TQString& ) const; - - virtual int heuristicContentMatch(const char* chars, int len) const = 0; - virtual int heuristicNameMatch(const char* hint) const; - - virtual TQByteArray fromUnicode(const TQString& uc, int from, int len) const; - virtual unsigned short characterFromUnicode(const TQString &str, int pos) const; - -protected: - TQTextCodec(); - static int simpleHeuristicNameMatch(const char* name, const char* hint); - -private: - friend class TQFont; - friend class TQFontEngineXLFD; - void fromUnicodeInternal( const TQChar *in, unsigned short *out, int length ); - - static TQTextCodec *cftr; - static TQTextCodec *cfcs; -}; - -inline TQTextCodec* TQTextCodec::codecForTr() { return cftr; } -inline void TQTextCodec::setCodecForTr(TQTextCodec *c) { cftr = c; } -inline TQTextCodec* TQTextCodec::codecForCStrings() { return cfcs; } -inline void TQTextCodec::setCodecForCStrings(TQTextCodec *c) { cfcs = c; } - -#endif // TQT_NO_TEXTCODEC -#endif // TQTEXTCODEC_H diff --git a/src/codecs/ntqtextcodecfactory.h b/src/codecs/ntqtextcodecfactory.h deleted file mode 100644 index 74cca82ca..000000000 --- a/src/codecs/ntqtextcodecfactory.h +++ /dev/null @@ -1,59 +0,0 @@ -/**************************************************************************** -** -** Definition of TQTextCodecFactory 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 TQTEXTCODECFACTORY_H -#define TQTEXTCODECFACTORY_H - -#ifndef QT_H -#include "tqstringlist.h" -#endif // QT_H - -#ifndef TQT_NO_TEXTCODEC - -class TQTextCodec; - -class TQ_EXPORT TQTextCodecFactory -{ -public: - static TQTextCodec *createForName( const TQString & ); - static TQTextCodec *createForMib( int ); -}; - -#endif // TQT_NO_TEXTCODEC - -#endif // TQTEXTCODECFACTORY_H diff --git a/src/codecs/ntqtextcodecplugin.h b/src/codecs/ntqtextcodecplugin.h deleted file mode 100644 index 13a83733d..000000000 --- a/src/codecs/ntqtextcodecplugin.h +++ /dev/null @@ -1,70 +0,0 @@ -/**************************************************************************** -** -** Definition of TQTextCodecPlugin class -** -** Created : 010920 -** -** 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. -** -**********************************************************************/ - -#ifndef TQTEXTCODECPLUGIN_H -#define TQTEXTCODECPLUGIN_H - -#ifndef QT_H -#include "ntqgplugin.h" -#include "tqstringlist.h" -#endif // QT_H - -#ifndef TQT_NO_TEXTCODECPLUGIN -class TQTextCodec; -class TQTextCodecPluginPrivate; - -class TQ_EXPORT TQTextCodecPlugin : public TQGPlugin -{ - TQ_OBJECT -public: - TQTextCodecPlugin(); - ~TQTextCodecPlugin(); - - virtual TQStringList names() const = 0; - virtual TQTextCodec *createForName( const TQString &name ) = 0; - - virtual TQValueList mibEnums() const = 0; - virtual TQTextCodec *createForMib( int mib ) = 0; - -private: - TQTextCodecPluginPrivate *d; -}; -#endif // TQT_NO_TEXTCODECPLUGIN -#endif // TQTEXTCODECPLUGIN_H diff --git a/src/codecs/ntqtsciicodec.h b/src/codecs/ntqtsciicodec.h index bbea40f2d..a71a3fe91 100644 --- a/src/codecs/ntqtsciicodec.h +++ b/src/codecs/ntqtsciicodec.h @@ -69,7 +69,7 @@ #define TQTSCIICODEC_H #ifndef QT_H -#include "ntqtextcodec.h" +#include "tqtextcodec.h" #endif // QT_H #ifndef TQT_NO_CODECS diff --git a/src/codecs/ntqutfcodec.h b/src/codecs/ntqutfcodec.h index c6303a3c4..c763238cd 100644 --- a/src/codecs/ntqutfcodec.h +++ b/src/codecs/ntqutfcodec.h @@ -42,7 +42,7 @@ #define TQUTFCODEC_H #ifndef QT_H -#include "ntqtextcodec.h" +#include "tqtextcodec.h" #endif // QT_H #ifndef TQT_NO_TEXTCODEC diff --git a/src/codecs/qfontcodecs_p.h b/src/codecs/qfontcodecs_p.h index cc2cd40b0..b9ba7ebd4 100644 --- a/src/codecs/qfontcodecs_p.h +++ b/src/codecs/qfontcodecs_p.h @@ -55,7 +55,7 @@ #ifndef QT_H #include "ntqglobal.h" -#include "ntqtextcodec.h" +#include "tqtextcodec.h" #endif // QT_H diff --git a/src/codecs/qisciicodec_p.h b/src/codecs/qisciicodec_p.h index 2fe0a1150..372415cf1 100644 --- a/src/codecs/qisciicodec_p.h +++ b/src/codecs/qisciicodec_p.h @@ -2,7 +2,7 @@ #define TQISCIICODEC_H #ifndef QT_H -#include "ntqtextcodec.h" +#include "tqtextcodec.h" #endif // QT_H #ifndef TQT_NO_CODECS diff --git a/src/codecs/qrtlcodec.cpp b/src/codecs/qrtlcodec.cpp index f4e471b0a..de377f538 100644 --- a/src/codecs/qrtlcodec.cpp +++ b/src/codecs/qrtlcodec.cpp @@ -39,7 +39,7 @@ **********************************************************************/ #include "ntqrtlcodec.h" -#include +#include #ifndef TQT_NO_CODEC_HEBREW diff --git a/src/codecs/qt_codecs.pri b/src/codecs/qt_codecs.pri index 196448d3b..80ec0c22f 100644 --- a/src/codecs/qt_codecs.pri +++ b/src/codecs/qt_codecs.pri @@ -14,12 +14,12 @@ tools { $$CODECS_H/ntqjpunicode.h \ $$CODECS_H/ntqrtlcodec.h \ $$CODECS_H/ntqsjiscodec.h \ - $$CODECS_H/ntqtextcodec.h \ + $$CODECS_H/tqtextcodec.h \ $$CODECS_H/ntqtsciicodec.h \ $$CODECS_H/ntqutfcodec.h \ - $$CODECS_P/qtextcodecinterface_p.h \ - $$CODECS_H/ntqtextcodecfactory.h \ - $$CODECS_H/ntqtextcodecplugin.h + $$CODECS_P/tqtextcodecinterface_p.h \ + $$CODECS_H/tqtextcodecfactory.h \ + $$CODECS_H/tqtextcodecplugin.h SOURCES += \ #$$CODECS_CPP/qasmocodec.cpp \ @@ -32,11 +32,11 @@ tools { $$CODECS_CPP/qjpunicode.cpp \ $$CODECS_CPP/qrtlcodec.cpp \ $$CODECS_CPP/qsjiscodec.cpp \ - $$CODECS_CPP/qtextcodec.cpp \ + $$CODECS_CPP/tqtextcodec.cpp \ $$CODECS_CPP/qtsciicodec.cpp \ $$CODECS_CPP/qutfcodec.cpp \ - $$CODECS_CPP/qtextcodecfactory.cpp \ - $$CODECS_CPP/qtextcodecplugin.cpp + $$CODECS_CPP/tqtextcodecfactory.cpp \ + $$CODECS_CPP/tqtextcodecplugin.cpp x11:SOURCES += $$CODECS_CPP/qfontcncodec.cpp \ $$CODECS_CPP/qfonthkcodec.cpp \ diff --git a/src/codecs/qtextcodec.cpp b/src/codecs/qtextcodec.cpp deleted file mode 100644 index 632dface1..000000000 --- a/src/codecs/qtextcodec.cpp +++ /dev/null @@ -1,3161 +0,0 @@ -/**************************************************************************** -** -** Implementation of TQTextCodec class -** -** Created : 981015 -** -** Copyright (C) 1998-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 "qplatformdefs.h" - -// UNIX Large File Support redefines open -> open64 -#if defined(open) -# undef open -#endif - -#include "ntqtextcodec.h" -#ifndef TQT_NO_TEXTCODEC - -#include "tqvaluelist.h" -#include "ntqtextcodecfactory.h" -#include "ntqutfcodec.h" -#include "ntqnamespace.h" -#ifndef TQT_NO_CODECS -#include "ntqrtlcodec.h" -#include "ntqtsciicodec.h" -#include "qisciicodec_p.h" -#endif // TQT_NO_CODECS -#ifndef TQT_NO_BIG_CODECS -#include "ntqbig5codec.h" -#include "ntqeucjpcodec.h" -#include "ntqeuckrcodec.h" -#include "ntqgb18030codec.h" -#include "ntqjiscodec.h" -#include "ntqjpunicode.h" -#include "ntqsjiscodec.h" -#endif // TQT_NO_BIG_CODECS -#include "ntqfile.h" -#include "tqstrlist.h" -#include "tqstring.h" -#include "../tools/qlocale_p.h" - -#if !defined(TQT_NO_CODECS) && !defined(TQT_NO_BIG_CODECS) && defined(TQ_WS_X11) -# include "qfontcodecs_p.h" -#endif - -#ifdef TQT_THREAD_SUPPORT -# include -#endif // TQT_THREAD_SUPPORT - -#include -#include -#ifndef Q_OS_TEMP -#include -#endif -#if defined(_XOPEN_UNIX) && !defined(Q_OS_QNX6) -#include -#endif - -static TQValueList *all = 0; -static bool codecs_destroyed = false; -static TQTextCodec * localeMapper = 0; - -class TQTextCodecCleanup { -public: - ~TQTextCodecCleanup() { - TQTextCodec::deleteAllCodecs(); - } -}; -static TQTextCodecCleanup qtextcodec_cleanup; - -/*! - Deletes all the created codecs. - - \warning Do not call this function. - - TQApplication calls this function just before exiting to delete - any TQTextCodec objects that may be lying around. Since various - other classes hold pointers to TQTextCodec objects, it is not safe - to call this function earlier. - - If you are using the utility classes (like TQString) but not using - TQApplication, calling this function at the very end of your - application may be helpful for chasing down memory leaks by - eliminating any TQTextCodec objects. -*/ - -void TQTextCodec::deleteAllCodecs() -{ - codecs_destroyed = true; - - if ( !all ) - return; - -#ifdef TQT_THREAD_SUPPORT - TQMutexLocker locker( tqt_global_mutexpool ? - tqt_global_mutexpool->get( &all ) : 0 ); -#endif // TQT_THREAD_SUPPORT - - TQValueList *ball = all; - all = 0; - TQValueList::Iterator it; - for ( it = ball->begin(); it != ball->end(); ++it ) { - delete *it; - *it = 0; - } - ball->clear(); - delete ball; - - localeMapper = 0; -} - -static void setup(); - -class TQTextStatelessEncoder: public TQTextEncoder { - const TQTextCodec* codec; -public: - TQTextStatelessEncoder(const TQTextCodec*); - TQCString fromUnicode(const TQString& uc, int& lenInOut); -}; - - -class TQTextStatelessDecoder : public TQTextDecoder { - const TQTextCodec* codec; -public: - TQTextStatelessDecoder(const TQTextCodec*); - TQString toUnicode(const char* chars, int len); -}; - -TQTextStatelessEncoder::TQTextStatelessEncoder(const TQTextCodec* c) : - codec(c) -{ -} - - -TQCString TQTextStatelessEncoder::fromUnicode(const TQString& uc, int& lenInOut) -{ - return codec->fromUnicode(uc,lenInOut); -} - - -TQTextStatelessDecoder::TQTextStatelessDecoder(const TQTextCodec* c) : - codec(c) -{ -} - - -TQString TQTextStatelessDecoder::toUnicode(const char* chars, int len) -{ - return codec->toUnicode(chars,len); -} - - - -/*! - \class TQTextCodec ntqtextcodec.h - \brief The TQTextCodec class provides conversion between text encodings. - \reentrant - \ingroup i18n - - TQt uses Unicode to store, draw and manipulate strings. In many - situations you may wish to deal with data that uses a different - encoding. For example, most Japanese documents are still stored in - Shift-JIS or ISO2022, while Russian users often have their - documents in KOI8-R or CP1251. - - TQt provides a set of TQTextCodec classes to help with converting - non-Unicode formats to and from Unicode. You can also create your - own codec classes (\link #subclassing see later\endlink). - - The supported encodings are: - \list - \i Latin1 - \i Big5 -- Chinese - \i Big5-HKSCS -- Chinese - \i eucJP -- Japanese - \i eucKR -- Korean - \i GB2312 -- Chinese - \i GBK -- Chinese - \i GB18030 -- Chinese - \i JIS7 -- Japanese - \i Shift-JIS -- Japanese - \i TSCII -- Tamil - \i utf8 -- Unicode, 8-bit - \i utf16 -- Unicode - \i KOI8-R -- Russian - \i KOI8-U -- Ukrainian - \i ISO8859-1 -- Western - \i ISO8859-2 -- Central European - \i ISO8859-3 -- Central European - \i ISO8859-4 -- Baltic - \i ISO8859-5 -- Cyrillic - \i ISO8859-6 -- Arabic - \i ISO8859-7 -- Greek - \i ISO8859-8 -- Hebrew, visually ordered - \i ISO8859-8-i -- Hebrew, logically ordered - \i ISO8859-9 -- Turkish - \i ISO8859-10 - \i ISO8859-13 - \i ISO8859-14 - \i ISO8859-15 -- Western - \i IBM 850 - \i IBM 866 - \i CP874 - \i CP1250 -- Central European - \i CP1251 -- Cyrillic - \i CP1252 -- Western - \i CP1253 -- Greek - \i CP1254 -- Turkish - \i CP1255 -- Hebrew - \i CP1256 -- Arabic - \i CP1257 -- Baltic - \i CP1258 - \i Apple Roman - \i TIS-620 -- Thai - \endlist - - TQTextCodecs can be used as follows to convert some locally encoded - string to Unicode. Suppose you have some string encoded in Russian - KOI8-R encoding, and want to convert it to Unicode. The simple way - to do this is: - - \code - TQCString locallyEncoded = "..."; // text to convert - TQTextCodec *codec = TQTextCodec::codecForName("KOI8-R"); // get the codec for KOI8-R - TQString unicodeString = codec->toUnicode( locallyEncoded ); - \endcode - - After this, \c{unicodeString} holds the text converted to Unicode. - Converting a string from Unicode to the local encoding is just as - easy: - - \code - TQString unicodeString = "..."; // any Unicode text - TQTextCodec *codec = TQTextCodec::codecForName("KOI8-R"); // get the codec for KOI8-R - TQCString locallyEncoded = codec->fromUnicode( unicodeString ); - \endcode - - Some care must be taken when trying to convert the data in chunks, - for example, when receiving it over a network. In such cases it is - possible that a multi-byte character will be split over two - chunks. At best this might result in the loss of a character and - at worst cause the entire conversion to fail. - - The approach to use in these situations is to create a TQTextDecoder - object for the codec and use this TQTextDecoder for the whole - decoding process, as shown below: - - \code - TQTextCodec *codec = TQTextCodec::codecForName( "Shift-JIS" ); - TQTextDecoder *decoder = codec->makeDecoder(); - - TQString unicodeString; - while( receiving_data ) { - TQByteArray chunk = new_data; - unicodeString += decoder->toUnicode( chunk.data(), chunk.length() ); - } - \endcode - - The TQTextDecoder object maintains state between chunks and therefore - works correctly even if a multi-byte character is split between - chunks. - - \target subclassing - \section1 Creating your own Codec class - - Support for new text encodings can be added to TQt by creating - TQTextCodec subclasses. - - Built-in codecs can be overridden by custom codecs since more - recently created TQTextCodec objects take precedence over earlier - ones. - - You may find it more convenient to make your codec class available - as a plugin; see the \link plugins-howto.html plugin - documentation\endlink for more details. - - The abstract virtual functions describe the encoder to the - system and the coder is used as required in the different - text file formats supported by TQTextStream, and under X11, for the - locale-specific character input and output. - - To add support for another 8-bit encoding to TQt, make a subclass - of TQTextCodec and implement at least the following methods: - - \code - const char* name() const - \endcode - Return the official name for the encoding. - - \code - int mibEnum() const - \endcode - Return the MIB enum for the encoding if it is listed in the - \link http://www.iana.org/assignments/character-sets - IANA character-sets encoding file\endlink. - - If the encoding is multi-byte then it will have "state"; that is, - the interpretation of some bytes will be dependent on some preceding - bytes. For such encodings, you must implement: - - \code - TQTextDecoder* makeDecoder() const - \endcode - Return a TQTextDecoder that remembers incomplete multi-byte sequence - prefixes or other required state. - - If the encoding does \e not require state, you should implement: - - \code - TQString toUnicode(const char* chars, int len) const - \endcode - Converts \e len characters from \e chars to Unicode. - - The base TQTextCodec class has default implementations of the above - two functions, \e{but they are mutually recursive}, so you must - re-implement at least one of them, or both for improved efficiency. - - For conversion from Unicode to 8-bit encodings, it is rarely necessary - to maintain state. However, two functions similar to the two above - are used for encoding: - - \code - TQTextEncoder* makeEncoder() const - \endcode - Return a TQTextEncoder. - - \code - TQCString fromUnicode(const TQString& uc, int& lenInOut ) const - \endcode - Converts \e lenInOut characters (of type TQChar) from the start of - the string \e uc, returning a TQCString result, and also returning - the \link TQCString::length() length\endlink of the result in - \e lenInOut. - - Again, these are mutually recursive so only one needs to be implemented, - or both if greater efficiency is possible. - - Finally, you must implement: - - \code - int heuristicContentMatch(const char* chars, int len) const - \endcode - Gives a value indicating how likely it is that \e len characters - from \e chars are in the encoding. - - A good model for this function is the - TQWindowsLocalCodec::heuristicContentMatch function found in the TQt - sources. - - A TQTextCodec subclass might have improved performance if you also - re-implement: - - \code - bool canEncode( TQChar ) const - \endcode - Test if a Unicode character can be encoded. - - \code - bool canEncode( const TQString& ) const - \endcode - Test if a string of Unicode characters can be encoded. - - \code - int heuristicNameMatch(const char* hint) const - \endcode - Test if a possibly non-standard name is referring to the codec. - - Codecs can also be created as \link plugins-howto.html plugins\endlink. -*/ - - -/*! - \nonreentrant - - Constructs a TQTextCodec, and gives it the highest precedence. The - TQTextCodec should always be constructed on the heap (i.e. with \c - new). TQt takes ownership and will delete it when the application - terminates. -*/ -TQTextCodec::TQTextCodec() -{ - // 'codecs_destroyed' should never be true at this point - if (!codecs_destroyed) - { - setup(); -#ifdef TQT_THREAD_SUPPORT - TQMutexLocker locker( tqt_global_mutexpool ? - tqt_global_mutexpool->get( &all ) : 0 ); -#endif // TQT_THREAD_SUPPORT - all->insert( all->begin(), this ); - } -} - - -/*! - \nonreentrant - - Destroys the TQTextCodec. Note that you should not delete codecs - yourself: once created they become TQt's responsibility. -*/ -TQTextCodec::~TQTextCodec() -{ - if ( !codecs_destroyed ) - tqWarning("TQTextCodec::~TQTextCodec() called by application"); - -#ifdef TQT_THREAD_SUPPORT - TQMutexLocker locker( tqt_global_mutexpool ? - tqt_global_mutexpool->get( &all ) : 0 ); -#endif // TQT_THREAD_SUPPORT - if ( all ) - all->remove( this ); -} - - -/*! - Returns a value indicating how likely it is that this decoder is - appropriate for decoding some format that has the given name. The - name is compared with the \a hint. - - A good match returns a positive number around the length of the - string. A bad match is negative. - - The default implementation calls simpleHeuristicNameMatch() with - the name of the codec. -*/ -int TQTextCodec::heuristicNameMatch(const char* hint) const -{ - return simpleHeuristicNameMatch(name(),hint); -} - - -// returns a string containing the letters and numbers from input, -// with a space separating run of a character class. e.g. "iso8859-1" -// becomes "iso 8859 1" -static TQString lettersAndNumbers( const char * input ) -{ - TQString result; - TQChar c; - - while( input && *input ) { - c = *input; - if ( c.isLetter() || c.isNumber() ) - result += c.lower(); - if ( input[1] ) { - // add space at character class transition, except - // transition from upper-case to lower-case letter - TQChar n( input[1] ); - if ( c.isLetter() && n.isLetter() ) { - if ( c == c.lower() && n == n.upper() ) - result += ' '; - } else if ( c.category() != n.category() ) { - result += ' '; - } - } - input++; - } - return result.simplifyWhiteSpace(); -} - -/*! - A simple utility function for heuristicNameMatch(): it does some - very minor character-skipping so that almost-exact matches score - high. \a name is the text we're matching and \a hint is used for - the comparison. -*/ -int TQTextCodec::simpleHeuristicNameMatch(const char* name, const char* hint) -{ - // if they're the same, return a perfect score. - if ( name && hint && *name && *hint && tqstricmp( name, hint ) == 0 ) - return tqstrlen( hint ); - - // if the letters and numbers are the same, we have an "almost" - // perfect match. - TQString h( lettersAndNumbers( hint ) ); - TQString n( lettersAndNumbers( name ) ); - if ( h == n ) - return tqstrlen( hint )-1; - - if ( h.stripWhiteSpace() == n.stripWhiteSpace() ) - return tqstrlen( hint )-2; - - // could do some more here, but I don't think it's worth it - - return 0; -} - - -/*! - Returns the TQTextCodec \a i positions from the most recently - inserted codec, or 0 if there is no such TQTextCodec. Thus, - codecForIndex(0) returns the most recently created TQTextCodec. -*/ -TQTextCodec* TQTextCodec::codecForIndex(int i) -{ - if (codecs_destroyed) - { - return nullptr; - } - - setup(); - return (uint)i >= all->count() ? 0 : *all->at(i); -} - - -/*! - Returns the TQTextCodec which matches the \link - TQTextCodec::mibEnum() MIBenum\endlink \a mib. -*/ -TQTextCodec* TQTextCodec::codecForMib(int mib) -{ - if (codecs_destroyed) - { - return nullptr; - } - - setup(); - TQValueList::ConstIterator i; - TQTextCodec* result=0; - for ( i = all->begin(); i != all->end(); ++i ) { - result = *i; - if ( result->mibEnum()==mib ) - return result; - } - -#if !defined(TQT_NO_COMPONENT) && !defined(QT_LITE_COMPONENT) - if ( !result || (result && result->mibEnum() != mib) ) { - TQTextCodec *codec = TQTextCodecFactory::createForMib(mib); - if (codec) - result = codec; - } -#endif // !TQT_NO_COMPONENT !QT_LITE_COMPONENT - - return result; -} - - - - - -#ifdef Q_OS_WIN32 -class TQWindowsLocalCodec: public TQTextCodec -{ -public: - TQWindowsLocalCodec(); - ~TQWindowsLocalCodec(); - - TQString toUnicode(const char* chars, int len) const; - TQCString fromUnicode(const TQString& uc, int& lenInOut ) const; - - const char* name() const; - int mibEnum() const; - - int heuristicContentMatch(const char* chars, int len) const; - - TQTextDecoder* makeDecoder() const; -}; - -TQWindowsLocalCodec::TQWindowsLocalCodec() -{ -} - -TQWindowsLocalCodec::~TQWindowsLocalCodec() -{ -} - - -TQString TQWindowsLocalCodec::toUnicode(const char* chars, int len) const -{ - if ( len == 1 && chars ) { // Optimization; avoids allocation - char c[2]; - c[0] = *chars; - c[1] = 0; - return qt_winMB2TQString( c, 2 ); - } - if ( len < 0 ) - return qt_winMB2TQString( chars ); - TQCString s(chars,len+1); - return qt_winMB2TQString(s); -} - -TQCString TQWindowsLocalCodec::fromUnicode(const TQString& uc, int& lenInOut ) const -{ - TQCString r = qt_winTQString2MB( uc, lenInOut ); - lenInOut = r.length(); - return r; -} - - -const char* TQWindowsLocalCodec::name() const -{ - return "System"; -} - -int TQWindowsLocalCodec::mibEnum() const -{ - return 0; -} - - -int TQWindowsLocalCodec::heuristicContentMatch(const char* chars, int len) const -{ - // ### Not a bad default implementation? - TQString t = toUnicode(chars,len); - int l = t.length(); - TQCString mb = fromUnicode(t,l); - int i=0; - while ( i < len ) { - if ( chars[i] == mb[i] ) - i++; - else - break; - } - return i; -} - -class TQWindowsLocalDecoder: public TQTextDecoder -{ - const TQWindowsLocalCodec* codec; - int nbuf; - uchar buf[4]; // hopefully this will be enough -public: - TQWindowsLocalDecoder(const TQWindowsLocalCodec *c) : codec(c), nbuf(0) - { - } - - TQString toUnicode(const char* chars, int len) - { - if (len != 1 && nbuf == 0) - return codec->toUnicode(chars, len); - if (len == 1) { - char c[sizeof buf + 2]; - memcpy(c, buf, nbuf); - c[nbuf] = *chars; - c[nbuf+1] = 0; - - // try to decode this: - TQString retval = codec->toUnicode(c, -1); - if ( retval.isEmpty() ) { - // it didn't return anything; we probably stopped mid-way in a multi-byte - // character - buf[nbuf++] = *chars; - if (nbuf + 1 == sizeof buf) { - tqWarning("TQWindowsLocalDecoder: exceeded max internal buffer size"); - nbuf = 0; - } - } - else - nbuf = 0; // decoded successfully - - return retval; - } - - if (len == -1) - len = (int)strlen(chars); - - // Ugh! We need to allocate memory - char *s = new char[nbuf + len + 1]; - memcpy(s, buf, nbuf); - memcpy(s + nbuf, chars, len); - s[nbuf + len] = 0; - - TQString retval = codec->toUnicode(s, -1); - nbuf = 0; - delete[] s; - return retval; - } -}; - -TQTextDecoder* TQWindowsLocalCodec::makeDecoder() const -{ - return new TQWindowsLocalDecoder(this); -} - -#else - -/* locale names mostly copied from XFree86 */ -static const char * const iso8859_2locales[] = { - "croatian", "cs", "cs_CS", "cs_CZ","cz", "cz_CZ", "czech", "hr", - "hr_HR", "hu", "hu_HU", "hungarian", "pl", "pl_PL", "polish", "ro", - "ro_RO", "rumanian", "serbocroatian", "sh", "sh_SP", "sh_YU", "sk", - "sk_SK", "sl", "sl_CS", "sl_SI", "slovak", "slovene", "sr_SP", 0 }; - -static const char * const iso8859_3locales[] = { - "eo", 0 }; - -static const char * const iso8859_4locales[] = { - "ee", "ee_EE", 0 }; - -static const char * const iso8859_5locales[] = { - "mk", "mk_MK", "sp", "sp_YU", 0 }; - -static const char * const cp_1251locales[] = { - "be", "be_BY", "bg", "bg_BG", "bulgarian", 0 }; - -static const char * const pt_154locales[] = { - "ba_RU", "ky", "ky_KG", "kk", "kk_KZ", 0 }; - -static const char * const iso8859_6locales[] = { - "ar_AA", "ar_SA", "arabic", 0 }; - -static const char * const iso8859_7locales[] = { - "el", "el_GR", "greek", 0 }; - -static const char * const iso8859_8locales[] = { - "hebrew", "he", "he_IL", "iw", "iw_IL", 0 }; - -static const char * const iso8859_9locales[] = { - "tr", "tr_TR", "turkish", 0 }; - -static const char * const iso8859_13locales[] = { - "lt", "lt_LT", "lv", "lv_LV", 0 }; - -static const char * const iso8859_15locales[] = { - "et", "et_EE", - // Euro countries - "br_FR", "ca_ES", "de", "de_AT", "de_BE", "de_DE", "de_LU", "en_IE", - "es", "es_ES", "eu_ES", "fi", "fi_FI", "finnish", "fr", "fr_FR", - "fr_BE", "fr_LU", "french", "ga_IE", "gl_ES", "it", "it_IT", "oc_FR", - "nl", "nl_BE", "nl_NL", "pt", "pt_PT", "sv_FI", "wa_BE", - 0 }; - -static const char * const koi8_ulocales[] = { - "uk", "uk_UA", "ru_UA", "ukrainian", 0 }; - -static const char * const tis_620locales[] = { - "th", "th_TH", "thai", 0 }; - -static const char * const tcvnlocales[] = { - "vi", "vi_VN", 0 }; - -static bool try_locale_list( const char * const locale[], const char * lang ) -{ - int i; - for( i=0; locale[i] && *locale[i] && strcmp(locale[i], lang); i++ ) - ; - return locale[i] != 0; -} - -// For the probably_koi8_locales we have to look. the standard says -// these are 8859-5, but almost all Russian users use KOI8-R and -// incorrectly set $LANG to ru_RU. We'll check tolower() to see what -// tolower() thinks ru_RU means. - -// If you read the history, it seems that many Russians blame ISO and -// Perestroika for the confusion. -// -// The real bug is that some programs break if the user specifies -// ru_RU.KOI8-R. - -static const char * const probably_koi8_rlocales[] = { - "ru", "ru_SU", "ru_RU", "russian", 0 }; - -static TQTextCodec * ru_RU_hack( const char * i ) { - TQTextCodec * ru_RU_codec = 0; - - TQCString origlocale = setlocale( LC_CTYPE, i ); - // unicode koi8r latin5 name - // 0x044E 0xC0 0xEE CYRILLIC SMALL LETTER YU - // 0x042E 0xE0 0xCE CYRILLIC CAPITAL LETTER YU - int latin5 = tolower( 0xCE ); - int koi8r = tolower( 0xE0 ); - if ( koi8r == 0xC0 && latin5 != 0xEE ) { - ru_RU_codec = TQTextCodec::codecForName( "KOI8-R" ); - } else if ( koi8r != 0xC0 && latin5 == 0xEE ) { - ru_RU_codec = TQTextCodec::codecForName( "ISO 8859-5" ); - } else { - // something else again... let's assume... *throws dice* - ru_RU_codec = TQTextCodec::codecForName( "KOI8-R" ); - tqWarning( "TQTextCodec: using KOI8-R, probe failed (%02x %02x %s)", - koi8r, latin5, i ); - } - setlocale( LC_CTYPE, origlocale.data() ); - - return ru_RU_codec; -} - -#endif - -/*! - Set the codec to \a c; this will be returned by codecForLocale(). - This might be needed for some applications that want to use their - own mechanism for setting the locale. - - \sa codecForLocale() -*/ -void TQTextCodec::setCodecForLocale(TQTextCodec *c) { - localeMapper = c; -} - -/*! Returns a pointer to the codec most suitable for this locale. */ - -TQTextCodec* TQTextCodec::codecForLocale() -{ - if (codecs_destroyed) - { - return nullptr; - } - - if (!localeMapper) - { - setup(); - } - - return localeMapper; -} - - -/*! - Searches all installed TQTextCodec objects and returns the one - which best matches \a name; the match is case-insensitive. Returns - 0 if no codec's heuristicNameMatch() reports a match better than - \a accuracy, or if \a name is a null string. - - \sa heuristicNameMatch() -*/ - -TQTextCodec* TQTextCodec::codecForName( const char* name, int accuracy ) -{ - if (codecs_destroyed) - { - return nullptr; - } - - if ( !name || !*name ) - return 0; - - setup(); - TQValueList::ConstIterator i; - TQTextCodec* result = 0; - int best = accuracy; - TQTextCodec* cursor; - for ( i = all->begin(); i != all->end(); ++i ) { - cursor = *i; - int s = cursor->heuristicNameMatch( name ); - if ( s > best ) { - best = s; - result = cursor; - } - } - -#if !defined(TQT_NO_COMPONENT) && !defined(QT_LITE_COMPONENT) - if ( !result ) - result = TQTextCodecFactory::createForName(name); -#endif // !TQT_NO_COMPONENT !QT_LITE_COMPONENT - - return result; -} - - -/*! - Searches all installed TQTextCodec objects, returning the one which - most recognizes the given content. May return 0. - - Note that this is often a poor choice, since character encodings - often use most of the available character sequences, and so only - by linguistic analysis could a true match be made. - - \a chars contains the string to check, and \a len contains the - number of characters in the string to use. - - \sa heuristicContentMatch() -*/ -TQTextCodec* TQTextCodec::codecForContent(const char* chars, int len) -{ - if (codecs_destroyed) - { - return nullptr; - } - - setup(); - TQValueList::ConstIterator i; - TQTextCodec* result = 0; - int best=0; - TQTextCodec* cursor; - for ( i = all->begin(); i != all->end(); ++i ) { - cursor = *i; - int s = cursor->heuristicContentMatch(chars,len); - if ( s > best ) { - best = s; - result = cursor; - } - } - return result; -} - - -/*! - \fn const char* TQTextCodec::name() const - - TQTextCodec subclasses must reimplement this function. It returns - the name of the encoding supported by the subclass. When choosing - a name for an encoding, consider these points: - \list - \i On X11, heuristicNameMatch( const char * hint ) - is used to test if a the TQTextCodec - can convert between Unicode and the encoding of a font - with encoding \e hint, such as "iso8859-1" for Latin-1 fonts, - "koi8-r" for Russian KOI8 fonts. - The default algorithm of heuristicNameMatch() uses name(). - \i Some applications may use this function to present - encodings to the end user. - \endlist - */ - -/*! - \fn int TQTextCodec::mibEnum() const - - Subclasses of TQTextCodec must reimplement this function. It - returns the MIBenum (see \link - http://www.iana.org/assignments/character-sets the - IANA character-sets encoding file\endlink for more information). - It is important that each TQTextCodec subclass returns the correct - unique value for this function. -*/ - - -/*! - Returns the preferred mime name of the encoding as defined in the - \link http://www.iana.org/assignments/character-sets - IANA character-sets encoding file\endlink. -*/ -const char* TQTextCodec::mimeName() const -{ - return name(); -} - - -/*! - \fn int TQTextCodec::heuristicContentMatch(const char* chars, int len) const - - TQTextCodec subclasses must reimplement this function. It examines - the first \a len bytes of \a chars and returns a value indicating - how likely it is that the string is a prefix of text encoded in - the encoding of the subclass. A negative return value indicates - that the text is detectably not in the encoding (e.g. it contains - characters undefined in the encoding). A return value of 0 - indicates that the text should be decoded with this codec rather - than as ASCII, but there is no particular evidence. The value - should range up to \a len. Thus, most decoders will return -1, 0, - or -\a len. - - The characters are not null terminated. - - \sa codecForContent(). -*/ - - -/*! - Creates a TQTextDecoder which stores enough state to decode chunks - of char* data to create chunks of Unicode data. The default - implementation creates a stateless decoder, which is only - sufficient for the simplest encodings where each byte corresponds - to exactly one Unicode character. - - The caller is responsible for deleting the returned object. -*/ -TQTextDecoder* TQTextCodec::makeDecoder() const -{ - return new TQTextStatelessDecoder(this); -} - - -/*! - Creates a TQTextEncoder which stores enough state to encode chunks - of Unicode data as char* data. The default implementation creates - a stateless encoder, which is only sufficient for the simplest - encodings where each Unicode character corresponds to exactly one - character. - - The caller is responsible for deleting the returned object. -*/ -TQTextEncoder* TQTextCodec::makeEncoder() const -{ - return new TQTextStatelessEncoder(this); -} - - -/*! - TQTextCodec subclasses must reimplement this function or - makeDecoder(). It converts the first \a len characters of \a chars - to Unicode. - - The default implementation makes a decoder with makeDecoder() and - converts the input with that. Note that the default makeDecoder() - implementation makes a decoder that simply calls - this function, hence subclasses \e must reimplement one function or - the other to avoid infinite recursion. -*/ -TQString TQTextCodec::toUnicode(const char* chars, int len) const -{ - if ( chars == 0 ) - return TQString::null; - TQTextDecoder* i = makeDecoder(); - TQString result = i->toUnicode(chars,len); - delete i; - return result; -} - - -/*! - TQTextCodec subclasses must reimplement either this function or - makeEncoder(). It converts the first \a lenInOut characters of \a - uc from Unicode to the encoding of the subclass. If \a lenInOut is - negative or too large, the length of \a uc is used instead. - - Converts \a lenInOut characters (not bytes) from \a uc, producing - a TQCString. \a lenInOut will be set to the \link - TQCString::length() length\endlink of the result (in bytes). - - The default implementation makes an encoder with makeEncoder() and - converts the input with that. Note that the default makeEncoder() - implementation makes an encoder that simply calls this function, - hence subclasses \e must reimplement one function or the other to - avoid infinite recursion. -*/ - -TQCString TQTextCodec::fromUnicode(const TQString& uc, int& lenInOut) const -{ - TQTextEncoder* i = makeEncoder(); - TQCString result = i->fromUnicode(uc, lenInOut); - delete i; - return result; -} - -/*! - \overload - \internal -*/ -TQByteArray TQTextCodec::fromUnicode( const TQString &str, int pos, int len ) const -{ - TQByteArray a; - if( len < 0 ) - len = str.length() - pos; - a = fromUnicode( str.mid(pos, len) ); - if( a.size() > 0 && a[(int)a.size() - 1] == '\0' ) - a.resize( a.size() - 1 ); - return a; -} - -/*! - \overload - - \a uc is the unicode source string. -*/ -TQCString TQTextCodec::fromUnicode(const TQString& uc) const -{ - int l = uc.length(); - return fromUnicode(uc,l); -} - -/*! - \overload - - \a a contains the source characters; \a len contains the number of - characters in \a a to use. -*/ -TQString TQTextCodec::toUnicode(const TQByteArray& a, int len) const -{ - int l = a.size(); - l = TQMIN( l, len ); - return toUnicode( a.data(), l ); -} - -/*! - \overload - - \a a contains the source characters. -*/ -TQString TQTextCodec::toUnicode(const TQByteArray& a) const -{ - int l = a.size(); - return toUnicode( a.data(), l ); -} - -/*! - \overload - - \a a contains the source characters; \a len contains the number of - characters in \a a to use. -*/ -TQString TQTextCodec::toUnicode(const TQCString& a, int len) const -{ - int l = a.length(); - l = TQMIN( l, len ); - return toUnicode( a.data(), l ); -} - -/*! - \overload - - \a a contains the source characters. -*/ -TQString TQTextCodec::toUnicode(const TQCString& a) const -{ - int l = a.length(); - return toUnicode( a.data(), l ); -} - -/*! - \overload - - \a chars contains the source characters. -*/ -TQString TQTextCodec::toUnicode(const char* chars) const -{ - return toUnicode(chars,tqstrlen(chars)); -} - -/*! - \internal -*/ -unsigned short TQTextCodec::characterFromUnicode(const TQString &str, int pos) const -{ - TQCString result = TQTextCodec::fromUnicode(TQString(str[pos])); - uchar *ch = (uchar *) result.data(); - ushort retval = 0; - if (result.size() > 2) { - retval = (ushort) *ch << 8; - ch++; - } - return retval + *ch; -} - -/*! - Returns TRUE if the Unicode character \a ch can be fully encoded - with this codec; otherwise returns FALSE. The default - implementation tests if the result of toUnicode(fromUnicode(ch)) - is the original \a ch. Subclasses may be able to improve the - efficiency. -*/ -bool TQTextCodec::canEncode( TQChar ch ) const -{ - return toUnicode(fromUnicode(ch)) == ch; -} - -/*! - \overload - - \a s contains the string being tested for encode-ability. -*/ -bool TQTextCodec::canEncode( const TQString& s ) const -{ - if ( s.isEmpty() ) - return TRUE; - return toUnicode(fromUnicode(s)) == s; -} - - - -/*! - \class TQTextEncoder ntqtextcodec.h - \brief The TQTextEncoder class provides a state-based encoder. - \reentrant - \ingroup i18n - - The encoder converts Unicode into another format, remembering any - state that is required between calls. - - \sa TQTextCodec::makeEncoder() -*/ - -/*! - Destroys the encoder. -*/ -TQTextEncoder::~TQTextEncoder() -{ -} - -/*! - \fn TQCString TQTextEncoder::fromUnicode(const TQString& uc, int& lenInOut) - - Converts \a lenInOut characters (not bytes) from \a uc, producing - a TQCString. \a lenInOut will be set to the \link - TQCString::length() length\endlink of the result (in bytes). - - The encoder is free to record state to use when subsequent calls - are made to this function (for example, it might change modes with - escape sequences if needed during the encoding of one string, then - assume that mode applies when a subsequent call begins). -*/ - -/*! - \class TQTextDecoder ntqtextcodec.h - \brief The TQTextDecoder class provides a state-based decoder. - \reentrant - \ingroup i18n - - The decoder converts a text format into Unicode, remembering any - state that is required between calls. - - \sa TQTextCodec::makeEncoder() -*/ - - -/*! - Destroys the decoder. -*/ -TQTextDecoder::~TQTextDecoder() -{ -} - -/*! - \fn TQString TQTextDecoder::toUnicode(const char* chars, int len) - - Converts the first \a len bytes in \a chars to Unicode, returning - the result. - - If not all characters are used (e.g. if only part of a multi-byte - encoding is at the end of the characters), the decoder remembers - enough state to continue with the next call to this function. -*/ - -#define CHAINED 0xffff - -struct TQMultiByteUnicodeTable { - // If multiByte, ignore unicode and index into multiByte - // with the next character. - TQMultiByteUnicodeTable() : unicode(0xfffd), multiByte(0) { } - - ~TQMultiByteUnicodeTable() - { - if ( multiByte ) - delete [] multiByte; - } - - ushort unicode; - TQMultiByteUnicodeTable* multiByte; -}; - -static int getByte(char* &cursor) -{ - int byte = 0; - if ( *cursor ) { - if ( cursor[1] == 'x' ) - byte = strtol(cursor+2,&cursor,16); - else if ( cursor[1] == 'd' ) - byte = strtol(cursor+2,&cursor,10); - else - byte = strtol(cursor+2,&cursor,8); - } - return byte&0xff; -} - -class TQTextCodecFromIOD; - -class TQTextCodecFromIODDecoder : public TQTextDecoder { - const TQTextCodecFromIOD* codec; - TQMultiByteUnicodeTable* mb; -public: - TQTextCodecFromIODDecoder(const TQTextCodecFromIOD* c); - TQString toUnicode(const char* chars, int len); -}; - -class TQTextCodecFromIOD : public TQTextCodec { - friend class TQTextCodecFromIODDecoder; - - TQCString n; - - // If from_unicode_page[row()][cell()] is 0 and from_unicode_page_multiByte, - // use from_unicode_page_multiByte[row()][cell()] as string. - char** from_unicode_page; - char*** from_unicode_page_multiByte; - char unkn; - - // Only one of these is used - ushort* to_unicode; - TQMultiByteUnicodeTable* to_unicode_multiByte; - int max_bytes_per_char; - TQStrList aliases; - - bool stateless() const { return !to_unicode_multiByte; } - -public: - TQTextCodecFromIOD(TQIODevice* iod) - { - from_unicode_page = 0; - to_unicode_multiByte = 0; - to_unicode = 0; - from_unicode_page_multiByte = 0; - max_bytes_per_char = 1; - - const int maxlen=100; - char line[maxlen]; - char esc='\\'; - char comm='%'; - bool incmap = FALSE; - while (iod->readLine(line,maxlen) > 0) { - if (0==tqstrnicmp(line,"",15)) - n = line+15; - else if (0==tqstrnicmp(line," ",14)) - esc = line[14]; - else if (0==tqstrnicmp(line," ",15)) - comm = line[15]; - else if (line[0]==comm && 0==tqstrnicmp(line+1," alias ",7)) { - aliases.append(line+8); - } else if (0==tqstrnicmp(line,"CHARMAP",7)) { - if (!from_unicode_page) { - from_unicode_page = new char*[256]; - for (int i=0; i<256; i++) - from_unicode_page[i]=0; - } - if (!to_unicode) { - to_unicode = new ushort[256]; - } - incmap = TRUE; - } else if (0==tqstrnicmp(line,"END CHARMAP",11)) - break; - else if (incmap) { - char* cursor = line; - int byte=-1,unicode=-1; - ushort* mb_unicode=0; - const int maxmb=8; // more -> we'll need to improve datastructures - char mb[maxmb+1]; - int nmb=0; - - while (*cursor) { - if (cursor[0]=='<' && cursor[1]=='U' && - cursor[2]>='0' && cursor[2]<='9' && - cursor[3]>='0' && cursor[3]<='9') { - - unicode = strtol(cursor+2,&cursor,16); - - } else if (*cursor==esc) { - - byte = getByte(cursor); - - if ( *cursor == esc ) { - if ( !to_unicode_multiByte ) { - to_unicode_multiByte = - new TQMultiByteUnicodeTable[256]; - for (int i=0; i<256; i++) { - to_unicode_multiByte[i].unicode = - to_unicode[i]; - to_unicode_multiByte[i].multiByte = 0; - } - delete [] to_unicode; - to_unicode = 0; - } - TQMultiByteUnicodeTable* mbut = - to_unicode_multiByte+byte; - mb[nmb++] = byte; - while ( nmb < maxmb && *cursor == esc ) { - // Always at least once - - mbut->unicode = CHAINED; - byte = getByte(cursor); - mb[nmb++] = byte; - if (!mbut->multiByte) { - mbut->multiByte = - new TQMultiByteUnicodeTable[256]; - } - mbut = mbut->multiByte+byte; - mb_unicode = & mbut->unicode; - } - - if ( nmb > max_bytes_per_char ) - max_bytes_per_char = nmb; - } - } else { - cursor++; - } - } - - if (unicode >= 0 && unicode <= 0xffff) - { - TQChar ch((ushort)unicode); - if (!from_unicode_page[ch.row()]) { - from_unicode_page[ch.row()] = new char[256]; - for (int i=0; i<256; i++) - from_unicode_page[ch.row()][i]=0; - } - if ( mb_unicode ) { - from_unicode_page[ch.row()][ch.cell()] = 0; - if (!from_unicode_page_multiByte) { - from_unicode_page_multiByte = new char**[256]; - for (int i=0; i<256; i++) - from_unicode_page_multiByte[i]=0; - } - if (!from_unicode_page_multiByte[ch.row()]) { - from_unicode_page_multiByte[ch.row()] = new char*[256]; - for (int i=0; i<256; i++) - from_unicode_page_multiByte[ch.row()][i] = 0; - } - mb[nmb++] = 0; - from_unicode_page_multiByte[ch.row()][ch.cell()] - = tqstrdup(mb); - *mb_unicode = unicode; - } else { - from_unicode_page[ch.row()][ch.cell()] = (char)byte; - if ( to_unicode ) - to_unicode[byte] = unicode; - else - to_unicode_multiByte[byte].unicode = unicode; - } - } else { - } - } - } - n = n.stripWhiteSpace(); - - unkn = '?'; // ##### Might be a bad choice. - } - - ~TQTextCodecFromIOD() - { - if ( from_unicode_page ) { - for (int i=0; i<256; i++) - if (from_unicode_page[i]) - delete [] from_unicode_page[i]; - } - if ( from_unicode_page_multiByte ) { - for (int i=0; i<256; i++) - if (from_unicode_page_multiByte[i]) - for (int j=0; j<256; j++) - if (from_unicode_page_multiByte[i][j]) - delete [] from_unicode_page_multiByte[i][j]; - } - if ( to_unicode ) - delete [] to_unicode; - if ( to_unicode_multiByte ) - delete [] to_unicode_multiByte; - } - - bool ok() const - { - return !!from_unicode_page; - } - - TQTextDecoder* makeDecoder() const - { - if ( stateless() ) - return TQTextCodec::makeDecoder(); - else - return new TQTextCodecFromIODDecoder(this); - } - - const char* name() const - { - return n; - } - - int mibEnum() const - { - return 0; // #### Unknown. - } - - int heuristicContentMatch(const char*, int) const - { - return 0; - } - - int heuristicNameMatch(const char* hint) const - { - int bestr = TQTextCodec::heuristicNameMatch(hint); - TQStrListIterator it(aliases); - char* a; - while ((a=it.current())) { - ++it; - int r = simpleHeuristicNameMatch(a,hint); - if (r > bestr) - bestr = r; - } - return bestr; - } - - TQString toUnicode(const char* chars, int len) const - { - const uchar* uchars = (const uchar*)chars; - TQString result; - TQMultiByteUnicodeTable* multiByte=to_unicode_multiByte; - if ( multiByte ) { - while (len--) { - TQMultiByteUnicodeTable& mb = multiByte[*uchars]; - if ( mb.multiByte ) { - // Chained multi-byte - multiByte = mb.multiByte; - } else { - result += TQChar(mb.unicode); - multiByte=to_unicode_multiByte; - } - uchars++; - } - } else { - while (len--) - result += TQChar(to_unicode[*uchars++]); - } - return result; - } - -#if !defined(Q_NO_USING_KEYWORD) - using TQTextCodec::fromUnicode; -#endif - TQCString fromUnicode(const TQString& uc, int& lenInOut) const - { - if (lenInOut > (int)uc.length()) - lenInOut = uc.length(); - int rlen = lenInOut*max_bytes_per_char; - TQCString rstr(rlen+1); - char* cursor = rstr.data(); - char* s=0; - int l = lenInOut; - int lout = 0; - for (int i=0; ito_unicode_multiByte; -} - -TQString TQTextCodecFromIODDecoder::toUnicode(const char* chars, int len) -{ - const uchar* uchars = (const uchar*)chars; - TQString result; - while (len--) { - TQMultiByteUnicodeTable& t = mb[*uchars]; - if ( t.multiByte ) { - // Chained multi-byte - mb = t.multiByte; - } else { - if ( t.unicode ) - result += TQChar(t.unicode); - mb=codec->to_unicode_multiByte; - } - uchars++; - } - return result; -} - -#ifndef TQT_NO_CODECS -// Cannot use
 or \code
-/*!
-    Reads a POSIX2 charmap definition from \a iod.
-    The parser recognizes the following lines:
-
-
-  <code_set_name> name
-  <escape_char> character
-  % alias alias
-  CHARMAP
-  <token> /xhexbyte <Uunicode> ...
-  <token> /ddecbyte <Uunicode> ...
-  <token> /octbyte <Uunicode> ...
-  <token> /any/any... <Uunicode> ...
-  END CHARMAP
-
- - The resulting TQTextCodec is returned (and also added to the global - list of codecs). The name() of the result is taken from the - code_set_name. - - Note that a codec constructed in this way uses much more memory - and is slower than a hand-written TQTextCodec subclass, since - tables in code are kept in memory shared by all TQt applications. - - \sa loadCharmapFile() -*/ -TQTextCodec* TQTextCodec::loadCharmap(TQIODevice* iod) -{ - TQTextCodecFromIOD* r = new TQTextCodecFromIOD(iod); - if ( !r->ok() ) { - delete r; - r = 0; - } - return r; -} - -/*! - A convenience function for loadCharmap() that loads the charmap - definition from the file \a filename. -*/ -TQTextCodec* TQTextCodec::loadCharmapFile(TQString filename) -{ - TQFile f(filename); - if (f.open(IO_ReadOnly)) { - TQTextCodecFromIOD* r = new TQTextCodecFromIOD(&f); - if ( !r->ok() ) - delete r; - else - return r; - } - return 0; -} - -#endif //TQT_NO_CODECS - -/*! - Returns a string representing the current language and - sublanguage, e.g. "pt" for Portuguese, or "pt_br" for Portuguese/Brazil. -*/ - -const char* TQTextCodec::locale() -{ - return TQLocalePrivate::systemLocaleName(); -} - -#ifndef TQT_NO_CODECS - -class TQSimpleTextCodec: public TQTextCodec -{ -public: - TQSimpleTextCodec( int ); - ~TQSimpleTextCodec(); - - TQString toUnicode(const char* chars, int len) const; -#if !defined(Q_NO_USING_KEYWORD) - using TQTextCodec::fromUnicode; -#endif - TQCString fromUnicode(const TQString& uc, int& lenInOut ) const; - unsigned short characterFromUnicode(const TQString &str, int pos) const; - - const char* name() const; - const char* mimeName() const; - int mibEnum() const; - - int heuristicContentMatch(const char* chars, int len) const; - - int heuristicNameMatch(const char* hint) const; -#if !defined(Q_NO_USING_KEYWORD) - using TQTextCodec::canEncode; -#endif - bool canEncode( TQChar ch ) const; - - void fromUnicode( const TQChar *in, unsigned short *out, int length ) const; - -private: - void buildReverseMap(); - - int forwardIndex; -#ifndef TQ_WS_QWS - TQMemArray *reverseMap; -#endif -}; - -#ifdef TQ_WS_QWS -static const TQSimpleTextCodec * reverseOwner = 0; -static TQMemArray * reverseMap = 0; -#endif - -#define LAST_MIB 2004 - -static const struct { - const char *mime; - const char * cs; - int mib; - TQ_UINT16 values[128]; -} unicodevalues[] = { - // from RFC 1489, ftp://ftp.isi.edu/in-notes/rfc1489.txt - { "KOI8-R", "KOI8-R", 2084, - { 0x2500, 0x2502, 0x250C, 0x2510, 0x2514, 0x2518, 0x251C, 0x2524, - 0x252C, 0x2534, 0x253C, 0x2580, 0x2584, 0x2588, 0x258C, 0x2590, - 0x2591, 0x2592, 0x2593, 0x2320, 0x25A0, 0x2219/**/, 0x221A, 0x2248, - 0x2264, 0x2265, 0x00A0, 0x2321, 0x00B0, 0x00B2, 0x00B7, 0x00F7, - 0x2550, 0x2551, 0x2552, 0x0451, 0x2553, 0x2554, 0x2555, 0x2556, - 0x2557, 0x2558, 0x2559, 0x255A, 0x255B, 0x255C, 0x255D, 0x255E, - 0x255F, 0x2560, 0x2561, 0x0401, 0x2562, 0x2563, 0x2564, 0x2565, - 0x2566, 0x2567, 0x2568, 0x2569, 0x256A, 0x256B, 0x256C, 0x00A9, - 0x044E, 0x0430, 0x0431, 0x0446, 0x0434, 0x0435, 0x0444, 0x0433, - 0x0445, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, - 0x043F, 0x044F, 0x0440, 0x0441, 0x0442, 0x0443, 0x0436, 0x0432, - 0x044C, 0x044B, 0x0437, 0x0448, 0x044D, 0x0449, 0x0447, 0x044A, - 0x042E, 0x0410, 0x0411, 0x0426, 0x0414, 0x0415, 0x0424, 0x0413, - 0x0425, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, - 0x041F, 0x042F, 0x0420, 0x0421, 0x0422, 0x0423, 0x0416, 0x0412, - 0x042C, 0x042B, 0x0417, 0x0428, 0x042D, 0x0429, 0x0427, 0x042A } }, - // /**/ - The BULLET OPERATOR is confused. Some people think - // it should be 0x2022 (BULLET). - - // from RFC 2319, ftp://ftp.isi.edu/in-notes/rfc2319.txt - { "KOI8-U", "KOI8-U", 2088, - { 0x2500, 0x2502, 0x250C, 0x2510, 0x2514, 0x2518, 0x251C, 0x2524, - 0x252C, 0x2534, 0x253C, 0x2580, 0x2584, 0x2588, 0x258C, 0x2590, - 0x2591, 0x2592, 0x2593, 0x2320, 0x25A0, 0x2219, 0x221A, 0x2248, - 0x2264, 0x2265, 0x00A0, 0x2321, 0x00B0, 0x00B2, 0x00B7, 0x00F7, - 0x2550, 0x2551, 0x2552, 0x0451, 0x0454, 0x2554, 0x0456, 0x0457, - 0x2557, 0x2558, 0x2559, 0x255A, 0x255B, 0x0491, 0x255D, 0x255E, - 0x255F, 0x2560, 0x2561, 0x0401, 0x0404, 0x2563, 0x0406, 0x0407, - 0x2566, 0x2567, 0x2568, 0x2569, 0x256A, 0x0490, 0x256C, 0x00A9, - 0x044E, 0x0430, 0x0431, 0x0446, 0x0434, 0x0435, 0x0444, 0x0433, - 0x0445, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, - 0x043F, 0x044F, 0x0440, 0x0441, 0x0442, 0x0443, 0x0436, 0x0432, - 0x044C, 0x044B, 0x0437, 0x0448, 0x044D, 0x0449, 0x0447, 0x044A, - 0x042E, 0x0410, 0x0411, 0x0426, 0x0414, 0x0415, 0x0424, 0x0413, - 0x0425, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, - 0x041F, 0x042F, 0x0420, 0x0421, 0x0422, 0x0423, 0x0416, 0x0412, - 0x042C, 0x042B, 0x0417, 0x0428, 0x042D, 0x0429, 0x0427, 0x042A } }, - - // next bits generated from tables on the Unicode 2.0 CD. we can - // use these tables since this is part of the transition to using - // unicode everywhere in qt. - - // $ for A in 8 9 A B C D E F ; do for B in 0 1 2 3 4 5 6 7 8 9 A B C D E F ; do echo 0x${A}${B} 0xFFFD ; done ; done > /tmp/digits ; for a in 8859-* ; do ( awk '/^0x[89ABCDEF]/{ print $1, $2 }' < $a ; cat /tmp/digits ) | sort | uniq -w4 | cut -c6- | paste '-d ' - - - - - - - - | sed -e 's/ /, /g' -e 's/$/,/' -e '$ s/,$/} },/' -e '1 s/^/{ /' > ~/tmp/$a ; done - - // then I inserted the files manually. - { "ISO-8859-2", "ISO 8859-2", 5, - { 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, - 0x00A0, 0x0104, 0x02D8, 0x0141, 0x00A4, 0x013D, 0x015A, 0x00A7, - 0x00A8, 0x0160, 0x015E, 0x0164, 0x0179, 0x00AD, 0x017D, 0x017B, - 0x00B0, 0x0105, 0x02DB, 0x0142, 0x00B4, 0x013E, 0x015B, 0x02C7, - 0x00B8, 0x0161, 0x015F, 0x0165, 0x017A, 0x02DD, 0x017E, 0x017C, - 0x0154, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x0139, 0x0106, 0x00C7, - 0x010C, 0x00C9, 0x0118, 0x00CB, 0x011A, 0x00CD, 0x00CE, 0x010E, - 0x0110, 0x0143, 0x0147, 0x00D3, 0x00D4, 0x0150, 0x00D6, 0x00D7, - 0x0158, 0x016E, 0x00DA, 0x0170, 0x00DC, 0x00DD, 0x0162, 0x00DF, - 0x0155, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x013A, 0x0107, 0x00E7, - 0x010D, 0x00E9, 0x0119, 0x00EB, 0x011B, 0x00ED, 0x00EE, 0x010F, - 0x0111, 0x0144, 0x0148, 0x00F3, 0x00F4, 0x0151, 0x00F6, 0x00F7, - 0x0159, 0x016F, 0x00FA, 0x0171, 0x00FC, 0x00FD, 0x0163, 0x02D9} }, - { "ISO-8859-3", "ISO 8859-3", 6, - { 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, - 0x00A0, 0x0126, 0x02D8, 0x00A3, 0x00A4, 0xFFFD, 0x0124, 0x00A7, - 0x00A8, 0x0130, 0x015E, 0x011E, 0x0134, 0x00AD, 0xFFFD, 0x017B, - 0x00B0, 0x0127, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x0125, 0x00B7, - 0x00B8, 0x0131, 0x015F, 0x011F, 0x0135, 0x00BD, 0xFFFD, 0x017C, - 0x00C0, 0x00C1, 0x00C2, 0xFFFD, 0x00C4, 0x010A, 0x0108, 0x00C7, - 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, - 0xFFFD, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x0120, 0x00D6, 0x00D7, - 0x011C, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x016C, 0x015C, 0x00DF, - 0x00E0, 0x00E1, 0x00E2, 0xFFFD, 0x00E4, 0x010B, 0x0109, 0x00E7, - 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, - 0xFFFD, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x0121, 0x00F6, 0x00F7, - 0x011D, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x016D, 0x015D, 0x02D9} }, - { "ISO-8859-4", "ISO 8859-4", 7, - { 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, - 0x00A0, 0x0104, 0x0138, 0x0156, 0x00A4, 0x0128, 0x013B, 0x00A7, - 0x00A8, 0x0160, 0x0112, 0x0122, 0x0166, 0x00AD, 0x017D, 0x00AF, - 0x00B0, 0x0105, 0x02DB, 0x0157, 0x00B4, 0x0129, 0x013C, 0x02C7, - 0x00B8, 0x0161, 0x0113, 0x0123, 0x0167, 0x014A, 0x017E, 0x014B, - 0x0100, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x012E, - 0x010C, 0x00C9, 0x0118, 0x00CB, 0x0116, 0x00CD, 0x00CE, 0x012A, - 0x0110, 0x0145, 0x014C, 0x0136, 0x00D4, 0x00D5, 0x00D6, 0x00D7, - 0x00D8, 0x0172, 0x00DA, 0x00DB, 0x00DC, 0x0168, 0x016A, 0x00DF, - 0x0101, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x012F, - 0x010D, 0x00E9, 0x0119, 0x00EB, 0x0117, 0x00ED, 0x00EE, 0x012B, - 0x0111, 0x0146, 0x014D, 0x0137, 0x00F4, 0x00F5, 0x00F6, 0x00F7, - 0x00F8, 0x0173, 0x00FA, 0x00FB, 0x00FC, 0x0169, 0x016B, 0x02D9} }, - { "ISO-8859-5", "ISO 8859-5", 8, - { 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, - 0x00A0, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407, - 0x0408, 0x0409, 0x040A, 0x040B, 0x040C, 0x00AD, 0x040E, 0x040F, - 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, - 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F, - 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, - 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F, - 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, - 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F, - 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, - 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F, - 0x2116, 0x0451, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456, 0x0457, - 0x0458, 0x0459, 0x045A, 0x045B, 0x045C, 0x00A7, 0x045E, 0x045F} }, - { "ISO-8859-6", "ISO 8859-6", 82, - { 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, - 0x00A0, 0xFFFD, 0xFFFD, 0xFFFD, 0x00A4, 0xFFFD, 0xFFFD, 0xFFFD, - 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0x060C, 0x00AD, 0xFFFD, 0xFFFD, - 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, - 0xFFFD, 0xFFFD, 0xFFFD, 0x061B, 0xFFFD, 0xFFFD, 0xFFFD, 0x061F, - 0xFFFD, 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627, - 0x0628, 0x0629, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E, 0x062F, - 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x0637, - 0x0638, 0x0639, 0x063A, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, - 0x0640, 0x0641, 0x0642, 0x0643, 0x0644, 0x0645, 0x0646, 0x0647, - 0x0648, 0x0649, 0x064A, 0x064B, 0x064C, 0x064D, 0x064E, 0x064F, - 0x0650, 0x0651, 0x0652, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, - 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD} }, - { "ISO-8859-7", "ISO 8859-7", 10, - { 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, - 0x00A0, 0x2018, 0x2019, 0x00A3, 0xFFFD, 0xFFFD, 0x00A6, 0x00A7, - 0x00A8, 0x00A9, 0xFFFD, 0x00AB, 0x00AC, 0x00AD, 0xFFFD, 0x2015, - 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x0384, 0x0385, 0x0386, 0x00B7, - 0x0388, 0x0389, 0x038A, 0x00BB, 0x038C, 0x00BD, 0x038E, 0x038F, - 0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, - 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, - 0x03A0, 0x03A1, 0xFFFD, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, - 0x03A8, 0x03A9, 0x03AA, 0x03AB, 0x03AC, 0x03AD, 0x03AE, 0x03AF, - 0x03B0, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, - 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, - 0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7, - 0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03CC, 0x03CD, 0x03CE, 0xFFFD} }, - { "ISO-8859-8-I", "ISO 8859-8-I", 85, - { 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, - 0x00A0, 0xFFFD, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, - 0x00A8, 0x00A9, 0x00D7, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x203E, - 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, - 0x00B8, 0x00B9, 0x00F7, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0xFFFD, - 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, - 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, - 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, - 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0x2017, - 0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, - 0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF, - 0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7, - 0x05E8, 0x05E9, 0x05EA, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD} }, - { "ISO-8859-9", "ISO 8859-9", 12, - { 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, - 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, - 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, - 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, - 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, - 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, - 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, - 0x011E, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, - 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x0130, 0x015E, 0x00DF, - 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, - 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, - 0x011F, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, - 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x0131, 0x015F, 0x00FF} }, - { "ISO-8859-10", "ISO 8859-10", 13, - { 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, - 0x00A0, 0x0104, 0x0112, 0x0122, 0x012A, 0x0128, 0x0136, 0x00A7, - 0x013B, 0x0110, 0x0160, 0x0166, 0x017D, 0x00AD, 0x016A, 0x014A, - 0x00B0, 0x0105, 0x0113, 0x0123, 0x012B, 0x0129, 0x0137, 0x00B7, - 0x013C, 0x0111, 0x0161, 0x0167, 0x017E, 0x2015, 0x016B, 0x014B, - 0x0100, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x012E, - 0x010C, 0x00C9, 0x0118, 0x00CB, 0x0116, 0x00CD, 0x00CE, 0x00CF, - 0x00D0, 0x0145, 0x014C, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x0168, - 0x00D8, 0x0172, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF, - 0x0101, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x012F, - 0x010D, 0x00E9, 0x0119, 0x00EB, 0x0117, 0x00ED, 0x00EE, 0x00EF, - 0x00F0, 0x0146, 0x014D, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x0169, - 0x00F8, 0x0173, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x0138} }, - { "ISO-8859-13", "ISO 8859-13", 109, - { 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, - 0x00A0, 0x201D, 0x00A2, 0x00A3, 0x00A4, 0x201E, 0x00A6, 0x00A7, - 0x00D8, 0x00A9, 0x0156, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00C6, - 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x201C, 0x00B5, 0x00B6, 0x00B7, - 0x00F8, 0x00B9, 0x0157, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00E6, - 0x0104, 0x012E, 0x0100, 0x0106, 0x00C4, 0x00C5, 0x0118, 0x0112, - 0x010C, 0x00C9, 0x0179, 0x0116, 0x0122, 0x0136, 0x012A, 0x013B, - 0x0160, 0x0143, 0x0145, 0x00D3, 0x014C, 0x00D5, 0x00D6, 0x00D7, - 0x0172, 0x0141, 0x015A, 0x016A, 0x00DC, 0x017B, 0x017D, 0x00DF, - 0x0105, 0x012F, 0x0101, 0x0107, 0x00E4, 0x00E5, 0x0119, 0x0113, - 0x010D, 0x00E9, 0x017A, 0x0117, 0x0123, 0x0137, 0x012B, 0x013C, - 0x0161, 0x0144, 0x0146, 0x00F3, 0x014D, 0x00F5, 0x00F6, 0x00F7, - 0x0173, 0x0142, 0x015B, 0x016B, 0x00FC, 0x017C, 0x017E, 0x2019} }, - { "ISO-8859-14", "ISO 8859-14", 110, - { 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, - 0x00A0, 0x1E02, 0x1E03, 0x00A3, 0x010A, 0x010B, 0x1E0A, 0x00A7, - 0x1E80, 0x00A9, 0x1E82, 0x1E0B, 0x1EF2, 0x00AD, 0x00AE, 0x0178, - 0x1E1E, 0x1E1F, 0x0120, 0x0121, 0x1E40, 0x1E41, 0x00B6, 0x1E56, - 0x1E81, 0x1E57, 0x1E83, 0x1E60, 0x1EF3, 0x1E84, 0x1E85, 0x1E61, - 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, - 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, - 0x0174, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x1E6A, - 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x0176, 0x00DF, - 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, - 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, - 0x0175, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x1E6B, - 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x0177, 0x00FF} }, - { "ISO-8859-16", "ISO 8859-16", 112, - { 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, - 0x00A0, 0x0104, 0x0105, 0x0141, 0x20AC, 0x201E, 0x0160, 0x00A7, - 0x0161, 0x00A9, 0x0218, 0x00AB, 0x0179, 0x00AD, 0x017A, 0x017B, - 0x00B0, 0x00B1, 0x010C, 0x0142, 0x017D, 0x201D, 0x00B6, 0x00B7, - 0x017E, 0x010D, 0x0219, 0x00BB, 0x0152, 0x0153, 0x0178, 0x017C, - 0x00C0, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x0106, 0x00C6, 0x00C7, - 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, - 0x0110, 0x0143, 0x00D2, 0x00D3, 0x00D4, 0x0150, 0x00D6, 0x015A, - 0x0170, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x0118, 0x021A, 0x00DF, - 0x00E0, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x0107, 0x00E6, 0x00E7, - 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, - 0x0111, 0x0144, 0x00F2, 0x00F3, 0x00F4, 0x0151, 0x00F6, 0x015B, - 0x0171, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x0119, 0x021B, 0x00FF} }, - - // next bits generated again from tables on the Unicode 3.0 CD. - - // $ for a in CP* ; do ( awk '/^0x[89ABCDEF]/{ print $1, $2 }' < $a ) | sort | sed -e 's/#UNDEF.*$/0xFFFD/' | cut -c6- | paste '-d ' - - - - - - - - | sed -e 's/ /, /g' -e 's/$/,/' -e '$ s/,$/} },/' -e '1 s/^/{ /' > ~/tmp/$a ; done - - { "CP 850", "IBM 850", 2009, - { 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, - 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5, - 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, - 0x00FF, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x0192, - 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, - 0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, - 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x00C0, - 0x00A9, 0x2563, 0x2551, 0x2557, 0x255D, 0x00A2, 0x00A5, 0x2510, - 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x00E3, 0x00C3, - 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4, - 0x00F0, 0x00D0, 0x00CA, 0x00CB, 0x00C8, 0x0131, 0x00CD, 0x00CE, - 0x00CF, 0x2518, 0x250C, 0x2588, 0x2584, 0x00A6, 0x00CC, 0x2580, - 0x00D3, 0x00DF, 0x00D4, 0x00D2, 0x00F5, 0x00D5, 0x00B5, 0x00FE, - 0x00DE, 0x00DA, 0x00DB, 0x00D9, 0x00FD, 0x00DD, 0x00AF, 0x00B4, - 0x00AD, 0x00B1, 0x2017, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x00B8, - 0x00B0, 0x00A8, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0} }, - { "CP 874", "CP 874", 0, //### what is the mib? - { 0x20AC, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0x2026, 0xFFFD, 0xFFFD, - 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, - 0xFFFD, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, - 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, - 0x00A0, 0x0E01, 0x0E02, 0x0E03, 0x0E04, 0x0E05, 0x0E06, 0x0E07, - 0x0E08, 0x0E09, 0x0E0A, 0x0E0B, 0x0E0C, 0x0E0D, 0x0E0E, 0x0E0F, - 0x0E10, 0x0E11, 0x0E12, 0x0E13, 0x0E14, 0x0E15, 0x0E16, 0x0E17, - 0x0E18, 0x0E19, 0x0E1A, 0x0E1B, 0x0E1C, 0x0E1D, 0x0E1E, 0x0E1F, - 0x0E20, 0x0E21, 0x0E22, 0x0E23, 0x0E24, 0x0E25, 0x0E26, 0x0E27, - 0x0E28, 0x0E29, 0x0E2A, 0x0E2B, 0x0E2C, 0x0E2D, 0x0E2E, 0x0E2F, - 0x0E30, 0x0E31, 0x0E32, 0x0E33, 0x0E34, 0x0E35, 0x0E36, 0x0E37, - 0x0E38, 0x0E39, 0x0E3A, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0x0E3F, - 0x0E40, 0x0E41, 0x0E42, 0x0E43, 0x0E44, 0x0E45, 0x0E46, 0x0E47, - 0x0E48, 0x0E49, 0x0E4A, 0x0E4B, 0x0E4C, 0x0E4D, 0x0E4E, 0x0E4F, - 0x0E50, 0x0E51, 0x0E52, 0x0E53, 0x0E54, 0x0E55, 0x0E56, 0x0E57, - 0x0E58, 0x0E59, 0x0E5A, 0x0E5B, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD} }, - { "IBM 866", "IBM 866", 2086, - { 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, - 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F, - 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, - 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F, - 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, - 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F, - 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, - 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, - 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, - 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, - 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, - 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, - 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, - 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F, - 0x0401, 0x0451, 0x0404, 0x0454, 0x0407, 0x0457, 0x040E, 0x045E, - 0x00B0, 0x2219, 0x00B7, 0x221A, 0x2116, 0x00A4, 0x25A0, 0x00A0} }, - - { "windows-1250", "CP 1250", 2250, - { 0x20AC, 0xFFFD, 0x201A, 0xFFFD, 0x201E, 0x2026, 0x2020, 0x2021, - 0xFFFD, 0x2030, 0x0160, 0x2039, 0x015A, 0x0164, 0x017D, 0x0179, - 0xFFFD, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, - 0xFFFD, 0x2122, 0x0161, 0x203A, 0x015B, 0x0165, 0x017E, 0x017A, - 0x00A0, 0x02C7, 0x02D8, 0x0141, 0x00A4, 0x0104, 0x00A6, 0x00A7, - 0x00A8, 0x00A9, 0x015E, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x017B, - 0x00B0, 0x00B1, 0x02DB, 0x0142, 0x00B4, 0x00B5, 0x00B6, 0x00B7, - 0x00B8, 0x0105, 0x015F, 0x00BB, 0x013D, 0x02DD, 0x013E, 0x017C, - 0x0154, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x0139, 0x0106, 0x00C7, - 0x010C, 0x00C9, 0x0118, 0x00CB, 0x011A, 0x00CD, 0x00CE, 0x010E, - 0x0110, 0x0143, 0x0147, 0x00D3, 0x00D4, 0x0150, 0x00D6, 0x00D7, - 0x0158, 0x016E, 0x00DA, 0x0170, 0x00DC, 0x00DD, 0x0162, 0x00DF, - 0x0155, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x013A, 0x0107, 0x00E7, - 0x010D, 0x00E9, 0x0119, 0x00EB, 0x011B, 0x00ED, 0x00EE, 0x010F, - 0x0111, 0x0144, 0x0148, 0x00F3, 0x00F4, 0x0151, 0x00F6, 0x00F7, - 0x0159, 0x016F, 0x00FA, 0x0171, 0x00FC, 0x00FD, 0x0163, 0x02D9} }, - { "windows-1251", "CP 1251", 2251, - { 0x0402, 0x0403, 0x201A, 0x0453, 0x201E, 0x2026, 0x2020, 0x2021, - 0x20AC, 0x2030, 0x0409, 0x2039, 0x040A, 0x040C, 0x040B, 0x040F, - 0x0452, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, - 0xFFFD, 0x2122, 0x0459, 0x203A, 0x045A, 0x045C, 0x045B, 0x045F, - 0x00A0, 0x040E, 0x045E, 0x0408, 0x00A4, 0x0490, 0x00A6, 0x00A7, - 0x0401, 0x00A9, 0x0404, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x0407, - 0x00B0, 0x00B1, 0x0406, 0x0456, 0x0491, 0x00B5, 0x00B6, 0x00B7, - 0x0451, 0x2116, 0x0454, 0x00BB, 0x0458, 0x0405, 0x0455, 0x0457, - 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, - 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F, - 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, - 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F, - 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, - 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F, - 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, - 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F} }, - { "windows-1252", "CP 1252", 2252, - { 0x20AC, 0xFFFD, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, - 0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0xFFFD, 0x017D, 0xFFFD, - 0xFFFD, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, - 0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0xFFFD, 0x017E, 0x0178, - 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, - 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, - 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, - 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, - 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, - 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, - 0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, - 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF, - 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, - 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, - 0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, - 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF} }, - { "windows-1253", "CP 1253", 2253, - { 0x20AC, 0xFFFD, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, - 0xFFFD, 0x2030, 0xFFFD, 0x2039, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, - 0xFFFD, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, - 0xFFFD, 0x2122, 0xFFFD, 0x203A, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, - 0x00A0, 0x0385, 0x0386, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, - 0x00A8, 0x00A9, 0xFFFD, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x2015, - 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x0384, 0x00B5, 0x00B6, 0x00B7, - 0x0388, 0x0389, 0x038A, 0x00BB, 0x038C, 0x00BD, 0x038E, 0x038F, - 0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, - 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, - 0x03A0, 0x03A1, 0xFFFD, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, - 0x03A8, 0x03A9, 0x03AA, 0x03AB, 0x03AC, 0x03AD, 0x03AE, 0x03AF, - 0x03B0, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, - 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, - 0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7, - 0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03CC, 0x03CD, 0x03CE, 0xFFFD} }, - { "windows-1254", "CP 1254", 2254, - { 0x20AC, 0xFFFD, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, - 0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0xFFFD, 0xFFFD, 0xFFFD, - 0xFFFD, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, - 0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0xFFFD, 0xFFFD, 0x0178, - 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, - 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, - 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, - 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, - 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, - 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, - 0x011E, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, - 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x0130, 0x015E, 0x00DF, - 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, - 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, - 0x011F, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, - 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x0131, 0x015F, 0x00FF} }, - { "windows-1255", "CP 1255", 2255, - { 0x20AC, 0xFFFD, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, - 0x02C6, 0x2030, 0xFFFD, 0x2039, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, - 0xFFFD, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, - 0x02DC, 0x2122, 0xFFFD, 0x203A, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, - 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x20AA, 0x00A5, 0x00A6, 0x00A7, - 0x00A8, 0x00A9, 0x00D7, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, - 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, - 0x00B8, 0x00B9, 0x00F7, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, - 0x05B0, 0x05B1, 0x05B2, 0x05B3, 0x05B4, 0x05B5, 0x05B6, 0x05B7, - 0x05B8, 0x05B9, 0xFFFD, 0x05BB, 0x05BC, 0x05BD, 0x05BE, 0x05BF, - 0x05C0, 0x05C1, 0x05C2, 0x05C3, 0x05F0, 0x05F1, 0x05F2, 0x05F3, - 0x05F4, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, - 0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, - 0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF, - 0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7, - 0x05E8, 0x05E9, 0x05EA, 0xFFFD, 0xFFFD, 0x200E, 0x200F, 0xFFFD} }, - { "windows-1256", "CP 1256", 2256, - { 0x20AC, 0x067E, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, - 0x02C6, 0x2030, 0x0679, 0x2039, 0x0152, 0x0686, 0x0698, 0x0688, - 0x06AF, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, - 0x06A9, 0x2122, 0x0691, 0x203A, 0x0153, 0x200C, 0x200D, 0x06BA, - 0x00A0, 0x060C, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, - 0x00A8, 0x00A9, 0x06BE, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, - 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, - 0x00B8, 0x00B9, 0x061B, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x061F, - 0x06C1, 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627, - 0x0628, 0x0629, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E, 0x062F, - 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x00D7, - 0x0637, 0x0638, 0x0639, 0x063A, 0x0640, 0x0641, 0x0642, 0x0643, - 0x00E0, 0x0644, 0x00E2, 0x0645, 0x0646, 0x0647, 0x0648, 0x00E7, - 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x0649, 0x064A, 0x00EE, 0x00EF, - 0x064B, 0x064C, 0x064D, 0x064E, 0x00F4, 0x064F, 0x0650, 0x00F7, - 0x0651, 0x00F9, 0x0652, 0x00FB, 0x00FC, 0x200E, 0x200F, 0x06D2} }, - { "windows-1257", "CP 1257", 2257, - { 0x20AC, 0xFFFD, 0x201A, 0xFFFD, 0x201E, 0x2026, 0x2020, 0x2021, - 0xFFFD, 0x2030, 0xFFFD, 0x2039, 0xFFFD, 0x00A8, 0x02C7, 0x00B8, - 0xFFFD, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, - 0xFFFD, 0x2122, 0xFFFD, 0x203A, 0xFFFD, 0x00AF, 0x02DB, 0xFFFD, - 0x00A0, 0xFFFD, 0x00A2, 0x00A3, 0x00A4, 0xFFFD, 0x00A6, 0x00A7, - 0x00D8, 0x00A9, 0x0156, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00C6, - 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, - 0x00F8, 0x00B9, 0x0157, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00E6, - 0x0104, 0x012E, 0x0100, 0x0106, 0x00C4, 0x00C5, 0x0118, 0x0112, - 0x010C, 0x00C9, 0x0179, 0x0116, 0x0122, 0x0136, 0x012A, 0x013B, - 0x0160, 0x0143, 0x0145, 0x00D3, 0x014C, 0x00D5, 0x00D6, 0x00D7, - 0x0172, 0x0141, 0x015A, 0x016A, 0x00DC, 0x017B, 0x017D, 0x00DF, - 0x0105, 0x012F, 0x0101, 0x0107, 0x00E4, 0x00E5, 0x0119, 0x0113, - 0x010D, 0x00E9, 0x017A, 0x0117, 0x0123, 0x0137, 0x012B, 0x013C, - 0x0161, 0x0144, 0x0146, 0x00F3, 0x014D, 0x00F5, 0x00F6, 0x00F7, - 0x0173, 0x0142, 0x015B, 0x016B, 0x00FC, 0x017C, 0x017E, 0x02D9} }, - { "windows-1258", "CP 1258", 2258, - { 0x20AC, 0xFFFD, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, - 0x02C6, 0x2030, 0xFFFD, 0x2039, 0x0152, 0xFFFD, 0xFFFD, 0xFFFD, - 0xFFFD, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, - 0x02DC, 0x2122, 0xFFFD, 0x203A, 0x0153, 0xFFFD, 0xFFFD, 0x0178, - 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, - 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, - 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, - 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, - 0x00C0, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x00C5, 0x00C6, 0x00C7, - 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x0300, 0x00CD, 0x00CE, 0x00CF, - 0x0110, 0x00D1, 0x0309, 0x00D3, 0x00D4, 0x01A0, 0x00D6, 0x00D7, - 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x01AF, 0x0303, 0x00DF, - 0x00E0, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x00E5, 0x00E6, 0x00E7, - 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x0301, 0x00ED, 0x00EE, 0x00EF, - 0x0111, 0x00F1, 0x0323, 0x00F3, 0x00F4, 0x01A1, 0x00F6, 0x00F7, - 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x01B0, 0x20AB, 0x00FF} }, - - { "Apple Roman", "Apple Roman", 0, - { 0x00C4, 0x00C5, 0x00C7, 0x00C9, 0x00D1, 0x00D6, 0x00DC, 0x00E1, - 0x00E0, 0x00E2, 0x00E4, 0x00E3, 0x00E5, 0x00E7, 0x00E9, 0x00E8, - 0x00EA, 0x00EB, 0x00ED, 0x00EC, 0x00EE, 0x00EF, 0x00F1, 0x00F3, - 0x00F2, 0x00F4, 0x00F6, 0x00F5, 0x00FA, 0x00F9, 0x00FB, 0x00FC, - 0x2020, 0x00B0, 0x00A2, 0x00A3, 0x00A7, 0x2022, 0x00B6, 0x00DF, - 0x00AE, 0x00A9, 0x2122, 0x00B4, 0x00A8, 0x2260, 0x00C6, 0x00D8, - 0x221E, 0x00B1, 0x2264, 0x2265, 0x00A5, 0x00B5, 0x2202, 0x2211, - 0x220F, 0x03C0, 0x222B, 0x00AA, 0x00BA, 0x03A9, 0x00E6, 0x00F8, - 0x00BF, 0x00A1, 0x00AC, 0x221A, 0x0192, 0x2248, 0x2206, 0x00AB, - 0x00BB, 0x2026, 0x00A0, 0x00C0, 0x00C3, 0x00D5, 0x0152, 0x0153, - 0x2013, 0x2014, 0x201C, 0x201D, 0x2018, 0x2019, 0x00F7, 0x25CA, - 0x00FF, 0x0178, 0x2044, 0x20AC, 0x2039, 0x203A, 0xFB01, 0xFB02, - 0x2021, 0x00B7, 0x201A, 0x201E, 0x2030, 0x00C2, 0x00CA, 0x00C1, - 0x00CB, 0x00C8, 0x00CD, 0x00CE, 0x00CF, 0x00CC, 0x00D3, 0x00D4, - 0xF8FF, 0x00D2, 0x00DA, 0x00DB, 0x00D9, 0x0131, 0x02C6, 0x02DC, - 0x00AF, 0x02D8, 0x02D9, 0x02DA, 0x00B8, 0x02DD, 0x02DB, 0x02C7} }, - - - - // This one is based on the charmap file - // /usr/share/i18n/charmaps/SAMI-WS2.gz, which is manually adapted - // to this format by Børre Gaup - { "WINSAMI2", "WS2", 0, - { 0x20AC, 0xFFFD, 0x010C, 0x0192, 0x010D, 0x01B7, 0x0292, 0x01EE, - 0x01EF, 0x0110, 0x0160, 0x2039, 0x0152, 0xFFFD, 0xFFFD, 0xFFFD, - 0xFFFD, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, - 0x0111, 0x01E6, 0x0161, 0x203A, 0x0153, 0xFFFD, 0xFFFD, 0x0178, - 0x00A0, 0x01E7, 0x01E4, 0x00A3, 0x00A4, 0x01E5, 0x00A6, 0x00A7, - 0x00A8, 0x00A9, 0x021E, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x021F, - 0x00B0, 0x00B1, 0x01E8, 0x01E9, 0x00B4, 0x00B5, 0x00B6, 0x00B7, - 0x014A, 0x014B, 0x0166, 0x00BB, 0x0167, 0x00BD, 0x017D, 0x017E, - 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, - 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, - 0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, - 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF, - 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, - 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, - 0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, - 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF} }, - - - // this one is generated from the charmap file located in /usr/share/i18n/charmaps - // on most Linux distributions. The thai character set tis620 is byte by byte equivalent - // to iso8859-11, so we name it 8859-11 here, but recognise the name tis620 too. - - // $ for A in 8 9 A B C D E F ; do for B in 0 1 2 3 4 5 6 7 8 9 A B C D E F ; do echo x${A}${B} 0xFFFD ; done ; done > /tmp/digits ; ( cut -c25- < TIS-620 ; cat /tmp/digits ) | awk '/^x[89ABCDEF]/{ print $1, $2 }' | sed -e 's///' | sort | uniq -w4 | cut -c5- | paste '-d ' - - - - - - - - | sed -e 's/ /, /g' -e 's/$/,/' -e '$ s/,$/} },/' -e '1 s/^/{ /' > ~/tmp/tis-620 - { "TIS-620", "ISO 8859-11", 2259, // Thai character set mib enum taken from tis620 (which is byte by byte equivalent) - { 0x20AC, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0x2026, 0xFFFD, 0xFFFD, - 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, - 0xFFFD, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, - 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, - 0xFFFD, 0x0E01, 0x0E02, 0x0E03, 0x0E04, 0x0E05, 0x0E06, 0x0E07, - 0x0E08, 0x0E09, 0x0E0A, 0x0E0B, 0x0E0C, 0x0E0D, 0x0E0E, 0x0E0F, - 0x0E10, 0x0E11, 0x0E12, 0x0E13, 0x0E14, 0x0E15, 0x0E16, 0x0E17, - 0x0E18, 0x0E19, 0x0E1A, 0x0E1B, 0x0E1C, 0x0E1D, 0x0E1E, 0x0E1F, - 0x0E20, 0x0E21, 0x0E22, 0x0E23, 0x0E24, 0x0E25, 0x0E26, 0x0E27, - 0x0E28, 0x0E29, 0x0E2A, 0x0E2B, 0x0E2C, 0x0E2D, 0x0E2E, 0x0E2F, - 0x0E30, 0x0E31, 0x0E32, 0x0E33, 0x0E34, 0x0E35, 0x0E36, 0x0E37, - 0x0E38, 0x0E39, 0x0E3A, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0x0E3F, - 0x0E40, 0x0E41, 0x0E42, 0x0E43, 0x0E44, 0x0E45, 0x0E46, 0x0E47, - 0x0E48, 0x0E49, 0x0E4A, 0x0E4B, 0x0E4C, 0x0E4D, 0x0E4E, 0x0E4F, - 0x0E50, 0x0E51, 0x0E52, 0x0E53, 0x0E54, 0x0E55, 0x0E56, 0x0E57, - 0x0E58, 0x0E59, 0x0E5A, 0x0E5B, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD } }, - - /* - Name: hp-roman8 [HP-PCL5,RFC1345,KXS2] - MIBenum: 2004 - Source: LaserJet IIP Printer User's Manual, - HP part no 33471-90901, Hewlet-Packard, June 1989. - Alias: roman8 - Alias: r8 - Alias: csHPRoman8 - */ - { "Roman8", "HP-Roman8", 2004, - { 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, - 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, - 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, - 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, - 0x00A0, 0x00C0, 0x00C2, 0x00C8, 0x00CA, 0x00CB, 0x00CE, 0x00CF, - 0x00B4, 0x02CB, 0x02C6, 0x00A8, 0x02DC, 0x00D9, 0x00DB, 0x20A4, - 0x00AF, 0x00DD, 0x00FD, 0x00B0, 0x00C7, 0x00E7, 0x00D1, 0x00F1, - 0x00A1, 0x00BF, 0x00A4, 0x00A3, 0x00A5, 0x00A7, 0x0192, 0x00A2, - 0x00E2, 0x00EA, 0x00F4, 0x00FB, 0x00E1, 0x00E9, 0x00F3, 0x00FA, - 0x00E0, 0x00E8, 0x00F2, 0x00F9, 0x00E4, 0x00EB, 0x00F6, 0x00FC, - 0x00C5, 0x00EE, 0x00D8, 0x00C6, 0x00E5, 0x00ED, 0x00F8, 0x00E6, - 0x00C4, 0x00EC, 0x00D6, 0x00DC, 0x00C9, 0x00EF, 0x00DF, 0x00D4, - 0x00C1, 0x00C3, 0x00E3, 0x00D0, 0x00F0, 0x00CD, 0x00CC, 0x00D3, - 0x00D2, 0x00D5, 0x00F5, 0x0160, 0x0161, 0x00DA, 0x0178, 0x00FF, - 0x00DE, 0x00FE, 0x00B7, 0x00B5, 0x00B6, 0x00BE, 0x2014, 0x00BC, - 0x00BD, 0x00AA, 0x00BA, 0x00AB, 0x25A0, 0x00BB, 0x00B1, 0xFFFD } } - - // if you add more chacater sets at the end, change LAST_MIB above -}; - -TQSimpleTextCodec::TQSimpleTextCodec( int i ) - : TQTextCodec(), forwardIndex( i ) -{ -#ifndef TQ_WS_QWS - reverseMap = 0; -#endif -} - - -TQSimpleTextCodec::~TQSimpleTextCodec() -{ -#ifndef TQ_WS_QWS - delete reverseMap; -#else - if ( reverseOwner == this ) { - delete reverseMap; - reverseMap = 0; - reverseOwner = 0; - } -#endif -} - -void TQSimpleTextCodec::buildReverseMap() -{ -#ifdef TQ_WS_QWS - if ( reverseOwner != this ) { - int m = 0; - int i = 0; - while( i < 128 ) { - if ( unicodevalues[forwardIndex].values[i] > m && - unicodevalues[forwardIndex].values[i] < 0xfffd ) - m = unicodevalues[forwardIndex].values[i]; - i++; - } - m++; - if ( !reverseMap ) - reverseMap = new TQMemArray( m ); - if ( m > (int)(reverseMap->size()) ) - reverseMap->resize( m ); - for( i = 0; i < 128 && i < m; i++ ) - (*reverseMap)[i] = (char)i; - for( ;i < m; i++ ) - (*reverseMap)[i] = 0; - for( i=128; i<256; i++ ) { - int u = unicodevalues[forwardIndex].values[i-128]; - if ( u < m ) - (*reverseMap)[u] = (char)(unsigned char)(i); - } - reverseOwner = this; - } -#else - if ( !reverseMap ) { - TQMemArray **map = &((TQSimpleTextCodec *)this)->reverseMap; - int m = 0; - int i = 0; - while( i < 128 ) { - if ( unicodevalues[forwardIndex].values[i] > m && - unicodevalues[forwardIndex].values[i] < 0xfffd ) - m = unicodevalues[forwardIndex].values[i]; - i++; - } - m++; - *map = new TQMemArray( m ); - for( i = 0; i < 128 && i < m; i++ ) - (**map)[i] = (char)i; - for( ;i < m; i++ ) - (**map)[i] = 0; - for( i=128; i<256; i++ ) { - int u = unicodevalues[forwardIndex].values[i-128]; - if ( u < m ) - (**map)[u] = (char)(unsigned char)(i); - } - } -#endif -} - -TQString TQSimpleTextCodec::toUnicode(const char* chars, int len) const -{ - if ( len <= 0 || chars == 0 ) - return TQString::null; - - const unsigned char * c = (const unsigned char *)chars; - int i; - - for ( i = 0; i < len; i++ ) - if ( c[i] == '\0' ) { - len = i; - break; - } - - TQString r; - r.setUnicode(0, len); - TQChar* uc = (TQChar*)r.unicode(); // const_cast - - for ( i = 0; i < len; i++ ) { - if ( c[i] > 127 ) - uc[i] = unicodevalues[forwardIndex].values[c[i]-128]; - else - uc[i] = c[i]; - } - return r; -} - - -TQCString TQSimpleTextCodec::fromUnicode(const TQString& uc, int& len ) const -{ -#ifdef TQ_WS_QWS - if ( this != reverseOwner ) -#else - if ( !reverseMap ) -#endif - ((TQSimpleTextCodec *)this)->buildReverseMap(); - - if ( len <0 || len > (int)uc.length() ) - len = uc.length(); - TQCString r( len+1 ); - int i = len; - int u; - const TQChar* ucp = uc.unicode(); - unsigned char* rp = (unsigned char *)r.data(); - unsigned char* rmp = reverseMap->data(); - int rmsize = (int) reverseMap->size(); - while( i-- ) - { - u = ucp->unicode(); - *rp = u < 128 ? u : (( u < rmsize ) ? (*(rmp+u)) : '?' ); - if ( *rp == 0 ) *rp = '?'; - rp++; - ucp++; - } - r[len] = 0; - return r; -} - -void TQSimpleTextCodec::fromUnicode( const TQChar *in, unsigned short *out, int length ) const -{ -#ifdef TQ_WS_QWS - if ( this != reverseOwner ) -#else - if ( !reverseMap ) -#endif - ((TQSimpleTextCodec *)this)->buildReverseMap(); - - unsigned char* rmp = reverseMap->data(); - int rmsize = (int) reverseMap->size(); - while ( length-- ) { - unsigned short u = in->unicode(); - *out = u < 128 ? u : (( u < rmsize ) ? (*(rmp+u)) : 0 ); - ++in; - ++out; - } -} - -unsigned short TQSimpleTextCodec::characterFromUnicode(const TQString &str, int pos) const -{ -#ifdef TQ_WS_QWS - if ( this != reverseOwner ) -#else - if ( !reverseMap ) -#endif - ((TQSimpleTextCodec *)this)->buildReverseMap(); - - unsigned short u = str[pos].unicode(); - unsigned char* rmp = reverseMap->data(); - int rmsize = (int) reverseMap->size(); - return u < 128 ? u : (( u < rmsize ) ? (*(rmp+u)) : 0 ); -} - -bool TQSimpleTextCodec::canEncode( TQChar ch ) const -{ -#ifdef TQ_WS_QWS - if ( this != reverseOwner ) -#else - if ( !reverseMap ) -#endif - ((TQSimpleTextCodec *)this)->buildReverseMap(); - - unsigned short u = ch.unicode(); - unsigned char* rmp = reverseMap->data(); - int rmsize = (int) reverseMap->size(); - return u < 128 ? TRUE : (( u < rmsize ) ? (*(rmp+u) != 0) : FALSE ); -} - -const char* TQSimpleTextCodec::name() const -{ - return unicodevalues[forwardIndex].cs; -} - -const char* TQSimpleTextCodec::mimeName() const -{ - return unicodevalues[forwardIndex].mime; -} - - -int TQSimpleTextCodec::mibEnum() const -{ - return unicodevalues[forwardIndex].mib; -} - -int TQSimpleTextCodec::heuristicNameMatch(const char* hint) const -{ - if ( tqstricmp( hint, mimeName() ) == 0 ) - return 10000; // return a large value - if ( hint[0]=='k' ) { - TQCString lhint = TQCString(hint).lower(); - // Help people with messy fonts - if ( lhint == "koi8-1" ) - return TQTextCodec::heuristicNameMatch("koi8-r")-1; - if ( lhint == "koi8-ru" ) - return TQTextCodec::heuristicNameMatch("koi8-r")-1; - } else if ( hint[0] == 't' && mibEnum() == 2259 /* iso8859-11 */ ) { - // 8859-11 and tis620 are byte by byte equivalent - int i = simpleHeuristicNameMatch("tis620-0", hint); - if( !i ) - i = simpleHeuristicNameMatch("tis-620", hint); - if( i ) return i; - } else if ( mibEnum() == 82 /* ISO 8859-6 */ ) { - int i = simpleHeuristicNameMatch("ISO 8859-6-I", hint); - if ( i ) - return i; - } - return TQTextCodec::heuristicNameMatch(hint); -} - -int TQSimpleTextCodec::heuristicContentMatch(const char* chars, int len) const -{ - if ( len<1 || !chars ) - return -1; - int i = 0; - const uchar * c = (const unsigned char *)chars; - int r = 0; - while( i= 128 ) { - if ( unicodevalues[forwardIndex].values[(*c)-128] == 0xfffd ) - return -1; - } - if ( (*c >= ' ' && *c < 127) || - *c == '\n' || *c == '\t' || *c == '\r' ) - r++; - i++; - c++; - } - if ( mibEnum()==4 ) - r+=1; - return r; -} - -#endif - -class TQLatin1Codec : public TQTextCodec -{ -public: -#if !defined(Q_NO_USING_KEYWORD) - using TQTextCodec::fromUnicode; - using TQTextCodec::toUnicode; -#endif - TQString toUnicode(const char* chars, int len) const; - TQCString fromUnicode(const TQString& uc, int& lenInOut ) const; - void fromUnicode( const TQChar *in, unsigned short *out, int length ) const; - unsigned short characterFromUnicode(const TQString &str, int pos) const; - - const char* name() const; - const char* mimeName() const; - int mibEnum() const; - - int heuristicContentMatch(const char* chars, int len) const; - -private: - int forwardIndex; -}; - - -TQString TQLatin1Codec::toUnicode(const char* chars, int len) const -{ - if ( chars == 0 ) - return TQString::null; - - return TQString::fromLatin1(chars, len); -} - - -TQCString TQLatin1Codec::fromUnicode(const TQString& uc, int& len ) const -{ - if ( len <0 || len > (int)uc.length() ) - len = uc.length(); - TQCString r( len+1 ); - char *d = r.data(); - int i = 0; - const TQChar *ch = uc.unicode(); - while ( i < len ) { - d[i] = ch->row() ? '?' : ch->cell(); - i++; - ch++; - } - r[len] = 0; - return r; -} - -void TQLatin1Codec::fromUnicode( const TQChar *in, unsigned short *out, int length ) const -{ - while ( length-- ) { - *out = in->row() ? 0 : in->cell(); - ++in; - ++out; - } -} - -unsigned short TQLatin1Codec::characterFromUnicode(const TQString &str, int pos) const -{ - const TQChar *ch = str.unicode() + pos; - if (ch->row()) - return 0; - return (unsigned short) ch->cell(); -} - - -const char* TQLatin1Codec::name() const -{ - return "ISO 8859-1"; -} - -const char* TQLatin1Codec::mimeName() const -{ - return "ISO-8859-1"; -} - - -int TQLatin1Codec::mibEnum() const -{ - return 4; -} - -int TQLatin1Codec::heuristicContentMatch(const char* chars, int len) const -{ - if ( len<1 || !chars ) - return -1; - int i = 0; - const uchar * c = (const unsigned char *)chars; - int r = 0; - while( i= 0x80 && *c < 0xa0 ) - return -1; - if ( (*c >= ' ' && *c < 127) || - *c == '\n' || *c == '\t' || *c == '\r' ) - r++; - i++; - c++; - } - if ( this == (const TQTextCodec *)codecForLocale() ) - r += 5; - return r; -} - -class TQLatin15Codec: public TQLatin1Codec -{ -public: - TQString toUnicode(const char* chars, int len) const; -#if !defined(Q_NO_USING_KEYWORD) - using TQLatin1Codec::fromUnicode; -#endif - TQCString fromUnicode(const TQString& uc, int& lenInOut ) const; - void fromUnicode( const TQChar *in, unsigned short *out, int length ) const; - unsigned short characterFromUnicode(const TQString &str, int pos) const; - - const char* name() const; - const char* mimeName() const; - int mibEnum() const; - -private: - int forwardIndex; -}; - - -TQString TQLatin15Codec::toUnicode(const char* chars, int len) const -{ - if ( chars == 0 ) - return TQString::null; - - TQString str = TQString::fromLatin1(chars, len); - TQChar *uc = (TQChar *)str.unicode(); - while( len-- ) { - switch( uc->unicode() ) { - case 0xa4: - *uc = 0x20ac; - break; - case 0xa6: - *uc = 0x0160; - break; - case 0xa8: - *uc = 0x0161; - break; - case 0xb4: - *uc = 0x017d; - break; - case 0xb8: - *uc = 0x017e; - break; - case 0xbc: - *uc = 0x0152; - break; - case 0xbd: - *uc = 0x0153; - break; - case 0xbe: - *uc = 0x0178; - break; - default: - break; - } - uc++; - } - return str; -} - -static inline unsigned char -latin15CharFromUnicode( unsigned short uc, bool replacement = TRUE ) -{ - uchar c; - if ( uc < 0x0100 ) { - if ( uc > 0xa3 && uc < 0xbf ) { - switch( uc ) { - case 0xa4: - case 0xa6: - case 0xa8: - case 0xb4: - case 0xb8: - case 0xbc: - case 0xbd: - case 0xbe: - c = replacement ? '?' : 0; - break; - default: - c = (unsigned char) uc; - break; - } - } else { - c = (unsigned char) uc; - } - } else { - if ( uc == 0x20ac ) - c = 0xa4; - else if ( (uc & 0xff00) == 0x0100 ) { - switch( uc ) { - case 0x0160: - c = 0xa6; - break; - case 0x0161: - c = 0xa8; - break; - case 0x017d: - c = 0xb4; - break; - case 0x017e: - c = 0xb8; - break; - case 0x0152: - c = 0xbc; - break; - case 0x0153: - c = 0xbd; - break; - case 0x0178: - c = 0xbe; - break; - default: - c = replacement ? '?' : 0; - } - } else { - c = replacement ? '?' : 0; - } - } - return c; -} - - -void TQLatin15Codec::fromUnicode( const TQChar *in, unsigned short *out, int length ) const -{ - while ( length-- ) { - *out = latin15CharFromUnicode( in->unicode(), FALSE ); - ++in; - ++out; - } -} - - -TQCString TQLatin15Codec::fromUnicode(const TQString& uc, int& len ) const -{ - if ( len <0 || len > (int)uc.length() ) - len = uc.length(); - TQCString r( len+1 ); - char *d = r.data(); - int i = 0; - const TQChar *ch = uc.unicode(); - while ( i < len ) { - d[i] = latin15CharFromUnicode( ch->unicode() ); - i++; - ch++; - } - r[len] = 0; - return r; -} - -unsigned short TQLatin15Codec::characterFromUnicode(const TQString &str, int pos) const -{ - return latin15CharFromUnicode( str.unicode()[pos].unicode(), FALSE ); -} - - -const char* TQLatin15Codec::name() const -{ - return "ISO 8859-15"; -} - -const char* TQLatin15Codec::mimeName() const -{ - return "ISO-8859-15"; -} - - -int TQLatin15Codec::mibEnum() const -{ - return 111; -} - -static TQTextCodec *checkForCodec(const char *name) { - TQTextCodec *c = TQTextCodec::codecForName(name); - if (!c) { - const char *at = strchr(name, '@'); - if (at) { - TQCString n(name, at - name + 1); - c = TQTextCodec::codecForName(n.data()); - } - } - return c; -} - -/* the next function is implicitely thread safe, - as they are only called by setup() which uses a mutex. -*/ -static void setupLocaleMapper() -{ -#ifdef Q_OS_WIN32 - localeMapper = TQTextCodec::codecForName( "System" ); -#else - -#if defined (_XOPEN_UNIX) && !defined(Q_OS_QNX6) && !defined(Q_OS_OSF) && !defined(Q_OS_MAC) - char *charset = nl_langinfo (CODESET); - if ( charset ) - localeMapper = TQTextCodec::codecForName( charset ); -#endif - - if ( !localeMapper ) { - // Very poorly defined and followed standards causes lots of code - // to try to get all the cases... - - // Try to determine locale codeset from locale name assigned to - // LC_CTYPE category. - - // First part is getting that locale name. First try setlocale() which - // definitely knows it, but since we cannot fully trust it, get ready - // to fall back to environment variables. - char * ctype = tqstrdup( setlocale( LC_CTYPE, 0 ) ); - - // Get the first nonempty value from $LC_ALL, $LC_CTYPE, and $LANG - // environment variables. - char * lang = tqstrdup( getenv("LC_ALL") ); - if ( !lang || lang[0] == 0 || strcmp( lang, "C" ) == 0 ) { - if ( lang ) delete [] lang; - lang = tqstrdup( getenv("LC_CTYPE") ); - } - if ( !lang || lang[0] == 0 || strcmp( lang, "C" ) == 0 ) { - if ( lang ) delete [] lang; - lang = tqstrdup( getenv("LANG") ); - } - - // Now try these in order: - // 1. CODESET from ctype if it contains a .CODESET part (e.g. en_US.ISO8859-15) - // 2. CODESET from lang if it contains a .CODESET part - // 3. ctype (maybe the locale is named "ISO-8859-1" or something) - // 4. locale (ditto) - // 5. check for "@euro" - // 6. guess locale from ctype unless ctype is "C" - // 7. guess locale from lang - - // 1. CODESET from ctype if it contains a .CODESET part (e.g. en_US.ISO8859-15) - char * codeset = ctype ? strchr( ctype, '.' ) : 0; - if ( codeset && *codeset == '.' ) - localeMapper = checkForCodec( codeset + 1 ); - - // 2. CODESET from lang if it contains a .CODESET part - codeset = lang ? strchr( lang, '.' ) : 0; - if ( !localeMapper && codeset && *codeset == '.' ) - localeMapper = checkForCodec( codeset + 1 ); - - // 3. ctype (maybe the locale is named "ISO-8859-1" or something) - if ( !localeMapper && ctype && *ctype != 0 && strcmp (ctype, "C") != 0 ) - localeMapper = checkForCodec( ctype ); - - // 4. locale (ditto) - if ( !localeMapper && lang && *lang != 0 ) - localeMapper = checkForCodec( lang ); - - // 5. "@euro" - if ( ( !localeMapper && ctype && strstr( ctype, "@euro" ) ) || (lang && strstr( lang, "@euro" ) ) ) - localeMapper = TQTextCodec::codecForName( "ISO 8859-15" ); - - // 6. guess locale from ctype unless ctype is "C" - // 7. guess locale from lang - char * try_by_name = ctype; - if ( ctype && *ctype != 0 && strcmp (ctype, "C") != 0 ) - try_by_name = lang; - - // Now do the guessing. - if ( lang && *lang && !localeMapper && try_by_name && *try_by_name ) { - if ( try_locale_list( iso8859_15locales, lang ) ) - localeMapper = TQTextCodec::codecForName( "ISO 8859-15" ); - else if ( try_locale_list( iso8859_2locales, lang ) ) - localeMapper = TQTextCodec::codecForName( "ISO 8859-2" ); - else if ( try_locale_list( iso8859_3locales, lang ) ) - localeMapper = TQTextCodec::codecForName( "ISO 8859-3" ); - else if ( try_locale_list( iso8859_4locales, lang ) ) - localeMapper = TQTextCodec::codecForName( "ISO 8859-4" ); - else if ( try_locale_list( iso8859_5locales, lang ) ) - localeMapper = TQTextCodec::codecForName( "ISO 8859-5" ); - else if ( try_locale_list( iso8859_6locales, lang ) ) - localeMapper = TQTextCodec::codecForName( "ISO 8859-6" ); - else if ( try_locale_list( iso8859_7locales, lang ) ) - localeMapper = TQTextCodec::codecForName( "ISO 8859-7" ); - else if ( try_locale_list( iso8859_8locales, lang ) ) - localeMapper = TQTextCodec::codecForName( "ISO 8859-8-I" ); - else if ( try_locale_list( iso8859_9locales, lang ) ) - localeMapper = TQTextCodec::codecForName( "ISO 8859-9" ); - else if ( try_locale_list( iso8859_13locales, lang ) ) - localeMapper = TQTextCodec::codecForName( "ISO 8859-13" ); - else if ( try_locale_list( tis_620locales, lang ) ) - localeMapper = TQTextCodec::codecForName( "ISO 8859-11" ); - else if ( try_locale_list( koi8_ulocales, lang ) ) - localeMapper = TQTextCodec::codecForName( "KOI8-U" ); - else if ( try_locale_list( cp_1251locales, lang ) ) - localeMapper = TQTextCodec::codecForName( "CP 1251" ); - else if ( try_locale_list( pt_154locales, lang ) ) - localeMapper = TQTextCodec::codecForName( "PT 154" ); - else if ( try_locale_list( probably_koi8_rlocales, lang ) ) - localeMapper = ru_RU_hack( lang ); - } - - delete [] ctype; - delete [] lang; - } - if ( localeMapper && localeMapper->mibEnum() == 11 ) - localeMapper = TQTextCodec::codecForName( "ISO 8859-8-I" ); - - // If everything failed, we default to 8859-1 - // We could perhaps default to 8859-15. - if ( !localeMapper ) - localeMapper = TQTextCodec::codecForName( "ISO 8859-1" ); -#endif -} - - -static void setup() -{ -#if defined(QT_CHECK_STATE) - if ( codecs_destroyed ) - { - // If codecs have been destroyed, the application is being destroyed. - // Do not create new codecs since this could lead to SEGV while trying to - // print a message using tqWarning/tqDebug/tqFatal at this stage - // - // Note: the use of `printf` instead of `tqWarning` is intentional. We should never - // get to this line of code. If we do, we are in some strange exception that we - // didn't think of. Using `tqWarning` could potentially lead to an infinite loop with - // `tqWarning` trying to setup codecs and this method calling `tqWarning` again. - // Using `printf` makes sure this never happens, even for exceptions we didn't foresee. - printf("TQTextCodec: setup() called when codecs have already been destroyed\n"); fflush(stdout); - return; - } -#endif - - if ( all ) return; - -#ifdef TQT_THREAD_SUPPORT - TQMutexLocker locker( tqt_global_mutexpool ? - tqt_global_mutexpool->get( &all ) : 0 ); -#endif // TQT_THREAD_SUPPORT - - all = new TQValueList; - - (void)new TQLatin1Codec; - (void)new TQLatin15Codec; - (void)new TQUtf8Codec; - (void)new TQUtf16Codec; - -#ifndef TQT_NO_CODECS - int i = 0; - do { - (void)new TQSimpleTextCodec( i ); - } while( unicodevalues[i++].mib != LAST_MIB ); - - (void)new TQTsciiCodec; - - for (i = 0; i < 9; ++i) { - (void)new TQIsciiCodec(i); - } -#endif // TQT_NO_CODECS -#ifndef TQT_NO_CODEC_HEBREW - (void)new TQHebrewCodec; -#endif -#ifndef TQT_NO_BIG_CODECS - (void)new TQBig5Codec; - (void)new TQBig5hkscsCodec; - (void)new TQEucJpCodec; - (void)new TQEucKrCodec; - (void)new TQGb2312Codec; - (void)new TQGbkCodec; - (void)new TQGb18030Codec; - (void)new TQJisCodec; - (void)new TQSjisCodec; -#endif // TQT_NO_BIG_CODECS - -#ifdef Q_OS_WIN32 - (void) new TQWindowsLocalCodec; -#endif // Q_OS_WIN32 - - if ( !localeMapper ) - setupLocaleMapper(); -} - -void TQTextCodec::fromUnicodeInternal( const TQChar *in, unsigned short *out, int length ) -{ - switch( mibEnum() ) { -#ifndef TQT_NO_CODECS - case 2084: - case 2088: - case 5: - case 6: - case 7: - case 8: - case 82: - case 10: - case 85: - case 12: - case 13: - case 109: - case 110: - case 2004: - case 2009: - case 2086: - case 2250: - case 2251: - case 2252: - case 2253: - case 2254: - case 2255: - case 2256: - case 2257: - case 2258: - case 2259: - ((TQSimpleTextCodec *)this)->fromUnicode( in, out, length ); - break; - -#if !defined(TQT_NO_BIG_CODECS) && defined(TQ_WS_X11) - // the TQFont*Codecs are only used on X11 - - case 15: - ((TQFontJis0201Codec *) this)->fromUnicode( in, out, length ); - break; - - case 63: - ((TQFontJis0208Codec *) this)->fromUnicode( in, out, length ); - break; - - case 36: - ((TQFontKsc5601Codec *) this)->fromUnicode( in, out, length ); - break; - - case 57: - ((TQFontGb2312Codec *) this)->fromUnicode( in, out, length ); - break; - - case -113: - ((TQFontGbkCodec *) this)->fromUnicode( in, out, length ); - break; - - case -114: - ((TQFontGb18030_0Codec *) this)->fromUnicode( in, out, length ); - break; - - case -2026: - ((TQFontBig5Codec *) this)->fromUnicode( in, out, length ); - break; - - case -2101: - ((TQFontBig5hkscsCodec *) this)->fromUnicode( in, out, length ); - break; - - case -4242: - ((TQFontLaoCodec *) this)->fromUnicode( in, out, length ); - break; -#endif -#endif // TQT_NO_CODECS - - case 4: - ((TQLatin1Codec *) this)->fromUnicode( in, out, length ); - break; - - case 111: - ((TQLatin15Codec *) this)->fromUnicode( in, out, length ); - break; - - default: - { - TQConstString string( in, length ); - TQString str = string.string(); - for ( int i = 0; i < length; i++ ) - out[i] = characterFromUnicode( str, i ); - } - } -} - - -/*! - \fn TQTextCodec* TQTextCodec::codecForTr() - - Returns the codec used by TQObject::tr() on its argument. If this - function returns 0 (the default), tr() assumes Latin-1. - - \sa setCodecForTr() -*/ - -/*! - \fn void TQTextCodec::setCodecForTr(TQTextCodec *c) - \nonreentrant - - Sets the codec used by TQObject::tr() on its argument to \a c. If - \a c is 0 (the default), tr() assumes Latin-1. - - If the literal quoted text in the program is not in the Latin-1 - encoding, this function can be used to set the appropriate - encoding. For example, software developed by Korean programmers - might use eucKR for all the text in the program, in which case the - main() function might look like this: - - \code - int main(int argc, char** argv) - { - TQApplication app(argc, argv); - ... install any additional codecs ... - TQTextCodec::setCodecForTr( TQTextCodec::codecForName("eucKR") ); - ... - } - \endcode - - Note that this is not the way to select the encoding that the \e - user has chosen. For example, to convert an application containing - literal English strings to Korean, all that is needed is for the - English strings to be passed through tr() and for translation - files to be loaded. For details of internationalization, see the - \link i18n.html TQt internationalization documentation\endlink. - - \sa codecForTr(), setCodecForTr(), setCodecForCStrings() -*/ - - -/*! - \fn TQTextCodec* TQTextCodec::codecForCStrings() - - Returns the codec used by TQString to convert to and from const - char* and TQCStrings. If this function returns 0 (the default), - TQString assumes Latin-1. - - \sa setCodecForCStrings() -*/ - -/*! - \fn void TQTextCodec::setCodecForCStrings(TQTextCodec *c) - \nonreentrant - - Sets the codec used by TQString to convert to and from const char* - and TQCStrings. If \a c is 0 (the default), TQString assumes Latin-1. - - \warning Some codecs do not preserve the characters in the ascii - range (0x00 to 0x7f). For example, the Japanese Shift-JIS - encoding maps the backslash character (0x5a) to the Yen character. - This leads to unexpected results when using the backslash - character to escape characters in strings used in e.g. regular - expressions. Use TQString::fromLatin1() to preserve characters in - the ascii range when needed. - - \sa codecForCStrings(), setCodecForTr(), setCodecForCStrings() -*/ - - -TQTextCodec *TQTextCodec::cftr = 0; -TQTextCodec *TQTextCodec::cfcs = 0; - - -#endif // TQT_NO_TEXTCODEC diff --git a/src/codecs/qtextcodecfactory.cpp b/src/codecs/qtextcodecfactory.cpp deleted file mode 100644 index 6a570157b..000000000 --- a/src/codecs/qtextcodecfactory.cpp +++ /dev/null @@ -1,131 +0,0 @@ -/**************************************************************************** -** -** Implementation of TQTextCodecFactory class -** -** Created : 010130 -** -** 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 "ntqtextcodecfactory.h" - -#ifndef TQT_NO_TEXTCODEC - -#ifndef TQT_NO_COMPONENT -#include "ntqapplication.h" -#include "ntqcleanuphandler.h" -#include -#include "qtextcodecinterface_p.h" - -#ifdef TQT_THREAD_SUPPORT -# include -#endif // TQT_THREAD_SUPPORT - -#include - - -static TQPluginManager *manager = 0; -static TQSingleCleanupHandler< TQPluginManager > cleanup_manager; - -static void create_manager() -{ - if ( manager ) // already created - return; - -#ifdef TQT_THREAD_SUPPORT - // protect manager creation - TQMutexLocker locker( tqt_global_mutexpool ? - tqt_global_mutexpool->get( &manager ) : 0); - - // we check the manager pointer again to make sure that another thread - // has not created the manager before us. - - if ( manager ) // already created - return; -#endif - - manager = - new TQPluginManager(IID_QTextCodecFactory, - TQApplication::libraryPaths(), "/codecs", - FALSE); - TQ_CHECK_PTR( manager ); - cleanup_manager.set( &manager ); -} - -#endif // TQT_NO_COMPONENT - - -TQTextCodec *TQTextCodecFactory::createForName(const TQString &name) -{ - TQTextCodec *codec = 0; - -#ifndef TQT_NO_COMPONENT - - // make sure the manager is created - create_manager(); - - TQInterfacePtr iface; - manager->queryInterface(name, &iface ); - - if (iface) - codec = iface->createForName(name); - -#endif // TQT_NO_COMPONENT - - return codec; -} - - -TQTextCodec *TQTextCodecFactory::createForMib(int mib) -{ - TQTextCodec *codec = 0; - -#ifndef TQT_NO_COMPONENT - - // make sure the manager is created - create_manager(); - - TQInterfacePtr iface; - manager->queryInterface("MIB-" + TQString::number(mib), &iface ); - - if (iface) - codec = iface->createForMib(mib); - -#endif // TQT_NO_COMPONENT - - return codec; -} - - -#endif // TQT_NO_TEXTCODEC diff --git a/src/codecs/qtextcodecinterface_p.h b/src/codecs/qtextcodecinterface_p.h deleted file mode 100644 index 5a8baa04a..000000000 --- a/src/codecs/qtextcodecinterface_p.h +++ /dev/null @@ -1,80 +0,0 @@ -/**************************************************************************** -** -** Definition of TQTextCodecFactoryInterface interface -** -** 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 TQTEXTCODECINTERFACE_P_H -#define TQTEXTCODECINTERFACE_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 qprinter_x11.cpp. -// 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 - -#ifndef TQT_NO_TEXTCODEC -#ifndef TQT_NO_COMPONENT - -class TQTextCodec; - - -// {F55BFA60-F695-11D4-823E-009027DC0F37} -#ifndef IID_QTextCodecFactory -#define IID_QTextCodecFactory TQUuid( 0xf55bfa60, 0xf695, 0x11d4, 0x82, 0x3e, 0x00, 0x90, 0x27, 0xdc, 0x0f, 0x37) -#endif - - -struct TQ_EXPORT TQTextCodecFactoryInterface : public TQFeatureListInterface -{ - virtual TQTextCodec *createForMib( int mib ) = 0; - virtual TQTextCodec *createForName( const TQString &name ) = 0; -}; - -#endif // TQT_NO_COMPONENT -#endif // TQT_NO_TEXTCODEC - -#endif // TQTEXTCODECINTERFACE_P_H diff --git a/src/codecs/qtextcodecplugin.cpp b/src/codecs/qtextcodecplugin.cpp deleted file mode 100644 index d59e8684d..000000000 --- a/src/codecs/qtextcodecplugin.cpp +++ /dev/null @@ -1,186 +0,0 @@ -/**************************************************************************** -** -** Implementation of TQTextCodecPlugin class -** -** Created : 010920 -** -** 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 "ntqtextcodecplugin.h" -#ifndef TQT_NO_TEXTCODECPLUGIN -#include "qtextcodecinterface_p.h" - -/*! - \class TQTextCodecPlugin ntqtextcodecplugin.h - \brief The TQTextCodecPlugin class provides an abstract base for custom TQTextCodec plugins. - \reentrant - \ingroup plugins - - The text codec plugin is a simple plugin interface that makes it - easy to create custom text codecs that can be loaded dynamically - into applications. - - Writing a text codec plugin is achieved by subclassing this base - class, reimplementing the pure virtual functions names(), - createForName(), mibEnums() and createForMib(), and exporting the - class with the \c TQ_EXPORT_PLUGIN macro. See the \link - plugins-howto.html TQt Plugins documentation \endlink for details. - - See the \link http://www.iana.org/assignments/character-sets IANA - character-sets encoding file\endlink for more information on mime - names and mib enums. -*/ - -/*! - \fn TQStringList TQTextCodecPlugin::names() const - - Returns the list of mime names supported by this plugin. - - \sa createForName() -*/ - -/*! - \fn TQTextCodec *TQTextCodecPlugin::createForName( const TQString &name ); - - Creates a TQTextCodec object for the codec called \a name. - - \sa names() -*/ - - -/*! - \fn TQValueList TQTextCodecPlugin::mibEnums() const - - Returns the list of mib enums supported by this plugin. - - \sa createForMib() -*/ - -/*! - \fn TQTextCodec *TQTextCodecPlugin::createForMib( int mib ); - - Creates a TQTextCodec object for the mib enum \a mib. - - (See \link - ftp://ftp.isi.edu/in-notes/iana/assignments/character-sets the - IANA character-sets encoding file\endlink for more information) - - \sa mibEnums() -*/ - - - -class TQTextCodecPluginPrivate : public TQTextCodecFactoryInterface -{ -public: - TQTextCodecPluginPrivate( TQTextCodecPlugin *p ) - : plugin( p ) - { - } - virtual ~TQTextCodecPluginPrivate(); - - TQRESULT queryInterface( const TQUuid &iid, TQUnknownInterface **iface ); - TQ_REFCOUNT; - - TQStringList featureList() const; - TQTextCodec *createForMib( int mib ); - TQTextCodec *createForName( const TQString &name ); - -private: - TQTextCodecPlugin *plugin; -}; - -TQTextCodecPluginPrivate::~TQTextCodecPluginPrivate() -{ - delete plugin; -} - -TQRESULT TQTextCodecPluginPrivate::queryInterface( const TQUuid &iid, TQUnknownInterface **iface ) -{ - *iface = 0; - - if ( iid == IID_QUnknown ) - *iface = this; - else if ( iid == IID_QFeatureList ) - *iface = this; - else if ( iid == IID_QTextCodecFactory ) - *iface = this; - else - return TQE_NOINTERFACE; - - (*iface)->addRef(); - return TQS_OK; -} - -TQStringList TQTextCodecPluginPrivate::featureList() const -{ - TQStringList keys = plugin->names(); - TQValueList mibs = plugin->mibEnums(); - for ( TQValueList::Iterator it = mibs.begin(); it != mibs.end(); ++it ) - keys += TQString("MIB-%1").arg( *it ); - return keys; -} - -TQTextCodec *TQTextCodecPluginPrivate::createForMib( int mib ) -{ - return plugin->createForMib( mib ); -} - -TQTextCodec *TQTextCodecPluginPrivate::createForName( const TQString &name ) -{ - return plugin->createForName( name ); -} - - -/*! - Constructs a text codec plugin. This is invoked automatically by - the \c TQ_EXPORT_PLUGIN macro. -*/ -TQTextCodecPlugin::TQTextCodecPlugin() - : TQGPlugin( d = new TQTextCodecPluginPrivate( this ) ) -{ -} - -/*! - Destroys the text codec plugin. - - You never have to call this explicitly. TQt destroys a plugin - automatically when it is no longer used. -*/ -TQTextCodecPlugin::~TQTextCodecPlugin() -{ -} - -#endif // TQT_NO_TEXTCODECPLUGIN diff --git a/src/codecs/tqtextcodec.cpp b/src/codecs/tqtextcodec.cpp new file mode 100644 index 000000000..cf7c6b93d --- /dev/null +++ b/src/codecs/tqtextcodec.cpp @@ -0,0 +1,3161 @@ +/**************************************************************************** +** +** Implementation of TQTextCodec class +** +** Created : 981015 +** +** Copyright (C) 1998-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 "qplatformdefs.h" + +// UNIX Large File Support redefines open -> open64 +#if defined(open) +# undef open +#endif + +#include "tqtextcodec.h" +#ifndef TQT_NO_TEXTCODEC + +#include "tqvaluelist.h" +#include "tqtextcodecfactory.h" +#include "ntqutfcodec.h" +#include "ntqnamespace.h" +#ifndef TQT_NO_CODECS +#include "ntqrtlcodec.h" +#include "ntqtsciicodec.h" +#include "qisciicodec_p.h" +#endif // TQT_NO_CODECS +#ifndef TQT_NO_BIG_CODECS +#include "ntqbig5codec.h" +#include "ntqeucjpcodec.h" +#include "ntqeuckrcodec.h" +#include "ntqgb18030codec.h" +#include "ntqjiscodec.h" +#include "ntqjpunicode.h" +#include "ntqsjiscodec.h" +#endif // TQT_NO_BIG_CODECS +#include "ntqfile.h" +#include "tqstrlist.h" +#include "tqstring.h" +#include "../tools/qlocale_p.h" + +#if !defined(TQT_NO_CODECS) && !defined(TQT_NO_BIG_CODECS) && defined(TQ_WS_X11) +# include "qfontcodecs_p.h" +#endif + +#ifdef TQT_THREAD_SUPPORT +# include +#endif // TQT_THREAD_SUPPORT + +#include +#include +#ifndef Q_OS_TEMP +#include +#endif +#if defined(_XOPEN_UNIX) && !defined(Q_OS_QNX6) +#include +#endif + +static TQValueList *all = 0; +static bool codecs_destroyed = false; +static TQTextCodec * localeMapper = 0; + +class TQTextCodecCleanup { +public: + ~TQTextCodecCleanup() { + TQTextCodec::deleteAllCodecs(); + } +}; +static TQTextCodecCleanup tqtextcodec_cleanup; + +/*! + Deletes all the created codecs. + + \warning Do not call this function. + + TQApplication calls this function just before exiting to delete + any TQTextCodec objects that may be lying around. Since various + other classes hold pointers to TQTextCodec objects, it is not safe + to call this function earlier. + + If you are using the utility classes (like TQString) but not using + TQApplication, calling this function at the very end of your + application may be helpful for chasing down memory leaks by + eliminating any TQTextCodec objects. +*/ + +void TQTextCodec::deleteAllCodecs() +{ + codecs_destroyed = true; + + if ( !all ) + return; + +#ifdef TQT_THREAD_SUPPORT + TQMutexLocker locker( tqt_global_mutexpool ? + tqt_global_mutexpool->get( &all ) : 0 ); +#endif // TQT_THREAD_SUPPORT + + TQValueList *ball = all; + all = 0; + TQValueList::Iterator it; + for ( it = ball->begin(); it != ball->end(); ++it ) { + delete *it; + *it = 0; + } + ball->clear(); + delete ball; + + localeMapper = 0; +} + +static void setup(); + +class TQTextStatelessEncoder: public TQTextEncoder { + const TQTextCodec* codec; +public: + TQTextStatelessEncoder(const TQTextCodec*); + TQCString fromUnicode(const TQString& uc, int& lenInOut); +}; + + +class TQTextStatelessDecoder : public TQTextDecoder { + const TQTextCodec* codec; +public: + TQTextStatelessDecoder(const TQTextCodec*); + TQString toUnicode(const char* chars, int len); +}; + +TQTextStatelessEncoder::TQTextStatelessEncoder(const TQTextCodec* c) : + codec(c) +{ +} + + +TQCString TQTextStatelessEncoder::fromUnicode(const TQString& uc, int& lenInOut) +{ + return codec->fromUnicode(uc,lenInOut); +} + + +TQTextStatelessDecoder::TQTextStatelessDecoder(const TQTextCodec* c) : + codec(c) +{ +} + + +TQString TQTextStatelessDecoder::toUnicode(const char* chars, int len) +{ + return codec->toUnicode(chars,len); +} + + + +/*! + \class TQTextCodec tqtextcodec.h + \brief The TQTextCodec class provides conversion between text encodings. + \reentrant + \ingroup i18n + + TQt uses Unicode to store, draw and manipulate strings. In many + situations you may wish to deal with data that uses a different + encoding. For example, most Japanese documents are still stored in + Shift-JIS or ISO2022, while Russian users often have their + documents in KOI8-R or CP1251. + + TQt provides a set of TQTextCodec classes to help with converting + non-Unicode formats to and from Unicode. You can also create your + own codec classes (\link #subclassing see later\endlink). + + The supported encodings are: + \list + \i Latin1 + \i Big5 -- Chinese + \i Big5-HKSCS -- Chinese + \i eucJP -- Japanese + \i eucKR -- Korean + \i GB2312 -- Chinese + \i GBK -- Chinese + \i GB18030 -- Chinese + \i JIS7 -- Japanese + \i Shift-JIS -- Japanese + \i TSCII -- Tamil + \i utf8 -- Unicode, 8-bit + \i utf16 -- Unicode + \i KOI8-R -- Russian + \i KOI8-U -- Ukrainian + \i ISO8859-1 -- Western + \i ISO8859-2 -- Central European + \i ISO8859-3 -- Central European + \i ISO8859-4 -- Baltic + \i ISO8859-5 -- Cyrillic + \i ISO8859-6 -- Arabic + \i ISO8859-7 -- Greek + \i ISO8859-8 -- Hebrew, visually ordered + \i ISO8859-8-i -- Hebrew, logically ordered + \i ISO8859-9 -- Turkish + \i ISO8859-10 + \i ISO8859-13 + \i ISO8859-14 + \i ISO8859-15 -- Western + \i IBM 850 + \i IBM 866 + \i CP874 + \i CP1250 -- Central European + \i CP1251 -- Cyrillic + \i CP1252 -- Western + \i CP1253 -- Greek + \i CP1254 -- Turkish + \i CP1255 -- Hebrew + \i CP1256 -- Arabic + \i CP1257 -- Baltic + \i CP1258 + \i Apple Roman + \i TIS-620 -- Thai + \endlist + + TQTextCodecs can be used as follows to convert some locally encoded + string to Unicode. Suppose you have some string encoded in Russian + KOI8-R encoding, and want to convert it to Unicode. The simple way + to do this is: + + \code + TQCString locallyEncoded = "..."; // text to convert + TQTextCodec *codec = TQTextCodec::codecForName("KOI8-R"); // get the codec for KOI8-R + TQString unicodeString = codec->toUnicode( locallyEncoded ); + \endcode + + After this, \c{unicodeString} holds the text converted to Unicode. + Converting a string from Unicode to the local encoding is just as + easy: + + \code + TQString unicodeString = "..."; // any Unicode text + TQTextCodec *codec = TQTextCodec::codecForName("KOI8-R"); // get the codec for KOI8-R + TQCString locallyEncoded = codec->fromUnicode( unicodeString ); + \endcode + + Some care must be taken when trying to convert the data in chunks, + for example, when receiving it over a network. In such cases it is + possible that a multi-byte character will be split over two + chunks. At best this might result in the loss of a character and + at worst cause the entire conversion to fail. + + The approach to use in these situations is to create a TQTextDecoder + object for the codec and use this TQTextDecoder for the whole + decoding process, as shown below: + + \code + TQTextCodec *codec = TQTextCodec::codecForName( "Shift-JIS" ); + TQTextDecoder *decoder = codec->makeDecoder(); + + TQString unicodeString; + while( receiving_data ) { + TQByteArray chunk = new_data; + unicodeString += decoder->toUnicode( chunk.data(), chunk.length() ); + } + \endcode + + The TQTextDecoder object maintains state between chunks and therefore + works correctly even if a multi-byte character is split between + chunks. + + \target subclassing + \section1 Creating your own Codec class + + Support for new text encodings can be added to TQt by creating + TQTextCodec subclasses. + + Built-in codecs can be overridden by custom codecs since more + recently created TQTextCodec objects take precedence over earlier + ones. + + You may find it more convenient to make your codec class available + as a plugin; see the \link plugins-howto.html plugin + documentation\endlink for more details. + + The abstract virtual functions describe the encoder to the + system and the coder is used as required in the different + text file formats supported by TQTextStream, and under X11, for the + locale-specific character input and output. + + To add support for another 8-bit encoding to TQt, make a subclass + of TQTextCodec and implement at least the following methods: + + \code + const char* name() const + \endcode + Return the official name for the encoding. + + \code + int mibEnum() const + \endcode + Return the MIB enum for the encoding if it is listed in the + \link http://www.iana.org/assignments/character-sets + IANA character-sets encoding file\endlink. + + If the encoding is multi-byte then it will have "state"; that is, + the interpretation of some bytes will be dependent on some preceding + bytes. For such encodings, you must implement: + + \code + TQTextDecoder* makeDecoder() const + \endcode + Return a TQTextDecoder that remembers incomplete multi-byte sequence + prefixes or other required state. + + If the encoding does \e not require state, you should implement: + + \code + TQString toUnicode(const char* chars, int len) const + \endcode + Converts \e len characters from \e chars to Unicode. + + The base TQTextCodec class has default implementations of the above + two functions, \e{but they are mutually recursive}, so you must + re-implement at least one of them, or both for improved efficiency. + + For conversion from Unicode to 8-bit encodings, it is rarely necessary + to maintain state. However, two functions similar to the two above + are used for encoding: + + \code + TQTextEncoder* makeEncoder() const + \endcode + Return a TQTextEncoder. + + \code + TQCString fromUnicode(const TQString& uc, int& lenInOut ) const + \endcode + Converts \e lenInOut characters (of type TQChar) from the start of + the string \e uc, returning a TQCString result, and also returning + the \link TQCString::length() length\endlink of the result in + \e lenInOut. + + Again, these are mutually recursive so only one needs to be implemented, + or both if greater efficiency is possible. + + Finally, you must implement: + + \code + int heuristicContentMatch(const char* chars, int len) const + \endcode + Gives a value indicating how likely it is that \e len characters + from \e chars are in the encoding. + + A good model for this function is the + TQWindowsLocalCodec::heuristicContentMatch function found in the TQt + sources. + + A TQTextCodec subclass might have improved performance if you also + re-implement: + + \code + bool canEncode( TQChar ) const + \endcode + Test if a Unicode character can be encoded. + + \code + bool canEncode( const TQString& ) const + \endcode + Test if a string of Unicode characters can be encoded. + + \code + int heuristicNameMatch(const char* hint) const + \endcode + Test if a possibly non-standard name is referring to the codec. + + Codecs can also be created as \link plugins-howto.html plugins\endlink. +*/ + + +/*! + \nonreentrant + + Constructs a TQTextCodec, and gives it the highest precedence. The + TQTextCodec should always be constructed on the heap (i.e. with \c + new). TQt takes ownership and will delete it when the application + terminates. +*/ +TQTextCodec::TQTextCodec() +{ + // 'codecs_destroyed' should never be true at this point + if (!codecs_destroyed) + { + setup(); +#ifdef TQT_THREAD_SUPPORT + TQMutexLocker locker( tqt_global_mutexpool ? + tqt_global_mutexpool->get( &all ) : 0 ); +#endif // TQT_THREAD_SUPPORT + all->insert( all->begin(), this ); + } +} + + +/*! + \nonreentrant + + Destroys the TQTextCodec. Note that you should not delete codecs + yourself: once created they become TQt's responsibility. +*/ +TQTextCodec::~TQTextCodec() +{ + if ( !codecs_destroyed ) + tqWarning("TQTextCodec::~TQTextCodec() called by application"); + +#ifdef TQT_THREAD_SUPPORT + TQMutexLocker locker( tqt_global_mutexpool ? + tqt_global_mutexpool->get( &all ) : 0 ); +#endif // TQT_THREAD_SUPPORT + if ( all ) + all->remove( this ); +} + + +/*! + Returns a value indicating how likely it is that this decoder is + appropriate for decoding some format that has the given name. The + name is compared with the \a hint. + + A good match returns a positive number around the length of the + string. A bad match is negative. + + The default implementation calls simpleHeuristicNameMatch() with + the name of the codec. +*/ +int TQTextCodec::heuristicNameMatch(const char* hint) const +{ + return simpleHeuristicNameMatch(name(),hint); +} + + +// returns a string containing the letters and numbers from input, +// with a space separating run of a character class. e.g. "iso8859-1" +// becomes "iso 8859 1" +static TQString lettersAndNumbers( const char * input ) +{ + TQString result; + TQChar c; + + while( input && *input ) { + c = *input; + if ( c.isLetter() || c.isNumber() ) + result += c.lower(); + if ( input[1] ) { + // add space at character class transition, except + // transition from upper-case to lower-case letter + TQChar n( input[1] ); + if ( c.isLetter() && n.isLetter() ) { + if ( c == c.lower() && n == n.upper() ) + result += ' '; + } else if ( c.category() != n.category() ) { + result += ' '; + } + } + input++; + } + return result.simplifyWhiteSpace(); +} + +/*! + A simple utility function for heuristicNameMatch(): it does some + very minor character-skipping so that almost-exact matches score + high. \a name is the text we're matching and \a hint is used for + the comparison. +*/ +int TQTextCodec::simpleHeuristicNameMatch(const char* name, const char* hint) +{ + // if they're the same, return a perfect score. + if ( name && hint && *name && *hint && tqstricmp( name, hint ) == 0 ) + return tqstrlen( hint ); + + // if the letters and numbers are the same, we have an "almost" + // perfect match. + TQString h( lettersAndNumbers( hint ) ); + TQString n( lettersAndNumbers( name ) ); + if ( h == n ) + return tqstrlen( hint )-1; + + if ( h.stripWhiteSpace() == n.stripWhiteSpace() ) + return tqstrlen( hint )-2; + + // could do some more here, but I don't think it's worth it + + return 0; +} + + +/*! + Returns the TQTextCodec \a i positions from the most recently + inserted codec, or 0 if there is no such TQTextCodec. Thus, + codecForIndex(0) returns the most recently created TQTextCodec. +*/ +TQTextCodec* TQTextCodec::codecForIndex(int i) +{ + if (codecs_destroyed) + { + return nullptr; + } + + setup(); + return (uint)i >= all->count() ? 0 : *all->at(i); +} + + +/*! + Returns the TQTextCodec which matches the \link + TQTextCodec::mibEnum() MIBenum\endlink \a mib. +*/ +TQTextCodec* TQTextCodec::codecForMib(int mib) +{ + if (codecs_destroyed) + { + return nullptr; + } + + setup(); + TQValueList::ConstIterator i; + TQTextCodec* result=0; + for ( i = all->begin(); i != all->end(); ++i ) { + result = *i; + if ( result->mibEnum()==mib ) + return result; + } + +#if !defined(TQT_NO_COMPONENT) && !defined(QT_LITE_COMPONENT) + if ( !result || (result && result->mibEnum() != mib) ) { + TQTextCodec *codec = TQTextCodecFactory::createForMib(mib); + if (codec) + result = codec; + } +#endif // !TQT_NO_COMPONENT !QT_LITE_COMPONENT + + return result; +} + + + + + +#ifdef Q_OS_WIN32 +class TQWindowsLocalCodec: public TQTextCodec +{ +public: + TQWindowsLocalCodec(); + ~TQWindowsLocalCodec(); + + TQString toUnicode(const char* chars, int len) const; + TQCString fromUnicode(const TQString& uc, int& lenInOut ) const; + + const char* name() const; + int mibEnum() const; + + int heuristicContentMatch(const char* chars, int len) const; + + TQTextDecoder* makeDecoder() const; +}; + +TQWindowsLocalCodec::TQWindowsLocalCodec() +{ +} + +TQWindowsLocalCodec::~TQWindowsLocalCodec() +{ +} + + +TQString TQWindowsLocalCodec::toUnicode(const char* chars, int len) const +{ + if ( len == 1 && chars ) { // Optimization; avoids allocation + char c[2]; + c[0] = *chars; + c[1] = 0; + return qt_winMB2TQString( c, 2 ); + } + if ( len < 0 ) + return qt_winMB2TQString( chars ); + TQCString s(chars,len+1); + return qt_winMB2TQString(s); +} + +TQCString TQWindowsLocalCodec::fromUnicode(const TQString& uc, int& lenInOut ) const +{ + TQCString r = qt_winTQString2MB( uc, lenInOut ); + lenInOut = r.length(); + return r; +} + + +const char* TQWindowsLocalCodec::name() const +{ + return "System"; +} + +int TQWindowsLocalCodec::mibEnum() const +{ + return 0; +} + + +int TQWindowsLocalCodec::heuristicContentMatch(const char* chars, int len) const +{ + // ### Not a bad default implementation? + TQString t = toUnicode(chars,len); + int l = t.length(); + TQCString mb = fromUnicode(t,l); + int i=0; + while ( i < len ) { + if ( chars[i] == mb[i] ) + i++; + else + break; + } + return i; +} + +class TQWindowsLocalDecoder: public TQTextDecoder +{ + const TQWindowsLocalCodec* codec; + int nbuf; + uchar buf[4]; // hopefully this will be enough +public: + TQWindowsLocalDecoder(const TQWindowsLocalCodec *c) : codec(c), nbuf(0) + { + } + + TQString toUnicode(const char* chars, int len) + { + if (len != 1 && nbuf == 0) + return codec->toUnicode(chars, len); + if (len == 1) { + char c[sizeof buf + 2]; + memcpy(c, buf, nbuf); + c[nbuf] = *chars; + c[nbuf+1] = 0; + + // try to decode this: + TQString retval = codec->toUnicode(c, -1); + if ( retval.isEmpty() ) { + // it didn't return anything; we probably stopped mid-way in a multi-byte + // character + buf[nbuf++] = *chars; + if (nbuf + 1 == sizeof buf) { + tqWarning("TQWindowsLocalDecoder: exceeded max internal buffer size"); + nbuf = 0; + } + } + else + nbuf = 0; // decoded successfully + + return retval; + } + + if (len == -1) + len = (int)strlen(chars); + + // Ugh! We need to allocate memory + char *s = new char[nbuf + len + 1]; + memcpy(s, buf, nbuf); + memcpy(s + nbuf, chars, len); + s[nbuf + len] = 0; + + TQString retval = codec->toUnicode(s, -1); + nbuf = 0; + delete[] s; + return retval; + } +}; + +TQTextDecoder* TQWindowsLocalCodec::makeDecoder() const +{ + return new TQWindowsLocalDecoder(this); +} + +#else + +/* locale names mostly copied from XFree86 */ +static const char * const iso8859_2locales[] = { + "croatian", "cs", "cs_CS", "cs_CZ","cz", "cz_CZ", "czech", "hr", + "hr_HR", "hu", "hu_HU", "hungarian", "pl", "pl_PL", "polish", "ro", + "ro_RO", "rumanian", "serbocroatian", "sh", "sh_SP", "sh_YU", "sk", + "sk_SK", "sl", "sl_CS", "sl_SI", "slovak", "slovene", "sr_SP", 0 }; + +static const char * const iso8859_3locales[] = { + "eo", 0 }; + +static const char * const iso8859_4locales[] = { + "ee", "ee_EE", 0 }; + +static const char * const iso8859_5locales[] = { + "mk", "mk_MK", "sp", "sp_YU", 0 }; + +static const char * const cp_1251locales[] = { + "be", "be_BY", "bg", "bg_BG", "bulgarian", 0 }; + +static const char * const pt_154locales[] = { + "ba_RU", "ky", "ky_KG", "kk", "kk_KZ", 0 }; + +static const char * const iso8859_6locales[] = { + "ar_AA", "ar_SA", "arabic", 0 }; + +static const char * const iso8859_7locales[] = { + "el", "el_GR", "greek", 0 }; + +static const char * const iso8859_8locales[] = { + "hebrew", "he", "he_IL", "iw", "iw_IL", 0 }; + +static const char * const iso8859_9locales[] = { + "tr", "tr_TR", "turkish", 0 }; + +static const char * const iso8859_13locales[] = { + "lt", "lt_LT", "lv", "lv_LV", 0 }; + +static const char * const iso8859_15locales[] = { + "et", "et_EE", + // Euro countries + "br_FR", "ca_ES", "de", "de_AT", "de_BE", "de_DE", "de_LU", "en_IE", + "es", "es_ES", "eu_ES", "fi", "fi_FI", "finnish", "fr", "fr_FR", + "fr_BE", "fr_LU", "french", "ga_IE", "gl_ES", "it", "it_IT", "oc_FR", + "nl", "nl_BE", "nl_NL", "pt", "pt_PT", "sv_FI", "wa_BE", + 0 }; + +static const char * const koi8_ulocales[] = { + "uk", "uk_UA", "ru_UA", "ukrainian", 0 }; + +static const char * const tis_620locales[] = { + "th", "th_TH", "thai", 0 }; + +static const char * const tcvnlocales[] = { + "vi", "vi_VN", 0 }; + +static bool try_locale_list( const char * const locale[], const char * lang ) +{ + int i; + for( i=0; locale[i] && *locale[i] && strcmp(locale[i], lang); i++ ) + ; + return locale[i] != 0; +} + +// For the probably_koi8_locales we have to look. the standard says +// these are 8859-5, but almost all Russian users use KOI8-R and +// incorrectly set $LANG to ru_RU. We'll check tolower() to see what +// tolower() thinks ru_RU means. + +// If you read the history, it seems that many Russians blame ISO and +// Perestroika for the confusion. +// +// The real bug is that some programs break if the user specifies +// ru_RU.KOI8-R. + +static const char * const probably_koi8_rlocales[] = { + "ru", "ru_SU", "ru_RU", "russian", 0 }; + +static TQTextCodec * ru_RU_hack( const char * i ) { + TQTextCodec * ru_RU_codec = 0; + + TQCString origlocale = setlocale( LC_CTYPE, i ); + // unicode koi8r latin5 name + // 0x044E 0xC0 0xEE CYRILLIC SMALL LETTER YU + // 0x042E 0xE0 0xCE CYRILLIC CAPITAL LETTER YU + int latin5 = tolower( 0xCE ); + int koi8r = tolower( 0xE0 ); + if ( koi8r == 0xC0 && latin5 != 0xEE ) { + ru_RU_codec = TQTextCodec::codecForName( "KOI8-R" ); + } else if ( koi8r != 0xC0 && latin5 == 0xEE ) { + ru_RU_codec = TQTextCodec::codecForName( "ISO 8859-5" ); + } else { + // something else again... let's assume... *throws dice* + ru_RU_codec = TQTextCodec::codecForName( "KOI8-R" ); + tqWarning( "TQTextCodec: using KOI8-R, probe failed (%02x %02x %s)", + koi8r, latin5, i ); + } + setlocale( LC_CTYPE, origlocale.data() ); + + return ru_RU_codec; +} + +#endif + +/*! + Set the codec to \a c; this will be returned by codecForLocale(). + This might be needed for some applications that want to use their + own mechanism for setting the locale. + + \sa codecForLocale() +*/ +void TQTextCodec::setCodecForLocale(TQTextCodec *c) { + localeMapper = c; +} + +/*! Returns a pointer to the codec most suitable for this locale. */ + +TQTextCodec* TQTextCodec::codecForLocale() +{ + if (codecs_destroyed) + { + return nullptr; + } + + if (!localeMapper) + { + setup(); + } + + return localeMapper; +} + + +/*! + Searches all installed TQTextCodec objects and returns the one + which best matches \a name; the match is case-insensitive. Returns + 0 if no codec's heuristicNameMatch() reports a match better than + \a accuracy, or if \a name is a null string. + + \sa heuristicNameMatch() +*/ + +TQTextCodec* TQTextCodec::codecForName( const char* name, int accuracy ) +{ + if (codecs_destroyed) + { + return nullptr; + } + + if ( !name || !*name ) + return 0; + + setup(); + TQValueList::ConstIterator i; + TQTextCodec* result = 0; + int best = accuracy; + TQTextCodec* cursor; + for ( i = all->begin(); i != all->end(); ++i ) { + cursor = *i; + int s = cursor->heuristicNameMatch( name ); + if ( s > best ) { + best = s; + result = cursor; + } + } + +#if !defined(TQT_NO_COMPONENT) && !defined(QT_LITE_COMPONENT) + if ( !result ) + result = TQTextCodecFactory::createForName(name); +#endif // !TQT_NO_COMPONENT !QT_LITE_COMPONENT + + return result; +} + + +/*! + Searches all installed TQTextCodec objects, returning the one which + most recognizes the given content. May return 0. + + Note that this is often a poor choice, since character encodings + often use most of the available character sequences, and so only + by linguistic analysis could a true match be made. + + \a chars contains the string to check, and \a len contains the + number of characters in the string to use. + + \sa heuristicContentMatch() +*/ +TQTextCodec* TQTextCodec::codecForContent(const char* chars, int len) +{ + if (codecs_destroyed) + { + return nullptr; + } + + setup(); + TQValueList::ConstIterator i; + TQTextCodec* result = 0; + int best=0; + TQTextCodec* cursor; + for ( i = all->begin(); i != all->end(); ++i ) { + cursor = *i; + int s = cursor->heuristicContentMatch(chars,len); + if ( s > best ) { + best = s; + result = cursor; + } + } + return result; +} + + +/*! + \fn const char* TQTextCodec::name() const + + TQTextCodec subclasses must reimplement this function. It returns + the name of the encoding supported by the subclass. When choosing + a name for an encoding, consider these points: + \list + \i On X11, heuristicNameMatch( const char * hint ) + is used to test if a the TQTextCodec + can convert between Unicode and the encoding of a font + with encoding \e hint, such as "iso8859-1" for Latin-1 fonts, + "koi8-r" for Russian KOI8 fonts. + The default algorithm of heuristicNameMatch() uses name(). + \i Some applications may use this function to present + encodings to the end user. + \endlist + */ + +/*! + \fn int TQTextCodec::mibEnum() const + + Subclasses of TQTextCodec must reimplement this function. It + returns the MIBenum (see \link + http://www.iana.org/assignments/character-sets the + IANA character-sets encoding file\endlink for more information). + It is important that each TQTextCodec subclass returns the correct + unique value for this function. +*/ + + +/*! + Returns the preferred mime name of the encoding as defined in the + \link http://www.iana.org/assignments/character-sets + IANA character-sets encoding file\endlink. +*/ +const char* TQTextCodec::mimeName() const +{ + return name(); +} + + +/*! + \fn int TQTextCodec::heuristicContentMatch(const char* chars, int len) const + + TQTextCodec subclasses must reimplement this function. It examines + the first \a len bytes of \a chars and returns a value indicating + how likely it is that the string is a prefix of text encoded in + the encoding of the subclass. A negative return value indicates + that the text is detectably not in the encoding (e.g. it contains + characters undefined in the encoding). A return value of 0 + indicates that the text should be decoded with this codec rather + than as ASCII, but there is no particular evidence. The value + should range up to \a len. Thus, most decoders will return -1, 0, + or -\a len. + + The characters are not null terminated. + + \sa codecForContent(). +*/ + + +/*! + Creates a TQTextDecoder which stores enough state to decode chunks + of char* data to create chunks of Unicode data. The default + implementation creates a stateless decoder, which is only + sufficient for the simplest encodings where each byte corresponds + to exactly one Unicode character. + + The caller is responsible for deleting the returned object. +*/ +TQTextDecoder* TQTextCodec::makeDecoder() const +{ + return new TQTextStatelessDecoder(this); +} + + +/*! + Creates a TQTextEncoder which stores enough state to encode chunks + of Unicode data as char* data. The default implementation creates + a stateless encoder, which is only sufficient for the simplest + encodings where each Unicode character corresponds to exactly one + character. + + The caller is responsible for deleting the returned object. +*/ +TQTextEncoder* TQTextCodec::makeEncoder() const +{ + return new TQTextStatelessEncoder(this); +} + + +/*! + TQTextCodec subclasses must reimplement this function or + makeDecoder(). It converts the first \a len characters of \a chars + to Unicode. + + The default implementation makes a decoder with makeDecoder() and + converts the input with that. Note that the default makeDecoder() + implementation makes a decoder that simply calls + this function, hence subclasses \e must reimplement one function or + the other to avoid infinite recursion. +*/ +TQString TQTextCodec::toUnicode(const char* chars, int len) const +{ + if ( chars == 0 ) + return TQString::null; + TQTextDecoder* i = makeDecoder(); + TQString result = i->toUnicode(chars,len); + delete i; + return result; +} + + +/*! + TQTextCodec subclasses must reimplement either this function or + makeEncoder(). It converts the first \a lenInOut characters of \a + uc from Unicode to the encoding of the subclass. If \a lenInOut is + negative or too large, the length of \a uc is used instead. + + Converts \a lenInOut characters (not bytes) from \a uc, producing + a TQCString. \a lenInOut will be set to the \link + TQCString::length() length\endlink of the result (in bytes). + + The default implementation makes an encoder with makeEncoder() and + converts the input with that. Note that the default makeEncoder() + implementation makes an encoder that simply calls this function, + hence subclasses \e must reimplement one function or the other to + avoid infinite recursion. +*/ + +TQCString TQTextCodec::fromUnicode(const TQString& uc, int& lenInOut) const +{ + TQTextEncoder* i = makeEncoder(); + TQCString result = i->fromUnicode(uc, lenInOut); + delete i; + return result; +} + +/*! + \overload + \internal +*/ +TQByteArray TQTextCodec::fromUnicode( const TQString &str, int pos, int len ) const +{ + TQByteArray a; + if( len < 0 ) + len = str.length() - pos; + a = fromUnicode( str.mid(pos, len) ); + if( a.size() > 0 && a[(int)a.size() - 1] == '\0' ) + a.resize( a.size() - 1 ); + return a; +} + +/*! + \overload + + \a uc is the unicode source string. +*/ +TQCString TQTextCodec::fromUnicode(const TQString& uc) const +{ + int l = uc.length(); + return fromUnicode(uc,l); +} + +/*! + \overload + + \a a contains the source characters; \a len contains the number of + characters in \a a to use. +*/ +TQString TQTextCodec::toUnicode(const TQByteArray& a, int len) const +{ + int l = a.size(); + l = TQMIN( l, len ); + return toUnicode( a.data(), l ); +} + +/*! + \overload + + \a a contains the source characters. +*/ +TQString TQTextCodec::toUnicode(const TQByteArray& a) const +{ + int l = a.size(); + return toUnicode( a.data(), l ); +} + +/*! + \overload + + \a a contains the source characters; \a len contains the number of + characters in \a a to use. +*/ +TQString TQTextCodec::toUnicode(const TQCString& a, int len) const +{ + int l = a.length(); + l = TQMIN( l, len ); + return toUnicode( a.data(), l ); +} + +/*! + \overload + + \a a contains the source characters. +*/ +TQString TQTextCodec::toUnicode(const TQCString& a) const +{ + int l = a.length(); + return toUnicode( a.data(), l ); +} + +/*! + \overload + + \a chars contains the source characters. +*/ +TQString TQTextCodec::toUnicode(const char* chars) const +{ + return toUnicode(chars,tqstrlen(chars)); +} + +/*! + \internal +*/ +unsigned short TQTextCodec::characterFromUnicode(const TQString &str, int pos) const +{ + TQCString result = TQTextCodec::fromUnicode(TQString(str[pos])); + uchar *ch = (uchar *) result.data(); + ushort retval = 0; + if (result.size() > 2) { + retval = (ushort) *ch << 8; + ch++; + } + return retval + *ch; +} + +/*! + Returns TRUE if the Unicode character \a ch can be fully encoded + with this codec; otherwise returns FALSE. The default + implementation tests if the result of toUnicode(fromUnicode(ch)) + is the original \a ch. Subclasses may be able to improve the + efficiency. +*/ +bool TQTextCodec::canEncode( TQChar ch ) const +{ + return toUnicode(fromUnicode(ch)) == ch; +} + +/*! + \overload + + \a s contains the string being tested for encode-ability. +*/ +bool TQTextCodec::canEncode( const TQString& s ) const +{ + if ( s.isEmpty() ) + return TRUE; + return toUnicode(fromUnicode(s)) == s; +} + + + +/*! + \class TQTextEncoder tqtextcodec.h + \brief The TQTextEncoder class provides a state-based encoder. + \reentrant + \ingroup i18n + + The encoder converts Unicode into another format, remembering any + state that is required between calls. + + \sa TQTextCodec::makeEncoder() +*/ + +/*! + Destroys the encoder. +*/ +TQTextEncoder::~TQTextEncoder() +{ +} + +/*! + \fn TQCString TQTextEncoder::fromUnicode(const TQString& uc, int& lenInOut) + + Converts \a lenInOut characters (not bytes) from \a uc, producing + a TQCString. \a lenInOut will be set to the \link + TQCString::length() length\endlink of the result (in bytes). + + The encoder is free to record state to use when subsequent calls + are made to this function (for example, it might change modes with + escape sequences if needed during the encoding of one string, then + assume that mode applies when a subsequent call begins). +*/ + +/*! + \class TQTextDecoder tqtextcodec.h + \brief The TQTextDecoder class provides a state-based decoder. + \reentrant + \ingroup i18n + + The decoder converts a text format into Unicode, remembering any + state that is required between calls. + + \sa TQTextCodec::makeEncoder() +*/ + + +/*! + Destroys the decoder. +*/ +TQTextDecoder::~TQTextDecoder() +{ +} + +/*! + \fn TQString TQTextDecoder::toUnicode(const char* chars, int len) + + Converts the first \a len bytes in \a chars to Unicode, returning + the result. + + If not all characters are used (e.g. if only part of a multi-byte + encoding is at the end of the characters), the decoder remembers + enough state to continue with the next call to this function. +*/ + +#define CHAINED 0xffff + +struct TQMultiByteUnicodeTable { + // If multiByte, ignore unicode and index into multiByte + // with the next character. + TQMultiByteUnicodeTable() : unicode(0xfffd), multiByte(0) { } + + ~TQMultiByteUnicodeTable() + { + if ( multiByte ) + delete [] multiByte; + } + + ushort unicode; + TQMultiByteUnicodeTable* multiByte; +}; + +static int getByte(char* &cursor) +{ + int byte = 0; + if ( *cursor ) { + if ( cursor[1] == 'x' ) + byte = strtol(cursor+2,&cursor,16); + else if ( cursor[1] == 'd' ) + byte = strtol(cursor+2,&cursor,10); + else + byte = strtol(cursor+2,&cursor,8); + } + return byte&0xff; +} + +class TQTextCodecFromIOD; + +class TQTextCodecFromIODDecoder : public TQTextDecoder { + const TQTextCodecFromIOD* codec; + TQMultiByteUnicodeTable* mb; +public: + TQTextCodecFromIODDecoder(const TQTextCodecFromIOD* c); + TQString toUnicode(const char* chars, int len); +}; + +class TQTextCodecFromIOD : public TQTextCodec { + friend class TQTextCodecFromIODDecoder; + + TQCString n; + + // If from_unicode_page[row()][cell()] is 0 and from_unicode_page_multiByte, + // use from_unicode_page_multiByte[row()][cell()] as string. + char** from_unicode_page; + char*** from_unicode_page_multiByte; + char unkn; + + // Only one of these is used + ushort* to_unicode; + TQMultiByteUnicodeTable* to_unicode_multiByte; + int max_bytes_per_char; + TQStrList aliases; + + bool stateless() const { return !to_unicode_multiByte; } + +public: + TQTextCodecFromIOD(TQIODevice* iod) + { + from_unicode_page = 0; + to_unicode_multiByte = 0; + to_unicode = 0; + from_unicode_page_multiByte = 0; + max_bytes_per_char = 1; + + const int maxlen=100; + char line[maxlen]; + char esc='\\'; + char comm='%'; + bool incmap = FALSE; + while (iod->readLine(line,maxlen) > 0) { + if (0==tqstrnicmp(line,"",15)) + n = line+15; + else if (0==tqstrnicmp(line," ",14)) + esc = line[14]; + else if (0==tqstrnicmp(line," ",15)) + comm = line[15]; + else if (line[0]==comm && 0==tqstrnicmp(line+1," alias ",7)) { + aliases.append(line+8); + } else if (0==tqstrnicmp(line,"CHARMAP",7)) { + if (!from_unicode_page) { + from_unicode_page = new char*[256]; + for (int i=0; i<256; i++) + from_unicode_page[i]=0; + } + if (!to_unicode) { + to_unicode = new ushort[256]; + } + incmap = TRUE; + } else if (0==tqstrnicmp(line,"END CHARMAP",11)) + break; + else if (incmap) { + char* cursor = line; + int byte=-1,unicode=-1; + ushort* mb_unicode=0; + const int maxmb=8; // more -> we'll need to improve datastructures + char mb[maxmb+1]; + int nmb=0; + + while (*cursor) { + if (cursor[0]=='<' && cursor[1]=='U' && + cursor[2]>='0' && cursor[2]<='9' && + cursor[3]>='0' && cursor[3]<='9') { + + unicode = strtol(cursor+2,&cursor,16); + + } else if (*cursor==esc) { + + byte = getByte(cursor); + + if ( *cursor == esc ) { + if ( !to_unicode_multiByte ) { + to_unicode_multiByte = + new TQMultiByteUnicodeTable[256]; + for (int i=0; i<256; i++) { + to_unicode_multiByte[i].unicode = + to_unicode[i]; + to_unicode_multiByte[i].multiByte = 0; + } + delete [] to_unicode; + to_unicode = 0; + } + TQMultiByteUnicodeTable* mbut = + to_unicode_multiByte+byte; + mb[nmb++] = byte; + while ( nmb < maxmb && *cursor == esc ) { + // Always at least once + + mbut->unicode = CHAINED; + byte = getByte(cursor); + mb[nmb++] = byte; + if (!mbut->multiByte) { + mbut->multiByte = + new TQMultiByteUnicodeTable[256]; + } + mbut = mbut->multiByte+byte; + mb_unicode = & mbut->unicode; + } + + if ( nmb > max_bytes_per_char ) + max_bytes_per_char = nmb; + } + } else { + cursor++; + } + } + + if (unicode >= 0 && unicode <= 0xffff) + { + TQChar ch((ushort)unicode); + if (!from_unicode_page[ch.row()]) { + from_unicode_page[ch.row()] = new char[256]; + for (int i=0; i<256; i++) + from_unicode_page[ch.row()][i]=0; + } + if ( mb_unicode ) { + from_unicode_page[ch.row()][ch.cell()] = 0; + if (!from_unicode_page_multiByte) { + from_unicode_page_multiByte = new char**[256]; + for (int i=0; i<256; i++) + from_unicode_page_multiByte[i]=0; + } + if (!from_unicode_page_multiByte[ch.row()]) { + from_unicode_page_multiByte[ch.row()] = new char*[256]; + for (int i=0; i<256; i++) + from_unicode_page_multiByte[ch.row()][i] = 0; + } + mb[nmb++] = 0; + from_unicode_page_multiByte[ch.row()][ch.cell()] + = tqstrdup(mb); + *mb_unicode = unicode; + } else { + from_unicode_page[ch.row()][ch.cell()] = (char)byte; + if ( to_unicode ) + to_unicode[byte] = unicode; + else + to_unicode_multiByte[byte].unicode = unicode; + } + } else { + } + } + } + n = n.stripWhiteSpace(); + + unkn = '?'; // ##### Might be a bad choice. + } + + ~TQTextCodecFromIOD() + { + if ( from_unicode_page ) { + for (int i=0; i<256; i++) + if (from_unicode_page[i]) + delete [] from_unicode_page[i]; + } + if ( from_unicode_page_multiByte ) { + for (int i=0; i<256; i++) + if (from_unicode_page_multiByte[i]) + for (int j=0; j<256; j++) + if (from_unicode_page_multiByte[i][j]) + delete [] from_unicode_page_multiByte[i][j]; + } + if ( to_unicode ) + delete [] to_unicode; + if ( to_unicode_multiByte ) + delete [] to_unicode_multiByte; + } + + bool ok() const + { + return !!from_unicode_page; + } + + TQTextDecoder* makeDecoder() const + { + if ( stateless() ) + return TQTextCodec::makeDecoder(); + else + return new TQTextCodecFromIODDecoder(this); + } + + const char* name() const + { + return n; + } + + int mibEnum() const + { + return 0; // #### Unknown. + } + + int heuristicContentMatch(const char*, int) const + { + return 0; + } + + int heuristicNameMatch(const char* hint) const + { + int bestr = TQTextCodec::heuristicNameMatch(hint); + TQStrListIterator it(aliases); + char* a; + while ((a=it.current())) { + ++it; + int r = simpleHeuristicNameMatch(a,hint); + if (r > bestr) + bestr = r; + } + return bestr; + } + + TQString toUnicode(const char* chars, int len) const + { + const uchar* uchars = (const uchar*)chars; + TQString result; + TQMultiByteUnicodeTable* multiByte=to_unicode_multiByte; + if ( multiByte ) { + while (len--) { + TQMultiByteUnicodeTable& mb = multiByte[*uchars]; + if ( mb.multiByte ) { + // Chained multi-byte + multiByte = mb.multiByte; + } else { + result += TQChar(mb.unicode); + multiByte=to_unicode_multiByte; + } + uchars++; + } + } else { + while (len--) + result += TQChar(to_unicode[*uchars++]); + } + return result; + } + +#if !defined(Q_NO_USING_KEYWORD) + using TQTextCodec::fromUnicode; +#endif + TQCString fromUnicode(const TQString& uc, int& lenInOut) const + { + if (lenInOut > (int)uc.length()) + lenInOut = uc.length(); + int rlen = lenInOut*max_bytes_per_char; + TQCString rstr(rlen+1); + char* cursor = rstr.data(); + char* s=0; + int l = lenInOut; + int lout = 0; + for (int i=0; ito_unicode_multiByte; +} + +TQString TQTextCodecFromIODDecoder::toUnicode(const char* chars, int len) +{ + const uchar* uchars = (const uchar*)chars; + TQString result; + while (len--) { + TQMultiByteUnicodeTable& t = mb[*uchars]; + if ( t.multiByte ) { + // Chained multi-byte + mb = t.multiByte; + } else { + if ( t.unicode ) + result += TQChar(t.unicode); + mb=codec->to_unicode_multiByte; + } + uchars++; + } + return result; +} + +#ifndef TQT_NO_CODECS +// Cannot use
 or \code
+/*!
+    Reads a POSIX2 charmap definition from \a iod.
+    The parser recognizes the following lines:
+
+
+  <code_set_name> name
+  <escape_char> character
+  % alias alias
+  CHARMAP
+  <token> /xhexbyte <Uunicode> ...
+  <token> /ddecbyte <Uunicode> ...
+  <token> /octbyte <Uunicode> ...
+  <token> /any/any... <Uunicode> ...
+  END CHARMAP
+
+ + The resulting TQTextCodec is returned (and also added to the global + list of codecs). The name() of the result is taken from the + code_set_name. + + Note that a codec constructed in this way uses much more memory + and is slower than a hand-written TQTextCodec subclass, since + tables in code are kept in memory shared by all TQt applications. + + \sa loadCharmapFile() +*/ +TQTextCodec* TQTextCodec::loadCharmap(TQIODevice* iod) +{ + TQTextCodecFromIOD* r = new TQTextCodecFromIOD(iod); + if ( !r->ok() ) { + delete r; + r = 0; + } + return r; +} + +/*! + A convenience function for loadCharmap() that loads the charmap + definition from the file \a filename. +*/ +TQTextCodec* TQTextCodec::loadCharmapFile(TQString filename) +{ + TQFile f(filename); + if (f.open(IO_ReadOnly)) { + TQTextCodecFromIOD* r = new TQTextCodecFromIOD(&f); + if ( !r->ok() ) + delete r; + else + return r; + } + return 0; +} + +#endif //TQT_NO_CODECS + +/*! + Returns a string representing the current language and + sublanguage, e.g. "pt" for Portuguese, or "pt_br" for Portuguese/Brazil. +*/ + +const char* TQTextCodec::locale() +{ + return TQLocalePrivate::systemLocaleName(); +} + +#ifndef TQT_NO_CODECS + +class TQSimpleTextCodec: public TQTextCodec +{ +public: + TQSimpleTextCodec( int ); + ~TQSimpleTextCodec(); + + TQString toUnicode(const char* chars, int len) const; +#if !defined(Q_NO_USING_KEYWORD) + using TQTextCodec::fromUnicode; +#endif + TQCString fromUnicode(const TQString& uc, int& lenInOut ) const; + unsigned short characterFromUnicode(const TQString &str, int pos) const; + + const char* name() const; + const char* mimeName() const; + int mibEnum() const; + + int heuristicContentMatch(const char* chars, int len) const; + + int heuristicNameMatch(const char* hint) const; +#if !defined(Q_NO_USING_KEYWORD) + using TQTextCodec::canEncode; +#endif + bool canEncode( TQChar ch ) const; + + void fromUnicode( const TQChar *in, unsigned short *out, int length ) const; + +private: + void buildReverseMap(); + + int forwardIndex; +#ifndef TQ_WS_QWS + TQMemArray *reverseMap; +#endif +}; + +#ifdef TQ_WS_QWS +static const TQSimpleTextCodec * reverseOwner = 0; +static TQMemArray * reverseMap = 0; +#endif + +#define LAST_MIB 2004 + +static const struct { + const char *mime; + const char * cs; + int mib; + TQ_UINT16 values[128]; +} unicodevalues[] = { + // from RFC 1489, ftp://ftp.isi.edu/in-notes/rfc1489.txt + { "KOI8-R", "KOI8-R", 2084, + { 0x2500, 0x2502, 0x250C, 0x2510, 0x2514, 0x2518, 0x251C, 0x2524, + 0x252C, 0x2534, 0x253C, 0x2580, 0x2584, 0x2588, 0x258C, 0x2590, + 0x2591, 0x2592, 0x2593, 0x2320, 0x25A0, 0x2219/**/, 0x221A, 0x2248, + 0x2264, 0x2265, 0x00A0, 0x2321, 0x00B0, 0x00B2, 0x00B7, 0x00F7, + 0x2550, 0x2551, 0x2552, 0x0451, 0x2553, 0x2554, 0x2555, 0x2556, + 0x2557, 0x2558, 0x2559, 0x255A, 0x255B, 0x255C, 0x255D, 0x255E, + 0x255F, 0x2560, 0x2561, 0x0401, 0x2562, 0x2563, 0x2564, 0x2565, + 0x2566, 0x2567, 0x2568, 0x2569, 0x256A, 0x256B, 0x256C, 0x00A9, + 0x044E, 0x0430, 0x0431, 0x0446, 0x0434, 0x0435, 0x0444, 0x0433, + 0x0445, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, + 0x043F, 0x044F, 0x0440, 0x0441, 0x0442, 0x0443, 0x0436, 0x0432, + 0x044C, 0x044B, 0x0437, 0x0448, 0x044D, 0x0449, 0x0447, 0x044A, + 0x042E, 0x0410, 0x0411, 0x0426, 0x0414, 0x0415, 0x0424, 0x0413, + 0x0425, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, + 0x041F, 0x042F, 0x0420, 0x0421, 0x0422, 0x0423, 0x0416, 0x0412, + 0x042C, 0x042B, 0x0417, 0x0428, 0x042D, 0x0429, 0x0427, 0x042A } }, + // /**/ - The BULLET OPERATOR is confused. Some people think + // it should be 0x2022 (BULLET). + + // from RFC 2319, ftp://ftp.isi.edu/in-notes/rfc2319.txt + { "KOI8-U", "KOI8-U", 2088, + { 0x2500, 0x2502, 0x250C, 0x2510, 0x2514, 0x2518, 0x251C, 0x2524, + 0x252C, 0x2534, 0x253C, 0x2580, 0x2584, 0x2588, 0x258C, 0x2590, + 0x2591, 0x2592, 0x2593, 0x2320, 0x25A0, 0x2219, 0x221A, 0x2248, + 0x2264, 0x2265, 0x00A0, 0x2321, 0x00B0, 0x00B2, 0x00B7, 0x00F7, + 0x2550, 0x2551, 0x2552, 0x0451, 0x0454, 0x2554, 0x0456, 0x0457, + 0x2557, 0x2558, 0x2559, 0x255A, 0x255B, 0x0491, 0x255D, 0x255E, + 0x255F, 0x2560, 0x2561, 0x0401, 0x0404, 0x2563, 0x0406, 0x0407, + 0x2566, 0x2567, 0x2568, 0x2569, 0x256A, 0x0490, 0x256C, 0x00A9, + 0x044E, 0x0430, 0x0431, 0x0446, 0x0434, 0x0435, 0x0444, 0x0433, + 0x0445, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, + 0x043F, 0x044F, 0x0440, 0x0441, 0x0442, 0x0443, 0x0436, 0x0432, + 0x044C, 0x044B, 0x0437, 0x0448, 0x044D, 0x0449, 0x0447, 0x044A, + 0x042E, 0x0410, 0x0411, 0x0426, 0x0414, 0x0415, 0x0424, 0x0413, + 0x0425, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, + 0x041F, 0x042F, 0x0420, 0x0421, 0x0422, 0x0423, 0x0416, 0x0412, + 0x042C, 0x042B, 0x0417, 0x0428, 0x042D, 0x0429, 0x0427, 0x042A } }, + + // next bits generated from tables on the Unicode 2.0 CD. we can + // use these tables since this is part of the transition to using + // unicode everywhere in qt. + + // $ for A in 8 9 A B C D E F ; do for B in 0 1 2 3 4 5 6 7 8 9 A B C D E F ; do echo 0x${A}${B} 0xFFFD ; done ; done > /tmp/digits ; for a in 8859-* ; do ( awk '/^0x[89ABCDEF]/{ print $1, $2 }' < $a ; cat /tmp/digits ) | sort | uniq -w4 | cut -c6- | paste '-d ' - - - - - - - - | sed -e 's/ /, /g' -e 's/$/,/' -e '$ s/,$/} },/' -e '1 s/^/{ /' > ~/tmp/$a ; done + + // then I inserted the files manually. + { "ISO-8859-2", "ISO 8859-2", 5, + { 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, + 0x00A0, 0x0104, 0x02D8, 0x0141, 0x00A4, 0x013D, 0x015A, 0x00A7, + 0x00A8, 0x0160, 0x015E, 0x0164, 0x0179, 0x00AD, 0x017D, 0x017B, + 0x00B0, 0x0105, 0x02DB, 0x0142, 0x00B4, 0x013E, 0x015B, 0x02C7, + 0x00B8, 0x0161, 0x015F, 0x0165, 0x017A, 0x02DD, 0x017E, 0x017C, + 0x0154, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x0139, 0x0106, 0x00C7, + 0x010C, 0x00C9, 0x0118, 0x00CB, 0x011A, 0x00CD, 0x00CE, 0x010E, + 0x0110, 0x0143, 0x0147, 0x00D3, 0x00D4, 0x0150, 0x00D6, 0x00D7, + 0x0158, 0x016E, 0x00DA, 0x0170, 0x00DC, 0x00DD, 0x0162, 0x00DF, + 0x0155, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x013A, 0x0107, 0x00E7, + 0x010D, 0x00E9, 0x0119, 0x00EB, 0x011B, 0x00ED, 0x00EE, 0x010F, + 0x0111, 0x0144, 0x0148, 0x00F3, 0x00F4, 0x0151, 0x00F6, 0x00F7, + 0x0159, 0x016F, 0x00FA, 0x0171, 0x00FC, 0x00FD, 0x0163, 0x02D9} }, + { "ISO-8859-3", "ISO 8859-3", 6, + { 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, + 0x00A0, 0x0126, 0x02D8, 0x00A3, 0x00A4, 0xFFFD, 0x0124, 0x00A7, + 0x00A8, 0x0130, 0x015E, 0x011E, 0x0134, 0x00AD, 0xFFFD, 0x017B, + 0x00B0, 0x0127, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x0125, 0x00B7, + 0x00B8, 0x0131, 0x015F, 0x011F, 0x0135, 0x00BD, 0xFFFD, 0x017C, + 0x00C0, 0x00C1, 0x00C2, 0xFFFD, 0x00C4, 0x010A, 0x0108, 0x00C7, + 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, + 0xFFFD, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x0120, 0x00D6, 0x00D7, + 0x011C, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x016C, 0x015C, 0x00DF, + 0x00E0, 0x00E1, 0x00E2, 0xFFFD, 0x00E4, 0x010B, 0x0109, 0x00E7, + 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, + 0xFFFD, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x0121, 0x00F6, 0x00F7, + 0x011D, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x016D, 0x015D, 0x02D9} }, + { "ISO-8859-4", "ISO 8859-4", 7, + { 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, + 0x00A0, 0x0104, 0x0138, 0x0156, 0x00A4, 0x0128, 0x013B, 0x00A7, + 0x00A8, 0x0160, 0x0112, 0x0122, 0x0166, 0x00AD, 0x017D, 0x00AF, + 0x00B0, 0x0105, 0x02DB, 0x0157, 0x00B4, 0x0129, 0x013C, 0x02C7, + 0x00B8, 0x0161, 0x0113, 0x0123, 0x0167, 0x014A, 0x017E, 0x014B, + 0x0100, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x012E, + 0x010C, 0x00C9, 0x0118, 0x00CB, 0x0116, 0x00CD, 0x00CE, 0x012A, + 0x0110, 0x0145, 0x014C, 0x0136, 0x00D4, 0x00D5, 0x00D6, 0x00D7, + 0x00D8, 0x0172, 0x00DA, 0x00DB, 0x00DC, 0x0168, 0x016A, 0x00DF, + 0x0101, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x012F, + 0x010D, 0x00E9, 0x0119, 0x00EB, 0x0117, 0x00ED, 0x00EE, 0x012B, + 0x0111, 0x0146, 0x014D, 0x0137, 0x00F4, 0x00F5, 0x00F6, 0x00F7, + 0x00F8, 0x0173, 0x00FA, 0x00FB, 0x00FC, 0x0169, 0x016B, 0x02D9} }, + { "ISO-8859-5", "ISO 8859-5", 8, + { 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, + 0x00A0, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407, + 0x0408, 0x0409, 0x040A, 0x040B, 0x040C, 0x00AD, 0x040E, 0x040F, + 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, + 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F, + 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, + 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F, + 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, + 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F, + 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, + 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F, + 0x2116, 0x0451, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456, 0x0457, + 0x0458, 0x0459, 0x045A, 0x045B, 0x045C, 0x00A7, 0x045E, 0x045F} }, + { "ISO-8859-6", "ISO 8859-6", 82, + { 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, + 0x00A0, 0xFFFD, 0xFFFD, 0xFFFD, 0x00A4, 0xFFFD, 0xFFFD, 0xFFFD, + 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0x060C, 0x00AD, 0xFFFD, 0xFFFD, + 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, + 0xFFFD, 0xFFFD, 0xFFFD, 0x061B, 0xFFFD, 0xFFFD, 0xFFFD, 0x061F, + 0xFFFD, 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627, + 0x0628, 0x0629, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E, 0x062F, + 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x0637, + 0x0638, 0x0639, 0x063A, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, + 0x0640, 0x0641, 0x0642, 0x0643, 0x0644, 0x0645, 0x0646, 0x0647, + 0x0648, 0x0649, 0x064A, 0x064B, 0x064C, 0x064D, 0x064E, 0x064F, + 0x0650, 0x0651, 0x0652, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, + 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD} }, + { "ISO-8859-7", "ISO 8859-7", 10, + { 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, + 0x00A0, 0x2018, 0x2019, 0x00A3, 0xFFFD, 0xFFFD, 0x00A6, 0x00A7, + 0x00A8, 0x00A9, 0xFFFD, 0x00AB, 0x00AC, 0x00AD, 0xFFFD, 0x2015, + 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x0384, 0x0385, 0x0386, 0x00B7, + 0x0388, 0x0389, 0x038A, 0x00BB, 0x038C, 0x00BD, 0x038E, 0x038F, + 0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, + 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, + 0x03A0, 0x03A1, 0xFFFD, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, + 0x03A8, 0x03A9, 0x03AA, 0x03AB, 0x03AC, 0x03AD, 0x03AE, 0x03AF, + 0x03B0, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, + 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, + 0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7, + 0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03CC, 0x03CD, 0x03CE, 0xFFFD} }, + { "ISO-8859-8-I", "ISO 8859-8-I", 85, + { 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, + 0x00A0, 0xFFFD, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, + 0x00A8, 0x00A9, 0x00D7, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x203E, + 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, + 0x00B8, 0x00B9, 0x00F7, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0xFFFD, + 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, + 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, + 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, + 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0x2017, + 0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, + 0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF, + 0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7, + 0x05E8, 0x05E9, 0x05EA, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD} }, + { "ISO-8859-9", "ISO 8859-9", 12, + { 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, + 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, + 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, + 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, + 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, + 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, + 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, + 0x011E, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, + 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x0130, 0x015E, 0x00DF, + 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, + 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, + 0x011F, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, + 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x0131, 0x015F, 0x00FF} }, + { "ISO-8859-10", "ISO 8859-10", 13, + { 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, + 0x00A0, 0x0104, 0x0112, 0x0122, 0x012A, 0x0128, 0x0136, 0x00A7, + 0x013B, 0x0110, 0x0160, 0x0166, 0x017D, 0x00AD, 0x016A, 0x014A, + 0x00B0, 0x0105, 0x0113, 0x0123, 0x012B, 0x0129, 0x0137, 0x00B7, + 0x013C, 0x0111, 0x0161, 0x0167, 0x017E, 0x2015, 0x016B, 0x014B, + 0x0100, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x012E, + 0x010C, 0x00C9, 0x0118, 0x00CB, 0x0116, 0x00CD, 0x00CE, 0x00CF, + 0x00D0, 0x0145, 0x014C, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x0168, + 0x00D8, 0x0172, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF, + 0x0101, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x012F, + 0x010D, 0x00E9, 0x0119, 0x00EB, 0x0117, 0x00ED, 0x00EE, 0x00EF, + 0x00F0, 0x0146, 0x014D, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x0169, + 0x00F8, 0x0173, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x0138} }, + { "ISO-8859-13", "ISO 8859-13", 109, + { 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, + 0x00A0, 0x201D, 0x00A2, 0x00A3, 0x00A4, 0x201E, 0x00A6, 0x00A7, + 0x00D8, 0x00A9, 0x0156, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00C6, + 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x201C, 0x00B5, 0x00B6, 0x00B7, + 0x00F8, 0x00B9, 0x0157, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00E6, + 0x0104, 0x012E, 0x0100, 0x0106, 0x00C4, 0x00C5, 0x0118, 0x0112, + 0x010C, 0x00C9, 0x0179, 0x0116, 0x0122, 0x0136, 0x012A, 0x013B, + 0x0160, 0x0143, 0x0145, 0x00D3, 0x014C, 0x00D5, 0x00D6, 0x00D7, + 0x0172, 0x0141, 0x015A, 0x016A, 0x00DC, 0x017B, 0x017D, 0x00DF, + 0x0105, 0x012F, 0x0101, 0x0107, 0x00E4, 0x00E5, 0x0119, 0x0113, + 0x010D, 0x00E9, 0x017A, 0x0117, 0x0123, 0x0137, 0x012B, 0x013C, + 0x0161, 0x0144, 0x0146, 0x00F3, 0x014D, 0x00F5, 0x00F6, 0x00F7, + 0x0173, 0x0142, 0x015B, 0x016B, 0x00FC, 0x017C, 0x017E, 0x2019} }, + { "ISO-8859-14", "ISO 8859-14", 110, + { 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, + 0x00A0, 0x1E02, 0x1E03, 0x00A3, 0x010A, 0x010B, 0x1E0A, 0x00A7, + 0x1E80, 0x00A9, 0x1E82, 0x1E0B, 0x1EF2, 0x00AD, 0x00AE, 0x0178, + 0x1E1E, 0x1E1F, 0x0120, 0x0121, 0x1E40, 0x1E41, 0x00B6, 0x1E56, + 0x1E81, 0x1E57, 0x1E83, 0x1E60, 0x1EF3, 0x1E84, 0x1E85, 0x1E61, + 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, + 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, + 0x0174, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x1E6A, + 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x0176, 0x00DF, + 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, + 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, + 0x0175, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x1E6B, + 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x0177, 0x00FF} }, + { "ISO-8859-16", "ISO 8859-16", 112, + { 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, + 0x00A0, 0x0104, 0x0105, 0x0141, 0x20AC, 0x201E, 0x0160, 0x00A7, + 0x0161, 0x00A9, 0x0218, 0x00AB, 0x0179, 0x00AD, 0x017A, 0x017B, + 0x00B0, 0x00B1, 0x010C, 0x0142, 0x017D, 0x201D, 0x00B6, 0x00B7, + 0x017E, 0x010D, 0x0219, 0x00BB, 0x0152, 0x0153, 0x0178, 0x017C, + 0x00C0, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x0106, 0x00C6, 0x00C7, + 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, + 0x0110, 0x0143, 0x00D2, 0x00D3, 0x00D4, 0x0150, 0x00D6, 0x015A, + 0x0170, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x0118, 0x021A, 0x00DF, + 0x00E0, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x0107, 0x00E6, 0x00E7, + 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, + 0x0111, 0x0144, 0x00F2, 0x00F3, 0x00F4, 0x0151, 0x00F6, 0x015B, + 0x0171, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x0119, 0x021B, 0x00FF} }, + + // next bits generated again from tables on the Unicode 3.0 CD. + + // $ for a in CP* ; do ( awk '/^0x[89ABCDEF]/{ print $1, $2 }' < $a ) | sort | sed -e 's/#UNDEF.*$/0xFFFD/' | cut -c6- | paste '-d ' - - - - - - - - | sed -e 's/ /, /g' -e 's/$/,/' -e '$ s/,$/} },/' -e '1 s/^/{ /' > ~/tmp/$a ; done + + { "CP 850", "IBM 850", 2009, + { 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, + 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5, + 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, + 0x00FF, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x0192, + 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, + 0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x00C0, + 0x00A9, 0x2563, 0x2551, 0x2557, 0x255D, 0x00A2, 0x00A5, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x00E3, 0x00C3, + 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4, + 0x00F0, 0x00D0, 0x00CA, 0x00CB, 0x00C8, 0x0131, 0x00CD, 0x00CE, + 0x00CF, 0x2518, 0x250C, 0x2588, 0x2584, 0x00A6, 0x00CC, 0x2580, + 0x00D3, 0x00DF, 0x00D4, 0x00D2, 0x00F5, 0x00D5, 0x00B5, 0x00FE, + 0x00DE, 0x00DA, 0x00DB, 0x00D9, 0x00FD, 0x00DD, 0x00AF, 0x00B4, + 0x00AD, 0x00B1, 0x2017, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x00B8, + 0x00B0, 0x00A8, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0} }, + { "CP 874", "CP 874", 0, //### what is the mib? + { 0x20AC, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0x2026, 0xFFFD, 0xFFFD, + 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, + 0xFFFD, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, + 0x00A0, 0x0E01, 0x0E02, 0x0E03, 0x0E04, 0x0E05, 0x0E06, 0x0E07, + 0x0E08, 0x0E09, 0x0E0A, 0x0E0B, 0x0E0C, 0x0E0D, 0x0E0E, 0x0E0F, + 0x0E10, 0x0E11, 0x0E12, 0x0E13, 0x0E14, 0x0E15, 0x0E16, 0x0E17, + 0x0E18, 0x0E19, 0x0E1A, 0x0E1B, 0x0E1C, 0x0E1D, 0x0E1E, 0x0E1F, + 0x0E20, 0x0E21, 0x0E22, 0x0E23, 0x0E24, 0x0E25, 0x0E26, 0x0E27, + 0x0E28, 0x0E29, 0x0E2A, 0x0E2B, 0x0E2C, 0x0E2D, 0x0E2E, 0x0E2F, + 0x0E30, 0x0E31, 0x0E32, 0x0E33, 0x0E34, 0x0E35, 0x0E36, 0x0E37, + 0x0E38, 0x0E39, 0x0E3A, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0x0E3F, + 0x0E40, 0x0E41, 0x0E42, 0x0E43, 0x0E44, 0x0E45, 0x0E46, 0x0E47, + 0x0E48, 0x0E49, 0x0E4A, 0x0E4B, 0x0E4C, 0x0E4D, 0x0E4E, 0x0E4F, + 0x0E50, 0x0E51, 0x0E52, 0x0E53, 0x0E54, 0x0E55, 0x0E56, 0x0E57, + 0x0E58, 0x0E59, 0x0E5A, 0x0E5B, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD} }, + { "IBM 866", "IBM 866", 2086, + { 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, + 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F, + 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, + 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F, + 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, + 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, + 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, + 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, + 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, + 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, + 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F, + 0x0401, 0x0451, 0x0404, 0x0454, 0x0407, 0x0457, 0x040E, 0x045E, + 0x00B0, 0x2219, 0x00B7, 0x221A, 0x2116, 0x00A4, 0x25A0, 0x00A0} }, + + { "windows-1250", "CP 1250", 2250, + { 0x20AC, 0xFFFD, 0x201A, 0xFFFD, 0x201E, 0x2026, 0x2020, 0x2021, + 0xFFFD, 0x2030, 0x0160, 0x2039, 0x015A, 0x0164, 0x017D, 0x0179, + 0xFFFD, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0xFFFD, 0x2122, 0x0161, 0x203A, 0x015B, 0x0165, 0x017E, 0x017A, + 0x00A0, 0x02C7, 0x02D8, 0x0141, 0x00A4, 0x0104, 0x00A6, 0x00A7, + 0x00A8, 0x00A9, 0x015E, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x017B, + 0x00B0, 0x00B1, 0x02DB, 0x0142, 0x00B4, 0x00B5, 0x00B6, 0x00B7, + 0x00B8, 0x0105, 0x015F, 0x00BB, 0x013D, 0x02DD, 0x013E, 0x017C, + 0x0154, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x0139, 0x0106, 0x00C7, + 0x010C, 0x00C9, 0x0118, 0x00CB, 0x011A, 0x00CD, 0x00CE, 0x010E, + 0x0110, 0x0143, 0x0147, 0x00D3, 0x00D4, 0x0150, 0x00D6, 0x00D7, + 0x0158, 0x016E, 0x00DA, 0x0170, 0x00DC, 0x00DD, 0x0162, 0x00DF, + 0x0155, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x013A, 0x0107, 0x00E7, + 0x010D, 0x00E9, 0x0119, 0x00EB, 0x011B, 0x00ED, 0x00EE, 0x010F, + 0x0111, 0x0144, 0x0148, 0x00F3, 0x00F4, 0x0151, 0x00F6, 0x00F7, + 0x0159, 0x016F, 0x00FA, 0x0171, 0x00FC, 0x00FD, 0x0163, 0x02D9} }, + { "windows-1251", "CP 1251", 2251, + { 0x0402, 0x0403, 0x201A, 0x0453, 0x201E, 0x2026, 0x2020, 0x2021, + 0x20AC, 0x2030, 0x0409, 0x2039, 0x040A, 0x040C, 0x040B, 0x040F, + 0x0452, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0xFFFD, 0x2122, 0x0459, 0x203A, 0x045A, 0x045C, 0x045B, 0x045F, + 0x00A0, 0x040E, 0x045E, 0x0408, 0x00A4, 0x0490, 0x00A6, 0x00A7, + 0x0401, 0x00A9, 0x0404, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x0407, + 0x00B0, 0x00B1, 0x0406, 0x0456, 0x0491, 0x00B5, 0x00B6, 0x00B7, + 0x0451, 0x2116, 0x0454, 0x00BB, 0x0458, 0x0405, 0x0455, 0x0457, + 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, + 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F, + 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, + 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F, + 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, + 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F, + 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, + 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F} }, + { "windows-1252", "CP 1252", 2252, + { 0x20AC, 0xFFFD, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, + 0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0xFFFD, 0x017D, 0xFFFD, + 0xFFFD, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0xFFFD, 0x017E, 0x0178, + 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, + 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, + 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, + 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, + 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, + 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, + 0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, + 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF, + 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, + 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, + 0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, + 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF} }, + { "windows-1253", "CP 1253", 2253, + { 0x20AC, 0xFFFD, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, + 0xFFFD, 0x2030, 0xFFFD, 0x2039, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, + 0xFFFD, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0xFFFD, 0x2122, 0xFFFD, 0x203A, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, + 0x00A0, 0x0385, 0x0386, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, + 0x00A8, 0x00A9, 0xFFFD, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x2015, + 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x0384, 0x00B5, 0x00B6, 0x00B7, + 0x0388, 0x0389, 0x038A, 0x00BB, 0x038C, 0x00BD, 0x038E, 0x038F, + 0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, + 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, + 0x03A0, 0x03A1, 0xFFFD, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, + 0x03A8, 0x03A9, 0x03AA, 0x03AB, 0x03AC, 0x03AD, 0x03AE, 0x03AF, + 0x03B0, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, + 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, + 0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7, + 0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03CC, 0x03CD, 0x03CE, 0xFFFD} }, + { "windows-1254", "CP 1254", 2254, + { 0x20AC, 0xFFFD, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, + 0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0xFFFD, 0xFFFD, 0xFFFD, + 0xFFFD, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0xFFFD, 0xFFFD, 0x0178, + 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, + 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, + 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, + 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, + 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, + 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, + 0x011E, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, + 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x0130, 0x015E, 0x00DF, + 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, + 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, + 0x011F, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, + 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x0131, 0x015F, 0x00FF} }, + { "windows-1255", "CP 1255", 2255, + { 0x20AC, 0xFFFD, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, + 0x02C6, 0x2030, 0xFFFD, 0x2039, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, + 0xFFFD, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0x02DC, 0x2122, 0xFFFD, 0x203A, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, + 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x20AA, 0x00A5, 0x00A6, 0x00A7, + 0x00A8, 0x00A9, 0x00D7, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, + 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, + 0x00B8, 0x00B9, 0x00F7, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, + 0x05B0, 0x05B1, 0x05B2, 0x05B3, 0x05B4, 0x05B5, 0x05B6, 0x05B7, + 0x05B8, 0x05B9, 0xFFFD, 0x05BB, 0x05BC, 0x05BD, 0x05BE, 0x05BF, + 0x05C0, 0x05C1, 0x05C2, 0x05C3, 0x05F0, 0x05F1, 0x05F2, 0x05F3, + 0x05F4, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, + 0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, + 0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF, + 0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7, + 0x05E8, 0x05E9, 0x05EA, 0xFFFD, 0xFFFD, 0x200E, 0x200F, 0xFFFD} }, + { "windows-1256", "CP 1256", 2256, + { 0x20AC, 0x067E, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, + 0x02C6, 0x2030, 0x0679, 0x2039, 0x0152, 0x0686, 0x0698, 0x0688, + 0x06AF, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0x06A9, 0x2122, 0x0691, 0x203A, 0x0153, 0x200C, 0x200D, 0x06BA, + 0x00A0, 0x060C, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, + 0x00A8, 0x00A9, 0x06BE, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, + 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, + 0x00B8, 0x00B9, 0x061B, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x061F, + 0x06C1, 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627, + 0x0628, 0x0629, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E, 0x062F, + 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x00D7, + 0x0637, 0x0638, 0x0639, 0x063A, 0x0640, 0x0641, 0x0642, 0x0643, + 0x00E0, 0x0644, 0x00E2, 0x0645, 0x0646, 0x0647, 0x0648, 0x00E7, + 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x0649, 0x064A, 0x00EE, 0x00EF, + 0x064B, 0x064C, 0x064D, 0x064E, 0x00F4, 0x064F, 0x0650, 0x00F7, + 0x0651, 0x00F9, 0x0652, 0x00FB, 0x00FC, 0x200E, 0x200F, 0x06D2} }, + { "windows-1257", "CP 1257", 2257, + { 0x20AC, 0xFFFD, 0x201A, 0xFFFD, 0x201E, 0x2026, 0x2020, 0x2021, + 0xFFFD, 0x2030, 0xFFFD, 0x2039, 0xFFFD, 0x00A8, 0x02C7, 0x00B8, + 0xFFFD, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0xFFFD, 0x2122, 0xFFFD, 0x203A, 0xFFFD, 0x00AF, 0x02DB, 0xFFFD, + 0x00A0, 0xFFFD, 0x00A2, 0x00A3, 0x00A4, 0xFFFD, 0x00A6, 0x00A7, + 0x00D8, 0x00A9, 0x0156, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00C6, + 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, + 0x00F8, 0x00B9, 0x0157, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00E6, + 0x0104, 0x012E, 0x0100, 0x0106, 0x00C4, 0x00C5, 0x0118, 0x0112, + 0x010C, 0x00C9, 0x0179, 0x0116, 0x0122, 0x0136, 0x012A, 0x013B, + 0x0160, 0x0143, 0x0145, 0x00D3, 0x014C, 0x00D5, 0x00D6, 0x00D7, + 0x0172, 0x0141, 0x015A, 0x016A, 0x00DC, 0x017B, 0x017D, 0x00DF, + 0x0105, 0x012F, 0x0101, 0x0107, 0x00E4, 0x00E5, 0x0119, 0x0113, + 0x010D, 0x00E9, 0x017A, 0x0117, 0x0123, 0x0137, 0x012B, 0x013C, + 0x0161, 0x0144, 0x0146, 0x00F3, 0x014D, 0x00F5, 0x00F6, 0x00F7, + 0x0173, 0x0142, 0x015B, 0x016B, 0x00FC, 0x017C, 0x017E, 0x02D9} }, + { "windows-1258", "CP 1258", 2258, + { 0x20AC, 0xFFFD, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, + 0x02C6, 0x2030, 0xFFFD, 0x2039, 0x0152, 0xFFFD, 0xFFFD, 0xFFFD, + 0xFFFD, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0x02DC, 0x2122, 0xFFFD, 0x203A, 0x0153, 0xFFFD, 0xFFFD, 0x0178, + 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, + 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, + 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, + 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, + 0x00C0, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x00C5, 0x00C6, 0x00C7, + 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x0300, 0x00CD, 0x00CE, 0x00CF, + 0x0110, 0x00D1, 0x0309, 0x00D3, 0x00D4, 0x01A0, 0x00D6, 0x00D7, + 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x01AF, 0x0303, 0x00DF, + 0x00E0, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x00E5, 0x00E6, 0x00E7, + 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x0301, 0x00ED, 0x00EE, 0x00EF, + 0x0111, 0x00F1, 0x0323, 0x00F3, 0x00F4, 0x01A1, 0x00F6, 0x00F7, + 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x01B0, 0x20AB, 0x00FF} }, + + { "Apple Roman", "Apple Roman", 0, + { 0x00C4, 0x00C5, 0x00C7, 0x00C9, 0x00D1, 0x00D6, 0x00DC, 0x00E1, + 0x00E0, 0x00E2, 0x00E4, 0x00E3, 0x00E5, 0x00E7, 0x00E9, 0x00E8, + 0x00EA, 0x00EB, 0x00ED, 0x00EC, 0x00EE, 0x00EF, 0x00F1, 0x00F3, + 0x00F2, 0x00F4, 0x00F6, 0x00F5, 0x00FA, 0x00F9, 0x00FB, 0x00FC, + 0x2020, 0x00B0, 0x00A2, 0x00A3, 0x00A7, 0x2022, 0x00B6, 0x00DF, + 0x00AE, 0x00A9, 0x2122, 0x00B4, 0x00A8, 0x2260, 0x00C6, 0x00D8, + 0x221E, 0x00B1, 0x2264, 0x2265, 0x00A5, 0x00B5, 0x2202, 0x2211, + 0x220F, 0x03C0, 0x222B, 0x00AA, 0x00BA, 0x03A9, 0x00E6, 0x00F8, + 0x00BF, 0x00A1, 0x00AC, 0x221A, 0x0192, 0x2248, 0x2206, 0x00AB, + 0x00BB, 0x2026, 0x00A0, 0x00C0, 0x00C3, 0x00D5, 0x0152, 0x0153, + 0x2013, 0x2014, 0x201C, 0x201D, 0x2018, 0x2019, 0x00F7, 0x25CA, + 0x00FF, 0x0178, 0x2044, 0x20AC, 0x2039, 0x203A, 0xFB01, 0xFB02, + 0x2021, 0x00B7, 0x201A, 0x201E, 0x2030, 0x00C2, 0x00CA, 0x00C1, + 0x00CB, 0x00C8, 0x00CD, 0x00CE, 0x00CF, 0x00CC, 0x00D3, 0x00D4, + 0xF8FF, 0x00D2, 0x00DA, 0x00DB, 0x00D9, 0x0131, 0x02C6, 0x02DC, + 0x00AF, 0x02D8, 0x02D9, 0x02DA, 0x00B8, 0x02DD, 0x02DB, 0x02C7} }, + + + + // This one is based on the charmap file + // /usr/share/i18n/charmaps/SAMI-WS2.gz, which is manually adapted + // to this format by Børre Gaup + { "WINSAMI2", "WS2", 0, + { 0x20AC, 0xFFFD, 0x010C, 0x0192, 0x010D, 0x01B7, 0x0292, 0x01EE, + 0x01EF, 0x0110, 0x0160, 0x2039, 0x0152, 0xFFFD, 0xFFFD, 0xFFFD, + 0xFFFD, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0x0111, 0x01E6, 0x0161, 0x203A, 0x0153, 0xFFFD, 0xFFFD, 0x0178, + 0x00A0, 0x01E7, 0x01E4, 0x00A3, 0x00A4, 0x01E5, 0x00A6, 0x00A7, + 0x00A8, 0x00A9, 0x021E, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x021F, + 0x00B0, 0x00B1, 0x01E8, 0x01E9, 0x00B4, 0x00B5, 0x00B6, 0x00B7, + 0x014A, 0x014B, 0x0166, 0x00BB, 0x0167, 0x00BD, 0x017D, 0x017E, + 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, + 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, + 0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, + 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF, + 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, + 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, + 0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, + 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF} }, + + + // this one is generated from the charmap file located in /usr/share/i18n/charmaps + // on most Linux distributions. The thai character set tis620 is byte by byte equivalent + // to iso8859-11, so we name it 8859-11 here, but recognise the name tis620 too. + + // $ for A in 8 9 A B C D E F ; do for B in 0 1 2 3 4 5 6 7 8 9 A B C D E F ; do echo x${A}${B} 0xFFFD ; done ; done > /tmp/digits ; ( cut -c25- < TIS-620 ; cat /tmp/digits ) | awk '/^x[89ABCDEF]/{ print $1, $2 }' | sed -e 's///' | sort | uniq -w4 | cut -c5- | paste '-d ' - - - - - - - - | sed -e 's/ /, /g' -e 's/$/,/' -e '$ s/,$/} },/' -e '1 s/^/{ /' > ~/tmp/tis-620 + { "TIS-620", "ISO 8859-11", 2259, // Thai character set mib enum taken from tis620 (which is byte by byte equivalent) + { 0x20AC, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0x2026, 0xFFFD, 0xFFFD, + 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, + 0xFFFD, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, + 0xFFFD, 0x0E01, 0x0E02, 0x0E03, 0x0E04, 0x0E05, 0x0E06, 0x0E07, + 0x0E08, 0x0E09, 0x0E0A, 0x0E0B, 0x0E0C, 0x0E0D, 0x0E0E, 0x0E0F, + 0x0E10, 0x0E11, 0x0E12, 0x0E13, 0x0E14, 0x0E15, 0x0E16, 0x0E17, + 0x0E18, 0x0E19, 0x0E1A, 0x0E1B, 0x0E1C, 0x0E1D, 0x0E1E, 0x0E1F, + 0x0E20, 0x0E21, 0x0E22, 0x0E23, 0x0E24, 0x0E25, 0x0E26, 0x0E27, + 0x0E28, 0x0E29, 0x0E2A, 0x0E2B, 0x0E2C, 0x0E2D, 0x0E2E, 0x0E2F, + 0x0E30, 0x0E31, 0x0E32, 0x0E33, 0x0E34, 0x0E35, 0x0E36, 0x0E37, + 0x0E38, 0x0E39, 0x0E3A, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0x0E3F, + 0x0E40, 0x0E41, 0x0E42, 0x0E43, 0x0E44, 0x0E45, 0x0E46, 0x0E47, + 0x0E48, 0x0E49, 0x0E4A, 0x0E4B, 0x0E4C, 0x0E4D, 0x0E4E, 0x0E4F, + 0x0E50, 0x0E51, 0x0E52, 0x0E53, 0x0E54, 0x0E55, 0x0E56, 0x0E57, + 0x0E58, 0x0E59, 0x0E5A, 0x0E5B, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD } }, + + /* + Name: hp-roman8 [HP-PCL5,RFC1345,KXS2] + MIBenum: 2004 + Source: LaserJet IIP Printer User's Manual, + HP part no 33471-90901, Hewlet-Packard, June 1989. + Alias: roman8 + Alias: r8 + Alias: csHPRoman8 + */ + { "Roman8", "HP-Roman8", 2004, + { 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, + 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, + 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, + 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, + 0x00A0, 0x00C0, 0x00C2, 0x00C8, 0x00CA, 0x00CB, 0x00CE, 0x00CF, + 0x00B4, 0x02CB, 0x02C6, 0x00A8, 0x02DC, 0x00D9, 0x00DB, 0x20A4, + 0x00AF, 0x00DD, 0x00FD, 0x00B0, 0x00C7, 0x00E7, 0x00D1, 0x00F1, + 0x00A1, 0x00BF, 0x00A4, 0x00A3, 0x00A5, 0x00A7, 0x0192, 0x00A2, + 0x00E2, 0x00EA, 0x00F4, 0x00FB, 0x00E1, 0x00E9, 0x00F3, 0x00FA, + 0x00E0, 0x00E8, 0x00F2, 0x00F9, 0x00E4, 0x00EB, 0x00F6, 0x00FC, + 0x00C5, 0x00EE, 0x00D8, 0x00C6, 0x00E5, 0x00ED, 0x00F8, 0x00E6, + 0x00C4, 0x00EC, 0x00D6, 0x00DC, 0x00C9, 0x00EF, 0x00DF, 0x00D4, + 0x00C1, 0x00C3, 0x00E3, 0x00D0, 0x00F0, 0x00CD, 0x00CC, 0x00D3, + 0x00D2, 0x00D5, 0x00F5, 0x0160, 0x0161, 0x00DA, 0x0178, 0x00FF, + 0x00DE, 0x00FE, 0x00B7, 0x00B5, 0x00B6, 0x00BE, 0x2014, 0x00BC, + 0x00BD, 0x00AA, 0x00BA, 0x00AB, 0x25A0, 0x00BB, 0x00B1, 0xFFFD } } + + // if you add more chacater sets at the end, change LAST_MIB above +}; + +TQSimpleTextCodec::TQSimpleTextCodec( int i ) + : TQTextCodec(), forwardIndex( i ) +{ +#ifndef TQ_WS_QWS + reverseMap = 0; +#endif +} + + +TQSimpleTextCodec::~TQSimpleTextCodec() +{ +#ifndef TQ_WS_QWS + delete reverseMap; +#else + if ( reverseOwner == this ) { + delete reverseMap; + reverseMap = 0; + reverseOwner = 0; + } +#endif +} + +void TQSimpleTextCodec::buildReverseMap() +{ +#ifdef TQ_WS_QWS + if ( reverseOwner != this ) { + int m = 0; + int i = 0; + while( i < 128 ) { + if ( unicodevalues[forwardIndex].values[i] > m && + unicodevalues[forwardIndex].values[i] < 0xfffd ) + m = unicodevalues[forwardIndex].values[i]; + i++; + } + m++; + if ( !reverseMap ) + reverseMap = new TQMemArray( m ); + if ( m > (int)(reverseMap->size()) ) + reverseMap->resize( m ); + for( i = 0; i < 128 && i < m; i++ ) + (*reverseMap)[i] = (char)i; + for( ;i < m; i++ ) + (*reverseMap)[i] = 0; + for( i=128; i<256; i++ ) { + int u = unicodevalues[forwardIndex].values[i-128]; + if ( u < m ) + (*reverseMap)[u] = (char)(unsigned char)(i); + } + reverseOwner = this; + } +#else + if ( !reverseMap ) { + TQMemArray **map = &((TQSimpleTextCodec *)this)->reverseMap; + int m = 0; + int i = 0; + while( i < 128 ) { + if ( unicodevalues[forwardIndex].values[i] > m && + unicodevalues[forwardIndex].values[i] < 0xfffd ) + m = unicodevalues[forwardIndex].values[i]; + i++; + } + m++; + *map = new TQMemArray( m ); + for( i = 0; i < 128 && i < m; i++ ) + (**map)[i] = (char)i; + for( ;i < m; i++ ) + (**map)[i] = 0; + for( i=128; i<256; i++ ) { + int u = unicodevalues[forwardIndex].values[i-128]; + if ( u < m ) + (**map)[u] = (char)(unsigned char)(i); + } + } +#endif +} + +TQString TQSimpleTextCodec::toUnicode(const char* chars, int len) const +{ + if ( len <= 0 || chars == 0 ) + return TQString::null; + + const unsigned char * c = (const unsigned char *)chars; + int i; + + for ( i = 0; i < len; i++ ) + if ( c[i] == '\0' ) { + len = i; + break; + } + + TQString r; + r.setUnicode(0, len); + TQChar* uc = (TQChar*)r.unicode(); // const_cast + + for ( i = 0; i < len; i++ ) { + if ( c[i] > 127 ) + uc[i] = unicodevalues[forwardIndex].values[c[i]-128]; + else + uc[i] = c[i]; + } + return r; +} + + +TQCString TQSimpleTextCodec::fromUnicode(const TQString& uc, int& len ) const +{ +#ifdef TQ_WS_QWS + if ( this != reverseOwner ) +#else + if ( !reverseMap ) +#endif + ((TQSimpleTextCodec *)this)->buildReverseMap(); + + if ( len <0 || len > (int)uc.length() ) + len = uc.length(); + TQCString r( len+1 ); + int i = len; + int u; + const TQChar* ucp = uc.unicode(); + unsigned char* rp = (unsigned char *)r.data(); + unsigned char* rmp = reverseMap->data(); + int rmsize = (int) reverseMap->size(); + while( i-- ) + { + u = ucp->unicode(); + *rp = u < 128 ? u : (( u < rmsize ) ? (*(rmp+u)) : '?' ); + if ( *rp == 0 ) *rp = '?'; + rp++; + ucp++; + } + r[len] = 0; + return r; +} + +void TQSimpleTextCodec::fromUnicode( const TQChar *in, unsigned short *out, int length ) const +{ +#ifdef TQ_WS_QWS + if ( this != reverseOwner ) +#else + if ( !reverseMap ) +#endif + ((TQSimpleTextCodec *)this)->buildReverseMap(); + + unsigned char* rmp = reverseMap->data(); + int rmsize = (int) reverseMap->size(); + while ( length-- ) { + unsigned short u = in->unicode(); + *out = u < 128 ? u : (( u < rmsize ) ? (*(rmp+u)) : 0 ); + ++in; + ++out; + } +} + +unsigned short TQSimpleTextCodec::characterFromUnicode(const TQString &str, int pos) const +{ +#ifdef TQ_WS_QWS + if ( this != reverseOwner ) +#else + if ( !reverseMap ) +#endif + ((TQSimpleTextCodec *)this)->buildReverseMap(); + + unsigned short u = str[pos].unicode(); + unsigned char* rmp = reverseMap->data(); + int rmsize = (int) reverseMap->size(); + return u < 128 ? u : (( u < rmsize ) ? (*(rmp+u)) : 0 ); +} + +bool TQSimpleTextCodec::canEncode( TQChar ch ) const +{ +#ifdef TQ_WS_QWS + if ( this != reverseOwner ) +#else + if ( !reverseMap ) +#endif + ((TQSimpleTextCodec *)this)->buildReverseMap(); + + unsigned short u = ch.unicode(); + unsigned char* rmp = reverseMap->data(); + int rmsize = (int) reverseMap->size(); + return u < 128 ? TRUE : (( u < rmsize ) ? (*(rmp+u) != 0) : FALSE ); +} + +const char* TQSimpleTextCodec::name() const +{ + return unicodevalues[forwardIndex].cs; +} + +const char* TQSimpleTextCodec::mimeName() const +{ + return unicodevalues[forwardIndex].mime; +} + + +int TQSimpleTextCodec::mibEnum() const +{ + return unicodevalues[forwardIndex].mib; +} + +int TQSimpleTextCodec::heuristicNameMatch(const char* hint) const +{ + if ( tqstricmp( hint, mimeName() ) == 0 ) + return 10000; // return a large value + if ( hint[0]=='k' ) { + TQCString lhint = TQCString(hint).lower(); + // Help people with messy fonts + if ( lhint == "koi8-1" ) + return TQTextCodec::heuristicNameMatch("koi8-r")-1; + if ( lhint == "koi8-ru" ) + return TQTextCodec::heuristicNameMatch("koi8-r")-1; + } else if ( hint[0] == 't' && mibEnum() == 2259 /* iso8859-11 */ ) { + // 8859-11 and tis620 are byte by byte equivalent + int i = simpleHeuristicNameMatch("tis620-0", hint); + if( !i ) + i = simpleHeuristicNameMatch("tis-620", hint); + if( i ) return i; + } else if ( mibEnum() == 82 /* ISO 8859-6 */ ) { + int i = simpleHeuristicNameMatch("ISO 8859-6-I", hint); + if ( i ) + return i; + } + return TQTextCodec::heuristicNameMatch(hint); +} + +int TQSimpleTextCodec::heuristicContentMatch(const char* chars, int len) const +{ + if ( len<1 || !chars ) + return -1; + int i = 0; + const uchar * c = (const unsigned char *)chars; + int r = 0; + while( i= 128 ) { + if ( unicodevalues[forwardIndex].values[(*c)-128] == 0xfffd ) + return -1; + } + if ( (*c >= ' ' && *c < 127) || + *c == '\n' || *c == '\t' || *c == '\r' ) + r++; + i++; + c++; + } + if ( mibEnum()==4 ) + r+=1; + return r; +} + +#endif + +class TQLatin1Codec : public TQTextCodec +{ +public: +#if !defined(Q_NO_USING_KEYWORD) + using TQTextCodec::fromUnicode; + using TQTextCodec::toUnicode; +#endif + TQString toUnicode(const char* chars, int len) const; + TQCString fromUnicode(const TQString& uc, int& lenInOut ) const; + void fromUnicode( const TQChar *in, unsigned short *out, int length ) const; + unsigned short characterFromUnicode(const TQString &str, int pos) const; + + const char* name() const; + const char* mimeName() const; + int mibEnum() const; + + int heuristicContentMatch(const char* chars, int len) const; + +private: + int forwardIndex; +}; + + +TQString TQLatin1Codec::toUnicode(const char* chars, int len) const +{ + if ( chars == 0 ) + return TQString::null; + + return TQString::fromLatin1(chars, len); +} + + +TQCString TQLatin1Codec::fromUnicode(const TQString& uc, int& len ) const +{ + if ( len <0 || len > (int)uc.length() ) + len = uc.length(); + TQCString r( len+1 ); + char *d = r.data(); + int i = 0; + const TQChar *ch = uc.unicode(); + while ( i < len ) { + d[i] = ch->row() ? '?' : ch->cell(); + i++; + ch++; + } + r[len] = 0; + return r; +} + +void TQLatin1Codec::fromUnicode( const TQChar *in, unsigned short *out, int length ) const +{ + while ( length-- ) { + *out = in->row() ? 0 : in->cell(); + ++in; + ++out; + } +} + +unsigned short TQLatin1Codec::characterFromUnicode(const TQString &str, int pos) const +{ + const TQChar *ch = str.unicode() + pos; + if (ch->row()) + return 0; + return (unsigned short) ch->cell(); +} + + +const char* TQLatin1Codec::name() const +{ + return "ISO 8859-1"; +} + +const char* TQLatin1Codec::mimeName() const +{ + return "ISO-8859-1"; +} + + +int TQLatin1Codec::mibEnum() const +{ + return 4; +} + +int TQLatin1Codec::heuristicContentMatch(const char* chars, int len) const +{ + if ( len<1 || !chars ) + return -1; + int i = 0; + const uchar * c = (const unsigned char *)chars; + int r = 0; + while( i= 0x80 && *c < 0xa0 ) + return -1; + if ( (*c >= ' ' && *c < 127) || + *c == '\n' || *c == '\t' || *c == '\r' ) + r++; + i++; + c++; + } + if ( this == (const TQTextCodec *)codecForLocale() ) + r += 5; + return r; +} + +class TQLatin15Codec: public TQLatin1Codec +{ +public: + TQString toUnicode(const char* chars, int len) const; +#if !defined(Q_NO_USING_KEYWORD) + using TQLatin1Codec::fromUnicode; +#endif + TQCString fromUnicode(const TQString& uc, int& lenInOut ) const; + void fromUnicode( const TQChar *in, unsigned short *out, int length ) const; + unsigned short characterFromUnicode(const TQString &str, int pos) const; + + const char* name() const; + const char* mimeName() const; + int mibEnum() const; + +private: + int forwardIndex; +}; + + +TQString TQLatin15Codec::toUnicode(const char* chars, int len) const +{ + if ( chars == 0 ) + return TQString::null; + + TQString str = TQString::fromLatin1(chars, len); + TQChar *uc = (TQChar *)str.unicode(); + while( len-- ) { + switch( uc->unicode() ) { + case 0xa4: + *uc = 0x20ac; + break; + case 0xa6: + *uc = 0x0160; + break; + case 0xa8: + *uc = 0x0161; + break; + case 0xb4: + *uc = 0x017d; + break; + case 0xb8: + *uc = 0x017e; + break; + case 0xbc: + *uc = 0x0152; + break; + case 0xbd: + *uc = 0x0153; + break; + case 0xbe: + *uc = 0x0178; + break; + default: + break; + } + uc++; + } + return str; +} + +static inline unsigned char +latin15CharFromUnicode( unsigned short uc, bool replacement = TRUE ) +{ + uchar c; + if ( uc < 0x0100 ) { + if ( uc > 0xa3 && uc < 0xbf ) { + switch( uc ) { + case 0xa4: + case 0xa6: + case 0xa8: + case 0xb4: + case 0xb8: + case 0xbc: + case 0xbd: + case 0xbe: + c = replacement ? '?' : 0; + break; + default: + c = (unsigned char) uc; + break; + } + } else { + c = (unsigned char) uc; + } + } else { + if ( uc == 0x20ac ) + c = 0xa4; + else if ( (uc & 0xff00) == 0x0100 ) { + switch( uc ) { + case 0x0160: + c = 0xa6; + break; + case 0x0161: + c = 0xa8; + break; + case 0x017d: + c = 0xb4; + break; + case 0x017e: + c = 0xb8; + break; + case 0x0152: + c = 0xbc; + break; + case 0x0153: + c = 0xbd; + break; + case 0x0178: + c = 0xbe; + break; + default: + c = replacement ? '?' : 0; + } + } else { + c = replacement ? '?' : 0; + } + } + return c; +} + + +void TQLatin15Codec::fromUnicode( const TQChar *in, unsigned short *out, int length ) const +{ + while ( length-- ) { + *out = latin15CharFromUnicode( in->unicode(), FALSE ); + ++in; + ++out; + } +} + + +TQCString TQLatin15Codec::fromUnicode(const TQString& uc, int& len ) const +{ + if ( len <0 || len > (int)uc.length() ) + len = uc.length(); + TQCString r( len+1 ); + char *d = r.data(); + int i = 0; + const TQChar *ch = uc.unicode(); + while ( i < len ) { + d[i] = latin15CharFromUnicode( ch->unicode() ); + i++; + ch++; + } + r[len] = 0; + return r; +} + +unsigned short TQLatin15Codec::characterFromUnicode(const TQString &str, int pos) const +{ + return latin15CharFromUnicode( str.unicode()[pos].unicode(), FALSE ); +} + + +const char* TQLatin15Codec::name() const +{ + return "ISO 8859-15"; +} + +const char* TQLatin15Codec::mimeName() const +{ + return "ISO-8859-15"; +} + + +int TQLatin15Codec::mibEnum() const +{ + return 111; +} + +static TQTextCodec *checkForCodec(const char *name) { + TQTextCodec *c = TQTextCodec::codecForName(name); + if (!c) { + const char *at = strchr(name, '@'); + if (at) { + TQCString n(name, at - name + 1); + c = TQTextCodec::codecForName(n.data()); + } + } + return c; +} + +/* the next function is implicitely thread safe, + as they are only called by setup() which uses a mutex. +*/ +static void setupLocaleMapper() +{ +#ifdef Q_OS_WIN32 + localeMapper = TQTextCodec::codecForName( "System" ); +#else + +#if defined (_XOPEN_UNIX) && !defined(Q_OS_QNX6) && !defined(Q_OS_OSF) && !defined(Q_OS_MAC) + char *charset = nl_langinfo (CODESET); + if ( charset ) + localeMapper = TQTextCodec::codecForName( charset ); +#endif + + if ( !localeMapper ) { + // Very poorly defined and followed standards causes lots of code + // to try to get all the cases... + + // Try to determine locale codeset from locale name assigned to + // LC_CTYPE category. + + // First part is getting that locale name. First try setlocale() which + // definitely knows it, but since we cannot fully trust it, get ready + // to fall back to environment variables. + char * ctype = tqstrdup( setlocale( LC_CTYPE, 0 ) ); + + // Get the first nonempty value from $LC_ALL, $LC_CTYPE, and $LANG + // environment variables. + char * lang = tqstrdup( getenv("LC_ALL") ); + if ( !lang || lang[0] == 0 || strcmp( lang, "C" ) == 0 ) { + if ( lang ) delete [] lang; + lang = tqstrdup( getenv("LC_CTYPE") ); + } + if ( !lang || lang[0] == 0 || strcmp( lang, "C" ) == 0 ) { + if ( lang ) delete [] lang; + lang = tqstrdup( getenv("LANG") ); + } + + // Now try these in order: + // 1. CODESET from ctype if it contains a .CODESET part (e.g. en_US.ISO8859-15) + // 2. CODESET from lang if it contains a .CODESET part + // 3. ctype (maybe the locale is named "ISO-8859-1" or something) + // 4. locale (ditto) + // 5. check for "@euro" + // 6. guess locale from ctype unless ctype is "C" + // 7. guess locale from lang + + // 1. CODESET from ctype if it contains a .CODESET part (e.g. en_US.ISO8859-15) + char * codeset = ctype ? strchr( ctype, '.' ) : 0; + if ( codeset && *codeset == '.' ) + localeMapper = checkForCodec( codeset + 1 ); + + // 2. CODESET from lang if it contains a .CODESET part + codeset = lang ? strchr( lang, '.' ) : 0; + if ( !localeMapper && codeset && *codeset == '.' ) + localeMapper = checkForCodec( codeset + 1 ); + + // 3. ctype (maybe the locale is named "ISO-8859-1" or something) + if ( !localeMapper && ctype && *ctype != 0 && strcmp (ctype, "C") != 0 ) + localeMapper = checkForCodec( ctype ); + + // 4. locale (ditto) + if ( !localeMapper && lang && *lang != 0 ) + localeMapper = checkForCodec( lang ); + + // 5. "@euro" + if ( ( !localeMapper && ctype && strstr( ctype, "@euro" ) ) || (lang && strstr( lang, "@euro" ) ) ) + localeMapper = TQTextCodec::codecForName( "ISO 8859-15" ); + + // 6. guess locale from ctype unless ctype is "C" + // 7. guess locale from lang + char * try_by_name = ctype; + if ( ctype && *ctype != 0 && strcmp (ctype, "C") != 0 ) + try_by_name = lang; + + // Now do the guessing. + if ( lang && *lang && !localeMapper && try_by_name && *try_by_name ) { + if ( try_locale_list( iso8859_15locales, lang ) ) + localeMapper = TQTextCodec::codecForName( "ISO 8859-15" ); + else if ( try_locale_list( iso8859_2locales, lang ) ) + localeMapper = TQTextCodec::codecForName( "ISO 8859-2" ); + else if ( try_locale_list( iso8859_3locales, lang ) ) + localeMapper = TQTextCodec::codecForName( "ISO 8859-3" ); + else if ( try_locale_list( iso8859_4locales, lang ) ) + localeMapper = TQTextCodec::codecForName( "ISO 8859-4" ); + else if ( try_locale_list( iso8859_5locales, lang ) ) + localeMapper = TQTextCodec::codecForName( "ISO 8859-5" ); + else if ( try_locale_list( iso8859_6locales, lang ) ) + localeMapper = TQTextCodec::codecForName( "ISO 8859-6" ); + else if ( try_locale_list( iso8859_7locales, lang ) ) + localeMapper = TQTextCodec::codecForName( "ISO 8859-7" ); + else if ( try_locale_list( iso8859_8locales, lang ) ) + localeMapper = TQTextCodec::codecForName( "ISO 8859-8-I" ); + else if ( try_locale_list( iso8859_9locales, lang ) ) + localeMapper = TQTextCodec::codecForName( "ISO 8859-9" ); + else if ( try_locale_list( iso8859_13locales, lang ) ) + localeMapper = TQTextCodec::codecForName( "ISO 8859-13" ); + else if ( try_locale_list( tis_620locales, lang ) ) + localeMapper = TQTextCodec::codecForName( "ISO 8859-11" ); + else if ( try_locale_list( koi8_ulocales, lang ) ) + localeMapper = TQTextCodec::codecForName( "KOI8-U" ); + else if ( try_locale_list( cp_1251locales, lang ) ) + localeMapper = TQTextCodec::codecForName( "CP 1251" ); + else if ( try_locale_list( pt_154locales, lang ) ) + localeMapper = TQTextCodec::codecForName( "PT 154" ); + else if ( try_locale_list( probably_koi8_rlocales, lang ) ) + localeMapper = ru_RU_hack( lang ); + } + + delete [] ctype; + delete [] lang; + } + if ( localeMapper && localeMapper->mibEnum() == 11 ) + localeMapper = TQTextCodec::codecForName( "ISO 8859-8-I" ); + + // If everything failed, we default to 8859-1 + // We could perhaps default to 8859-15. + if ( !localeMapper ) + localeMapper = TQTextCodec::codecForName( "ISO 8859-1" ); +#endif +} + + +static void setup() +{ +#if defined(QT_CHECK_STATE) + if ( codecs_destroyed ) + { + // If codecs have been destroyed, the application is being destroyed. + // Do not create new codecs since this could lead to SEGV while trying to + // print a message using tqWarning/tqDebug/tqFatal at this stage + // + // Note: the use of `printf` instead of `tqWarning` is intentional. We should never + // get to this line of code. If we do, we are in some strange exception that we + // didn't think of. Using `tqWarning` could potentially lead to an infinite loop with + // `tqWarning` trying to setup codecs and this method calling `tqWarning` again. + // Using `printf` makes sure this never happens, even for exceptions we didn't foresee. + printf("TQTextCodec: setup() called when codecs have already been destroyed\n"); fflush(stdout); + return; + } +#endif + + if ( all ) return; + +#ifdef TQT_THREAD_SUPPORT + TQMutexLocker locker( tqt_global_mutexpool ? + tqt_global_mutexpool->get( &all ) : 0 ); +#endif // TQT_THREAD_SUPPORT + + all = new TQValueList; + + (void)new TQLatin1Codec; + (void)new TQLatin15Codec; + (void)new TQUtf8Codec; + (void)new TQUtf16Codec; + +#ifndef TQT_NO_CODECS + int i = 0; + do { + (void)new TQSimpleTextCodec( i ); + } while( unicodevalues[i++].mib != LAST_MIB ); + + (void)new TQTsciiCodec; + + for (i = 0; i < 9; ++i) { + (void)new TQIsciiCodec(i); + } +#endif // TQT_NO_CODECS +#ifndef TQT_NO_CODEC_HEBREW + (void)new TQHebrewCodec; +#endif +#ifndef TQT_NO_BIG_CODECS + (void)new TQBig5Codec; + (void)new TQBig5hkscsCodec; + (void)new TQEucJpCodec; + (void)new TQEucKrCodec; + (void)new TQGb2312Codec; + (void)new TQGbkCodec; + (void)new TQGb18030Codec; + (void)new TQJisCodec; + (void)new TQSjisCodec; +#endif // TQT_NO_BIG_CODECS + +#ifdef Q_OS_WIN32 + (void) new TQWindowsLocalCodec; +#endif // Q_OS_WIN32 + + if ( !localeMapper ) + setupLocaleMapper(); +} + +void TQTextCodec::fromUnicodeInternal( const TQChar *in, unsigned short *out, int length ) +{ + switch( mibEnum() ) { +#ifndef TQT_NO_CODECS + case 2084: + case 2088: + case 5: + case 6: + case 7: + case 8: + case 82: + case 10: + case 85: + case 12: + case 13: + case 109: + case 110: + case 2004: + case 2009: + case 2086: + case 2250: + case 2251: + case 2252: + case 2253: + case 2254: + case 2255: + case 2256: + case 2257: + case 2258: + case 2259: + ((TQSimpleTextCodec *)this)->fromUnicode( in, out, length ); + break; + +#if !defined(TQT_NO_BIG_CODECS) && defined(TQ_WS_X11) + // the TQFont*Codecs are only used on X11 + + case 15: + ((TQFontJis0201Codec *) this)->fromUnicode( in, out, length ); + break; + + case 63: + ((TQFontJis0208Codec *) this)->fromUnicode( in, out, length ); + break; + + case 36: + ((TQFontKsc5601Codec *) this)->fromUnicode( in, out, length ); + break; + + case 57: + ((TQFontGb2312Codec *) this)->fromUnicode( in, out, length ); + break; + + case -113: + ((TQFontGbkCodec *) this)->fromUnicode( in, out, length ); + break; + + case -114: + ((TQFontGb18030_0Codec *) this)->fromUnicode( in, out, length ); + break; + + case -2026: + ((TQFontBig5Codec *) this)->fromUnicode( in, out, length ); + break; + + case -2101: + ((TQFontBig5hkscsCodec *) this)->fromUnicode( in, out, length ); + break; + + case -4242: + ((TQFontLaoCodec *) this)->fromUnicode( in, out, length ); + break; +#endif +#endif // TQT_NO_CODECS + + case 4: + ((TQLatin1Codec *) this)->fromUnicode( in, out, length ); + break; + + case 111: + ((TQLatin15Codec *) this)->fromUnicode( in, out, length ); + break; + + default: + { + TQConstString string( in, length ); + TQString str = string.string(); + for ( int i = 0; i < length; i++ ) + out[i] = characterFromUnicode( str, i ); + } + } +} + + +/*! + \fn TQTextCodec* TQTextCodec::codecForTr() + + Returns the codec used by TQObject::tr() on its argument. If this + function returns 0 (the default), tr() assumes Latin-1. + + \sa setCodecForTr() +*/ + +/*! + \fn void TQTextCodec::setCodecForTr(TQTextCodec *c) + \nonreentrant + + Sets the codec used by TQObject::tr() on its argument to \a c. If + \a c is 0 (the default), tr() assumes Latin-1. + + If the literal quoted text in the program is not in the Latin-1 + encoding, this function can be used to set the appropriate + encoding. For example, software developed by Korean programmers + might use eucKR for all the text in the program, in which case the + main() function might look like this: + + \code + int main(int argc, char** argv) + { + TQApplication app(argc, argv); + ... install any additional codecs ... + TQTextCodec::setCodecForTr( TQTextCodec::codecForName("eucKR") ); + ... + } + \endcode + + Note that this is not the way to select the encoding that the \e + user has chosen. For example, to convert an application containing + literal English strings to Korean, all that is needed is for the + English strings to be passed through tr() and for translation + files to be loaded. For details of internationalization, see the + \link i18n.html TQt internationalization documentation\endlink. + + \sa codecForTr(), setCodecForTr(), setCodecForCStrings() +*/ + + +/*! + \fn TQTextCodec* TQTextCodec::codecForCStrings() + + Returns the codec used by TQString to convert to and from const + char* and TQCStrings. If this function returns 0 (the default), + TQString assumes Latin-1. + + \sa setCodecForCStrings() +*/ + +/*! + \fn void TQTextCodec::setCodecForCStrings(TQTextCodec *c) + \nonreentrant + + Sets the codec used by TQString to convert to and from const char* + and TQCStrings. If \a c is 0 (the default), TQString assumes Latin-1. + + \warning Some codecs do not preserve the characters in the ascii + range (0x00 to 0x7f). For example, the Japanese Shift-JIS + encoding maps the backslash character (0x5a) to the Yen character. + This leads to unexpected results when using the backslash + character to escape characters in strings used in e.g. regular + expressions. Use TQString::fromLatin1() to preserve characters in + the ascii range when needed. + + \sa codecForCStrings(), setCodecForTr(), setCodecForCStrings() +*/ + + +TQTextCodec *TQTextCodec::cftr = 0; +TQTextCodec *TQTextCodec::cfcs = 0; + + +#endif // TQT_NO_TEXTCODEC diff --git a/src/codecs/tqtextcodec.h b/src/codecs/tqtextcodec.h new file mode 100644 index 000000000..f5554d261 --- /dev/null +++ b/src/codecs/tqtextcodec.h @@ -0,0 +1,134 @@ +/**************************************************************************** +** +** Definition of TQTextCodec class +** +** Created : 981015 +** +** Copyright (C) 1998-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 TQTEXTCODEC_H +#define TQTEXTCODEC_H + +#ifndef QT_H +#include "tqstring.h" +#endif // QT_H + +#ifndef TQT_NO_TEXTCODEC + +class TQTextCodec; +class TQIODevice; +class TQFont; + +class TQ_EXPORT TQTextEncoder { +public: + virtual ~TQTextEncoder(); + virtual TQCString fromUnicode(const TQString& uc, int& lenInOut) = 0; +}; + +class TQ_EXPORT TQTextDecoder { +public: + virtual ~TQTextDecoder(); + virtual TQString toUnicode(const char* chars, int len) = 0; +}; + +class TQ_EXPORT TQTextCodec { +public: + virtual ~TQTextCodec(); + +#ifndef TQT_NO_CODECS + static TQTextCodec* loadCharmap(TQIODevice*); + static TQTextCodec* loadCharmapFile(TQString filename); +#endif //TQT_NO_CODECS + static TQTextCodec* codecForMib(int mib); + static TQTextCodec* codecForName(const char* hint, int accuracy=0); + static TQTextCodec* codecForContent(const char* chars, int len); + static TQTextCodec* codecForIndex(int i); + static TQTextCodec* codecForLocale(); + static void setCodecForLocale(TQTextCodec *c); + + static TQTextCodec* codecForTr(); + static void setCodecForTr(TQTextCodec *c); + static TQTextCodec* codecForCStrings(); + static void setCodecForCStrings(TQTextCodec *c); + + static void deleteAllCodecs(); + + static const char* locale(); + + virtual const char* name() const = 0; + virtual const char* mimeName() const; + virtual int mibEnum() const = 0; + + virtual TQTextDecoder* makeDecoder() const; + virtual TQTextEncoder* makeEncoder() const; + + virtual TQString toUnicode(const char* chars, int len) const; + virtual TQCString fromUnicode(const TQString& uc, int& lenInOut) const; + + TQCString fromUnicode(const TQString& uc) const; + TQString toUnicode(const TQByteArray&, int len) const; + TQString toUnicode(const TQByteArray&) const; + TQString toUnicode(const TQCString&, int len) const; + TQString toUnicode(const TQCString&) const; + TQString toUnicode(const char* chars) const; + virtual bool canEncode( TQChar ) const; + virtual bool canEncode( const TQString& ) const; + + virtual int heuristicContentMatch(const char* chars, int len) const = 0; + virtual int heuristicNameMatch(const char* hint) const; + + virtual TQByteArray fromUnicode(const TQString& uc, int from, int len) const; + virtual unsigned short characterFromUnicode(const TQString &str, int pos) const; + +protected: + TQTextCodec(); + static int simpleHeuristicNameMatch(const char* name, const char* hint); + +private: + friend class TQFont; + friend class TQFontEngineXLFD; + void fromUnicodeInternal( const TQChar *in, unsigned short *out, int length ); + + static TQTextCodec *cftr; + static TQTextCodec *cfcs; +}; + +inline TQTextCodec* TQTextCodec::codecForTr() { return cftr; } +inline void TQTextCodec::setCodecForTr(TQTextCodec *c) { cftr = c; } +inline TQTextCodec* TQTextCodec::codecForCStrings() { return cfcs; } +inline void TQTextCodec::setCodecForCStrings(TQTextCodec *c) { cfcs = c; } + +#endif // TQT_NO_TEXTCODEC +#endif // TQTEXTCODEC_H diff --git a/src/codecs/tqtextcodecfactory.cpp b/src/codecs/tqtextcodecfactory.cpp new file mode 100644 index 000000000..24ac82a09 --- /dev/null +++ b/src/codecs/tqtextcodecfactory.cpp @@ -0,0 +1,131 @@ +/**************************************************************************** +** +** Implementation of TQTextCodecFactory class +** +** Created : 010130 +** +** 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 "tqtextcodecfactory.h" + +#ifndef TQT_NO_TEXTCODEC + +#ifndef TQT_NO_COMPONENT +#include "ntqapplication.h" +#include "ntqcleanuphandler.h" +#include +#include "tqtextcodecinterface_p.h" + +#ifdef TQT_THREAD_SUPPORT +# include +#endif // TQT_THREAD_SUPPORT + +#include + + +static TQPluginManager *manager = 0; +static TQSingleCleanupHandler< TQPluginManager > cleanup_manager; + +static void create_manager() +{ + if ( manager ) // already created + return; + +#ifdef TQT_THREAD_SUPPORT + // protect manager creation + TQMutexLocker locker( tqt_global_mutexpool ? + tqt_global_mutexpool->get( &manager ) : 0); + + // we check the manager pointer again to make sure that another thread + // has not created the manager before us. + + if ( manager ) // already created + return; +#endif + + manager = + new TQPluginManager(IID_QTextCodecFactory, + TQApplication::libraryPaths(), "/codecs", + FALSE); + TQ_CHECK_PTR( manager ); + cleanup_manager.set( &manager ); +} + +#endif // TQT_NO_COMPONENT + + +TQTextCodec *TQTextCodecFactory::createForName(const TQString &name) +{ + TQTextCodec *codec = 0; + +#ifndef TQT_NO_COMPONENT + + // make sure the manager is created + create_manager(); + + TQInterfacePtr iface; + manager->queryInterface(name, &iface ); + + if (iface) + codec = iface->createForName(name); + +#endif // TQT_NO_COMPONENT + + return codec; +} + + +TQTextCodec *TQTextCodecFactory::createForMib(int mib) +{ + TQTextCodec *codec = 0; + +#ifndef TQT_NO_COMPONENT + + // make sure the manager is created + create_manager(); + + TQInterfacePtr iface; + manager->queryInterface("MIB-" + TQString::number(mib), &iface ); + + if (iface) + codec = iface->createForMib(mib); + +#endif // TQT_NO_COMPONENT + + return codec; +} + + +#endif // TQT_NO_TEXTCODEC diff --git a/src/codecs/tqtextcodecfactory.h b/src/codecs/tqtextcodecfactory.h new file mode 100644 index 000000000..74cca82ca --- /dev/null +++ b/src/codecs/tqtextcodecfactory.h @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** Definition of TQTextCodecFactory 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 TQTEXTCODECFACTORY_H +#define TQTEXTCODECFACTORY_H + +#ifndef QT_H +#include "tqstringlist.h" +#endif // QT_H + +#ifndef TQT_NO_TEXTCODEC + +class TQTextCodec; + +class TQ_EXPORT TQTextCodecFactory +{ +public: + static TQTextCodec *createForName( const TQString & ); + static TQTextCodec *createForMib( int ); +}; + +#endif // TQT_NO_TEXTCODEC + +#endif // TQTEXTCODECFACTORY_H diff --git a/src/codecs/tqtextcodecinterface_p.h b/src/codecs/tqtextcodecinterface_p.h new file mode 100644 index 000000000..5a8baa04a --- /dev/null +++ b/src/codecs/tqtextcodecinterface_p.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Definition of TQTextCodecFactoryInterface interface +** +** 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 TQTEXTCODECINTERFACE_P_H +#define TQTEXTCODECINTERFACE_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 qprinter_x11.cpp. +// 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 + +#ifndef TQT_NO_TEXTCODEC +#ifndef TQT_NO_COMPONENT + +class TQTextCodec; + + +// {F55BFA60-F695-11D4-823E-009027DC0F37} +#ifndef IID_QTextCodecFactory +#define IID_QTextCodecFactory TQUuid( 0xf55bfa60, 0xf695, 0x11d4, 0x82, 0x3e, 0x00, 0x90, 0x27, 0xdc, 0x0f, 0x37) +#endif + + +struct TQ_EXPORT TQTextCodecFactoryInterface : public TQFeatureListInterface +{ + virtual TQTextCodec *createForMib( int mib ) = 0; + virtual TQTextCodec *createForName( const TQString &name ) = 0; +}; + +#endif // TQT_NO_COMPONENT +#endif // TQT_NO_TEXTCODEC + +#endif // TQTEXTCODECINTERFACE_P_H diff --git a/src/codecs/tqtextcodecplugin.cpp b/src/codecs/tqtextcodecplugin.cpp new file mode 100644 index 000000000..046b009f7 --- /dev/null +++ b/src/codecs/tqtextcodecplugin.cpp @@ -0,0 +1,186 @@ +/**************************************************************************** +** +** Implementation of TQTextCodecPlugin class +** +** Created : 010920 +** +** 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 "tqtextcodecplugin.h" +#ifndef TQT_NO_TEXTCODECPLUGIN +#include "tqtextcodecinterface_p.h" + +/*! + \class TQTextCodecPlugin tqtextcodecplugin.h + \brief The TQTextCodecPlugin class provides an abstract base for custom TQTextCodec plugins. + \reentrant + \ingroup plugins + + The text codec plugin is a simple plugin interface that makes it + easy to create custom text codecs that can be loaded dynamically + into applications. + + Writing a text codec plugin is achieved by subclassing this base + class, reimplementing the pure virtual functions names(), + createForName(), mibEnums() and createForMib(), and exporting the + class with the \c TQ_EXPORT_PLUGIN macro. See the \link + plugins-howto.html TQt Plugins documentation \endlink for details. + + See the \link http://www.iana.org/assignments/character-sets IANA + character-sets encoding file\endlink for more information on mime + names and mib enums. +*/ + +/*! + \fn TQStringList TQTextCodecPlugin::names() const + + Returns the list of mime names supported by this plugin. + + \sa createForName() +*/ + +/*! + \fn TQTextCodec *TQTextCodecPlugin::createForName( const TQString &name ); + + Creates a TQTextCodec object for the codec called \a name. + + \sa names() +*/ + + +/*! + \fn TQValueList TQTextCodecPlugin::mibEnums() const + + Returns the list of mib enums supported by this plugin. + + \sa createForMib() +*/ + +/*! + \fn TQTextCodec *TQTextCodecPlugin::createForMib( int mib ); + + Creates a TQTextCodec object for the mib enum \a mib. + + (See \link + ftp://ftp.isi.edu/in-notes/iana/assignments/character-sets the + IANA character-sets encoding file\endlink for more information) + + \sa mibEnums() +*/ + + + +class TQTextCodecPluginPrivate : public TQTextCodecFactoryInterface +{ +public: + TQTextCodecPluginPrivate( TQTextCodecPlugin *p ) + : plugin( p ) + { + } + virtual ~TQTextCodecPluginPrivate(); + + TQRESULT queryInterface( const TQUuid &iid, TQUnknownInterface **iface ); + TQ_REFCOUNT; + + TQStringList featureList() const; + TQTextCodec *createForMib( int mib ); + TQTextCodec *createForName( const TQString &name ); + +private: + TQTextCodecPlugin *plugin; +}; + +TQTextCodecPluginPrivate::~TQTextCodecPluginPrivate() +{ + delete plugin; +} + +TQRESULT TQTextCodecPluginPrivate::queryInterface( const TQUuid &iid, TQUnknownInterface **iface ) +{ + *iface = 0; + + if ( iid == IID_QUnknown ) + *iface = this; + else if ( iid == IID_QFeatureList ) + *iface = this; + else if ( iid == IID_QTextCodecFactory ) + *iface = this; + else + return TQE_NOINTERFACE; + + (*iface)->addRef(); + return TQS_OK; +} + +TQStringList TQTextCodecPluginPrivate::featureList() const +{ + TQStringList keys = plugin->names(); + TQValueList mibs = plugin->mibEnums(); + for ( TQValueList::Iterator it = mibs.begin(); it != mibs.end(); ++it ) + keys += TQString("MIB-%1").arg( *it ); + return keys; +} + +TQTextCodec *TQTextCodecPluginPrivate::createForMib( int mib ) +{ + return plugin->createForMib( mib ); +} + +TQTextCodec *TQTextCodecPluginPrivate::createForName( const TQString &name ) +{ + return plugin->createForName( name ); +} + + +/*! + Constructs a text codec plugin. This is invoked automatically by + the \c TQ_EXPORT_PLUGIN macro. +*/ +TQTextCodecPlugin::TQTextCodecPlugin() + : TQGPlugin( d = new TQTextCodecPluginPrivate( this ) ) +{ +} + +/*! + Destroys the text codec plugin. + + You never have to call this explicitly. TQt destroys a plugin + automatically when it is no longer used. +*/ +TQTextCodecPlugin::~TQTextCodecPlugin() +{ +} + +#endif // TQT_NO_TEXTCODECPLUGIN diff --git a/src/codecs/tqtextcodecplugin.h b/src/codecs/tqtextcodecplugin.h new file mode 100644 index 000000000..13a83733d --- /dev/null +++ b/src/codecs/tqtextcodecplugin.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Definition of TQTextCodecPlugin class +** +** Created : 010920 +** +** 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. +** +**********************************************************************/ + +#ifndef TQTEXTCODECPLUGIN_H +#define TQTEXTCODECPLUGIN_H + +#ifndef QT_H +#include "ntqgplugin.h" +#include "tqstringlist.h" +#endif // QT_H + +#ifndef TQT_NO_TEXTCODECPLUGIN +class TQTextCodec; +class TQTextCodecPluginPrivate; + +class TQ_EXPORT TQTextCodecPlugin : public TQGPlugin +{ + TQ_OBJECT +public: + TQTextCodecPlugin(); + ~TQTextCodecPlugin(); + + virtual TQStringList names() const = 0; + virtual TQTextCodec *createForName( const TQString &name ) = 0; + + virtual TQValueList mibEnums() const = 0; + virtual TQTextCodec *createForMib( int mib ) = 0; + +private: + TQTextCodecPluginPrivate *d; +}; +#endif // TQT_NO_TEXTCODECPLUGIN +#endif // TQTEXTCODECPLUGIN_H diff --git a/src/dialogs/qerrormessage.cpp b/src/dialogs/qerrormessage.cpp index 9d27e023a..e2b302e55 100644 --- a/src/dialogs/qerrormessage.cpp +++ b/src/dialogs/qerrormessage.cpp @@ -51,7 +51,7 @@ #include "ntqpushbutton.h" #include "tqstringlist.h" #include "ntqstylesheet.h" -#include "ntqtextview.h" +#include "tqtextview.h" #include #include diff --git a/src/dialogs/qprintdialog.cpp b/src/dialogs/qprintdialog.cpp index 0e37e8615..2402de7d3 100644 --- a/src/dialogs/qprintdialog.cpp +++ b/src/dialogs/qprintdialog.cpp @@ -44,7 +44,7 @@ #include "ntqfiledialog.h" #include "ntqfile.h" -#include "ntqtextstream.h" +#include "tqtextstream.h" #include "ntqcombobox.h" #include "ntqframe.h" #include "ntqlabel.h" diff --git a/src/kernel/ntqnamespace.h b/src/kernel/ntqnamespace.h index 8bdc0a374..03c58309c 100644 --- a/src/kernel/ntqnamespace.h +++ b/src/kernel/ntqnamespace.h @@ -920,7 +920,7 @@ public: LogText }; - // Documented in qtextedit.cpp + // Documented in tqtextedit.cpp enum AnchorAttribute { AnchorName, AnchorHref diff --git a/src/kernel/ntqt.h b/src/kernel/ntqt.h index 876d07c1f..3e62736f3 100644 --- a/src/kernel/ntqt.h +++ b/src/kernel/ntqt.h @@ -36,7 +36,7 @@ #include "tqpair.h" #include "ntqpoint.h" #include -#include "ntqtextstream.h" +#include "tqtextstream.h" #include "ntqfontinfo.h" #include "ntqsizepolicy.h" #include "ntqtl.h" @@ -65,7 +65,7 @@ #include "ntqpalette.h" #include "tqwidget.h" #include "ntqjpunicode.h" -#include "ntqtextcodec.h" +#include "tqtextcodec.h" #include "ntqpixmap.h" #include #include "ntqiconset.h" @@ -224,18 +224,18 @@ #include #include #include -#include "ntqtextedit.h" +#include "tqtextedit.h" #include #include #include "tqsqleditorfactory.h" #include -#include +#include #include -#include -#include +#include +#include #include #include "ntqtoolbar.h" -#include +#include #include "ntqwaitcondition.h" #include #include @@ -295,7 +295,7 @@ #include "private/qrichtext_p.h" #include "private/qsvgdevice_p.h" #include "private/qfontcodecs_p.h" -#include "private/qtextcodecinterface_p.h" +#include "private/tqtextcodecinterface_p.h" #include "private/qpsprinter_p.h" #include "private/qtitlebar_p.h" #include "private/qucom_p.h" @@ -325,7 +325,7 @@ #endif #ifdef TQ_WS_QWS -#include +#include #include "qfontmanager_qws.h" #include #include diff --git a/src/kernel/qapplication.cpp b/src/kernel/qapplication.cpp index e5b28642b..baf5ba495 100644 --- a/src/kernel/qapplication.cpp +++ b/src/kernel/qapplication.cpp @@ -49,7 +49,7 @@ #include "ntqcleanuphandler.h" #include "ntqtranslator.h" -#include "ntqtextcodec.h" +#include "tqtextcodec.h" #include "ntqsessionmanager.h" #include "ntqdragobject.h" #include "ntqclipboard.h" diff --git a/src/kernel/qapplication_x11.cpp b/src/kernel/qapplication_x11.cpp index 57c55feba..0cfd812c2 100644 --- a/src/kernel/qapplication_x11.cpp +++ b/src/kernel/qapplication_x11.cpp @@ -74,7 +74,7 @@ #include "ntqpainter.h" #include "ntqpixmapcache.h" #include "ntqdatetime.h" -#include "ntqtextcodec.h" +#include "tqtextcodec.h" #include "ntqdatastream.h" #include "ntqbuffer.h" #include "ntqsocketnotifier.h" diff --git a/src/kernel/qclipboard_x11.cpp b/src/kernel/qclipboard_x11.cpp index 51fbc63ab..7776cf606 100644 --- a/src/kernel/qclipboard_x11.cpp +++ b/src/kernel/qclipboard_x11.cpp @@ -70,7 +70,7 @@ #include "ntqdatetime.h" #include "ntqdragobject.h" #include "ntqbuffer.h" -#include "ntqtextcodec.h" +#include "tqtextcodec.h" #include "tqvaluelist.h" #include "tqmap.h" #include "qt_x11_p.h" diff --git a/src/kernel/qdragobject.cpp b/src/kernel/qdragobject.cpp index 5e6a0dab9..9854c33a3 100644 --- a/src/kernel/qdragobject.cpp +++ b/src/kernel/qdragobject.cpp @@ -46,7 +46,7 @@ #ifndef TQT_NO_MIME #include "ntqdragobject.h" -#include "ntqtextcodec.h" +#include "tqtextcodec.h" #include "ntqapplication.h" #include "ntqpoint.h" #include "tqwidget.h" diff --git a/src/kernel/qfont.cpp b/src/kernel/qfont.cpp index b442a3253..387f75dfe 100644 --- a/src/kernel/qfont.cpp +++ b/src/kernel/qfont.cpp @@ -59,7 +59,7 @@ #include "qfontdata_p.h" #include "qfontengine_p.h" #include "qpainter_p.h" -#include "qtextengine_p.h" +#include "tqtextengine_p.h" // #define TQFONTCACHE_DEBUG #ifdef TQFONTCACHE_DEBUG diff --git a/src/kernel/qfont_x11.cpp b/src/kernel/qfont_x11.cpp index 3cd207c65..07c3fe2c6 100644 --- a/src/kernel/qfont_x11.cpp +++ b/src/kernel/qfont_x11.cpp @@ -52,13 +52,13 @@ #include "ntqfontmetrics.h" #include "ntqpaintdevice.h" #include "ntqpaintdevicemetrics.h" -#include "ntqtextcodec.h" +#include "tqtextcodec.h" #include #include #include "qfontdata_p.h" #include "qfontengine_p.h" -#include "qtextengine_p.h" +#include "tqtextengine_p.h" #include "qt_x11_p.h" diff --git a/src/kernel/qfontengine_p.h b/src/kernel/qfontengine_p.h index 17aa618b6..9e3c31261 100644 --- a/src/kernel/qfontengine_p.h +++ b/src/kernel/qfontengine_p.h @@ -46,7 +46,7 @@ #include "tqptrdict.h" #endif -#include "qtextengine_p.h" +#include "tqtextengine_p.h" class TQPaintDevice; @@ -475,7 +475,7 @@ class TQTextEngine; #ifndef TQT_NO_XFTFREETYPE #include "qscriptengine_p.h" -#include "qtextengine_p.h" +#include "tqtextengine_p.h" #include #include FT_FREETYPE_H #include "ftxopen.h" diff --git a/src/kernel/qfontengine_x11.cpp b/src/kernel/qfontengine_x11.cpp index 5cf756265..54bedb33e 100644 --- a/src/kernel/qfontengine_x11.cpp +++ b/src/kernel/qfontengine_x11.cpp @@ -42,7 +42,7 @@ #include #include -#include +#include #include "ntqbitmap.h" #include "ntqfontdatabase.h" @@ -54,7 +54,7 @@ #include "qt_x11_p.h" #include "ntqfont.h" -#include "qtextengine_p.h" +#include "tqtextengine_p.h" #include diff --git a/src/kernel/qpainter.cpp b/src/kernel/qpainter.cpp index 3f91a8023..82840cc27 100644 --- a/src/kernel/qpainter.cpp +++ b/src/kernel/qpainter.cpp @@ -56,7 +56,7 @@ #endif #include -#include "qtextlayout_p.h" +#include "tqtextlayout_p.h" #include "qfontengine_p.h" #ifndef TQT_NO_TRANSFORMATIONS diff --git a/src/kernel/qpainter_x11.cpp b/src/kernel/qpainter_x11.cpp index a4f71fc00..0e72d64da 100644 --- a/src/kernel/qpainter_x11.cpp +++ b/src/kernel/qpainter_x11.cpp @@ -45,15 +45,15 @@ #include "tqwidget.h" #include "ntqbitmap.h" #include "ntqpixmapcache.h" -#include "ntqtextcodec.h" +#include "tqtextcodec.h" #include "ntqpaintdevicemetrics.h" #include "qt_x11_p.h" -#include "qtextlayout_p.h" +#include "tqtextlayout_p.h" #include "qfontdata_p.h" #include "qfontengine_p.h" -#include "qtextengine_p.h" +#include "tqtextengine_p.h" #include @@ -435,7 +435,7 @@ static void init_gc_cache() // #define GC_CACHE_STAT #if defined(GC_CACHE_STAT) -#include "ntqtextstream.h" +#include "tqtextstream.h" #include "ntqbuffer.h" static int g_numhits = 0; diff --git a/src/kernel/qpsprinter.cpp b/src/kernel/qpsprinter.cpp index 6974fdf6c..22acd9832 100644 --- a/src/kernel/qpsprinter.cpp +++ b/src/kernel/qpsprinter.cpp @@ -67,7 +67,7 @@ #include "ntqfile.h" #include "ntqbuffer.h" #include "ntqintdict.h" -#include "ntqtextcodec.h" +#include "tqtextcodec.h" #include "ntqsettings.h" #include "tqmap.h" #include "ntqfontdatabase.h" @@ -98,8 +98,8 @@ #if defined( TQ_WS_X11 ) || defined (TQ_WS_QWS) #include "qfontdata_p.h" #include "qfontengine_p.h" -#include "qtextlayout_p.h" -#include "qtextengine_p.h" +#include "tqtextlayout_p.h" +#include "tqtextengine_p.h" extern bool tqt_has_xft; #endif diff --git a/src/kernel/qpsprinter_p.h b/src/kernel/qpsprinter_p.h index 6b96a965d..47939b1db 100644 --- a/src/kernel/qpsprinter_p.h +++ b/src/kernel/qpsprinter_p.h @@ -59,7 +59,7 @@ #ifndef QT_H #include "ntqprinter.h" -#include "ntqtextstream.h" +#include "tqtextstream.h" #endif // QT_H #ifndef TQT_NO_PRINTER diff --git a/src/kernel/qrichtext.cpp b/src/kernel/qrichtext.cpp index 484553d3e..cd4c31055 100644 --- a/src/kernel/qrichtext.cpp +++ b/src/kernel/qrichtext.cpp @@ -45,7 +45,7 @@ #include "tqstringlist.h" #include "ntqfont.h" -#include "ntqtextstream.h" +#include "tqtextstream.h" #include "ntqfile.h" #include "ntqapplication.h" #include "tqmap.h" @@ -62,7 +62,7 @@ #include "tqptrdict.h" #include "ntqstyle.h" #include "ntqcleanuphandler.h" -#include "qtextengine_p.h" +#include "tqtextengine_p.h" #include #include diff --git a/src/kernel/qrichtext_p.h b/src/kernel/qrichtext_p.h index 52762c6b4..58fed9826 100644 --- a/src/kernel/qrichtext_p.h +++ b/src/kernel/qrichtext_p.h @@ -118,7 +118,7 @@ public: enum Type { Regular=0, Custom=1, Anchor=2, CustomAnchor=3 }; TQChar c; - // this is the same struct as in qtextengine_p.h. Don't change! + // 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) diff --git a/src/kernel/qscriptengine.cpp b/src/kernel/qscriptengine.cpp index 08cac102f..5e18dad56 100644 --- a/src/kernel/qscriptengine.cpp +++ b/src/kernel/qscriptengine.cpp @@ -40,7 +40,7 @@ #include "ntqrect.h" #include "ntqfont.h" #include -#include "qtextengine_p.h" +#include "tqtextengine_p.h" #include "qfontengine_p.h" #include diff --git a/src/kernel/qscriptengine_p.h b/src/kernel/qscriptengine_p.h index 1c5d55370..77dd87b96 100644 --- a/src/kernel/qscriptengine_p.h +++ b/src/kernel/qscriptengine_p.h @@ -48,7 +48,7 @@ // We mean it. // -#include "qtextengine_p.h" +#include "tqtextengine_p.h" class TQString; struct TQCharAttributes; diff --git a/src/kernel/qscriptengine_x11.cpp b/src/kernel/qscriptengine_x11.cpp index 97ae6828b..6c1190fb3 100644 --- a/src/kernel/qscriptengine_x11.cpp +++ b/src/kernel/qscriptengine_x11.cpp @@ -1899,7 +1899,7 @@ static void indic_attributes(int script, const TQString &text, int from, int len // // -------------------------------------------------------------------------------------------------------------------------------------------- -#include +#include #include diff --git a/src/kernel/qt_kernel.pri b/src/kernel/qt_kernel.pri index cf370058b..5f20c7111 100644 --- a/src/kernel/qt_kernel.pri +++ b/src/kernel/qt_kernel.pri @@ -94,9 +94,9 @@ kernel { $$KERNEL_H/ntqgplugin.h \ $$KERNEL_H/ntqsimplerichtext.h \ $$KERNEL_CPP/qscriptengine_p.h \ - $$KERNEL_CPP/qtextengine_p.h \ + $$KERNEL_CPP/tqtextengine_p.h \ $$KERNEL_CPP/qfontengine_p.h \ - $$KERNEL_CPP/qtextlayout_p.h + $$KERNEL_CPP/tqtextlayout_p.h inputmethod { unix:x11 { @@ -264,8 +264,8 @@ kernel { $$KERNEL_CPP/qgplugin.cpp \ $$KERNEL_CPP/qsimplerichtext.cpp \ $$KERNEL_CPP/qscriptengine.cpp \ - $$KERNEL_CPP/qtextlayout.cpp \ - $$KERNEL_CPP/qtextengine.cpp + $$KERNEL_CPP/tqtextlayout.cpp \ + $$KERNEL_CPP/tqtextengine.cpp unix:HEADERS += $$KERNEL_P/qpsprinter_p.h \ $$KERNEL_H/ntqfontdatabase.h diff --git a/src/kernel/qtextengine.cpp b/src/kernel/qtextengine.cpp deleted file mode 100644 index e1a806f52..000000000 --- a/src/kernel/qtextengine.cpp +++ /dev/null @@ -1,1180 +0,0 @@ -/**************************************************************************** -** -** Text engine classes -** -** Copyright (C) 2005-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 "qtextengine_p.h" - -#include "qscriptengine_p.h" -#include -#include "qfontdata_p.h" -#include "qfontengine_p.h" -#include -#include -#include - -// ----------------------------------------------------------------------------------------------------- -// -// The BiDi algorithm -// -// ----------------------------------------------------------------------------------------------------- - - -#define BIDI_DEBUG 0//2 -#if (BIDI_DEBUG >= 1) -#include -using namespace std; - -static const char *directions[] = { - "DirL", "DirR", "DirEN", "DirES", "DirET", "DirAN", "DirCS", "DirB", "DirS", "DirWS", "DirON", - "DirLRE", "DirLRO", "DirAL", "DirRLE", "DirRLO", "DirPDF", "DirNSM", "DirBN" -}; - -#endif - -struct BidiStatus { - BidiStatus() { - eor = TQChar::DirON; - lastStrong = TQChar::DirON; - last = TQChar:: DirON; - dir = TQChar::DirON; - } - TQChar::Direction eor; - TQChar::Direction lastStrong; - TQChar::Direction last; - TQChar::Direction dir; -}; - -struct BidiControl { - struct Context { - unsigned char level : 6; - unsigned char override : 1; - unsigned char unused : 1; - }; - - inline BidiControl( bool rtl ) - : cCtx( 0 ), singleLine( FALSE ) { - ctx[0].level = (rtl ? 1 : 0); - ctx[0].override = FALSE; - } - - inline void embed( int level, bool override = FALSE ) { - if ( ctx[cCtx].level < 61 && cCtx < 61 ) { - (void) ++cCtx; - ctx[cCtx].level = level; - ctx[cCtx].override = override; - } - } - inline void pdf() { - if ( cCtx ) (void) --cCtx; - } - - inline uchar level() const { - return ctx[cCtx].level; - } - inline bool override() const { - return ctx[cCtx].override; - } - inline TQChar::Direction basicDirection() { - return (ctx[0].level ? TQChar::DirR : TQChar:: DirL ); - } - inline uchar baseLevel() { - return ctx[0].level; - } - inline TQChar::Direction direction() { - return ((ctx[cCtx].level%2) ? TQChar::DirR : TQChar:: DirL ); - } - - Context ctx[63]; - unsigned int cCtx : 8; - bool singleLine : 8; -}; - -static TQChar::Direction basicDirection( const TQString &str ) -{ - int len = str.length(); - int pos = 0; - const TQChar *uc = str.unicode() + pos; - while( pos < len ) { - switch( direction( *uc ) ) - { - case TQChar::DirL: - case TQChar::DirLRO: - case TQChar::DirLRE: - return TQChar::DirL; - case TQChar::DirR: - case TQChar::DirAL: - case TQChar::DirRLO: - case TQChar::DirRLE: - return TQChar::DirR; - default: - break; - } - ++pos; - ++uc; - } - return TQChar::DirL; -} - - -static void tqAppendItems(TQTextEngine *engine, int &start, int &stop, BidiControl &control, TQChar::Direction dir ) -{ - TQScriptItemArray &items = engine->items; - const TQChar *text = engine->string.unicode(); - - if ( start > stop ) { - // #### the algorithm is currently not really safe against this. Still needs fixing. -// tqWarning( "Bidi: appendItems() internal error" ); - return; - } - - int level = control.level(); - - if(dir != TQChar::DirON && !control.override()) { - // add level of run (cases I1 & I2) - if( level % 2 ) { - if(dir == TQChar::DirL || dir == TQChar::DirAN || dir == TQChar::DirEN ) - level++; - } else { - if( dir == TQChar::DirR ) - level++; - else if( dir == TQChar::DirAN || dir == TQChar::DirEN ) - level += 2; - } - } - -#if (BIDI_DEBUG >= 1) - tqDebug("new run: dir=%s from %d, to %d level = %d\n", directions[dir], start, stop, level); -#endif - TQFont::Script script = TQFont::NoScript; - TQScriptItem item; - item.position = start; - item.analysis.script = script; - item.analysis.bidiLevel = level; - item.analysis.override = control.override(); - item.analysis.reserved = 0; - - if ( control.singleLine ) { - for ( int i = start; i <= stop; i++ ) { - - unsigned short uc = text[i].unicode(); - TQFont::Script s = (TQFont::Script)scriptForChar( uc ); - if (s == TQFont::UnknownScript || s == TQFont::CombiningMarks) - s = script; - - if (s != script) { - item.analysis.script = s; - item.analysis.bidiLevel = level; - item.position = i; - items.append( item ); - script = s; - } - } - } else { - for ( int i = start; i <= stop; i++ ) { - - unsigned short uc = text[i].unicode(); - TQFont::Script s = (TQFont::Script)scriptForChar( uc ); - if (s == TQFont::UnknownScript || s == TQFont::CombiningMarks) - s = script; - - TQChar::Category category = ::category( uc ); - if ( uc == 0xfffcU || uc == 0x2028U ) { - item.analysis.bidiLevel = level % 2 ? level-1 : level; - item.analysis.script = TQFont::Latin; - item.isObject = TRUE; - s = TQFont::NoScript; - } else if ((uc >= 9 && uc <=13) || - (category >= TQChar::Separator_Space && category <= TQChar::Separator_Paragraph)) { - item.analysis.script = TQFont::Latin; - item.isSpace = TRUE; - item.isTab = ( uc == '\t' ); - item.analysis.bidiLevel = item.isTab ? control.baseLevel() : level; - s = TQFont::NoScript; - } else if ( s != script && (category != TQChar::Mark_NonSpacing || script == TQFont::NoScript)) { - item.analysis.script = s; - item.analysis.bidiLevel = level; - } else { - if (i - start < 32000) - continue; - start = i; - } - - item.position = i; - items.append( item ); - script = s; - item.isSpace = item.isTab = item.isObject = FALSE; - } - } - ++stop; - start = stop; -} - -typedef void (* fAppendItems)(TQTextEngine *, int &start, int &stop, BidiControl &control, TQChar::Direction dir); -static fAppendItems appendItems = tqAppendItems; - -// creates the next TQScript items. -static void bidiItemize( TQTextEngine *engine, bool rightToLeft, int mode ) -{ - BidiControl control( rightToLeft ); - if ( mode & TQTextEngine::SingleLine ) - control.singleLine = TRUE; - - int sor = 0; - int eor = -1; - - // ### should get rid of this! - bool first = TRUE; - - int length = engine->string.length(); - - if ( !length ) - return; - - const TQChar *unicode = engine->string.unicode(); - int current = 0; - - TQChar::Direction dir = rightToLeft ? TQChar::DirR : TQChar::DirL; - BidiStatus status; - TQChar::Direction sdir = direction( *unicode ); - if ( sdir != TQChar::DirL && sdir != TQChar::DirR && sdir != TQChar::DirAL && sdir != TQChar::DirEN && sdir != TQChar::DirAN ) - sdir = TQChar::DirON; - else - dir = TQChar::DirON; - status.eor = sdir; - status.lastStrong = rightToLeft ? TQChar::DirR : TQChar::DirL; - status.last = status.lastStrong; - status.dir = sdir; -#if (BIDI_DEBUG >= 2) - tqDebug("---- bidiReorder --- '%s'", engine->string.utf8().data()); - tqDebug("rightToLeft = %d", rightToLeft); -#endif - - - while ( current <= length ) { - - TQChar::Direction dirCurrent; - if ( current == (int)length ) - dirCurrent = control.basicDirection(); - else - dirCurrent = direction( unicode[current] ); - -#if (BIDI_DEBUG >= 2) - cout << "pos=" << current << " dir=" << directions[dir] - << " current=" << directions[dirCurrent] << " last=" << directions[status.last] - << " eor=" << eor << "/" << directions[status.eor] - << " sor=" << sor << " lastStrong=" - << directions[status.lastStrong] - << " level=" << (int)control.level() << endl; -#endif - - switch(dirCurrent) { - - // embedding and overrides (X1-X9 in the BiDi specs) - case TQChar::DirRLE: - case TQChar::DirRLO: - case TQChar::DirLRE: - case TQChar::DirLRO: - { - bool rtl = (dirCurrent == TQChar::DirRLE || dirCurrent == TQChar::DirRLO ); - bool override = (dirCurrent == TQChar::DirLRO || dirCurrent == TQChar::DirRLO ); - - uchar level = control.level(); - if( (level%2 != 0) == rtl ) - level += 2; - else - level++; - if(level < 61) { - eor = current-1; - appendItems(engine, sor, eor, control, dir); - eor = current; - control.embed( level, override ); - TQChar::Direction edir = (rtl ? TQChar::DirR : TQChar::DirL ); - dir = status.eor = edir; - status.lastStrong = edir; - } - break; - } - case TQChar::DirPDF: - { - if (dir != control.direction()) { - eor = current-1; - appendItems(engine, sor, eor, control, dir); - dir = control.direction(); - } - eor = current; - appendItems(engine, sor, eor, control, dir); - dir = TQChar::DirON; status.eor = TQChar::DirON; - status.last = control.direction(); - control.pdf(); - if ( control.override() ) - dir = control.direction(); - else - dir = TQChar::DirON; - status.lastStrong = control.direction(); - break; - } - - // strong types - case TQChar::DirL: - if(dir == TQChar::DirON) - dir = TQChar::DirL; - switch(status.last) - { - case TQChar::DirL: - eor = current; status.eor = TQChar::DirL; break; - case TQChar::DirR: - case TQChar::DirAL: - case TQChar::DirEN: - case TQChar::DirAN: - if ( !first ) { - appendItems(engine, sor, eor, control, dir); - dir = eor < length ? direction( unicode[eor] ) : control.basicDirection(); - status.eor = dir; - } else { - eor = current; status.eor = dir; - } - break; - case TQChar::DirES: - case TQChar::DirET: - case TQChar::DirCS: - case TQChar::DirBN: - case TQChar::DirB: - case TQChar::DirS: - case TQChar::DirWS: - case TQChar::DirON: - if(dir != TQChar::DirL) { - //last stuff takes embedding dir - if( control.direction() == TQChar::DirR ) { - if(status.eor != TQChar::DirR) { - // AN or EN - appendItems(engine, sor, eor, control, dir); - status.eor = TQChar::DirON; - dir = TQChar::DirR; - } - eor = current - 1; - appendItems(engine, sor, eor, control, dir); - dir = eor < length ? direction( unicode[eor] ) : control.basicDirection(); - status.eor = dir; - } else { - if(status.eor != TQChar::DirL) { - appendItems(engine, sor, eor, control, dir); - status.eor = TQChar::DirON; - dir = TQChar::DirL; - } else { - eor = current; status.eor = TQChar::DirL; break; - } - } - } else { - eor = current; status.eor = TQChar::DirL; - } - default: - break; - } - status.lastStrong = TQChar::DirL; - break; - case TQChar::DirAL: - case TQChar::DirR: - if(dir == TQChar::DirON) dir = TQChar::DirR; - switch(status.last) - { - case TQChar::DirL: - case TQChar::DirEN: - case TQChar::DirAN: - if ( !first ) { - appendItems(engine, sor, eor, control, dir); - dir = TQChar::DirON; status.eor = TQChar::DirON; - break; - } - case TQChar::DirR: - case TQChar::DirAL: - eor = current; status.eor = TQChar::DirR; break; - case TQChar::DirES: - case TQChar::DirET: - case TQChar::DirCS: - case TQChar::DirBN: - case TQChar::DirB: - case TQChar::DirS: - case TQChar::DirWS: - case TQChar::DirON: - if( status.eor != TQChar::DirR && status.eor != TQChar::DirAL ) { - //last stuff takes embedding dir - if(control.direction() == TQChar::DirR - || status.lastStrong == TQChar::DirR || status.lastStrong == TQChar::DirAL) { - appendItems(engine, sor, eor, control, dir); - dir = TQChar::DirON; status.eor = TQChar::DirON; - dir = TQChar::DirR; - eor = current; - } else { - eor = current - 1; - appendItems(engine, sor, eor, control, dir); - dir = TQChar::DirON; status.eor = TQChar::DirON; - dir = TQChar::DirR; - } - } else { - eor = current; status.eor = TQChar::DirR; - } - default: - break; - } - status.lastStrong = dirCurrent; - break; - - // weak types: - - case TQChar::DirNSM: - if (eor == current-1) - eor = current; - break; - case TQChar::DirEN: - // if last strong was AL change EN to AN - if(status.lastStrong != TQChar::DirAL) { - if(dir == TQChar::DirON) { - if(status.lastStrong == TQChar::DirL) - dir = TQChar::DirL; - else - dir = TQChar::DirEN; - } - switch(status.last) - { - case TQChar::DirET: - if ( status.lastStrong == TQChar::DirR || status.lastStrong == TQChar::DirAL ) { - appendItems(engine, sor, eor, control, dir); - status.eor = TQChar::DirON; - dir = TQChar::DirAN; - } - // fall through - case TQChar::DirEN: - case TQChar::DirL: - eor = current; - status.eor = dirCurrent; - break; - case TQChar::DirR: - case TQChar::DirAL: - case TQChar::DirAN: - if ( !first ) - appendItems(engine, sor, eor, control, dir); - status.eor = TQChar::DirEN; - dir = TQChar::DirAN; break; - case TQChar::DirES: - case TQChar::DirCS: - if(status.eor == TQChar::DirEN || dir == TQChar::DirAN) { - eor = current; break; - } - case TQChar::DirBN: - case TQChar::DirB: - case TQChar::DirS: - case TQChar::DirWS: - case TQChar::DirON: - if(status.eor == TQChar::DirR) { - // neutrals go to R - eor = current - 1; - appendItems(engine, sor, eor, control, dir); - dir = TQChar::DirON; status.eor = TQChar::DirEN; - dir = TQChar::DirAN; - } - else if( status.eor == TQChar::DirL || - (status.eor == TQChar::DirEN && status.lastStrong == TQChar::DirL)) { - eor = current; status.eor = dirCurrent; - } else { - // numbers on both sides, neutrals get right to left direction - if(dir != TQChar::DirL) { - appendItems(engine, sor, eor, control, dir); - dir = TQChar::DirON; status.eor = TQChar::DirON; - eor = current - 1; - dir = TQChar::DirR; - appendItems(engine, sor, eor, control, dir); - dir = TQChar::DirON; status.eor = TQChar::DirON; - dir = TQChar::DirAN; - } else { - eor = current; status.eor = dirCurrent; - } - } - default: - break; - } - break; - } - case TQChar::DirAN: - dirCurrent = TQChar::DirAN; - if(dir == TQChar::DirON) dir = TQChar::DirAN; - switch(status.last) - { - case TQChar::DirL: - case TQChar::DirAN: - eor = current; status.eor = TQChar::DirAN; break; - case TQChar::DirR: - case TQChar::DirAL: - case TQChar::DirEN: - if ( !first ) - appendItems(engine, sor, eor, control, dir); - dir = TQChar::DirON; status.eor = TQChar::DirAN; - break; - case TQChar::DirCS: - if(status.eor == TQChar::DirAN) { - eor = current; break; - } - case TQChar::DirES: - case TQChar::DirET: - case TQChar::DirBN: - case TQChar::DirB: - case TQChar::DirS: - case TQChar::DirWS: - case TQChar::DirON: - if(status.eor == TQChar::DirR) { - // neutrals go to R - eor = current - 1; - appendItems(engine, sor, eor, control, dir); - status.eor = TQChar::DirAN; - dir = TQChar::DirAN; - } else if( status.eor == TQChar::DirL || - (status.eor == TQChar::DirEN && status.lastStrong == TQChar::DirL)) { - eor = current; status.eor = dirCurrent; - } else { - // numbers on both sides, neutrals get right to left direction - if(dir != TQChar::DirL) { - appendItems(engine, sor, eor, control, dir); - status.eor = TQChar::DirON; - eor = current - 1; - dir = TQChar::DirR; - appendItems(engine, sor, eor, control, dir); - status.eor = TQChar::DirAN; - dir = TQChar::DirAN; - } else { - eor = current; status.eor = dirCurrent; - } - } - default: - break; - } - break; - case TQChar::DirES: - case TQChar::DirCS: - break; - case TQChar::DirET: - if(status.last == TQChar::DirEN) { - dirCurrent = TQChar::DirEN; - eor = current; status.eor = dirCurrent; - } - break; - - // boundary neutrals should be ignored - case TQChar::DirBN: - break; - // neutrals - case TQChar::DirB: - // ### what do we do with newline and paragraph separators that come to here? - break; - case TQChar::DirS: - // ### implement rule L1 - break; - case TQChar::DirWS: - case TQChar::DirON: - break; - default: - break; - } - - //cout << " after: dir=" << // dir << " current=" << dirCurrent << " last=" << status.last << " eor=" << status.eor << " lastStrong=" << status.lastStrong << " embedding=" << control.direction() << endl; - - if(current >= (int)length) break; - - // set status.last as needed. - switch(dirCurrent) { - case TQChar::DirET: - case TQChar::DirES: - case TQChar::DirCS: - case TQChar::DirS: - case TQChar::DirWS: - case TQChar::DirON: - switch(status.last) - { - case TQChar::DirL: - case TQChar::DirR: - case TQChar::DirAL: - case TQChar::DirEN: - case TQChar::DirAN: - status.last = dirCurrent; - break; - default: - status.last = TQChar::DirON; - } - break; - case TQChar::DirNSM: - case TQChar::DirBN: - // ignore these - break; - case TQChar::DirLRO: - case TQChar::DirLRE: - status.last = TQChar::DirL; - break; - case TQChar::DirRLO: - case TQChar::DirRLE: - status.last = TQChar::DirR; - break; - case TQChar::DirEN: - if ( status.last == TQChar::DirL ) { - status.last = TQChar::DirL; - break; - } - // fall through - default: - status.last = dirCurrent; - } - - first = FALSE; - ++current; - } - -#if (BIDI_DEBUG >= 1) - cout << "reached end of line current=" << current << ", eor=" << eor << endl; -#endif - eor = current - 1; // remove dummy char - - if ( sor <= eor ) - appendItems(engine, sor, eor, control, dir); - - -} - -void TQTextEngine::bidiReorder( int numItems, const TQ_UINT8 *levels, int *visualOrder ) -{ - - // first find highest and lowest levels - uchar levelLow = 128; - uchar levelHigh = 0; - int i = 0; - while ( i < numItems ) { - //printf("level = %d\n", r->level); - if ( levels[i] > levelHigh ) - levelHigh = levels[i]; - if ( levels[i] < levelLow ) - levelLow = levels[i]; - i++; - } - - // implements reordering of the line (L2 according to BiDi spec): - // L2. From the highest level found in the text to the lowest odd level on each line, - // reverse any contiguous sequence of characters that are at that level or higher. - - // reversing is only done up to the lowest odd level - if(!(levelLow%2)) levelLow++; - -#if (BIDI_DEBUG >= 1) - cout << "reorderLine: lineLow = " << (uint)levelLow << ", lineHigh = " << (uint)levelHigh << endl; -#endif - - int count = numItems - 1; - for ( i = 0; i < numItems; i++ ) - visualOrder[i] = i; - - while(levelHigh >= levelLow) { - int i = 0; - while ( i < count ) { - while(i < count && levels[i] < levelHigh) i++; - int start = i; - while(i <= count && levels[i] >= levelHigh) i++; - int end = i-1; - - if(start != end) { - //cout << "reversing from " << start << " to " << end << endl; - for(int j = 0; j < (end-start+1)/2; j++) { - int tmp = visualOrder[start+j]; - visualOrder[start+j] = visualOrder[end-j]; - visualOrder[end-j] = tmp; - } - } - i++; - } - levelHigh--; - } - -#if (BIDI_DEBUG >= 1) - cout << "visual order is:" << endl; - for ( i = 0; i < numItems; i++ ) - cout << visualOrder[i] << endl; -#endif -} - - -// ----------------------------------------------------------------------------------------------------- -// -// The line break algorithm. See http://www.unicode.org/reports/tr14/tr14-13.html -// -// ----------------------------------------------------------------------------------------------------- - -/* The Unicode algorithm does in our opinion allow line breaks at some - places they shouldn't be allowed. The following changes were thus - made in comparison to the Unicode reference: - - CL->AL from Dbk to Ibk - CL->PR from Dbk to Ibk - EX->AL from Dbk to Ibk - IS->AL from Dbk to Ibk - PO->AL from Dbk to Ibk - SY->AL from Dbk to Ibk - SY->PO from Dbk to Ibk - SY->PR from Dbk to Ibk - SY->OP from Dbk to Ibk - Al->OP from Dbk to Ibk - AL->HY from Dbk to Ibk - AL->PR from Dbk to Ibk - AL->PO from Dbk to Ibk - PR->PR from Dbk to Ibk - PO->PO from Dbk to Ibk - PR->PO from Dbk to Ibk - PO->PR from Dbk to Ibk - HY->PO from Dbk to Ibk - HY->PR from Dbk to Ibk - HY->OP from Dbk to Ibk - PO->OP from Dbk to Ibk - NU->EX from Dbk to Ibk - NU->PR from Dbk to Ibk - PO->NU from Dbk to Ibk - EX->PO from Dbk to Ibk -*/ - -enum break_action { - Dbk, // Direct break - Ibk, // Indirect break; only allowed if space between the two chars - Pbk // Prohibited break; no break allowed even if space between chars -}; - -// The following line break classes are not treated by the table: -// SA, BK, CR, LF, SG, CB, SP -static const TQ_UINT8 breakTable[TQUnicodeTables::LineBreak_CM+1][TQUnicodeTables::LineBreak_CM+1] = -{ - // OP, CL, QU, GL, NS, EX, SY, IS, PR, PO, NU, AL, ID, IN, HY, BA, BB, B2, ZW, CM - { Pbk, Pbk, Pbk, Pbk, Pbk, Pbk, Pbk, Pbk, Pbk, Pbk, Pbk, Pbk, Pbk, Pbk, Pbk, Pbk, Pbk, Pbk, Pbk, Pbk }, // OP - { Dbk, Pbk, Ibk, Pbk, Pbk, Pbk, Pbk, Pbk, Ibk, Ibk, Dbk, Ibk, Dbk, Dbk, Ibk, Ibk, Pbk, Pbk, Pbk, Pbk }, // CL - { Pbk, Pbk, Ibk, Pbk, Ibk, Pbk, Pbk, Pbk, Ibk, Ibk, Ibk, Ibk, Ibk, Ibk, Ibk, Ibk, Ibk, Ibk, Pbk, Pbk }, // QU - { Ibk, Pbk, Ibk, Pbk, Ibk, Pbk, Pbk, Pbk, Ibk, Ibk, Ibk, Ibk, Ibk, Ibk, Ibk, Ibk, Ibk, Ibk, Pbk, Pbk }, // GL - { Dbk, Pbk, Ibk, Pbk, Ibk, Pbk, Pbk, Pbk, Dbk, Dbk, Dbk, Dbk, Dbk, Dbk, Ibk, Ibk, Dbk, Dbk, Pbk, Ibk }, // NS - { Dbk, Pbk, Ibk, Pbk, Ibk, Pbk, Pbk, Pbk, Dbk, Ibk, Ibk, Ibk, Dbk, Dbk, Ibk, Ibk, Dbk, Dbk, Pbk, Ibk }, // EX - { Ibk, Pbk, Ibk, Pbk, Ibk, Pbk, Pbk, Pbk, Ibk, Ibk, Ibk, Ibk, Dbk, Dbk, Ibk, Ibk, Dbk, Dbk, Pbk, Ibk }, // SY - { Dbk, Pbk, Ibk, Pbk, Ibk, Pbk, Pbk, Pbk, Dbk, Dbk, Ibk, Ibk, Dbk, Dbk, Ibk, Ibk, Dbk, Dbk, Pbk, Ibk }, // IS - { Ibk, Pbk, Ibk, Pbk, Ibk, Pbk, Pbk, Pbk, Ibk, Ibk, Ibk, Ibk, Ibk, Dbk, Ibk, Ibk, Dbk, Dbk, Pbk, Pbk }, // PR - { Ibk, Pbk, Ibk, Pbk, Ibk, Pbk, Pbk, Pbk, Ibk, Ibk, Ibk, Ibk, Dbk, Dbk, Ibk, Ibk, Dbk, Dbk, Pbk, Ibk }, // PO - { Dbk, Pbk, Ibk, Pbk, Ibk, Pbk, Pbk, Pbk, Ibk, Ibk, Ibk, Ibk, Dbk, Ibk, Ibk, Ibk, Dbk, Dbk, Pbk, Pbk }, // NU - { Ibk, Pbk, Ibk, Pbk, Ibk, Pbk, Pbk, Pbk, Ibk, Ibk, Ibk, Ibk, Dbk, Ibk, Ibk, Ibk, Dbk, Dbk, Pbk, Pbk }, // AL - { Dbk, Pbk, Ibk, Pbk, Ibk, Pbk, Pbk, Pbk, Dbk, Ibk, Dbk, Dbk, Dbk, Ibk, Ibk, Ibk, Dbk, Dbk, Pbk, Ibk }, // ID - { Dbk, Pbk, Ibk, Pbk, Ibk, Pbk, Pbk, Pbk, Dbk, Dbk, Dbk, Dbk, Dbk, Ibk, Ibk, Ibk, Dbk, Dbk, Pbk, Ibk }, // IN - { Ibk, Pbk, Ibk, Pbk, Ibk, Pbk, Pbk, Pbk, Ibk, Ibk, Ibk, Ibk, Dbk, Dbk, Ibk, Ibk, Dbk, Dbk, Pbk, Ibk }, // HY - { Dbk, Pbk, Ibk, Pbk, Ibk, Pbk, Pbk, Pbk, Dbk, Dbk, Dbk, Dbk, Dbk, Dbk, Ibk, Ibk, Dbk, Dbk, Pbk, Ibk }, // BA - { Ibk, Pbk, Ibk, Pbk, Ibk, Pbk, Pbk, Pbk, Ibk, Ibk, Ibk, Ibk, Ibk, Ibk, Ibk, Ibk, Ibk, Ibk, Pbk, Ibk }, // BB - { Dbk, Pbk, Ibk, Pbk, Ibk, Pbk, Pbk, Pbk, Dbk, Dbk, Dbk, Dbk, Dbk, Dbk, Ibk, Ibk, Dbk, Pbk, Pbk, Ibk }, // B2 - { Dbk, Dbk, Dbk, Dbk, Dbk, Dbk, Dbk, Dbk, Dbk, Dbk, Dbk, Dbk, Dbk, Dbk, Dbk, Dbk, Dbk, Dbk, Pbk, Ibk }, // ZW - { Dbk, Pbk, Ibk, Pbk, Ibk, Pbk, Pbk, Pbk, Dbk, Ibk, Dbk, Dbk, Dbk, Ibk, Ibk, Ibk, Dbk, Dbk, Pbk, Pbk } // CM -}; - -// set the soft break flag at every possible line breaking point. This needs correct clustering information. -static void calcLineBreaks(const TQString &str, TQCharAttributes *charAttributes) -{ - int len = str.length(); - if (!len) - return; - - const TQChar *uc = str.unicode(); - int cls = lineBreakClass(*uc); - if (cls >= TQUnicodeTables::LineBreak_CM) - cls = TQUnicodeTables::LineBreak_ID; - - charAttributes[0].softBreak = FALSE; - charAttributes[0].whiteSpace = (cls == TQUnicodeTables::LineBreak_SP); - charAttributes[0].charStop = TRUE; - - for (int i = 1; i < len; ++i) { - int ncls = ::lineBreakClass(uc[i]); - int category = ::category(uc[i]); - if (category == TQChar::Mark_NonSpacing) - goto nsm; - - if (category == TQChar::Other_Surrogate) { - // char stop only on first pair - if (uc[i].unicode() >= 0xd800 && uc[i].unicode() < 0xdc00 && i < len-1 - && uc[i+1].unicode() >= 0xdc00 && uc[i+1].unicode() < 0xe000) - goto nsm; - // ### correctly handle second surrogate - } - - if (ncls == TQUnicodeTables::LineBreak_SP) { - charAttributes[i].softBreak = FALSE; - charAttributes[i].whiteSpace = TRUE; - charAttributes[i].charStop = TRUE; - cls = ncls; - continue; - } - - - if (cls == TQUnicodeTables::LineBreak_SA && ncls == TQUnicodeTables::LineBreak_SA) { - // two complex chars (thai or lao), thai_attributes might override, but here - // we do a best guess - charAttributes[i].softBreak = TRUE; - charAttributes[i].whiteSpace = FALSE; - charAttributes[i].charStop = TRUE; - cls = ncls; - continue; - } - { - int tcls = ncls; - if (tcls >= TQUnicodeTables::LineBreak_SA) - tcls = TQUnicodeTables::LineBreak_ID; - if (cls >= TQUnicodeTables::LineBreak_SA) - cls = TQUnicodeTables::LineBreak_ID; - - bool softBreak; - int brk = breakTable[cls][tcls]; - if (brk == Ibk) - softBreak = (cls == TQUnicodeTables::LineBreak_SP); - else - softBreak = (brk == Dbk); -// tqDebug("char = %c %04x, cls=%d, ncls=%d, brk=%d soft=%d", uc[i].cell(), uc[i].unicode(), cls, ncls, brk, charAttributes[i].softBreak); - charAttributes[i].softBreak = softBreak; - charAttributes[i].whiteSpace = FALSE; - charAttributes[i].charStop = TRUE; - cls = ncls; - } - continue; - nsm: - charAttributes[i].softBreak = FALSE; - charAttributes[i].whiteSpace = FALSE; - charAttributes[i].charStop = FALSE; - } -} - -#if defined( TQ_WS_X11 ) || defined ( TQ_WS_QWS ) -# include "qtextengine_unix.cpp" -#elif defined( TQ_WS_WIN ) -# include "qtextengine_win.cpp" -#elif defined( TQ_WS_MAC ) -# include "qtextengine_mac.cpp" -#endif - - - -TQTextEngine::TQTextEngine( const TQString &str, TQFontPrivate *f ) - : string( str ), fnt( f ), direction( TQChar::DirON ), haveCharAttributes( FALSE ), widthOnly( FALSE ) -{ -#ifdef TQ_WS_WIN - if ( !resolvedUsp10 ) - resolveUsp10(); -#endif - if ( fnt ) fnt->ref(); - - num_glyphs = TQMAX( 16, str.length()*3/2 ); - int space_charAttributes = (sizeof(TQCharAttributes)*str.length()+sizeof(void*)-1)/sizeof(void*); - int space_logClusters = (sizeof(unsigned short)*str.length()+sizeof(void*)-1)/sizeof(void*); - int space_glyphs = (sizeof(glyph_t)*num_glyphs+sizeof(void*)-1)/sizeof(void*); - int space_advances = (sizeof(advance_t)*num_glyphs+sizeof(void*)-1)/sizeof(void*); - int space_offsets = (sizeof(qoffset_t)*num_glyphs+sizeof(void*)-1)/sizeof(void*); - int space_glyphAttributes = (sizeof(GlyphAttributes)*num_glyphs+sizeof(void*)-1)/sizeof(void*); - - allocated = space_charAttributes + space_glyphs + space_advances + - space_offsets + space_logClusters + space_glyphAttributes; - memory = (void **)::malloc( allocated*sizeof( void * ) ); - memset( memory, 0, allocated*sizeof( void * ) ); - - void **m = memory; - m += space_charAttributes; - logClustersPtr = (unsigned short *) m; - m += space_logClusters; - glyphPtr = (glyph_t *) m; - m += space_glyphs; - advancePtr = (advance_t *) m; - m += space_advances; - offsetsPtr = (qoffset_t *) m; - m += space_offsets; - glyphAttributesPtr = (GlyphAttributes *) m; - - used = 0; -} - -TQTextEngine::~TQTextEngine() -{ - if ( fnt && fnt->deref()) - delete fnt; - free( memory ); - allocated = 0; -} - -void TQTextEngine::reallocate( int totalGlyphs ) -{ - int new_num_glyphs = totalGlyphs; - int space_charAttributes = (sizeof(TQCharAttributes)*string.length()+sizeof(void*)-1)/sizeof(void*); - int space_logClusters = (sizeof(unsigned short)*string.length()+sizeof(void*)-1)/sizeof(void*); - int space_glyphs = (sizeof(glyph_t)*new_num_glyphs+sizeof(void*)-1)/sizeof(void*); - int space_advances = (sizeof(advance_t)*new_num_glyphs+sizeof(void*)-1)/sizeof(void*); - int space_offsets = (sizeof(qoffset_t)*new_num_glyphs+sizeof(void*)-1)/sizeof(void*); - int space_glyphAttributes = (sizeof(GlyphAttributes)*new_num_glyphs+sizeof(void*)-1)/sizeof(void*); - - int newAllocated = space_charAttributes + space_glyphs + space_advances + - space_offsets + space_logClusters + space_glyphAttributes; - void ** newMemory = (void **)::malloc( newAllocated*sizeof( void * ) ); - - void **nm = newMemory; - memcpy( nm, memory, string.length()*sizeof(TQCharAttributes) ); - nm += space_charAttributes; - memcpy( nm, logClustersPtr, num_glyphs*sizeof(unsigned short) ); - logClustersPtr = (unsigned short *) nm; - nm += space_logClusters; - memcpy( nm, glyphPtr, num_glyphs*sizeof(glyph_t) ); - glyphPtr = (glyph_t *) nm; - nm += space_glyphs; - memcpy( nm, advancePtr, num_glyphs*sizeof(advance_t) ); - advancePtr = (advance_t *) nm; - nm += space_advances; - memcpy( nm, offsetsPtr, num_glyphs*sizeof(qoffset_t) ); - offsetsPtr = (qoffset_t *) nm; - nm += space_offsets; - memcpy( nm, glyphAttributesPtr, num_glyphs*sizeof(GlyphAttributes) ); - glyphAttributesPtr = (GlyphAttributes *) nm; - - free( memory ); - memory = newMemory; - allocated = newAllocated; - num_glyphs = new_num_glyphs; -} - -const TQCharAttributes *TQTextEngine::attributes() -{ - TQCharAttributes *charAttributes = (TQCharAttributes *) memory; - if ( haveCharAttributes ) - return charAttributes; - - if ( !items.d ) - itemize(); - - ensureSpace(string.length()); - charAttributes = (TQCharAttributes *) memory; - calcLineBreaks(string, charAttributes); - - for ( int i = 0; i < items.size(); i++ ) { - TQScriptItem &si = items[i]; -#ifdef TQ_WS_WIN - int script = uspScriptForItem(this, i); -#else - int script = si.analysis.script; -#endif - Q_ASSERT( script < TQFont::NScripts ); - AttributeFunction attributes = scriptEngines[script].charAttributes; - if (!attributes) - continue; - int from = si.position; - int len = length( i ); - attributes( script, string, from, len, charAttributes ); - } - - haveCharAttributes = TRUE; - return charAttributes; -} - -void TQTextEngine::splitItem( int item, int pos ) -{ - if ( pos <= 0 ) - return; - - // we have to ensure we get correct shaping for arabic and other - // complex languages so we have to call shape _before_ we split the item. - shape(item); - - if ( items.d->size == items.d->alloc ) - items.resize( items.d->size + 1 ); - - int numMove = items.d->size - item-1; - if ( numMove > 0 ) - memmove( items.d->items + item+2, items.d->items +item+1, numMove*sizeof( TQScriptItem ) ); - items.d->size++; - TQScriptItem &newItem = items.d->items[item+1]; - TQScriptItem &oldItem = items.d->items[item]; - newItem = oldItem; - items.d->items[item+1].position += pos; - if ( newItem.fontEngine ) - newItem.fontEngine->ref(); - - if (oldItem.num_glyphs) { - // already shaped, break glyphs aswell - int breakGlyph = logClusters(&oldItem)[pos]; - - newItem.num_glyphs = oldItem.num_glyphs - breakGlyph; - oldItem.num_glyphs = breakGlyph; - newItem.glyph_data_offset = oldItem.glyph_data_offset + breakGlyph; - - for (int i = 0; i < newItem.num_glyphs; i++) - logClusters(&newItem)[i] -= breakGlyph; - - int w = 0; - const advance_t *a = advances(&oldItem); - for(int j = 0; j < breakGlyph; ++j) - w += *(a++); - - newItem.width = oldItem.width - w; - oldItem.width = w; - } - -// tqDebug("split at position %d itempos=%d", pos, item ); -} - - -int TQTextEngine::width( int from, int len ) const -{ - int w = 0; - -// tqDebug("TQTextEngine::width( from = %d, len = %d ), numItems=%d, strleng=%d", from, len, items.size(), string.length() ); - for ( int i = 0; i < items.size(); i++ ) { - TQScriptItem *si = &items[i]; - int pos = si->position; - int ilen = length( i ); -// tqDebug("item %d: from %d len %d", i, pos, ilen ); - if ( pos >= from + len ) - break; - if ( pos + ilen > from ) { - if ( !si->num_glyphs ) - shape( i ); - - advance_t *advances = this->advances( si ); - unsigned short *logClusters = this->logClusters( si ); - -// fprintf( stderr, " logclusters:" ); -// for ( int k = 0; k < ilen; k++ ) -// fprintf( stderr, " %d", logClusters[k] ); -// fprintf( stderr, "\n" ); - // do the simple thing for now and give the first glyph in a cluster the full width, all other ones 0. - int charFrom = from - pos; - if ( charFrom < 0 ) - charFrom = 0; - int glyphStart = logClusters[charFrom]; - if ( charFrom > 0 && logClusters[charFrom-1] == glyphStart ) - while ( charFrom < ilen && logClusters[charFrom] == glyphStart ) - charFrom++; - if ( charFrom < ilen ) { - glyphStart = logClusters[charFrom]; - int charEnd = from + len - 1 - pos; - if ( charEnd >= ilen ) - charEnd = ilen-1; - int glyphEnd = logClusters[charEnd]; - while ( charEnd < ilen && logClusters[charEnd] == glyphEnd ) - charEnd++; - glyphEnd = (charEnd == ilen) ? si->num_glyphs : logClusters[charEnd]; - -// tqDebug("char: start=%d end=%d / glyph: start = %d, end = %d", charFrom, charEnd, glyphStart, glyphEnd ); - for ( int i = glyphStart; i < glyphEnd; i++ ) - w += advances[i]; - } - } - } -// tqDebug(" --> w= %d ", w ); - return w; -} - -void TQTextEngine::itemize( int mode ) -{ - if ( !items.d ) { - int size = 8; - items.d = (TQScriptItemArrayPrivate *)malloc( sizeof( TQScriptItemArrayPrivate ) + - sizeof( TQScriptItem ) * size ); - items.d->alloc = size; - } - items.d->size = 0; - if ( string.length() == 0 ) - return; - - if ( !(mode & NoBidi) ) { - if ( direction == TQChar::DirON ) - direction = basicDirection( string ); - bidiItemize( this, direction == TQChar::DirR, mode ); - } else { - BidiControl control( FALSE ); - if ( mode & TQTextEngine::SingleLine ) - control.singleLine = TRUE; - int start = 0; - int stop = string.length() - 1; - appendItems(this, start, stop, control, TQChar::DirL); - } - if ( (mode & WidthOnly) == WidthOnly ) - widthOnly = TRUE; -} - -glyph_metrics_t TQTextEngine::boundingBox( int from, int len ) const -{ - glyph_metrics_t gm; - - for ( int i = 0; i < items.size(); i++ ) { - TQScriptItem *si = &items[i]; - int pos = si->position; - int ilen = length( i ); - if ( pos > from + len ) - break; - if ( pos + len > from ) { - if ( !si->num_glyphs ) - shape( i ); - advance_t *advances = this->advances( si ); - unsigned short *logClusters = this->logClusters( si ); - glyph_t *glyphs = this->glyphs( si ); - qoffset_t *offsets = this->offsets( si ); - - // do the simple thing for now and give the first glyph in a cluster the full width, all other ones 0. - int charFrom = from - pos; - if ( charFrom < 0 ) - charFrom = 0; - int glyphStart = logClusters[charFrom]; - if ( charFrom > 0 && logClusters[charFrom-1] == glyphStart ) - while ( charFrom < ilen && logClusters[charFrom] == glyphStart ) - charFrom++; - if ( charFrom < ilen ) { - glyphStart = logClusters[charFrom]; - int charEnd = from + len - 1 - pos; - if ( charEnd >= ilen ) - charEnd = ilen-1; - int glyphEnd = logClusters[charEnd]; - while ( charEnd < ilen && logClusters[charEnd] == glyphEnd ) - charEnd++; - glyphEnd = (charEnd == ilen) ? si->num_glyphs : logClusters[charEnd]; - if ( glyphStart <= glyphEnd ) { - TQFontEngine *fe = si->fontEngine; - glyph_metrics_t m = fe->boundingBox( glyphs+glyphStart, advances+glyphStart, - offsets+glyphStart, glyphEnd-glyphStart ); - gm.x = TQMIN( gm.x, m.x + gm.xoff ); - gm.y = TQMIN( gm.y, m.y + gm.yoff ); - gm.width = TQMAX( gm.width, m.width+gm.xoff ); - gm.height = TQMAX( gm.height, m.height+gm.yoff ); - gm.xoff += m.xoff; - gm.yoff += m.yoff; - } - } - } - } - return gm; -} diff --git a/src/kernel/qtextengine_p.h b/src/kernel/qtextengine_p.h deleted file mode 100644 index 774302a07..000000000 --- a/src/kernel/qtextengine_p.h +++ /dev/null @@ -1,377 +0,0 @@ -/**************************************************************************** -** -** ??? -** -** 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. -** -** 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 TQTEXTENGINE_P_H -#define TQTEXTENGINE_P_H - -#ifndef QT_H -#include "ntqglobal.h" -#include "tqstring.h" -#include "ntqnamespace.h" -#include -#endif // QT_H - -#include -#ifndef Q_OS_TEMP -#include -#endif // Q_OS_TEMP - -class TQFontPrivate; -class TQString; - -class TQOpenType; -class TQPainter; - -// this uses the same coordinate system as TQt, but a different one to freetype and Xft. -// * y is usually negative, and is equal to the ascent. -// * negative yoff means the following stuff is drawn higher up. -// the characters bounding rect is given by TQRect( x,y,width,height), it's advance by -// xoo and yoff -struct glyph_metrics_t -{ - inline glyph_metrics_t() { - x = 100000; - y = 100000; - width = 0; - height = 0; - xoff = 0; - yoff = 0; - } - inline glyph_metrics_t( int _x, int _y, int _width, int _height, int _xoff, int _yoff ) { - x = _x; - y = _y; - width = _width; - height = _height; - xoff = _xoff; - yoff = _yoff; - } - int x; - int y; - int width; - int height; - int xoff; - int yoff; -}; - -#if defined( TQ_WS_X11 ) || defined ( TQ_WS_QWS ) -typedef unsigned short glyph_t; - -struct qoffset_t { - short x; - short y; -}; - -typedef int advance_t; - -struct TQScriptAnalysis -{ - unsigned short script : 7; - unsigned short bidiLevel : 6; // Unicode Bidi algorithm embedding level (0-61) - unsigned short override : 1; // Set when in LRO/RLO embedding - unsigned short reserved : 2; - bool operator == ( const TQScriptAnalysis &other ) { - return - script == other.script && - bidiLevel == other.bidiLevel; - // ### -// && override == other.override; - } - -}; - -#elif defined( TQ_WS_MAC ) - -typedef unsigned short glyph_t; - -struct qoffset_t { - short x; - short y; -}; - -typedef int advance_t; - -struct TQScriptAnalysis -{ - unsigned short script : 7; - unsigned short bidiLevel : 6; // Unicode Bidi algorithm embedding level (0-61) - unsigned short override : 1; // Set when in LRO/RLO embedding - unsigned short reserved : 2; - bool operator == ( const TQScriptAnalysis &other ) { - return - script == other.script && - bidiLevel == other.bidiLevel; - // ### -// && override == other.override; - } - -}; - -#elif defined( TQ_WS_WIN ) - -// do not change the definitions below unless you know what you are doing! -// it is designed to be compatible with the types found in uniscribe. - -typedef unsigned short glyph_t; - -struct qoffset_t { - int x; - int y; -}; - -typedef int advance_t; - -struct TQScriptAnalysis { - unsigned short script :10; - unsigned short rtl :1; - unsigned short layoutRTL :1; - unsigned short linkBefore :1; - unsigned short linkAfter :1; - unsigned short logicalOrder :1; - unsigned short noGlyphIndex :1; - unsigned short bidiLevel :5; - unsigned short override :1; - unsigned short inhibitSymSwap :1; - unsigned short charShape :1; - unsigned short digitSubstitute :1; - unsigned short inhibitLigate :1; - unsigned short fDisplayZWG :1; - unsigned short arabicNumContext :1; - unsigned short gcpClusters :1; - unsigned short reserved :1; - unsigned short engineReserved :2; -}; - -inline bool operator == ( const TQScriptAnalysis &sa1, const TQScriptAnalysis &sa2 ) -{ - return - sa1.script == sa2.script && - sa1.bidiLevel == sa2.bidiLevel; - // ### -// && override == other.override; -} - -#endif - -// enum and struct are made to be compatible with Uniscribe, dont change unless you know what you're doing. -struct GlyphAttributes { - // highest value means highest priority for justification. Justification is done by first inserting kashidas - // starting with the highest priority positions, then stretching spaces, afterwards extending inter char - // spacing, and last spacing between arabic words. - // NoJustification is for example set for arabic where no Kashida can be inserted or for diacritics. - enum Justification { - NoJustification= 0, // Justification can't be applied after this glyph - Arabic_Space = 1, // This glyph represents a space inside arabic text - Character = 2, // Inter-character justification point follows this glyph - Space = 4, // This glyph represents a blank outside an Arabic run - Arabic_Normal = 7, // Normal Middle-Of-Word glyph that connects to the right (begin) - Arabic_Waw = 8, // Next character is final form of Waw/Ain/Qaf/Fa - Arabic_BaRa = 9, // Next two chars are Ba + Ra/Ya/AlefMaksura - Arabic_Alef = 10, // Next character is final form of Alef/Tah/Lam/Kaf/Gaf - Arabic_HaaDal = 11, // Next character is final form of Haa/Dal/Taa Marbutah - Arabic_Seen = 12, // Initial or Medial form Of Seen/Sad - Arabic_Kashida = 13 // Kashida(U+640) in middle of word - }; - unsigned short justification :4; // Justification class - unsigned short clusterStart :1; // First glyph of representation of cluster - unsigned short mark :1; // needs to be positioned around base char - unsigned short zeroWidth :1; // ZWJ, ZWNJ etc, with no width, currently used as "Don't print" for ZWSP - unsigned short reserved :1; - unsigned short combiningClass :8; -}; - -// also this is compatible to uniscribe. Do not change. -struct TQCharAttributes { - uchar softBreak :1; // Potential linebreak point _before_ this character - 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 invalid :1; - uchar reserved :3; -}; - -inline bool qIsZeroWidthChar(ushort uc) -{ - return (uc >= 0x200b && uc <= 0x200f /* ZW Space, ZWNJ, ZWJ, LRM and RLM */) - || (uc >= 0x2028 && uc <= 0x202f /* LS, PS, LRE, RLE, PDF, LRO, RLO, NNBSP */) - || (uc >= 0x206a && uc <= 0x206f /* ISS, ASS, IAFS, AFS, NADS, NODS */); -} - -class TQFontEngine; - -struct TQScriptItem -{ - inline TQScriptItem() : position( 0 ), isSpace( FALSE ), isTab( FALSE ), - isObject( FALSE ), hasPositioning( FALSE ), - descent( -1 ), ascent( -1 ), width( -1 ), - x( 0 ), y( 0 ), num_glyphs( 0 ), glyph_data_offset( 0 ), - fontEngine( 0 ) { } - int position; - TQScriptAnalysis analysis; - unsigned short isSpace : 1; - unsigned short isTab : 1; - unsigned short isObject : 1; - unsigned short hasPositioning : 1; - unsigned short complex : 1; // Windows only - unsigned short private_use : 1; // Windows only - unsigned short reserved : 10; - short descent; - int ascent; - int width; - int x; - int y; - int num_glyphs; - int glyph_data_offset; - TQFontEngine *fontEngine; -}; - -struct TQScriptItemArrayPrivate -{ - unsigned int alloc; - unsigned int size; - TQScriptItem items[1]; -}; - -class TQScriptItemArray -{ -public: - TQScriptItemArray() : d( 0 ) {} - ~TQScriptItemArray(); - - inline TQScriptItem &operator[] (int i) const {return d->items[i]; } - inline void append( const TQScriptItem &item ) { - if ( d->size == d->alloc ) - resize( d->size + 1 ); - d->items[d->size] = item; - d->size++; - } - inline int size() const { return d ? d->size : 0; } - - void resize( int s ); - void clear(); - - TQScriptItemArrayPrivate *d; -private: -#ifdef TQ_DISABLE_COPY - TQScriptItemArray( const TQScriptItemArray & ); - TQScriptItemArray &operator = ( const TQScriptItemArray & ); -#endif -}; - -class TQFontPrivate; - -class TQ_EXPORT TQTextEngine { -public: - TQTextEngine( const TQString &str, TQFontPrivate *f ); - ~TQTextEngine(); - - enum Mode { - Full = 0x00, - NoBidi = 0x01, - SingleLine = 0x02, - WidthOnly = 0x07 - }; - - void itemize( int mode = Full ); - - static void bidiReorder( int numRuns, const TQ_UINT8 *levels, int *visualOrder ); - - const TQCharAttributes *attributes(); - void shape( int item ) const; - - // ### we need something for justification - - enum Edge { - Leading, - Trailing - }; - enum ShaperFlag { - RightToLeft = 0x0001, - Mirrored = 0x0001 - }; - - int width( int charFrom, int numChars ) const; - glyph_metrics_t boundingBox( int from, int len ) const; - - TQScriptItemArray items; - TQString string; - TQFontPrivate *fnt; - int lineWidth; - int widthUsed; - int firstItemInLine; - int currentItem; - TQChar::Direction direction : 5; - unsigned int haveCharAttributes : 1; - unsigned int widthOnly : 1; - unsigned int reserved : 25; - - int length( int item ) const { - const TQScriptItem &si = items[item]; - int from = si.position; - item++; - return ( item < items.size() ? items[item].position : string.length() ) - from; - } - void splitItem( int item, int pos ); - - unsigned short *logClustersPtr; - glyph_t *glyphPtr; - advance_t *advancePtr; - qoffset_t *offsetsPtr; - GlyphAttributes *glyphAttributesPtr; - - inline unsigned short *logClusters( const TQScriptItem *si ) const - { return logClustersPtr+si->position; } - inline glyph_t *glyphs( const TQScriptItem *si ) const - { return glyphPtr+si->glyph_data_offset; } - inline advance_t *advances( const TQScriptItem *si ) const - { return advancePtr+si->glyph_data_offset; } - inline qoffset_t *offsets( const TQScriptItem *si ) const - { return offsetsPtr+si->glyph_data_offset; } - inline GlyphAttributes *glyphAttributes( const TQScriptItem *si ) const - { return glyphAttributesPtr+si->glyph_data_offset; } - - void reallocate( int totalGlyphs ); - inline void ensureSpace( int nGlyphs ) const { - if ( num_glyphs - used < nGlyphs ) - ((TQTextEngine *)this)->reallocate( ( (used + nGlyphs + 16) >> 4 ) << 4 ); - } - - int allocated; - void **memory; - int num_glyphs; - int used; -}; - -#endif diff --git a/src/kernel/qtextengine_unix.cpp b/src/kernel/qtextengine_unix.cpp deleted file mode 100644 index 0d5e3b920..000000000 --- a/src/kernel/qtextengine_unix.cpp +++ /dev/null @@ -1,127 +0,0 @@ -/**************************************************************************** -** -** Text engine classes -** -** Copyright (C) 2005-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 - - -TQScriptItemArray::~TQScriptItemArray() -{ - clear(); - free( d ); -} - -void TQScriptItemArray::clear() -{ - if ( d ) { - for ( unsigned int i = 0; i < d->size; i++ ) { - TQScriptItem &si = d->items[i]; - if ( si.fontEngine ) - si.fontEngine->deref(); - } - d->size = 0; - } -} - -void TQScriptItemArray::resize( int s ) -{ - int alloc = (s + 8) >> 3 << 3; - d = (TQScriptItemArrayPrivate *)realloc( d, sizeof( TQScriptItemArrayPrivate ) + - sizeof( TQScriptItem ) * alloc ); - d->alloc = alloc; -} - -void TQTextEngine::shape( int item ) const -{ - assert( item < items.size() ); - TQScriptItem &si = items[item]; - - if ( si.num_glyphs ) - return; - - TQFont::Script script = (TQFont::Script)si.analysis.script; - si.glyph_data_offset = used; - - if ( !si.fontEngine ) - si.fontEngine = fnt->engineForScript( script ); - si.fontEngine->ref(); - - si.ascent = si.fontEngine->ascent(); - si.descent = si.fontEngine->descent(); - si.num_glyphs = 0; - - if ( si.fontEngine && si.fontEngine != (TQFontEngine*)-1 ) { - TQShaperItem shaper_item; - shaper_item.script = si.analysis.script; - shaper_item.string = &string; - shaper_item.from = si.position; - shaper_item.length = length(item); - shaper_item.font = si.fontEngine; - shaper_item.num_glyphs = TQMAX(int(num_glyphs - used), shaper_item.length); - shaper_item.flags = si.analysis.bidiLevel % 2 ? RightToLeft : 0; - shaper_item.has_positioning = FALSE; - - while (1) { -// tqDebug(" . num_glyphs=%d, used=%d, item.num_glyphs=%d", num_glyphs, used, shaper_item.num_glyphs); - ensureSpace(shaper_item.num_glyphs); - shaper_item.num_glyphs = num_glyphs - used; -// tqDebug(" .. num_glyphs=%d, used=%d, item.num_glyphs=%d", num_glyphs, used, shaper_item.num_glyphs); - shaper_item.glyphs = glyphs(&si); - shaper_item.advances = advances(&si); - shaper_item.offsets = offsets(&si); - shaper_item.attributes = glyphAttributes(&si); - shaper_item.log_clusters = logClusters(&si); - if (scriptEngines[shaper_item.script].shape(&shaper_item)) - break; - } - - si.num_glyphs = shaper_item.num_glyphs; - si.hasPositioning = shaper_item.has_positioning; - } - ((TQTextEngine *)this)->used += si.num_glyphs; - - si.width = 0; - advance_t *advances = this->advances( &si ); - advance_t *end = advances + si.num_glyphs; - while ( advances < end ) { -// tqDebug("advances[%d] = %d", advances - this->advances(&si), *advances); - si.width += *(advances++); - } - - return; -} - diff --git a/src/kernel/qtextlayout.cpp b/src/kernel/qtextlayout.cpp deleted file mode 100644 index 777e61ad7..000000000 --- a/src/kernel/qtextlayout.cpp +++ /dev/null @@ -1,643 +0,0 @@ -/**************************************************************************** -** -** ??? -** -** Copyright (C) 2005-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 "qtextlayout_p.h" -#include "qtextengine_p.h" - -#include -#include -#include - - -TQRect TQTextItem::rect() const -{ - TQScriptItem& si = engine->items[item]; - return TQRect( si.x, si.y, si.width, si.ascent+si.descent ); -} - -int TQTextItem::x() const -{ - return engine->items[item].x; -} - -int TQTextItem::y() const -{ - return engine->items[item].y; -} - -int TQTextItem::width() const -{ - return engine->items[item].width; -} - -int TQTextItem::ascent() const -{ - return engine->items[item].ascent; -} - -int TQTextItem::descent() const -{ - return engine->items[item].descent; -} - -void TQTextItem::setWidth( int w ) -{ - engine->items[item].width = w; -} - -void TQTextItem::setAscent( int a ) -{ - engine->items[item].ascent = a; -} - -void TQTextItem::setDescent( int d ) -{ - engine->items[item].descent = d; -} - -int TQTextItem::from() const -{ - return engine->items[item].position; -} - -int TQTextItem::length() const -{ - return engine->length(item); -} - - -int TQTextItem::cursorToX( int *cPos, Edge edge ) const -{ - int pos = *cPos; - TQScriptItem *si = &engine->items[item]; - - engine->shape( item ); - advance_t *advances = engine->advances( si ); - GlyphAttributes *glyphAttributes = engine->glyphAttributes( si ); - unsigned short *logClusters = engine->logClusters( si ); - - int l = engine->length( item ); - if ( pos > l ) - pos = l; - if ( pos < 0 ) - pos = 0; - - int glyph_pos = pos == l ? si->num_glyphs : logClusters[pos]; - if ( edge == Trailing ) { - // trailing edge is leading edge of next cluster - while ( glyph_pos < si->num_glyphs && !glyphAttributes[glyph_pos].clusterStart ) - glyph_pos++; - } - - int x = 0; - bool reverse = engine->items[item].analysis.bidiLevel % 2; - - if ( reverse ) { - for ( int i = si->num_glyphs-1; i >= glyph_pos; i-- ) - x += advances[i]; - } else { - for ( int i = 0; i < glyph_pos; i++ ) - x += advances[i]; - } -// tqDebug("cursorToX: pos=%d, gpos=%d x=%d", pos, glyph_pos, x ); - *cPos = pos; - return x; -} - -int TQTextItem::xToCursor( int x, CursorPosition cpos ) const -{ - TQScriptItem *si = &engine->items[item]; - engine->shape( item ); - advance_t *advances = engine->advances( si ); - unsigned short *logClusters = engine->logClusters( si ); - - int l = engine->length( item ); - bool reverse = si->analysis.bidiLevel % 2; - if ( x < 0 ) - return reverse ? l : 0; - - - if ( reverse ) { - int width = 0; - for ( int i = 0; i < si->num_glyphs; i++ ) { - width += advances[i]; - } - x = -x + width; - } - int cp_before = 0; - int cp_after = 0; - int x_before = 0; - int x_after = 0; - - int lastCluster = 0; - for ( int i = 1; i <= l; i++ ) { - int newCluster = i < l ? logClusters[i] : si->num_glyphs; - if ( newCluster != lastCluster ) { - // calculate cluster width - cp_before = cp_after; - x_before = x_after; - cp_after = i; - for ( int j = lastCluster; j < newCluster; j++ ) - x_after += advances[j]; - // tqDebug("cluster boundary: lastCluster=%d, newCluster=%d, x_before=%d, x_after=%d", - // lastCluster, newCluster, x_before, x_after ); - if ( x_after > x ) - break; - lastCluster = newCluster; - } - } - - bool before = ( cpos == OnCharacters || (x - x_before) < (x_after - x) ); - -// tqDebug("got cursor position for %d: %d/%d, x_ba=%d/%d using %d", -// x, cp_before,cp_after, x_before, x_after, before ? cp_before : cp_after ); - - return before ? cp_before : cp_after; - -} - - -bool TQTextItem::isRightToLeft() const -{ - return (engine->items[item].analysis.bidiLevel % 2); -} - -bool TQTextItem::isObject() const -{ - return engine->items[item].isObject; -} - -bool TQTextItem::isSpace() const -{ - return engine->items[item].isSpace; -} - -bool TQTextItem::isTab() const -{ - return engine->items[item].isTab; -} - - -TQTextLayout::TQTextLayout() - :d(0) {} - -TQTextLayout::TQTextLayout( const TQString& string, TQPainter *p ) -{ - TQFontPrivate *f = p ? ( p->pfont ? p->pfont->d : p->cfont.d ) : TQApplication::font().d; - d = new TQTextEngine( (string.isNull() ? (const TQString&)TQString::fromLatin1("") : string), f ); -} - -TQTextLayout::TQTextLayout( const TQString& string, const TQFont& fnt ) -{ - d = new TQTextEngine( (string.isNull() ? (const TQString&)TQString::fromLatin1("") : string), fnt.d ); -} - -TQTextLayout::~TQTextLayout() -{ - delete d; -} - -void TQTextLayout::setText( const TQString& string, const TQFont& fnt ) -{ - delete d; - d = new TQTextEngine( (string.isNull() ? (const TQString&)TQString::fromLatin1("") : string), fnt.d ); -} - -/* add an additional item boundary eg. for style change */ -void TQTextLayout::setBoundary( int strPos ) -{ - if ( strPos <= 0 || strPos >= (int)d->string.length() ) - return; - - int itemToSplit = 0; - while ( itemToSplit < d->items.size() && d->items[itemToSplit].position <= strPos ) - itemToSplit++; - itemToSplit--; - if ( d->items[itemToSplit].position == strPos ) { - // already a split at the requested position - return; - } - d->splitItem( itemToSplit, strPos - d->items[itemToSplit].position ); -} - - -int TQTextLayout::numItems() const -{ - return d->items.size(); -} - -TQTextItem TQTextLayout::itemAt( int i ) const -{ - return TQTextItem( i, d ); -} - - -TQTextItem TQTextLayout::findItem( int strPos ) const -{ - if ( strPos == 0 && d->items.size() ) - return TQTextItem( 0, d ); - // ## TODO use bsearch - for ( int i = d->items.size()-1; i >= 0; --i ) { - if ( d->items[i].position < strPos ) - return TQTextItem( i, d ); - } - return TQTextItem(); -} - - -void TQTextLayout::beginLayout( TQTextLayout::LayoutMode m ) -{ - d->items.clear(); - TQTextEngine::Mode mode = TQTextEngine::Full; - if (m == NoBidi) - mode = TQTextEngine::NoBidi; - else if (m == SingleLine) - mode = TQTextEngine::SingleLine; - d->itemize( mode ); - d->currentItem = 0; - d->firstItemInLine = -1; -} - -void TQTextLayout::beginLine( int width ) -{ - d->lineWidth = width; - d->widthUsed = 0; - d->firstItemInLine = -1; -} - -bool TQTextLayout::atEnd() const -{ - return d->currentItem >= d->items.size(); -} - -TQTextItem TQTextLayout::nextItem() -{ - d->currentItem++; - - if ( d->currentItem >= d->items.size() ) - return TQTextItem(); - - d->shape( d->currentItem ); - return TQTextItem( d->currentItem, d ); -} - -TQTextItem TQTextLayout::currentItem() -{ - if ( d->currentItem >= d->items.size() ) - return TQTextItem(); - - d->shape( d->currentItem ); - return TQTextItem( d->currentItem, d ); -} - -/* ## maybe also currentItem() */ -void TQTextLayout::setLineWidth( int newWidth ) -{ - d->lineWidth = newWidth; -} - -int TQTextLayout::lineWidth() const -{ - return d->lineWidth; -} - -int TQTextLayout::widthUsed() const -{ - return d->widthUsed; -} - -int TQTextLayout::availableWidth() const -{ - return d->lineWidth - d->widthUsed; -} - - -/* returns true if completely added */ -TQTextLayout::Result TQTextLayout::addCurrentItem() -{ - if ( d->firstItemInLine == -1 ) - d->firstItemInLine = d->currentItem; - TQScriptItem ¤t = d->items[d->currentItem]; - d->shape( d->currentItem ); - d->widthUsed += current.width; -// tqDebug("trying to add item %d with width %d, remaining %d", d->currentItem, current.width, d->lineWidth-d->widthUsed ); - - d->currentItem++; - - return (d->widthUsed <= d->lineWidth - || (d->currentItem < d->items.size() && d->items[d->currentItem].isSpace)) ? Ok : LineFull; -} - -TQTextLayout::Result TQTextLayout::endLine( int x, int y, int alignment, - int *ascent, int *descent, int *lineLeft, int *lineRight ) -{ - int available = d->lineWidth; - int numRuns = 0; - int numSpaceItems = 0; - TQ_UINT8 _levels[128]; - int _visual[128]; - TQ_UINT8 *levels = _levels; - int *visual = _visual; - int i; - TQTextLayout::Result result = LineEmpty; - -// tqDebug("endLine x=%d, y=%d, first=%d, current=%d lw=%d wu=%d", x, y, d->firstItemInLine, d->currentItem, d->lineWidth, d->widthUsed ); - int width_nobreak_found = d->widthUsed; - if ( d->firstItemInLine == -1 ) - goto end; - - if ( !(alignment & (TQt::SingleLine|TQt::IncludeTrailingSpaces)) - && d->currentItem > d->firstItemInLine && d->items[d->currentItem-1].isSpace ) { - int i = d->currentItem-1; - while ( i > d->firstItemInLine && d->items[i].isSpace ) { - numSpaceItems++; - d->widthUsed -= d->items[i--].width; - } - } - - if ( (alignment & (TQt::WordBreak|TQt::BreakAnywhere)) && - d->widthUsed > d->lineWidth ) { - // find linebreak - - // even though we removed trailing spaces the line was too wide. We'll have to break at an earlier - // position. To not confuse the layouting below, reset the number of space items - numSpaceItems = 0; - - - bool breakany = alignment & TQt::BreakAnywhere; - - const TQCharAttributes *attrs = d->attributes(); - int w = 0; - int itemWidth = 0; - int breakItem = d->firstItemInLine; - int breakPosition = -1; -#if 0 - // we iterate backwards or forward depending on what we guess is closer - if ( d->widthUsed - d->lineWidth < d->lineWidth ) { - // backwards search should be faster - - } else -#endif - { - int tmpWidth = 0; - int swidth = 0; - // forward search is probably faster - for ( int i = d->firstItemInLine; i < d->currentItem; i++ ) { - const TQScriptItem *si = &d->items[i]; - int length = d->length( i ); - const TQCharAttributes *itemAttrs = attrs + si->position; - - advance_t *advances = d->advances( si ); - unsigned short *logClusters = d->logClusters( si ); - - int lastGlyph = 0; - int tmpItemWidth = 0; - -// tqDebug("looking for break in item %d, isSpace=%d", i, si->isSpace ); - if(si->isSpace && !(alignment & (TQt::SingleLine|TQt::IncludeTrailingSpaces))) { - swidth += si->width; - } else { - tmpWidth += swidth; - swidth = 0; - for ( int pos = 0; pos < length; pos++ ) { -// tqDebug("advance=%d, w=%d, tmpWidth=%d, softbreak=%d, whitespace=%d", -// *advances, w, tmpWidth, itemAttrs->softBreak, itemAttrs->whiteSpace ); - int glyph = logClusters[pos]; - if ( lastGlyph != glyph ) { - while ( lastGlyph < glyph ) - tmpItemWidth += advances[lastGlyph++]; - if ( breakPosition != -1 && w + tmpWidth + tmpItemWidth > d->lineWidth ) { -// tqDebug("found break at w=%d, tmpWidth=%d, tmpItemWidth=%d", w, tmpWidth, tmpItemWidth); - d->widthUsed = w; - goto found; - } - } - if ( (itemAttrs->softBreak || - ( breakany && itemAttrs->charStop ) ) && - (i != d->firstItemInLine || pos != 0) ) { - if ( breakItem != i ) - itemWidth = 0; - if (itemAttrs->softBreak) - breakany = FALSE; - breakItem = i; - breakPosition = pos; -// tqDebug("found possible break at item %d, position %d (absolute=%d), w=%d, tmpWidth=%d, tmpItemWidth=%d", breakItem, breakPosition, d->items[breakItem].position+breakPosition, w, tmpWidth, tmpItemWidth); - w += tmpWidth + tmpItemWidth; - itemWidth += tmpItemWidth; - tmpWidth = 0; - tmpItemWidth = 0; - } - itemAttrs++; - } - while ( lastGlyph < si->num_glyphs ) - tmpItemWidth += advances[lastGlyph++]; - tmpWidth += tmpItemWidth; - if ( w + tmpWidth > d->lineWidth ) { - d->widthUsed = w; - goto found; - } - } - } - } - - found: - // no valid break point found - if ( breakPosition == -1 ) { - d->widthUsed = width_nobreak_found; - goto nobreak; - } - -// tqDebug("linebreak at item %d, position %d, wu=%d", breakItem, breakPosition, d->widthUsed ); - // split the line - if ( breakPosition > 0 ) { -// int length = d->length( breakItem ); - -// tqDebug("splitting item, itemWidth=%d", itemWidth); - // not a full item, need to break - d->splitItem( breakItem, breakPosition ); - d->currentItem = breakItem+1; - } else { - d->currentItem = breakItem; - } - } - - result = Ok; - - nobreak: - // position the objects in the line - available -= d->widthUsed; - - numRuns = d->currentItem - d->firstItemInLine - numSpaceItems; - if ( numRuns > 127 ) { - levels = new TQ_UINT8[numRuns]; - visual = new int[numRuns]; - } - -// tqDebug("reordering %d runs, numSpaceItems=%d", numRuns, numSpaceItems ); - for ( i = 0; i < numRuns; i++ ) { - levels[i] = d->items[i+d->firstItemInLine].analysis.bidiLevel; -// tqDebug(" level = %d", d->items[i+d->firstItemInLine].analysis.bidiLevel ); - } - d->bidiReorder( numRuns, levels, visual ); - - end: - // ### FIXME - if ( alignment & TQt::AlignJustify ) { - // #### justify items - alignment = TQt::AlignAuto; - } - if ( (alignment & TQt::AlignHorizontal_Mask) == TQt::AlignAuto ) - alignment = TQt::AlignLeft; - if ( alignment & TQt::AlignRight ) - x += available; - else if ( alignment & TQt::AlignHCenter ) - x += available/2; - - - int asc = ascent ? *ascent : 0; - int desc = descent ? *descent : 0; - - for ( i = 0; i < numRuns; i++ ) { - TQScriptItem &si = d->items[d->firstItemInLine+visual[i]]; - asc = TQMAX( asc, si.ascent ); - desc = TQMAX( desc, si.descent ); - } - - int left = x; - for ( i = 0; i < numRuns; i++ ) { - TQScriptItem &si = d->items[d->firstItemInLine+visual[i]]; -// tqDebug("positioning item %d with width %d (from=%d/length=%d) at %d", d->firstItemInLine+visual[i], si.width, si.position, -// d->length(d->firstItemInLine+visual[i]), x ); - si.x = x; - si.y = y + asc; - x += si.width; - } - int right = x; - - if ( numSpaceItems ) { - if ( d->items[d->firstItemInLine+numRuns].analysis.bidiLevel % 2 ) { - x = left; - for ( i = 0; i < numSpaceItems; i++ ) { - TQScriptItem &si = d->items[d->firstItemInLine + numRuns + i]; - x -= si.width; - si.x = x; - si.y = y + asc; - } - } else { - for ( i = 0; i < numSpaceItems; i++ ) { - TQScriptItem &si = d->items[d->firstItemInLine + numRuns + i]; - si.x = x; - si.y = y + asc; - x += si.width; - } - } - } - - if ( lineLeft ) - *lineLeft = left; - if ( lineRight ) - *lineRight = right; - if ( ascent ) - *ascent = asc; - if ( descent ) - *descent = desc; - - if (levels != _levels) - delete []levels; - if (visual != _visual) - delete []visual; - - return result; -} - -void TQTextLayout::endLayout() -{ - // nothing to do currently -} - - -int TQTextLayout::nextCursorPosition( int oldPos, CursorMode mode ) const -{ -// tqDebug("looking for next cursor pos for %d", oldPos ); - const TQCharAttributes *attributes = d->attributes(); - int len = d->string.length(); - if ( oldPos >= len ) - return oldPos; - oldPos++; - if ( mode == SkipCharacters ) { - while ( oldPos < len && !attributes[oldPos].charStop ) - oldPos++; - } else { - while ( oldPos < len && !attributes[oldPos].wordStop && !attributes[oldPos-1].whiteSpace ) - oldPos++; - } -// tqDebug(" -> %d", oldPos ); - return oldPos; -} - -int TQTextLayout::previousCursorPosition( int oldPos, CursorMode mode ) const -{ -// tqDebug("looking for previous cursor pos for %d", oldPos ); - const TQCharAttributes *attributes = d->attributes(); - if ( oldPos <= 0 ) - return 0; - oldPos--; - if ( mode == SkipCharacters ) { - while ( oldPos && !attributes[oldPos].charStop ) - oldPos--; - } else { - while ( oldPos && !attributes[oldPos].wordStop && !attributes[oldPos-1].whiteSpace ) - oldPos--; - } -// tqDebug(" -> %d", oldPos ); - return oldPos; -} - - -bool TQTextLayout::validCursorPosition( int pos ) const -{ - const TQCharAttributes *attributes = d->attributes(); - if ( pos < 0 || pos > (int)d->string.length() ) - return FALSE; - return attributes[pos].charStop; -} - -void TQTextLayout::setDirection(TQChar::Direction dir) -{ - d->direction = dir; -} diff --git a/src/kernel/qtextlayout_p.h b/src/kernel/qtextlayout_p.h deleted file mode 100644 index 64c7f64db..000000000 --- a/src/kernel/qtextlayout_p.h +++ /dev/null @@ -1,184 +0,0 @@ -/**************************************************************************** -** -** ??? -** -** 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. -** -** 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 TQTEXTLAYOUT_P_H -#define TQTEXTLAYOUT_P_H - -#ifndef QT_H -#include "tqstring.h" -#include "ntqnamespace.h" -#include "ntqrect.h" -#endif // QT_H - -class TQTextEngine; -class TQFont; - -class TQ_EXPORT TQTextItem -{ -public: - inline TQTextItem() : item(0), engine(0) {} - inline bool isValid() const { return (bool)engine; } - - TQRect rect() const; - int x() const; - int y() const; - int width() const; - int ascent() const; - int descent() const; - - enum Edge { - Leading, - Trailing - }; - enum CursorPosition { - BetweenCharacters, - OnCharacters - }; - - /* cPos gets set to the valid position */ - int cursorToX( int *cPos, Edge edge = Leading ) const; - inline int cursorToX( int cPos, Edge edge = Leading ) const { return cursorToX( &cPos, edge ); } - int xToCursor( int x, CursorPosition = BetweenCharacters ) const; - - bool isRightToLeft() const; - bool isObject() const; - bool isSpace() const; - bool isTab() const; - - void setWidth( int w ); - void setAscent( int a ); - void setDescent( int d ); - - int from() const; - int length() const; - -private: - friend class TQTextLayout; - friend class TQPainter; - friend class TQPSPrinter; - TQTextItem( int i, TQTextEngine *e ) : item( i ), engine( e ) {} - int item; - TQTextEngine *engine; -}; - - -class TQPainter; - -class TQ_EXPORT TQTextLayout -{ -public: - // does itemization - TQTextLayout(); - TQTextLayout( const TQString& string, TQPainter * = 0 ); - TQTextLayout( const TQString& string, const TQFont& fnt ); - ~TQTextLayout(); - - void setText( const TQString& string, const TQFont& fnt ); - - enum LineBreakStrategy { - AtWordBoundaries, - AtCharBoundaries - }; - - /* add an additional item boundary eg. for style change */ - void setBoundary( int strPos ); - - int numItems() const; - TQTextItem itemAt( int i ) const; - TQTextItem findItem( int strPos ) const; - - enum LayoutMode { - NoBidi, - SingleLine, - MultiLine - }; - void beginLayout( LayoutMode m = MultiLine ); - void beginLine( int width ); - - bool atEnd() const; - TQTextItem nextItem(); - TQTextItem currentItem(); - /* ## maybe also currentItem() */ - void setLineWidth( int newWidth ); - int lineWidth() const; - int widthUsed() const; - int availableWidth() const; - - enum Result { - Ok, - LineFull, - LineEmpty, - Error - }; - /* returns true if completely added */ - Result addCurrentItem(); - - /* Note: if ascent and descent are used they must be initialized to the minimum ascent/descent - acceptable for the line. TQFontMetrics::ascent/descent() is usually the right choice */ - Result endLine( int x = 0, int y = 0, int alignment = TQt::AlignLeft, - int *ascent = 0, int *descent = 0, int *left = 0, int *right = 0 ); - void endLayout(); - - enum CursorMode { - SkipCharacters, - SkipWords - }; - bool validCursorPosition( int pos ) const; - int nextCursorPosition( int oldPos, CursorMode mode = SkipCharacters ) const; - int previousCursorPosition( int oldPos, CursorMode mode = SkipCharacters ) const; - - void setDirection(TQChar::Direction); -private: - TQTextLayout( TQTextEngine *e ) : d( e ) {} - /* disable copy and assignment */ - TQTextLayout( const TQTextLayout & ) {} - void operator = ( const TQTextLayout & ) {} - - friend class TQTextItem; - friend class TQPainter; - friend class TQPSPrinter; - TQTextEngine *d; -}; - - -/* - class TQPainter { - ..... - void drawTextItem( int x, int y, TQTextItem *item ); - }; -*/ - -#endif diff --git a/src/kernel/tqimage.cpp b/src/kernel/tqimage.cpp index 7a454818e..d31168c70 100644 --- a/src/kernel/tqimage.cpp +++ b/src/kernel/tqimage.cpp @@ -42,7 +42,7 @@ #include "ntqregexp.h" #include "ntqfile.h" #include "ntqdatastream.h" -#include "ntqtextstream.h" +#include "tqtextstream.h" #include "ntqbuffer.h" #include "tqptrlist.h" #include "ntqasyncimageio.h" diff --git a/src/kernel/tqtextengine.cpp b/src/kernel/tqtextengine.cpp new file mode 100644 index 000000000..b66fb7d95 --- /dev/null +++ b/src/kernel/tqtextengine.cpp @@ -0,0 +1,1180 @@ +/**************************************************************************** +** +** Text engine classes +** +** Copyright (C) 2005-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 "tqtextengine_p.h" + +#include "qscriptengine_p.h" +#include +#include "qfontdata_p.h" +#include "qfontengine_p.h" +#include +#include +#include + +// ----------------------------------------------------------------------------------------------------- +// +// The BiDi algorithm +// +// ----------------------------------------------------------------------------------------------------- + + +#define BIDI_DEBUG 0//2 +#if (BIDI_DEBUG >= 1) +#include +using namespace std; + +static const char *directions[] = { + "DirL", "DirR", "DirEN", "DirES", "DirET", "DirAN", "DirCS", "DirB", "DirS", "DirWS", "DirON", + "DirLRE", "DirLRO", "DirAL", "DirRLE", "DirRLO", "DirPDF", "DirNSM", "DirBN" +}; + +#endif + +struct BidiStatus { + BidiStatus() { + eor = TQChar::DirON; + lastStrong = TQChar::DirON; + last = TQChar:: DirON; + dir = TQChar::DirON; + } + TQChar::Direction eor; + TQChar::Direction lastStrong; + TQChar::Direction last; + TQChar::Direction dir; +}; + +struct BidiControl { + struct Context { + unsigned char level : 6; + unsigned char override : 1; + unsigned char unused : 1; + }; + + inline BidiControl( bool rtl ) + : cCtx( 0 ), singleLine( FALSE ) { + ctx[0].level = (rtl ? 1 : 0); + ctx[0].override = FALSE; + } + + inline void embed( int level, bool override = FALSE ) { + if ( ctx[cCtx].level < 61 && cCtx < 61 ) { + (void) ++cCtx; + ctx[cCtx].level = level; + ctx[cCtx].override = override; + } + } + inline void pdf() { + if ( cCtx ) (void) --cCtx; + } + + inline uchar level() const { + return ctx[cCtx].level; + } + inline bool override() const { + return ctx[cCtx].override; + } + inline TQChar::Direction basicDirection() { + return (ctx[0].level ? TQChar::DirR : TQChar:: DirL ); + } + inline uchar baseLevel() { + return ctx[0].level; + } + inline TQChar::Direction direction() { + return ((ctx[cCtx].level%2) ? TQChar::DirR : TQChar:: DirL ); + } + + Context ctx[63]; + unsigned int cCtx : 8; + bool singleLine : 8; +}; + +static TQChar::Direction basicDirection( const TQString &str ) +{ + int len = str.length(); + int pos = 0; + const TQChar *uc = str.unicode() + pos; + while( pos < len ) { + switch( direction( *uc ) ) + { + case TQChar::DirL: + case TQChar::DirLRO: + case TQChar::DirLRE: + return TQChar::DirL; + case TQChar::DirR: + case TQChar::DirAL: + case TQChar::DirRLO: + case TQChar::DirRLE: + return TQChar::DirR; + default: + break; + } + ++pos; + ++uc; + } + return TQChar::DirL; +} + + +static void tqAppendItems(TQTextEngine *engine, int &start, int &stop, BidiControl &control, TQChar::Direction dir ) +{ + TQScriptItemArray &items = engine->items; + const TQChar *text = engine->string.unicode(); + + if ( start > stop ) { + // #### the algorithm is currently not really safe against this. Still needs fixing. +// tqWarning( "Bidi: appendItems() internal error" ); + return; + } + + int level = control.level(); + + if(dir != TQChar::DirON && !control.override()) { + // add level of run (cases I1 & I2) + if( level % 2 ) { + if(dir == TQChar::DirL || dir == TQChar::DirAN || dir == TQChar::DirEN ) + level++; + } else { + if( dir == TQChar::DirR ) + level++; + else if( dir == TQChar::DirAN || dir == TQChar::DirEN ) + level += 2; + } + } + +#if (BIDI_DEBUG >= 1) + tqDebug("new run: dir=%s from %d, to %d level = %d\n", directions[dir], start, stop, level); +#endif + TQFont::Script script = TQFont::NoScript; + TQScriptItem item; + item.position = start; + item.analysis.script = script; + item.analysis.bidiLevel = level; + item.analysis.override = control.override(); + item.analysis.reserved = 0; + + if ( control.singleLine ) { + for ( int i = start; i <= stop; i++ ) { + + unsigned short uc = text[i].unicode(); + TQFont::Script s = (TQFont::Script)scriptForChar( uc ); + if (s == TQFont::UnknownScript || s == TQFont::CombiningMarks) + s = script; + + if (s != script) { + item.analysis.script = s; + item.analysis.bidiLevel = level; + item.position = i; + items.append( item ); + script = s; + } + } + } else { + for ( int i = start; i <= stop; i++ ) { + + unsigned short uc = text[i].unicode(); + TQFont::Script s = (TQFont::Script)scriptForChar( uc ); + if (s == TQFont::UnknownScript || s == TQFont::CombiningMarks) + s = script; + + TQChar::Category category = ::category( uc ); + if ( uc == 0xfffcU || uc == 0x2028U ) { + item.analysis.bidiLevel = level % 2 ? level-1 : level; + item.analysis.script = TQFont::Latin; + item.isObject = TRUE; + s = TQFont::NoScript; + } else if ((uc >= 9 && uc <=13) || + (category >= TQChar::Separator_Space && category <= TQChar::Separator_Paragraph)) { + item.analysis.script = TQFont::Latin; + item.isSpace = TRUE; + item.isTab = ( uc == '\t' ); + item.analysis.bidiLevel = item.isTab ? control.baseLevel() : level; + s = TQFont::NoScript; + } else if ( s != script && (category != TQChar::Mark_NonSpacing || script == TQFont::NoScript)) { + item.analysis.script = s; + item.analysis.bidiLevel = level; + } else { + if (i - start < 32000) + continue; + start = i; + } + + item.position = i; + items.append( item ); + script = s; + item.isSpace = item.isTab = item.isObject = FALSE; + } + } + ++stop; + start = stop; +} + +typedef void (* fAppendItems)(TQTextEngine *, int &start, int &stop, BidiControl &control, TQChar::Direction dir); +static fAppendItems appendItems = tqAppendItems; + +// creates the next TQScript items. +static void bidiItemize( TQTextEngine *engine, bool rightToLeft, int mode ) +{ + BidiControl control( rightToLeft ); + if ( mode & TQTextEngine::SingleLine ) + control.singleLine = TRUE; + + int sor = 0; + int eor = -1; + + // ### should get rid of this! + bool first = TRUE; + + int length = engine->string.length(); + + if ( !length ) + return; + + const TQChar *unicode = engine->string.unicode(); + int current = 0; + + TQChar::Direction dir = rightToLeft ? TQChar::DirR : TQChar::DirL; + BidiStatus status; + TQChar::Direction sdir = direction( *unicode ); + if ( sdir != TQChar::DirL && sdir != TQChar::DirR && sdir != TQChar::DirAL && sdir != TQChar::DirEN && sdir != TQChar::DirAN ) + sdir = TQChar::DirON; + else + dir = TQChar::DirON; + status.eor = sdir; + status.lastStrong = rightToLeft ? TQChar::DirR : TQChar::DirL; + status.last = status.lastStrong; + status.dir = sdir; +#if (BIDI_DEBUG >= 2) + tqDebug("---- bidiReorder --- '%s'", engine->string.utf8().data()); + tqDebug("rightToLeft = %d", rightToLeft); +#endif + + + while ( current <= length ) { + + TQChar::Direction dirCurrent; + if ( current == (int)length ) + dirCurrent = control.basicDirection(); + else + dirCurrent = direction( unicode[current] ); + +#if (BIDI_DEBUG >= 2) + cout << "pos=" << current << " dir=" << directions[dir] + << " current=" << directions[dirCurrent] << " last=" << directions[status.last] + << " eor=" << eor << "/" << directions[status.eor] + << " sor=" << sor << " lastStrong=" + << directions[status.lastStrong] + << " level=" << (int)control.level() << endl; +#endif + + switch(dirCurrent) { + + // embedding and overrides (X1-X9 in the BiDi specs) + case TQChar::DirRLE: + case TQChar::DirRLO: + case TQChar::DirLRE: + case TQChar::DirLRO: + { + bool rtl = (dirCurrent == TQChar::DirRLE || dirCurrent == TQChar::DirRLO ); + bool override = (dirCurrent == TQChar::DirLRO || dirCurrent == TQChar::DirRLO ); + + uchar level = control.level(); + if( (level%2 != 0) == rtl ) + level += 2; + else + level++; + if(level < 61) { + eor = current-1; + appendItems(engine, sor, eor, control, dir); + eor = current; + control.embed( level, override ); + TQChar::Direction edir = (rtl ? TQChar::DirR : TQChar::DirL ); + dir = status.eor = edir; + status.lastStrong = edir; + } + break; + } + case TQChar::DirPDF: + { + if (dir != control.direction()) { + eor = current-1; + appendItems(engine, sor, eor, control, dir); + dir = control.direction(); + } + eor = current; + appendItems(engine, sor, eor, control, dir); + dir = TQChar::DirON; status.eor = TQChar::DirON; + status.last = control.direction(); + control.pdf(); + if ( control.override() ) + dir = control.direction(); + else + dir = TQChar::DirON; + status.lastStrong = control.direction(); + break; + } + + // strong types + case TQChar::DirL: + if(dir == TQChar::DirON) + dir = TQChar::DirL; + switch(status.last) + { + case TQChar::DirL: + eor = current; status.eor = TQChar::DirL; break; + case TQChar::DirR: + case TQChar::DirAL: + case TQChar::DirEN: + case TQChar::DirAN: + if ( !first ) { + appendItems(engine, sor, eor, control, dir); + dir = eor < length ? direction( unicode[eor] ) : control.basicDirection(); + status.eor = dir; + } else { + eor = current; status.eor = dir; + } + break; + case TQChar::DirES: + case TQChar::DirET: + case TQChar::DirCS: + case TQChar::DirBN: + case TQChar::DirB: + case TQChar::DirS: + case TQChar::DirWS: + case TQChar::DirON: + if(dir != TQChar::DirL) { + //last stuff takes embedding dir + if( control.direction() == TQChar::DirR ) { + if(status.eor != TQChar::DirR) { + // AN or EN + appendItems(engine, sor, eor, control, dir); + status.eor = TQChar::DirON; + dir = TQChar::DirR; + } + eor = current - 1; + appendItems(engine, sor, eor, control, dir); + dir = eor < length ? direction( unicode[eor] ) : control.basicDirection(); + status.eor = dir; + } else { + if(status.eor != TQChar::DirL) { + appendItems(engine, sor, eor, control, dir); + status.eor = TQChar::DirON; + dir = TQChar::DirL; + } else { + eor = current; status.eor = TQChar::DirL; break; + } + } + } else { + eor = current; status.eor = TQChar::DirL; + } + default: + break; + } + status.lastStrong = TQChar::DirL; + break; + case TQChar::DirAL: + case TQChar::DirR: + if(dir == TQChar::DirON) dir = TQChar::DirR; + switch(status.last) + { + case TQChar::DirL: + case TQChar::DirEN: + case TQChar::DirAN: + if ( !first ) { + appendItems(engine, sor, eor, control, dir); + dir = TQChar::DirON; status.eor = TQChar::DirON; + break; + } + case TQChar::DirR: + case TQChar::DirAL: + eor = current; status.eor = TQChar::DirR; break; + case TQChar::DirES: + case TQChar::DirET: + case TQChar::DirCS: + case TQChar::DirBN: + case TQChar::DirB: + case TQChar::DirS: + case TQChar::DirWS: + case TQChar::DirON: + if( status.eor != TQChar::DirR && status.eor != TQChar::DirAL ) { + //last stuff takes embedding dir + if(control.direction() == TQChar::DirR + || status.lastStrong == TQChar::DirR || status.lastStrong == TQChar::DirAL) { + appendItems(engine, sor, eor, control, dir); + dir = TQChar::DirON; status.eor = TQChar::DirON; + dir = TQChar::DirR; + eor = current; + } else { + eor = current - 1; + appendItems(engine, sor, eor, control, dir); + dir = TQChar::DirON; status.eor = TQChar::DirON; + dir = TQChar::DirR; + } + } else { + eor = current; status.eor = TQChar::DirR; + } + default: + break; + } + status.lastStrong = dirCurrent; + break; + + // weak types: + + case TQChar::DirNSM: + if (eor == current-1) + eor = current; + break; + case TQChar::DirEN: + // if last strong was AL change EN to AN + if(status.lastStrong != TQChar::DirAL) { + if(dir == TQChar::DirON) { + if(status.lastStrong == TQChar::DirL) + dir = TQChar::DirL; + else + dir = TQChar::DirEN; + } + switch(status.last) + { + case TQChar::DirET: + if ( status.lastStrong == TQChar::DirR || status.lastStrong == TQChar::DirAL ) { + appendItems(engine, sor, eor, control, dir); + status.eor = TQChar::DirON; + dir = TQChar::DirAN; + } + // fall through + case TQChar::DirEN: + case TQChar::DirL: + eor = current; + status.eor = dirCurrent; + break; + case TQChar::DirR: + case TQChar::DirAL: + case TQChar::DirAN: + if ( !first ) + appendItems(engine, sor, eor, control, dir); + status.eor = TQChar::DirEN; + dir = TQChar::DirAN; break; + case TQChar::DirES: + case TQChar::DirCS: + if(status.eor == TQChar::DirEN || dir == TQChar::DirAN) { + eor = current; break; + } + case TQChar::DirBN: + case TQChar::DirB: + case TQChar::DirS: + case TQChar::DirWS: + case TQChar::DirON: + if(status.eor == TQChar::DirR) { + // neutrals go to R + eor = current - 1; + appendItems(engine, sor, eor, control, dir); + dir = TQChar::DirON; status.eor = TQChar::DirEN; + dir = TQChar::DirAN; + } + else if( status.eor == TQChar::DirL || + (status.eor == TQChar::DirEN && status.lastStrong == TQChar::DirL)) { + eor = current; status.eor = dirCurrent; + } else { + // numbers on both sides, neutrals get right to left direction + if(dir != TQChar::DirL) { + appendItems(engine, sor, eor, control, dir); + dir = TQChar::DirON; status.eor = TQChar::DirON; + eor = current - 1; + dir = TQChar::DirR; + appendItems(engine, sor, eor, control, dir); + dir = TQChar::DirON; status.eor = TQChar::DirON; + dir = TQChar::DirAN; + } else { + eor = current; status.eor = dirCurrent; + } + } + default: + break; + } + break; + } + case TQChar::DirAN: + dirCurrent = TQChar::DirAN; + if(dir == TQChar::DirON) dir = TQChar::DirAN; + switch(status.last) + { + case TQChar::DirL: + case TQChar::DirAN: + eor = current; status.eor = TQChar::DirAN; break; + case TQChar::DirR: + case TQChar::DirAL: + case TQChar::DirEN: + if ( !first ) + appendItems(engine, sor, eor, control, dir); + dir = TQChar::DirON; status.eor = TQChar::DirAN; + break; + case TQChar::DirCS: + if(status.eor == TQChar::DirAN) { + eor = current; break; + } + case TQChar::DirES: + case TQChar::DirET: + case TQChar::DirBN: + case TQChar::DirB: + case TQChar::DirS: + case TQChar::DirWS: + case TQChar::DirON: + if(status.eor == TQChar::DirR) { + // neutrals go to R + eor = current - 1; + appendItems(engine, sor, eor, control, dir); + status.eor = TQChar::DirAN; + dir = TQChar::DirAN; + } else if( status.eor == TQChar::DirL || + (status.eor == TQChar::DirEN && status.lastStrong == TQChar::DirL)) { + eor = current; status.eor = dirCurrent; + } else { + // numbers on both sides, neutrals get right to left direction + if(dir != TQChar::DirL) { + appendItems(engine, sor, eor, control, dir); + status.eor = TQChar::DirON; + eor = current - 1; + dir = TQChar::DirR; + appendItems(engine, sor, eor, control, dir); + status.eor = TQChar::DirAN; + dir = TQChar::DirAN; + } else { + eor = current; status.eor = dirCurrent; + } + } + default: + break; + } + break; + case TQChar::DirES: + case TQChar::DirCS: + break; + case TQChar::DirET: + if(status.last == TQChar::DirEN) { + dirCurrent = TQChar::DirEN; + eor = current; status.eor = dirCurrent; + } + break; + + // boundary neutrals should be ignored + case TQChar::DirBN: + break; + // neutrals + case TQChar::DirB: + // ### what do we do with newline and paragraph separators that come to here? + break; + case TQChar::DirS: + // ### implement rule L1 + break; + case TQChar::DirWS: + case TQChar::DirON: + break; + default: + break; + } + + //cout << " after: dir=" << // dir << " current=" << dirCurrent << " last=" << status.last << " eor=" << status.eor << " lastStrong=" << status.lastStrong << " embedding=" << control.direction() << endl; + + if(current >= (int)length) break; + + // set status.last as needed. + switch(dirCurrent) { + case TQChar::DirET: + case TQChar::DirES: + case TQChar::DirCS: + case TQChar::DirS: + case TQChar::DirWS: + case TQChar::DirON: + switch(status.last) + { + case TQChar::DirL: + case TQChar::DirR: + case TQChar::DirAL: + case TQChar::DirEN: + case TQChar::DirAN: + status.last = dirCurrent; + break; + default: + status.last = TQChar::DirON; + } + break; + case TQChar::DirNSM: + case TQChar::DirBN: + // ignore these + break; + case TQChar::DirLRO: + case TQChar::DirLRE: + status.last = TQChar::DirL; + break; + case TQChar::DirRLO: + case TQChar::DirRLE: + status.last = TQChar::DirR; + break; + case TQChar::DirEN: + if ( status.last == TQChar::DirL ) { + status.last = TQChar::DirL; + break; + } + // fall through + default: + status.last = dirCurrent; + } + + first = FALSE; + ++current; + } + +#if (BIDI_DEBUG >= 1) + cout << "reached end of line current=" << current << ", eor=" << eor << endl; +#endif + eor = current - 1; // remove dummy char + + if ( sor <= eor ) + appendItems(engine, sor, eor, control, dir); + + +} + +void TQTextEngine::bidiReorder( int numItems, const TQ_UINT8 *levels, int *visualOrder ) +{ + + // first find highest and lowest levels + uchar levelLow = 128; + uchar levelHigh = 0; + int i = 0; + while ( i < numItems ) { + //printf("level = %d\n", r->level); + if ( levels[i] > levelHigh ) + levelHigh = levels[i]; + if ( levels[i] < levelLow ) + levelLow = levels[i]; + i++; + } + + // implements reordering of the line (L2 according to BiDi spec): + // L2. From the highest level found in the text to the lowest odd level on each line, + // reverse any contiguous sequence of characters that are at that level or higher. + + // reversing is only done up to the lowest odd level + if(!(levelLow%2)) levelLow++; + +#if (BIDI_DEBUG >= 1) + cout << "reorderLine: lineLow = " << (uint)levelLow << ", lineHigh = " << (uint)levelHigh << endl; +#endif + + int count = numItems - 1; + for ( i = 0; i < numItems; i++ ) + visualOrder[i] = i; + + while(levelHigh >= levelLow) { + int i = 0; + while ( i < count ) { + while(i < count && levels[i] < levelHigh) i++; + int start = i; + while(i <= count && levels[i] >= levelHigh) i++; + int end = i-1; + + if(start != end) { + //cout << "reversing from " << start << " to " << end << endl; + for(int j = 0; j < (end-start+1)/2; j++) { + int tmp = visualOrder[start+j]; + visualOrder[start+j] = visualOrder[end-j]; + visualOrder[end-j] = tmp; + } + } + i++; + } + levelHigh--; + } + +#if (BIDI_DEBUG >= 1) + cout << "visual order is:" << endl; + for ( i = 0; i < numItems; i++ ) + cout << visualOrder[i] << endl; +#endif +} + + +// ----------------------------------------------------------------------------------------------------- +// +// The line break algorithm. See http://www.unicode.org/reports/tr14/tr14-13.html +// +// ----------------------------------------------------------------------------------------------------- + +/* The Unicode algorithm does in our opinion allow line breaks at some + places they shouldn't be allowed. The following changes were thus + made in comparison to the Unicode reference: + + CL->AL from Dbk to Ibk + CL->PR from Dbk to Ibk + EX->AL from Dbk to Ibk + IS->AL from Dbk to Ibk + PO->AL from Dbk to Ibk + SY->AL from Dbk to Ibk + SY->PO from Dbk to Ibk + SY->PR from Dbk to Ibk + SY->OP from Dbk to Ibk + Al->OP from Dbk to Ibk + AL->HY from Dbk to Ibk + AL->PR from Dbk to Ibk + AL->PO from Dbk to Ibk + PR->PR from Dbk to Ibk + PO->PO from Dbk to Ibk + PR->PO from Dbk to Ibk + PO->PR from Dbk to Ibk + HY->PO from Dbk to Ibk + HY->PR from Dbk to Ibk + HY->OP from Dbk to Ibk + PO->OP from Dbk to Ibk + NU->EX from Dbk to Ibk + NU->PR from Dbk to Ibk + PO->NU from Dbk to Ibk + EX->PO from Dbk to Ibk +*/ + +enum break_action { + Dbk, // Direct break + Ibk, // Indirect break; only allowed if space between the two chars + Pbk // Prohibited break; no break allowed even if space between chars +}; + +// The following line break classes are not treated by the table: +// SA, BK, CR, LF, SG, CB, SP +static const TQ_UINT8 breakTable[TQUnicodeTables::LineBreak_CM+1][TQUnicodeTables::LineBreak_CM+1] = +{ + // OP, CL, QU, GL, NS, EX, SY, IS, PR, PO, NU, AL, ID, IN, HY, BA, BB, B2, ZW, CM + { Pbk, Pbk, Pbk, Pbk, Pbk, Pbk, Pbk, Pbk, Pbk, Pbk, Pbk, Pbk, Pbk, Pbk, Pbk, Pbk, Pbk, Pbk, Pbk, Pbk }, // OP + { Dbk, Pbk, Ibk, Pbk, Pbk, Pbk, Pbk, Pbk, Ibk, Ibk, Dbk, Ibk, Dbk, Dbk, Ibk, Ibk, Pbk, Pbk, Pbk, Pbk }, // CL + { Pbk, Pbk, Ibk, Pbk, Ibk, Pbk, Pbk, Pbk, Ibk, Ibk, Ibk, Ibk, Ibk, Ibk, Ibk, Ibk, Ibk, Ibk, Pbk, Pbk }, // QU + { Ibk, Pbk, Ibk, Pbk, Ibk, Pbk, Pbk, Pbk, Ibk, Ibk, Ibk, Ibk, Ibk, Ibk, Ibk, Ibk, Ibk, Ibk, Pbk, Pbk }, // GL + { Dbk, Pbk, Ibk, Pbk, Ibk, Pbk, Pbk, Pbk, Dbk, Dbk, Dbk, Dbk, Dbk, Dbk, Ibk, Ibk, Dbk, Dbk, Pbk, Ibk }, // NS + { Dbk, Pbk, Ibk, Pbk, Ibk, Pbk, Pbk, Pbk, Dbk, Ibk, Ibk, Ibk, Dbk, Dbk, Ibk, Ibk, Dbk, Dbk, Pbk, Ibk }, // EX + { Ibk, Pbk, Ibk, Pbk, Ibk, Pbk, Pbk, Pbk, Ibk, Ibk, Ibk, Ibk, Dbk, Dbk, Ibk, Ibk, Dbk, Dbk, Pbk, Ibk }, // SY + { Dbk, Pbk, Ibk, Pbk, Ibk, Pbk, Pbk, Pbk, Dbk, Dbk, Ibk, Ibk, Dbk, Dbk, Ibk, Ibk, Dbk, Dbk, Pbk, Ibk }, // IS + { Ibk, Pbk, Ibk, Pbk, Ibk, Pbk, Pbk, Pbk, Ibk, Ibk, Ibk, Ibk, Ibk, Dbk, Ibk, Ibk, Dbk, Dbk, Pbk, Pbk }, // PR + { Ibk, Pbk, Ibk, Pbk, Ibk, Pbk, Pbk, Pbk, Ibk, Ibk, Ibk, Ibk, Dbk, Dbk, Ibk, Ibk, Dbk, Dbk, Pbk, Ibk }, // PO + { Dbk, Pbk, Ibk, Pbk, Ibk, Pbk, Pbk, Pbk, Ibk, Ibk, Ibk, Ibk, Dbk, Ibk, Ibk, Ibk, Dbk, Dbk, Pbk, Pbk }, // NU + { Ibk, Pbk, Ibk, Pbk, Ibk, Pbk, Pbk, Pbk, Ibk, Ibk, Ibk, Ibk, Dbk, Ibk, Ibk, Ibk, Dbk, Dbk, Pbk, Pbk }, // AL + { Dbk, Pbk, Ibk, Pbk, Ibk, Pbk, Pbk, Pbk, Dbk, Ibk, Dbk, Dbk, Dbk, Ibk, Ibk, Ibk, Dbk, Dbk, Pbk, Ibk }, // ID + { Dbk, Pbk, Ibk, Pbk, Ibk, Pbk, Pbk, Pbk, Dbk, Dbk, Dbk, Dbk, Dbk, Ibk, Ibk, Ibk, Dbk, Dbk, Pbk, Ibk }, // IN + { Ibk, Pbk, Ibk, Pbk, Ibk, Pbk, Pbk, Pbk, Ibk, Ibk, Ibk, Ibk, Dbk, Dbk, Ibk, Ibk, Dbk, Dbk, Pbk, Ibk }, // HY + { Dbk, Pbk, Ibk, Pbk, Ibk, Pbk, Pbk, Pbk, Dbk, Dbk, Dbk, Dbk, Dbk, Dbk, Ibk, Ibk, Dbk, Dbk, Pbk, Ibk }, // BA + { Ibk, Pbk, Ibk, Pbk, Ibk, Pbk, Pbk, Pbk, Ibk, Ibk, Ibk, Ibk, Ibk, Ibk, Ibk, Ibk, Ibk, Ibk, Pbk, Ibk }, // BB + { Dbk, Pbk, Ibk, Pbk, Ibk, Pbk, Pbk, Pbk, Dbk, Dbk, Dbk, Dbk, Dbk, Dbk, Ibk, Ibk, Dbk, Pbk, Pbk, Ibk }, // B2 + { Dbk, Dbk, Dbk, Dbk, Dbk, Dbk, Dbk, Dbk, Dbk, Dbk, Dbk, Dbk, Dbk, Dbk, Dbk, Dbk, Dbk, Dbk, Pbk, Ibk }, // ZW + { Dbk, Pbk, Ibk, Pbk, Ibk, Pbk, Pbk, Pbk, Dbk, Ibk, Dbk, Dbk, Dbk, Ibk, Ibk, Ibk, Dbk, Dbk, Pbk, Pbk } // CM +}; + +// set the soft break flag at every possible line breaking point. This needs correct clustering information. +static void calcLineBreaks(const TQString &str, TQCharAttributes *charAttributes) +{ + int len = str.length(); + if (!len) + return; + + const TQChar *uc = str.unicode(); + int cls = lineBreakClass(*uc); + if (cls >= TQUnicodeTables::LineBreak_CM) + cls = TQUnicodeTables::LineBreak_ID; + + charAttributes[0].softBreak = FALSE; + charAttributes[0].whiteSpace = (cls == TQUnicodeTables::LineBreak_SP); + charAttributes[0].charStop = TRUE; + + for (int i = 1; i < len; ++i) { + int ncls = ::lineBreakClass(uc[i]); + int category = ::category(uc[i]); + if (category == TQChar::Mark_NonSpacing) + goto nsm; + + if (category == TQChar::Other_Surrogate) { + // char stop only on first pair + if (uc[i].unicode() >= 0xd800 && uc[i].unicode() < 0xdc00 && i < len-1 + && uc[i+1].unicode() >= 0xdc00 && uc[i+1].unicode() < 0xe000) + goto nsm; + // ### correctly handle second surrogate + } + + if (ncls == TQUnicodeTables::LineBreak_SP) { + charAttributes[i].softBreak = FALSE; + charAttributes[i].whiteSpace = TRUE; + charAttributes[i].charStop = TRUE; + cls = ncls; + continue; + } + + + if (cls == TQUnicodeTables::LineBreak_SA && ncls == TQUnicodeTables::LineBreak_SA) { + // two complex chars (thai or lao), thai_attributes might override, but here + // we do a best guess + charAttributes[i].softBreak = TRUE; + charAttributes[i].whiteSpace = FALSE; + charAttributes[i].charStop = TRUE; + cls = ncls; + continue; + } + { + int tcls = ncls; + if (tcls >= TQUnicodeTables::LineBreak_SA) + tcls = TQUnicodeTables::LineBreak_ID; + if (cls >= TQUnicodeTables::LineBreak_SA) + cls = TQUnicodeTables::LineBreak_ID; + + bool softBreak; + int brk = breakTable[cls][tcls]; + if (brk == Ibk) + softBreak = (cls == TQUnicodeTables::LineBreak_SP); + else + softBreak = (brk == Dbk); +// tqDebug("char = %c %04x, cls=%d, ncls=%d, brk=%d soft=%d", uc[i].cell(), uc[i].unicode(), cls, ncls, brk, charAttributes[i].softBreak); + charAttributes[i].softBreak = softBreak; + charAttributes[i].whiteSpace = FALSE; + charAttributes[i].charStop = TRUE; + cls = ncls; + } + continue; + nsm: + charAttributes[i].softBreak = FALSE; + charAttributes[i].whiteSpace = FALSE; + charAttributes[i].charStop = FALSE; + } +} + +#if defined( TQ_WS_X11 ) || defined ( TQ_WS_QWS ) +# include "tqtextengine_unix.cpp" +#elif defined( TQ_WS_WIN ) +# include "tqtextengine_win.cpp" +#elif defined( TQ_WS_MAC ) +# include "tqtextengine_mac.cpp" +#endif + + + +TQTextEngine::TQTextEngine( const TQString &str, TQFontPrivate *f ) + : string( str ), fnt( f ), direction( TQChar::DirON ), haveCharAttributes( FALSE ), widthOnly( FALSE ) +{ +#ifdef TQ_WS_WIN + if ( !resolvedUsp10 ) + resolveUsp10(); +#endif + if ( fnt ) fnt->ref(); + + num_glyphs = TQMAX( 16, str.length()*3/2 ); + int space_charAttributes = (sizeof(TQCharAttributes)*str.length()+sizeof(void*)-1)/sizeof(void*); + int space_logClusters = (sizeof(unsigned short)*str.length()+sizeof(void*)-1)/sizeof(void*); + int space_glyphs = (sizeof(glyph_t)*num_glyphs+sizeof(void*)-1)/sizeof(void*); + int space_advances = (sizeof(advance_t)*num_glyphs+sizeof(void*)-1)/sizeof(void*); + int space_offsets = (sizeof(qoffset_t)*num_glyphs+sizeof(void*)-1)/sizeof(void*); + int space_glyphAttributes = (sizeof(GlyphAttributes)*num_glyphs+sizeof(void*)-1)/sizeof(void*); + + allocated = space_charAttributes + space_glyphs + space_advances + + space_offsets + space_logClusters + space_glyphAttributes; + memory = (void **)::malloc( allocated*sizeof( void * ) ); + memset( memory, 0, allocated*sizeof( void * ) ); + + void **m = memory; + m += space_charAttributes; + logClustersPtr = (unsigned short *) m; + m += space_logClusters; + glyphPtr = (glyph_t *) m; + m += space_glyphs; + advancePtr = (advance_t *) m; + m += space_advances; + offsetsPtr = (qoffset_t *) m; + m += space_offsets; + glyphAttributesPtr = (GlyphAttributes *) m; + + used = 0; +} + +TQTextEngine::~TQTextEngine() +{ + if ( fnt && fnt->deref()) + delete fnt; + free( memory ); + allocated = 0; +} + +void TQTextEngine::reallocate( int totalGlyphs ) +{ + int new_num_glyphs = totalGlyphs; + int space_charAttributes = (sizeof(TQCharAttributes)*string.length()+sizeof(void*)-1)/sizeof(void*); + int space_logClusters = (sizeof(unsigned short)*string.length()+sizeof(void*)-1)/sizeof(void*); + int space_glyphs = (sizeof(glyph_t)*new_num_glyphs+sizeof(void*)-1)/sizeof(void*); + int space_advances = (sizeof(advance_t)*new_num_glyphs+sizeof(void*)-1)/sizeof(void*); + int space_offsets = (sizeof(qoffset_t)*new_num_glyphs+sizeof(void*)-1)/sizeof(void*); + int space_glyphAttributes = (sizeof(GlyphAttributes)*new_num_glyphs+sizeof(void*)-1)/sizeof(void*); + + int newAllocated = space_charAttributes + space_glyphs + space_advances + + space_offsets + space_logClusters + space_glyphAttributes; + void ** newMemory = (void **)::malloc( newAllocated*sizeof( void * ) ); + + void **nm = newMemory; + memcpy( nm, memory, string.length()*sizeof(TQCharAttributes) ); + nm += space_charAttributes; + memcpy( nm, logClustersPtr, num_glyphs*sizeof(unsigned short) ); + logClustersPtr = (unsigned short *) nm; + nm += space_logClusters; + memcpy( nm, glyphPtr, num_glyphs*sizeof(glyph_t) ); + glyphPtr = (glyph_t *) nm; + nm += space_glyphs; + memcpy( nm, advancePtr, num_glyphs*sizeof(advance_t) ); + advancePtr = (advance_t *) nm; + nm += space_advances; + memcpy( nm, offsetsPtr, num_glyphs*sizeof(qoffset_t) ); + offsetsPtr = (qoffset_t *) nm; + nm += space_offsets; + memcpy( nm, glyphAttributesPtr, num_glyphs*sizeof(GlyphAttributes) ); + glyphAttributesPtr = (GlyphAttributes *) nm; + + free( memory ); + memory = newMemory; + allocated = newAllocated; + num_glyphs = new_num_glyphs; +} + +const TQCharAttributes *TQTextEngine::attributes() +{ + TQCharAttributes *charAttributes = (TQCharAttributes *) memory; + if ( haveCharAttributes ) + return charAttributes; + + if ( !items.d ) + itemize(); + + ensureSpace(string.length()); + charAttributes = (TQCharAttributes *) memory; + calcLineBreaks(string, charAttributes); + + for ( int i = 0; i < items.size(); i++ ) { + TQScriptItem &si = items[i]; +#ifdef TQ_WS_WIN + int script = uspScriptForItem(this, i); +#else + int script = si.analysis.script; +#endif + Q_ASSERT( script < TQFont::NScripts ); + AttributeFunction attributes = scriptEngines[script].charAttributes; + if (!attributes) + continue; + int from = si.position; + int len = length( i ); + attributes( script, string, from, len, charAttributes ); + } + + haveCharAttributes = TRUE; + return charAttributes; +} + +void TQTextEngine::splitItem( int item, int pos ) +{ + if ( pos <= 0 ) + return; + + // we have to ensure we get correct shaping for arabic and other + // complex languages so we have to call shape _before_ we split the item. + shape(item); + + if ( items.d->size == items.d->alloc ) + items.resize( items.d->size + 1 ); + + int numMove = items.d->size - item-1; + if ( numMove > 0 ) + memmove( items.d->items + item+2, items.d->items +item+1, numMove*sizeof( TQScriptItem ) ); + items.d->size++; + TQScriptItem &newItem = items.d->items[item+1]; + TQScriptItem &oldItem = items.d->items[item]; + newItem = oldItem; + items.d->items[item+1].position += pos; + if ( newItem.fontEngine ) + newItem.fontEngine->ref(); + + if (oldItem.num_glyphs) { + // already shaped, break glyphs aswell + int breakGlyph = logClusters(&oldItem)[pos]; + + newItem.num_glyphs = oldItem.num_glyphs - breakGlyph; + oldItem.num_glyphs = breakGlyph; + newItem.glyph_data_offset = oldItem.glyph_data_offset + breakGlyph; + + for (int i = 0; i < newItem.num_glyphs; i++) + logClusters(&newItem)[i] -= breakGlyph; + + int w = 0; + const advance_t *a = advances(&oldItem); + for(int j = 0; j < breakGlyph; ++j) + w += *(a++); + + newItem.width = oldItem.width - w; + oldItem.width = w; + } + +// tqDebug("split at position %d itempos=%d", pos, item ); +} + + +int TQTextEngine::width( int from, int len ) const +{ + int w = 0; + +// tqDebug("TQTextEngine::width( from = %d, len = %d ), numItems=%d, strleng=%d", from, len, items.size(), string.length() ); + for ( int i = 0; i < items.size(); i++ ) { + TQScriptItem *si = &items[i]; + int pos = si->position; + int ilen = length( i ); +// tqDebug("item %d: from %d len %d", i, pos, ilen ); + if ( pos >= from + len ) + break; + if ( pos + ilen > from ) { + if ( !si->num_glyphs ) + shape( i ); + + advance_t *advances = this->advances( si ); + unsigned short *logClusters = this->logClusters( si ); + +// fprintf( stderr, " logclusters:" ); +// for ( int k = 0; k < ilen; k++ ) +// fprintf( stderr, " %d", logClusters[k] ); +// fprintf( stderr, "\n" ); + // do the simple thing for now and give the first glyph in a cluster the full width, all other ones 0. + int charFrom = from - pos; + if ( charFrom < 0 ) + charFrom = 0; + int glyphStart = logClusters[charFrom]; + if ( charFrom > 0 && logClusters[charFrom-1] == glyphStart ) + while ( charFrom < ilen && logClusters[charFrom] == glyphStart ) + charFrom++; + if ( charFrom < ilen ) { + glyphStart = logClusters[charFrom]; + int charEnd = from + len - 1 - pos; + if ( charEnd >= ilen ) + charEnd = ilen-1; + int glyphEnd = logClusters[charEnd]; + while ( charEnd < ilen && logClusters[charEnd] == glyphEnd ) + charEnd++; + glyphEnd = (charEnd == ilen) ? si->num_glyphs : logClusters[charEnd]; + +// tqDebug("char: start=%d end=%d / glyph: start = %d, end = %d", charFrom, charEnd, glyphStart, glyphEnd ); + for ( int i = glyphStart; i < glyphEnd; i++ ) + w += advances[i]; + } + } + } +// tqDebug(" --> w= %d ", w ); + return w; +} + +void TQTextEngine::itemize( int mode ) +{ + if ( !items.d ) { + int size = 8; + items.d = (TQScriptItemArrayPrivate *)malloc( sizeof( TQScriptItemArrayPrivate ) + + sizeof( TQScriptItem ) * size ); + items.d->alloc = size; + } + items.d->size = 0; + if ( string.length() == 0 ) + return; + + if ( !(mode & NoBidi) ) { + if ( direction == TQChar::DirON ) + direction = basicDirection( string ); + bidiItemize( this, direction == TQChar::DirR, mode ); + } else { + BidiControl control( FALSE ); + if ( mode & TQTextEngine::SingleLine ) + control.singleLine = TRUE; + int start = 0; + int stop = string.length() - 1; + appendItems(this, start, stop, control, TQChar::DirL); + } + if ( (mode & WidthOnly) == WidthOnly ) + widthOnly = TRUE; +} + +glyph_metrics_t TQTextEngine::boundingBox( int from, int len ) const +{ + glyph_metrics_t gm; + + for ( int i = 0; i < items.size(); i++ ) { + TQScriptItem *si = &items[i]; + int pos = si->position; + int ilen = length( i ); + if ( pos > from + len ) + break; + if ( pos + len > from ) { + if ( !si->num_glyphs ) + shape( i ); + advance_t *advances = this->advances( si ); + unsigned short *logClusters = this->logClusters( si ); + glyph_t *glyphs = this->glyphs( si ); + qoffset_t *offsets = this->offsets( si ); + + // do the simple thing for now and give the first glyph in a cluster the full width, all other ones 0. + int charFrom = from - pos; + if ( charFrom < 0 ) + charFrom = 0; + int glyphStart = logClusters[charFrom]; + if ( charFrom > 0 && logClusters[charFrom-1] == glyphStart ) + while ( charFrom < ilen && logClusters[charFrom] == glyphStart ) + charFrom++; + if ( charFrom < ilen ) { + glyphStart = logClusters[charFrom]; + int charEnd = from + len - 1 - pos; + if ( charEnd >= ilen ) + charEnd = ilen-1; + int glyphEnd = logClusters[charEnd]; + while ( charEnd < ilen && logClusters[charEnd] == glyphEnd ) + charEnd++; + glyphEnd = (charEnd == ilen) ? si->num_glyphs : logClusters[charEnd]; + if ( glyphStart <= glyphEnd ) { + TQFontEngine *fe = si->fontEngine; + glyph_metrics_t m = fe->boundingBox( glyphs+glyphStart, advances+glyphStart, + offsets+glyphStart, glyphEnd-glyphStart ); + gm.x = TQMIN( gm.x, m.x + gm.xoff ); + gm.y = TQMIN( gm.y, m.y + gm.yoff ); + gm.width = TQMAX( gm.width, m.width+gm.xoff ); + gm.height = TQMAX( gm.height, m.height+gm.yoff ); + gm.xoff += m.xoff; + gm.yoff += m.yoff; + } + } + } + } + return gm; +} diff --git a/src/kernel/tqtextengine_p.h b/src/kernel/tqtextengine_p.h new file mode 100644 index 000000000..774302a07 --- /dev/null +++ b/src/kernel/tqtextengine_p.h @@ -0,0 +1,377 @@ +/**************************************************************************** +** +** ??? +** +** 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. +** +** 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 TQTEXTENGINE_P_H +#define TQTEXTENGINE_P_H + +#ifndef QT_H +#include "ntqglobal.h" +#include "tqstring.h" +#include "ntqnamespace.h" +#include +#endif // QT_H + +#include +#ifndef Q_OS_TEMP +#include +#endif // Q_OS_TEMP + +class TQFontPrivate; +class TQString; + +class TQOpenType; +class TQPainter; + +// this uses the same coordinate system as TQt, but a different one to freetype and Xft. +// * y is usually negative, and is equal to the ascent. +// * negative yoff means the following stuff is drawn higher up. +// the characters bounding rect is given by TQRect( x,y,width,height), it's advance by +// xoo and yoff +struct glyph_metrics_t +{ + inline glyph_metrics_t() { + x = 100000; + y = 100000; + width = 0; + height = 0; + xoff = 0; + yoff = 0; + } + inline glyph_metrics_t( int _x, int _y, int _width, int _height, int _xoff, int _yoff ) { + x = _x; + y = _y; + width = _width; + height = _height; + xoff = _xoff; + yoff = _yoff; + } + int x; + int y; + int width; + int height; + int xoff; + int yoff; +}; + +#if defined( TQ_WS_X11 ) || defined ( TQ_WS_QWS ) +typedef unsigned short glyph_t; + +struct qoffset_t { + short x; + short y; +}; + +typedef int advance_t; + +struct TQScriptAnalysis +{ + unsigned short script : 7; + unsigned short bidiLevel : 6; // Unicode Bidi algorithm embedding level (0-61) + unsigned short override : 1; // Set when in LRO/RLO embedding + unsigned short reserved : 2; + bool operator == ( const TQScriptAnalysis &other ) { + return + script == other.script && + bidiLevel == other.bidiLevel; + // ### +// && override == other.override; + } + +}; + +#elif defined( TQ_WS_MAC ) + +typedef unsigned short glyph_t; + +struct qoffset_t { + short x; + short y; +}; + +typedef int advance_t; + +struct TQScriptAnalysis +{ + unsigned short script : 7; + unsigned short bidiLevel : 6; // Unicode Bidi algorithm embedding level (0-61) + unsigned short override : 1; // Set when in LRO/RLO embedding + unsigned short reserved : 2; + bool operator == ( const TQScriptAnalysis &other ) { + return + script == other.script && + bidiLevel == other.bidiLevel; + // ### +// && override == other.override; + } + +}; + +#elif defined( TQ_WS_WIN ) + +// do not change the definitions below unless you know what you are doing! +// it is designed to be compatible with the types found in uniscribe. + +typedef unsigned short glyph_t; + +struct qoffset_t { + int x; + int y; +}; + +typedef int advance_t; + +struct TQScriptAnalysis { + unsigned short script :10; + unsigned short rtl :1; + unsigned short layoutRTL :1; + unsigned short linkBefore :1; + unsigned short linkAfter :1; + unsigned short logicalOrder :1; + unsigned short noGlyphIndex :1; + unsigned short bidiLevel :5; + unsigned short override :1; + unsigned short inhibitSymSwap :1; + unsigned short charShape :1; + unsigned short digitSubstitute :1; + unsigned short inhibitLigate :1; + unsigned short fDisplayZWG :1; + unsigned short arabicNumContext :1; + unsigned short gcpClusters :1; + unsigned short reserved :1; + unsigned short engineReserved :2; +}; + +inline bool operator == ( const TQScriptAnalysis &sa1, const TQScriptAnalysis &sa2 ) +{ + return + sa1.script == sa2.script && + sa1.bidiLevel == sa2.bidiLevel; + // ### +// && override == other.override; +} + +#endif + +// enum and struct are made to be compatible with Uniscribe, dont change unless you know what you're doing. +struct GlyphAttributes { + // highest value means highest priority for justification. Justification is done by first inserting kashidas + // starting with the highest priority positions, then stretching spaces, afterwards extending inter char + // spacing, and last spacing between arabic words. + // NoJustification is for example set for arabic where no Kashida can be inserted or for diacritics. + enum Justification { + NoJustification= 0, // Justification can't be applied after this glyph + Arabic_Space = 1, // This glyph represents a space inside arabic text + Character = 2, // Inter-character justification point follows this glyph + Space = 4, // This glyph represents a blank outside an Arabic run + Arabic_Normal = 7, // Normal Middle-Of-Word glyph that connects to the right (begin) + Arabic_Waw = 8, // Next character is final form of Waw/Ain/Qaf/Fa + Arabic_BaRa = 9, // Next two chars are Ba + Ra/Ya/AlefMaksura + Arabic_Alef = 10, // Next character is final form of Alef/Tah/Lam/Kaf/Gaf + Arabic_HaaDal = 11, // Next character is final form of Haa/Dal/Taa Marbutah + Arabic_Seen = 12, // Initial or Medial form Of Seen/Sad + Arabic_Kashida = 13 // Kashida(U+640) in middle of word + }; + unsigned short justification :4; // Justification class + unsigned short clusterStart :1; // First glyph of representation of cluster + unsigned short mark :1; // needs to be positioned around base char + unsigned short zeroWidth :1; // ZWJ, ZWNJ etc, with no width, currently used as "Don't print" for ZWSP + unsigned short reserved :1; + unsigned short combiningClass :8; +}; + +// also this is compatible to uniscribe. Do not change. +struct TQCharAttributes { + uchar softBreak :1; // Potential linebreak point _before_ this character + 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 invalid :1; + uchar reserved :3; +}; + +inline bool qIsZeroWidthChar(ushort uc) +{ + return (uc >= 0x200b && uc <= 0x200f /* ZW Space, ZWNJ, ZWJ, LRM and RLM */) + || (uc >= 0x2028 && uc <= 0x202f /* LS, PS, LRE, RLE, PDF, LRO, RLO, NNBSP */) + || (uc >= 0x206a && uc <= 0x206f /* ISS, ASS, IAFS, AFS, NADS, NODS */); +} + +class TQFontEngine; + +struct TQScriptItem +{ + inline TQScriptItem() : position( 0 ), isSpace( FALSE ), isTab( FALSE ), + isObject( FALSE ), hasPositioning( FALSE ), + descent( -1 ), ascent( -1 ), width( -1 ), + x( 0 ), y( 0 ), num_glyphs( 0 ), glyph_data_offset( 0 ), + fontEngine( 0 ) { } + int position; + TQScriptAnalysis analysis; + unsigned short isSpace : 1; + unsigned short isTab : 1; + unsigned short isObject : 1; + unsigned short hasPositioning : 1; + unsigned short complex : 1; // Windows only + unsigned short private_use : 1; // Windows only + unsigned short reserved : 10; + short descent; + int ascent; + int width; + int x; + int y; + int num_glyphs; + int glyph_data_offset; + TQFontEngine *fontEngine; +}; + +struct TQScriptItemArrayPrivate +{ + unsigned int alloc; + unsigned int size; + TQScriptItem items[1]; +}; + +class TQScriptItemArray +{ +public: + TQScriptItemArray() : d( 0 ) {} + ~TQScriptItemArray(); + + inline TQScriptItem &operator[] (int i) const {return d->items[i]; } + inline void append( const TQScriptItem &item ) { + if ( d->size == d->alloc ) + resize( d->size + 1 ); + d->items[d->size] = item; + d->size++; + } + inline int size() const { return d ? d->size : 0; } + + void resize( int s ); + void clear(); + + TQScriptItemArrayPrivate *d; +private: +#ifdef TQ_DISABLE_COPY + TQScriptItemArray( const TQScriptItemArray & ); + TQScriptItemArray &operator = ( const TQScriptItemArray & ); +#endif +}; + +class TQFontPrivate; + +class TQ_EXPORT TQTextEngine { +public: + TQTextEngine( const TQString &str, TQFontPrivate *f ); + ~TQTextEngine(); + + enum Mode { + Full = 0x00, + NoBidi = 0x01, + SingleLine = 0x02, + WidthOnly = 0x07 + }; + + void itemize( int mode = Full ); + + static void bidiReorder( int numRuns, const TQ_UINT8 *levels, int *visualOrder ); + + const TQCharAttributes *attributes(); + void shape( int item ) const; + + // ### we need something for justification + + enum Edge { + Leading, + Trailing + }; + enum ShaperFlag { + RightToLeft = 0x0001, + Mirrored = 0x0001 + }; + + int width( int charFrom, int numChars ) const; + glyph_metrics_t boundingBox( int from, int len ) const; + + TQScriptItemArray items; + TQString string; + TQFontPrivate *fnt; + int lineWidth; + int widthUsed; + int firstItemInLine; + int currentItem; + TQChar::Direction direction : 5; + unsigned int haveCharAttributes : 1; + unsigned int widthOnly : 1; + unsigned int reserved : 25; + + int length( int item ) const { + const TQScriptItem &si = items[item]; + int from = si.position; + item++; + return ( item < items.size() ? items[item].position : string.length() ) - from; + } + void splitItem( int item, int pos ); + + unsigned short *logClustersPtr; + glyph_t *glyphPtr; + advance_t *advancePtr; + qoffset_t *offsetsPtr; + GlyphAttributes *glyphAttributesPtr; + + inline unsigned short *logClusters( const TQScriptItem *si ) const + { return logClustersPtr+si->position; } + inline glyph_t *glyphs( const TQScriptItem *si ) const + { return glyphPtr+si->glyph_data_offset; } + inline advance_t *advances( const TQScriptItem *si ) const + { return advancePtr+si->glyph_data_offset; } + inline qoffset_t *offsets( const TQScriptItem *si ) const + { return offsetsPtr+si->glyph_data_offset; } + inline GlyphAttributes *glyphAttributes( const TQScriptItem *si ) const + { return glyphAttributesPtr+si->glyph_data_offset; } + + void reallocate( int totalGlyphs ); + inline void ensureSpace( int nGlyphs ) const { + if ( num_glyphs - used < nGlyphs ) + ((TQTextEngine *)this)->reallocate( ( (used + nGlyphs + 16) >> 4 ) << 4 ); + } + + int allocated; + void **memory; + int num_glyphs; + int used; +}; + +#endif diff --git a/src/kernel/tqtextengine_unix.cpp b/src/kernel/tqtextengine_unix.cpp new file mode 100644 index 000000000..0d5e3b920 --- /dev/null +++ b/src/kernel/tqtextengine_unix.cpp @@ -0,0 +1,127 @@ +/**************************************************************************** +** +** Text engine classes +** +** Copyright (C) 2005-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 + + +TQScriptItemArray::~TQScriptItemArray() +{ + clear(); + free( d ); +} + +void TQScriptItemArray::clear() +{ + if ( d ) { + for ( unsigned int i = 0; i < d->size; i++ ) { + TQScriptItem &si = d->items[i]; + if ( si.fontEngine ) + si.fontEngine->deref(); + } + d->size = 0; + } +} + +void TQScriptItemArray::resize( int s ) +{ + int alloc = (s + 8) >> 3 << 3; + d = (TQScriptItemArrayPrivate *)realloc( d, sizeof( TQScriptItemArrayPrivate ) + + sizeof( TQScriptItem ) * alloc ); + d->alloc = alloc; +} + +void TQTextEngine::shape( int item ) const +{ + assert( item < items.size() ); + TQScriptItem &si = items[item]; + + if ( si.num_glyphs ) + return; + + TQFont::Script script = (TQFont::Script)si.analysis.script; + si.glyph_data_offset = used; + + if ( !si.fontEngine ) + si.fontEngine = fnt->engineForScript( script ); + si.fontEngine->ref(); + + si.ascent = si.fontEngine->ascent(); + si.descent = si.fontEngine->descent(); + si.num_glyphs = 0; + + if ( si.fontEngine && si.fontEngine != (TQFontEngine*)-1 ) { + TQShaperItem shaper_item; + shaper_item.script = si.analysis.script; + shaper_item.string = &string; + shaper_item.from = si.position; + shaper_item.length = length(item); + shaper_item.font = si.fontEngine; + shaper_item.num_glyphs = TQMAX(int(num_glyphs - used), shaper_item.length); + shaper_item.flags = si.analysis.bidiLevel % 2 ? RightToLeft : 0; + shaper_item.has_positioning = FALSE; + + while (1) { +// tqDebug(" . num_glyphs=%d, used=%d, item.num_glyphs=%d", num_glyphs, used, shaper_item.num_glyphs); + ensureSpace(shaper_item.num_glyphs); + shaper_item.num_glyphs = num_glyphs - used; +// tqDebug(" .. num_glyphs=%d, used=%d, item.num_glyphs=%d", num_glyphs, used, shaper_item.num_glyphs); + shaper_item.glyphs = glyphs(&si); + shaper_item.advances = advances(&si); + shaper_item.offsets = offsets(&si); + shaper_item.attributes = glyphAttributes(&si); + shaper_item.log_clusters = logClusters(&si); + if (scriptEngines[shaper_item.script].shape(&shaper_item)) + break; + } + + si.num_glyphs = shaper_item.num_glyphs; + si.hasPositioning = shaper_item.has_positioning; + } + ((TQTextEngine *)this)->used += si.num_glyphs; + + si.width = 0; + advance_t *advances = this->advances( &si ); + advance_t *end = advances + si.num_glyphs; + while ( advances < end ) { +// tqDebug("advances[%d] = %d", advances - this->advances(&si), *advances); + si.width += *(advances++); + } + + return; +} + diff --git a/src/kernel/tqtextlayout.cpp b/src/kernel/tqtextlayout.cpp new file mode 100644 index 000000000..41be6076a --- /dev/null +++ b/src/kernel/tqtextlayout.cpp @@ -0,0 +1,643 @@ +/**************************************************************************** +** +** ??? +** +** Copyright (C) 2005-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 "tqtextlayout_p.h" +#include "tqtextengine_p.h" + +#include +#include +#include + + +TQRect TQTextItem::rect() const +{ + TQScriptItem& si = engine->items[item]; + return TQRect( si.x, si.y, si.width, si.ascent+si.descent ); +} + +int TQTextItem::x() const +{ + return engine->items[item].x; +} + +int TQTextItem::y() const +{ + return engine->items[item].y; +} + +int TQTextItem::width() const +{ + return engine->items[item].width; +} + +int TQTextItem::ascent() const +{ + return engine->items[item].ascent; +} + +int TQTextItem::descent() const +{ + return engine->items[item].descent; +} + +void TQTextItem::setWidth( int w ) +{ + engine->items[item].width = w; +} + +void TQTextItem::setAscent( int a ) +{ + engine->items[item].ascent = a; +} + +void TQTextItem::setDescent( int d ) +{ + engine->items[item].descent = d; +} + +int TQTextItem::from() const +{ + return engine->items[item].position; +} + +int TQTextItem::length() const +{ + return engine->length(item); +} + + +int TQTextItem::cursorToX( int *cPos, Edge edge ) const +{ + int pos = *cPos; + TQScriptItem *si = &engine->items[item]; + + engine->shape( item ); + advance_t *advances = engine->advances( si ); + GlyphAttributes *glyphAttributes = engine->glyphAttributes( si ); + unsigned short *logClusters = engine->logClusters( si ); + + int l = engine->length( item ); + if ( pos > l ) + pos = l; + if ( pos < 0 ) + pos = 0; + + int glyph_pos = pos == l ? si->num_glyphs : logClusters[pos]; + if ( edge == Trailing ) { + // trailing edge is leading edge of next cluster + while ( glyph_pos < si->num_glyphs && !glyphAttributes[glyph_pos].clusterStart ) + glyph_pos++; + } + + int x = 0; + bool reverse = engine->items[item].analysis.bidiLevel % 2; + + if ( reverse ) { + for ( int i = si->num_glyphs-1; i >= glyph_pos; i-- ) + x += advances[i]; + } else { + for ( int i = 0; i < glyph_pos; i++ ) + x += advances[i]; + } +// tqDebug("cursorToX: pos=%d, gpos=%d x=%d", pos, glyph_pos, x ); + *cPos = pos; + return x; +} + +int TQTextItem::xToCursor( int x, CursorPosition cpos ) const +{ + TQScriptItem *si = &engine->items[item]; + engine->shape( item ); + advance_t *advances = engine->advances( si ); + unsigned short *logClusters = engine->logClusters( si ); + + int l = engine->length( item ); + bool reverse = si->analysis.bidiLevel % 2; + if ( x < 0 ) + return reverse ? l : 0; + + + if ( reverse ) { + int width = 0; + for ( int i = 0; i < si->num_glyphs; i++ ) { + width += advances[i]; + } + x = -x + width; + } + int cp_before = 0; + int cp_after = 0; + int x_before = 0; + int x_after = 0; + + int lastCluster = 0; + for ( int i = 1; i <= l; i++ ) { + int newCluster = i < l ? logClusters[i] : si->num_glyphs; + if ( newCluster != lastCluster ) { + // calculate cluster width + cp_before = cp_after; + x_before = x_after; + cp_after = i; + for ( int j = lastCluster; j < newCluster; j++ ) + x_after += advances[j]; + // tqDebug("cluster boundary: lastCluster=%d, newCluster=%d, x_before=%d, x_after=%d", + // lastCluster, newCluster, x_before, x_after ); + if ( x_after > x ) + break; + lastCluster = newCluster; + } + } + + bool before = ( cpos == OnCharacters || (x - x_before) < (x_after - x) ); + +// tqDebug("got cursor position for %d: %d/%d, x_ba=%d/%d using %d", +// x, cp_before,cp_after, x_before, x_after, before ? cp_before : cp_after ); + + return before ? cp_before : cp_after; + +} + + +bool TQTextItem::isRightToLeft() const +{ + return (engine->items[item].analysis.bidiLevel % 2); +} + +bool TQTextItem::isObject() const +{ + return engine->items[item].isObject; +} + +bool TQTextItem::isSpace() const +{ + return engine->items[item].isSpace; +} + +bool TQTextItem::isTab() const +{ + return engine->items[item].isTab; +} + + +TQTextLayout::TQTextLayout() + :d(0) {} + +TQTextLayout::TQTextLayout( const TQString& string, TQPainter *p ) +{ + TQFontPrivate *f = p ? ( p->pfont ? p->pfont->d : p->cfont.d ) : TQApplication::font().d; + d = new TQTextEngine( (string.isNull() ? (const TQString&)TQString::fromLatin1("") : string), f ); +} + +TQTextLayout::TQTextLayout( const TQString& string, const TQFont& fnt ) +{ + d = new TQTextEngine( (string.isNull() ? (const TQString&)TQString::fromLatin1("") : string), fnt.d ); +} + +TQTextLayout::~TQTextLayout() +{ + delete d; +} + +void TQTextLayout::setText( const TQString& string, const TQFont& fnt ) +{ + delete d; + d = new TQTextEngine( (string.isNull() ? (const TQString&)TQString::fromLatin1("") : string), fnt.d ); +} + +/* add an additional item boundary eg. for style change */ +void TQTextLayout::setBoundary( int strPos ) +{ + if ( strPos <= 0 || strPos >= (int)d->string.length() ) + return; + + int itemToSplit = 0; + while ( itemToSplit < d->items.size() && d->items[itemToSplit].position <= strPos ) + itemToSplit++; + itemToSplit--; + if ( d->items[itemToSplit].position == strPos ) { + // already a split at the requested position + return; + } + d->splitItem( itemToSplit, strPos - d->items[itemToSplit].position ); +} + + +int TQTextLayout::numItems() const +{ + return d->items.size(); +} + +TQTextItem TQTextLayout::itemAt( int i ) const +{ + return TQTextItem( i, d ); +} + + +TQTextItem TQTextLayout::findItem( int strPos ) const +{ + if ( strPos == 0 && d->items.size() ) + return TQTextItem( 0, d ); + // ## TODO use bsearch + for ( int i = d->items.size()-1; i >= 0; --i ) { + if ( d->items[i].position < strPos ) + return TQTextItem( i, d ); + } + return TQTextItem(); +} + + +void TQTextLayout::beginLayout( TQTextLayout::LayoutMode m ) +{ + d->items.clear(); + TQTextEngine::Mode mode = TQTextEngine::Full; + if (m == NoBidi) + mode = TQTextEngine::NoBidi; + else if (m == SingleLine) + mode = TQTextEngine::SingleLine; + d->itemize( mode ); + d->currentItem = 0; + d->firstItemInLine = -1; +} + +void TQTextLayout::beginLine( int width ) +{ + d->lineWidth = width; + d->widthUsed = 0; + d->firstItemInLine = -1; +} + +bool TQTextLayout::atEnd() const +{ + return d->currentItem >= d->items.size(); +} + +TQTextItem TQTextLayout::nextItem() +{ + d->currentItem++; + + if ( d->currentItem >= d->items.size() ) + return TQTextItem(); + + d->shape( d->currentItem ); + return TQTextItem( d->currentItem, d ); +} + +TQTextItem TQTextLayout::currentItem() +{ + if ( d->currentItem >= d->items.size() ) + return TQTextItem(); + + d->shape( d->currentItem ); + return TQTextItem( d->currentItem, d ); +} + +/* ## maybe also currentItem() */ +void TQTextLayout::setLineWidth( int newWidth ) +{ + d->lineWidth = newWidth; +} + +int TQTextLayout::lineWidth() const +{ + return d->lineWidth; +} + +int TQTextLayout::widthUsed() const +{ + return d->widthUsed; +} + +int TQTextLayout::availableWidth() const +{ + return d->lineWidth - d->widthUsed; +} + + +/* returns true if completely added */ +TQTextLayout::Result TQTextLayout::addCurrentItem() +{ + if ( d->firstItemInLine == -1 ) + d->firstItemInLine = d->currentItem; + TQScriptItem ¤t = d->items[d->currentItem]; + d->shape( d->currentItem ); + d->widthUsed += current.width; +// tqDebug("trying to add item %d with width %d, remaining %d", d->currentItem, current.width, d->lineWidth-d->widthUsed ); + + d->currentItem++; + + return (d->widthUsed <= d->lineWidth + || (d->currentItem < d->items.size() && d->items[d->currentItem].isSpace)) ? Ok : LineFull; +} + +TQTextLayout::Result TQTextLayout::endLine( int x, int y, int alignment, + int *ascent, int *descent, int *lineLeft, int *lineRight ) +{ + int available = d->lineWidth; + int numRuns = 0; + int numSpaceItems = 0; + TQ_UINT8 _levels[128]; + int _visual[128]; + TQ_UINT8 *levels = _levels; + int *visual = _visual; + int i; + TQTextLayout::Result result = LineEmpty; + +// tqDebug("endLine x=%d, y=%d, first=%d, current=%d lw=%d wu=%d", x, y, d->firstItemInLine, d->currentItem, d->lineWidth, d->widthUsed ); + int width_nobreak_found = d->widthUsed; + if ( d->firstItemInLine == -1 ) + goto end; + + if ( !(alignment & (TQt::SingleLine|TQt::IncludeTrailingSpaces)) + && d->currentItem > d->firstItemInLine && d->items[d->currentItem-1].isSpace ) { + int i = d->currentItem-1; + while ( i > d->firstItemInLine && d->items[i].isSpace ) { + numSpaceItems++; + d->widthUsed -= d->items[i--].width; + } + } + + if ( (alignment & (TQt::WordBreak|TQt::BreakAnywhere)) && + d->widthUsed > d->lineWidth ) { + // find linebreak + + // even though we removed trailing spaces the line was too wide. We'll have to break at an earlier + // position. To not confuse the layouting below, reset the number of space items + numSpaceItems = 0; + + + bool breakany = alignment & TQt::BreakAnywhere; + + const TQCharAttributes *attrs = d->attributes(); + int w = 0; + int itemWidth = 0; + int breakItem = d->firstItemInLine; + int breakPosition = -1; +#if 0 + // we iterate backwards or forward depending on what we guess is closer + if ( d->widthUsed - d->lineWidth < d->lineWidth ) { + // backwards search should be faster + + } else +#endif + { + int tmpWidth = 0; + int swidth = 0; + // forward search is probably faster + for ( int i = d->firstItemInLine; i < d->currentItem; i++ ) { + const TQScriptItem *si = &d->items[i]; + int length = d->length( i ); + const TQCharAttributes *itemAttrs = attrs + si->position; + + advance_t *advances = d->advances( si ); + unsigned short *logClusters = d->logClusters( si ); + + int lastGlyph = 0; + int tmpItemWidth = 0; + +// tqDebug("looking for break in item %d, isSpace=%d", i, si->isSpace ); + if(si->isSpace && !(alignment & (TQt::SingleLine|TQt::IncludeTrailingSpaces))) { + swidth += si->width; + } else { + tmpWidth += swidth; + swidth = 0; + for ( int pos = 0; pos < length; pos++ ) { +// tqDebug("advance=%d, w=%d, tmpWidth=%d, softbreak=%d, whitespace=%d", +// *advances, w, tmpWidth, itemAttrs->softBreak, itemAttrs->whiteSpace ); + int glyph = logClusters[pos]; + if ( lastGlyph != glyph ) { + while ( lastGlyph < glyph ) + tmpItemWidth += advances[lastGlyph++]; + if ( breakPosition != -1 && w + tmpWidth + tmpItemWidth > d->lineWidth ) { +// tqDebug("found break at w=%d, tmpWidth=%d, tmpItemWidth=%d", w, tmpWidth, tmpItemWidth); + d->widthUsed = w; + goto found; + } + } + if ( (itemAttrs->softBreak || + ( breakany && itemAttrs->charStop ) ) && + (i != d->firstItemInLine || pos != 0) ) { + if ( breakItem != i ) + itemWidth = 0; + if (itemAttrs->softBreak) + breakany = FALSE; + breakItem = i; + breakPosition = pos; +// tqDebug("found possible break at item %d, position %d (absolute=%d), w=%d, tmpWidth=%d, tmpItemWidth=%d", breakItem, breakPosition, d->items[breakItem].position+breakPosition, w, tmpWidth, tmpItemWidth); + w += tmpWidth + tmpItemWidth; + itemWidth += tmpItemWidth; + tmpWidth = 0; + tmpItemWidth = 0; + } + itemAttrs++; + } + while ( lastGlyph < si->num_glyphs ) + tmpItemWidth += advances[lastGlyph++]; + tmpWidth += tmpItemWidth; + if ( w + tmpWidth > d->lineWidth ) { + d->widthUsed = w; + goto found; + } + } + } + } + + found: + // no valid break point found + if ( breakPosition == -1 ) { + d->widthUsed = width_nobreak_found; + goto nobreak; + } + +// tqDebug("linebreak at item %d, position %d, wu=%d", breakItem, breakPosition, d->widthUsed ); + // split the line + if ( breakPosition > 0 ) { +// int length = d->length( breakItem ); + +// tqDebug("splitting item, itemWidth=%d", itemWidth); + // not a full item, need to break + d->splitItem( breakItem, breakPosition ); + d->currentItem = breakItem+1; + } else { + d->currentItem = breakItem; + } + } + + result = Ok; + + nobreak: + // position the objects in the line + available -= d->widthUsed; + + numRuns = d->currentItem - d->firstItemInLine - numSpaceItems; + if ( numRuns > 127 ) { + levels = new TQ_UINT8[numRuns]; + visual = new int[numRuns]; + } + +// tqDebug("reordering %d runs, numSpaceItems=%d", numRuns, numSpaceItems ); + for ( i = 0; i < numRuns; i++ ) { + levels[i] = d->items[i+d->firstItemInLine].analysis.bidiLevel; +// tqDebug(" level = %d", d->items[i+d->firstItemInLine].analysis.bidiLevel ); + } + d->bidiReorder( numRuns, levels, visual ); + + end: + // ### FIXME + if ( alignment & TQt::AlignJustify ) { + // #### justify items + alignment = TQt::AlignAuto; + } + if ( (alignment & TQt::AlignHorizontal_Mask) == TQt::AlignAuto ) + alignment = TQt::AlignLeft; + if ( alignment & TQt::AlignRight ) + x += available; + else if ( alignment & TQt::AlignHCenter ) + x += available/2; + + + int asc = ascent ? *ascent : 0; + int desc = descent ? *descent : 0; + + for ( i = 0; i < numRuns; i++ ) { + TQScriptItem &si = d->items[d->firstItemInLine+visual[i]]; + asc = TQMAX( asc, si.ascent ); + desc = TQMAX( desc, si.descent ); + } + + int left = x; + for ( i = 0; i < numRuns; i++ ) { + TQScriptItem &si = d->items[d->firstItemInLine+visual[i]]; +// tqDebug("positioning item %d with width %d (from=%d/length=%d) at %d", d->firstItemInLine+visual[i], si.width, si.position, +// d->length(d->firstItemInLine+visual[i]), x ); + si.x = x; + si.y = y + asc; + x += si.width; + } + int right = x; + + if ( numSpaceItems ) { + if ( d->items[d->firstItemInLine+numRuns].analysis.bidiLevel % 2 ) { + x = left; + for ( i = 0; i < numSpaceItems; i++ ) { + TQScriptItem &si = d->items[d->firstItemInLine + numRuns + i]; + x -= si.width; + si.x = x; + si.y = y + asc; + } + } else { + for ( i = 0; i < numSpaceItems; i++ ) { + TQScriptItem &si = d->items[d->firstItemInLine + numRuns + i]; + si.x = x; + si.y = y + asc; + x += si.width; + } + } + } + + if ( lineLeft ) + *lineLeft = left; + if ( lineRight ) + *lineRight = right; + if ( ascent ) + *ascent = asc; + if ( descent ) + *descent = desc; + + if (levels != _levels) + delete []levels; + if (visual != _visual) + delete []visual; + + return result; +} + +void TQTextLayout::endLayout() +{ + // nothing to do currently +} + + +int TQTextLayout::nextCursorPosition( int oldPos, CursorMode mode ) const +{ +// tqDebug("looking for next cursor pos for %d", oldPos ); + const TQCharAttributes *attributes = d->attributes(); + int len = d->string.length(); + if ( oldPos >= len ) + return oldPos; + oldPos++; + if ( mode == SkipCharacters ) { + while ( oldPos < len && !attributes[oldPos].charStop ) + oldPos++; + } else { + while ( oldPos < len && !attributes[oldPos].wordStop && !attributes[oldPos-1].whiteSpace ) + oldPos++; + } +// tqDebug(" -> %d", oldPos ); + return oldPos; +} + +int TQTextLayout::previousCursorPosition( int oldPos, CursorMode mode ) const +{ +// tqDebug("looking for previous cursor pos for %d", oldPos ); + const TQCharAttributes *attributes = d->attributes(); + if ( oldPos <= 0 ) + return 0; + oldPos--; + if ( mode == SkipCharacters ) { + while ( oldPos && !attributes[oldPos].charStop ) + oldPos--; + } else { + while ( oldPos && !attributes[oldPos].wordStop && !attributes[oldPos-1].whiteSpace ) + oldPos--; + } +// tqDebug(" -> %d", oldPos ); + return oldPos; +} + + +bool TQTextLayout::validCursorPosition( int pos ) const +{ + const TQCharAttributes *attributes = d->attributes(); + if ( pos < 0 || pos > (int)d->string.length() ) + return FALSE; + return attributes[pos].charStop; +} + +void TQTextLayout::setDirection(TQChar::Direction dir) +{ + d->direction = dir; +} diff --git a/src/kernel/tqtextlayout_p.h b/src/kernel/tqtextlayout_p.h new file mode 100644 index 000000000..64c7f64db --- /dev/null +++ b/src/kernel/tqtextlayout_p.h @@ -0,0 +1,184 @@ +/**************************************************************************** +** +** ??? +** +** 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. +** +** 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 TQTEXTLAYOUT_P_H +#define TQTEXTLAYOUT_P_H + +#ifndef QT_H +#include "tqstring.h" +#include "ntqnamespace.h" +#include "ntqrect.h" +#endif // QT_H + +class TQTextEngine; +class TQFont; + +class TQ_EXPORT TQTextItem +{ +public: + inline TQTextItem() : item(0), engine(0) {} + inline bool isValid() const { return (bool)engine; } + + TQRect rect() const; + int x() const; + int y() const; + int width() const; + int ascent() const; + int descent() const; + + enum Edge { + Leading, + Trailing + }; + enum CursorPosition { + BetweenCharacters, + OnCharacters + }; + + /* cPos gets set to the valid position */ + int cursorToX( int *cPos, Edge edge = Leading ) const; + inline int cursorToX( int cPos, Edge edge = Leading ) const { return cursorToX( &cPos, edge ); } + int xToCursor( int x, CursorPosition = BetweenCharacters ) const; + + bool isRightToLeft() const; + bool isObject() const; + bool isSpace() const; + bool isTab() const; + + void setWidth( int w ); + void setAscent( int a ); + void setDescent( int d ); + + int from() const; + int length() const; + +private: + friend class TQTextLayout; + friend class TQPainter; + friend class TQPSPrinter; + TQTextItem( int i, TQTextEngine *e ) : item( i ), engine( e ) {} + int item; + TQTextEngine *engine; +}; + + +class TQPainter; + +class TQ_EXPORT TQTextLayout +{ +public: + // does itemization + TQTextLayout(); + TQTextLayout( const TQString& string, TQPainter * = 0 ); + TQTextLayout( const TQString& string, const TQFont& fnt ); + ~TQTextLayout(); + + void setText( const TQString& string, const TQFont& fnt ); + + enum LineBreakStrategy { + AtWordBoundaries, + AtCharBoundaries + }; + + /* add an additional item boundary eg. for style change */ + void setBoundary( int strPos ); + + int numItems() const; + TQTextItem itemAt( int i ) const; + TQTextItem findItem( int strPos ) const; + + enum LayoutMode { + NoBidi, + SingleLine, + MultiLine + }; + void beginLayout( LayoutMode m = MultiLine ); + void beginLine( int width ); + + bool atEnd() const; + TQTextItem nextItem(); + TQTextItem currentItem(); + /* ## maybe also currentItem() */ + void setLineWidth( int newWidth ); + int lineWidth() const; + int widthUsed() const; + int availableWidth() const; + + enum Result { + Ok, + LineFull, + LineEmpty, + Error + }; + /* returns true if completely added */ + Result addCurrentItem(); + + /* Note: if ascent and descent are used they must be initialized to the minimum ascent/descent + acceptable for the line. TQFontMetrics::ascent/descent() is usually the right choice */ + Result endLine( int x = 0, int y = 0, int alignment = TQt::AlignLeft, + int *ascent = 0, int *descent = 0, int *left = 0, int *right = 0 ); + void endLayout(); + + enum CursorMode { + SkipCharacters, + SkipWords + }; + bool validCursorPosition( int pos ) const; + int nextCursorPosition( int oldPos, CursorMode mode = SkipCharacters ) const; + int previousCursorPosition( int oldPos, CursorMode mode = SkipCharacters ) const; + + void setDirection(TQChar::Direction); +private: + TQTextLayout( TQTextEngine *e ) : d( e ) {} + /* disable copy and assignment */ + TQTextLayout( const TQTextLayout & ) {} + void operator = ( const TQTextLayout & ) {} + + friend class TQTextItem; + friend class TQPainter; + friend class TQPSPrinter; + TQTextEngine *d; +}; + + +/* + class TQPainter { + ..... + void drawTextItem( int x, int y, TQTextItem *item ); + }; +*/ + +#endif diff --git a/src/kernel/tqwidget_x11.cpp b/src/kernel/tqwidget_x11.cpp index ff33dddbf..78d1e850e 100644 --- a/src/kernel/tqwidget_x11.cpp +++ b/src/kernel/tqwidget_x11.cpp @@ -47,7 +47,7 @@ #include "tqimage.h" #include "tqobjectlist.h" #include "ntqlayout.h" -#include "ntqtextcodec.h" +#include "tqtextcodec.h" #include "ntqdatetime.h" #include "ntqcursor.h" #include "qt_x11_p.h" @@ -3055,7 +3055,7 @@ void TQWidget::destroyInputContext() /*! This function is called when text widgets need to be neutral state to - execute text operations properly. See qlineedit.cpp and qtextedit.cpp as + execute text operations properly. See qlineedit.cpp and tqtextedit.cpp as example. Ordinary reset that along with changing focus to another widget, diff --git a/src/moc/moc.pro b/src/moc/moc.pro index e2f92ef17..566a8589f 100644 --- a/src/moc/moc.pro +++ b/src/moc/moc.pro @@ -31,11 +31,11 @@ SOURCES = ../tools/qbuffer.cpp \ ../tools/qlocale.cpp \ ../tools/qunicodetables.cpp \ ../tools/tqstringlist.cpp \ - ../tools/qtextstream.cpp \ + ../tools/tqtextstream.cpp \ ../tools/qbitarray.cpp \ ../tools/tqmap.cpp \ ../tools/qgcache.cpp \ - ../codecs/qtextcodec.cpp \ + ../codecs/tqtextcodec.cpp \ ../codecs/qutfcodec.cpp isEmpty(QT_PRODUCT)|contains(QT_PRODUCT, qt-internal) { diff --git a/src/network/qdns.cpp b/src/network/qdns.cpp index 4be302d5a..dc641569a 100644 --- a/src/network/qdns.cpp +++ b/src/network/qdns.cpp @@ -74,7 +74,7 @@ #include "tqstrlist.h" #include "tqptrdict.h" #include "ntqfile.h" -#include "ntqtextstream.h" +#include "tqtextstream.h" #include "ntqsocketdevice.h" #include "ntqcleanuphandler.h" #include diff --git a/src/network/qftp.cpp b/src/network/qftp.cpp index ac4d442e0..b5da887d6 100644 --- a/src/network/qftp.cpp +++ b/src/network/qftp.cpp @@ -53,7 +53,7 @@ #include "tqptrdict.h" // binary compatibility #ifndef TQT_NO_TEXTCODEC -#include "ntqtextcodec.h" +#include "tqtextcodec.h" #endif //#define TQFTPPI_DEBUG diff --git a/src/network/qhttp.cpp b/src/network/qhttp.cpp index 8f88e0340..b37d4789d 100644 --- a/src/network/qhttp.cpp +++ b/src/network/qhttp.cpp @@ -43,7 +43,7 @@ #ifndef TQT_NO_NETWORKPROTOCOL_HTTP #include "ntqsocket.h" -#include "ntqtextstream.h" +#include "tqtextstream.h" #include "tqmap.h" #include "tqstring.h" #include "tqstringlist.h" diff --git a/src/qt.pro b/src/qt.pro index e66adeef5..e359ea36c 100644 --- a/src/qt.pro +++ b/src/qt.pro @@ -182,14 +182,14 @@ wince-* { $$KERNEL_CPP/ntqgplugin.h \ $$KERNEL_CPP/tqimageformatplugin.h \ $$STYLES_CPP/ntqstyleplugin.h \ - $$CODECS_CPP/ntqtextcodecplugin.h \ + $$CODECS_CPP/tqtextcodecplugin.h \ $$WIDGETS_CPP/tqwidgetplugin.h SOURCES -= $$TOOLS_CPP/qcomlibrary.cpp \ $$KERNEL_CPP/qgplugin.cpp \ $$KERNEL_CPP/tqimageformatplugin.cpp \ $$STYLES_CPP/qstyleplugin.cpp \ - $$CODECS_CPP/qtextcodecplugin.cpp \ + $$CODECS_CPP/tqtextcodecplugin.cpp \ $$WIDGETS_CPP/tqwidgetplugin.cpp } diff --git a/src/styles/qsgistyle.cpp b/src/styles/qsgistyle.cpp index 54b9bfc8c..8fd36f70e 100644 --- a/src/styles/qsgistyle.cpp +++ b/src/styles/qsgistyle.cpp @@ -54,7 +54,7 @@ #include "ntqscrollbar.h" #include "ntqcombobox.h" #include "ntqslider.h" -#include "ntqtextedit.h" +#include "tqtextedit.h" #include "ntqtoolbar.h" #include "ntqlineedit.h" #include "ntqmenubar.h" diff --git a/src/tools/ntqtextstream.h b/src/tools/ntqtextstream.h deleted file mode 100644 index ab2366b39..000000000 --- a/src/tools/ntqtextstream.h +++ /dev/null @@ -1,341 +0,0 @@ -/**************************************************************************** -** -** Definition of TQTextStream class -** -** Created : 940922 -** -** 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 TQTEXTSTREAM_H -#define TQTEXTSTREAM_H - -#ifndef QT_H -#include "ntqiodevice.h" -#include "tqstring.h" -#include -#endif // QT_H - -#ifndef TQT_NO_TEXTSTREAM -class TQTextCodec; -class TQTextDecoder; - -class TQTextStreamPrivate; - -class TQ_EXPORT TQTextStream // text stream class -{ -public: - enum Encoding { Locale, Latin1, Unicode, UnicodeNetworkOrder, - UnicodeReverse, RawUnicode, UnicodeUTF8 }; - - void setEncoding( Encoding ); -#ifndef TQT_NO_TEXTCODEC - void setCodec( TQTextCodec* ); - TQTextCodec *codec(); -#endif - - TQTextStream(); - TQTextStream( TQIODevice * ); - TQTextStream( TQString*, int mode ); - TQTextStream( TQString&, int mode ); // obsolete - TQTextStream( TQByteArray, int mode ); - TQTextStream( FILE *, int mode ); - virtual ~TQTextStream(); - - TQIODevice *device() const; - void setDevice( TQIODevice * ); - void unsetDevice(); - - bool atEnd() const; - bool eof() const; - - TQTextStream &operator>>( TQChar & ); - TQTextStream &operator>>( char & ); - TQTextStream &operator>>( signed short & ); - TQTextStream &operator>>( unsigned short & ); - TQTextStream &operator>>( signed int & ); - TQTextStream &operator>>( unsigned int & ); - TQTextStream &operator>>( signed long & ); - TQTextStream &operator>>( unsigned long & ); - TQTextStream &operator>>( float & ); - TQTextStream &operator>>( double & ); - TQTextStream &operator>>( char * ); - TQTextStream &operator>>( TQString & ); - TQTextStream &operator>>( TQCString & ); - - TQTextStream &operator<<( TQChar ); - TQTextStream &operator<<( char ); - TQTextStream &operator<<( signed short ); - TQTextStream &operator<<( unsigned short ); - TQTextStream &operator<<( signed int ); - TQTextStream &operator<<( unsigned int ); - TQTextStream &operator<<( signed long ); - TQTextStream &operator<<( unsigned long ); - TQTextStream &operator<<( signed long long ); - TQTextStream &operator<<( unsigned long long ); - TQTextStream &operator<<( float ); - TQTextStream &operator<<( double ); - TQTextStream &operator<<( const char* ); - TQTextStream &operator<<( const TQString & ); - TQTextStream &operator<<( const TQCString & ); - TQTextStream &operator<<( void * ); // any pointer - - TQTextStream &readRawBytes( char *, uint len ); - TQTextStream &writeRawBytes( const char* , uint len ); - - TQString readLine(); - TQString read(); - void skipWhiteSpace(); - - enum { - skipws = 0x0001, // skip whitespace on input - left = 0x0002, // left-adjust output - right = 0x0004, // right-adjust output - internal = 0x0008, // pad after sign - bin = 0x0010, // binary format integer - oct = 0x0020, // octal format integer - dec = 0x0040, // decimal format integer - hex = 0x0080, // hex format integer - showbase = 0x0100, // show base indicator - showpoint = 0x0200, // force decimal point (float) - uppercase = 0x0400, // upper-case hex output - showpos = 0x0800, // add '+' to positive integers - scientific= 0x1000, // scientific float output - fixed = 0x2000 // fixed float output - }; - - static const int basefield; // bin | oct | dec | hex - static const int adjustfield; // left | right | internal - static const int floatfield; // scientific | fixed - - int flags() const; - int flags( int f ); - int setf( int bits ); - int setf( int bits, int mask ); - int unsetf( int bits ); - - void reset(); - - int width() const; - int width( int ); - int fill() const; - int fill( int ); - int precision() const; - int precision( int ); - -private: - long input_int(); - void init(); - TQTextStream &output_int( int, unsigned long long, bool ); - - TQIODevice *dev; - - int fflags; - int fwidth; - int fillchar; - int fprec; - bool doUnicodeHeader; - bool owndev; - TQTextCodec *mapper; - TQTextStreamPrivate * d; - TQChar unused1; // ### remove in TQt 4.0 - bool latin1; - bool internalOrder; - bool networkOrder; - void *unused2; // ### remove in TQt 4.0 - - TQChar eat_ws(); - uint ts_getline( TQChar* ); - void ts_ungetc( TQChar ); - TQChar ts_getc(); - uint ts_getbuf( TQChar*, uint ); - void ts_putc(int); - void ts_putc(TQChar); - bool ts_isspace(TQChar); - bool ts_isdigit(TQChar); - ulong input_bin(); - ulong input_oct(); - ulong input_dec(); - ulong input_hex(); - double input_double(); - TQTextStream &writeBlock( const char* p, uint len ); - TQTextStream &writeBlock( const TQChar* p, uint len ); - -private: // Disabled copy constructor and operator= -#if defined(TQ_DISABLE_COPY) - TQTextStream( const TQTextStream & ); - TQTextStream &operator=( const TQTextStream & ); -#endif -}; - -typedef TQTextStream TQTS; - -class TQ_EXPORT TQTextIStream : public TQTextStream { -public: - TQTextIStream( const TQString* s ) : - TQTextStream((TQString*)s,IO_ReadOnly) { } - TQTextIStream( TQByteArray ba ) : - TQTextStream(ba,IO_ReadOnly) { } - TQTextIStream( FILE *f ) : - TQTextStream(f,IO_ReadOnly) { } - -private: // Disabled copy constructor and operator= -#if defined(TQ_DISABLE_COPY) - TQTextIStream( const TQTextIStream & ); - TQTextIStream &operator=( const TQTextIStream & ); -#endif -}; - -class TQ_EXPORT TQTextOStream : public TQTextStream { -public: - TQTextOStream( TQString* s ) : - TQTextStream(s,IO_WriteOnly) { } - TQTextOStream( TQByteArray ba ) : - TQTextStream(ba,IO_WriteOnly) { } - TQTextOStream( FILE *f ) : - TQTextStream(f,IO_WriteOnly) { } - -private: // Disabled copy constructor and operator= -#if defined(TQ_DISABLE_COPY) - TQTextOStream( const TQTextOStream & ); - TQTextOStream &operator=( const TQTextOStream & ); -#endif -}; - -/***************************************************************************** - TQTextStream inline functions - *****************************************************************************/ - -inline TQIODevice *TQTextStream::device() const -{ return dev; } - -inline bool TQTextStream::atEnd() const -{ return dev ? dev->atEnd() : FALSE; } - -inline bool TQTextStream::eof() const -{ return atEnd(); } - -inline int TQTextStream::flags() const -{ return fflags; } - -inline int TQTextStream::flags( int f ) -{ int oldf = fflags; fflags = f; return oldf; } - -inline int TQTextStream::setf( int bits ) -{ int oldf = fflags; fflags |= bits; return oldf; } - -inline int TQTextStream::setf( int bits, int mask ) -{ int oldf = fflags; fflags = (fflags & ~mask) | (bits & mask); return oldf; } - -inline int TQTextStream::unsetf( int bits ) -{ int oldf = fflags; fflags &= ~bits; return oldf; } - -inline int TQTextStream::width() const -{ return fwidth; } - -inline int TQTextStream::width( int w ) -{ int oldw = fwidth; fwidth = w; return oldw; } - -inline int TQTextStream::fill() const -{ return fillchar; } - -inline int TQTextStream::fill( int f ) -{ int oldc = fillchar; fillchar = f; return oldc; } - -inline int TQTextStream::precision() const -{ return fprec; } - -inline int TQTextStream::precision( int p ) -{ int oldp = fprec; fprec = p; return oldp; } - -/*! - Returns one character from the stream, or EOF. -*/ -inline TQChar TQTextStream::ts_getc() -{ TQChar r; return ( ts_getbuf( &r,1 ) == 1 ? r : TQChar((ushort)0xffff) ); } - -/***************************************************************************** - TQTextStream manipulators - *****************************************************************************/ - -typedef TQTextStream & (*TQTSFUNC)(TQTextStream &);// manipulator function -typedef int (TQTextStream::*TQTSMFI)(int); // manipulator w/int argument - -class TQ_EXPORT TQTSManip { // text stream manipulator -public: - TQTSManip( TQTSMFI m, int a ) { mf=m; arg=a; } - void exec( TQTextStream &s ) { (s.*mf)(arg); } -private: - TQTSMFI mf; // TQTextStream member function - int arg; // member function argument -}; - -TQ_EXPORT inline TQTextStream &operator>>( TQTextStream &s, TQTSFUNC f ) -{ return (*f)( s ); } - -TQ_EXPORT inline TQTextStream &operator<<( TQTextStream &s, TQTSFUNC f ) -{ return (*f)( s ); } - -TQ_EXPORT inline TQTextStream &operator<<( TQTextStream &s, TQTSManip m ) -{ m.exec(s); return s; } - -TQ_EXPORT TQTextStream &bin( TQTextStream &s ); // set bin notation -TQ_EXPORT TQTextStream &oct( TQTextStream &s ); // set oct notation -TQ_EXPORT TQTextStream &dec( TQTextStream &s ); // set dec notation -TQ_EXPORT TQTextStream &hex( TQTextStream &s ); // set hex notation -TQ_EXPORT TQTextStream &endl( TQTextStream &s ); // insert EOL ('\n') -TQ_EXPORT TQTextStream &flush( TQTextStream &s ); // flush output -TQ_EXPORT TQTextStream &ws( TQTextStream &s ); // eat whitespace on input -TQ_EXPORT TQTextStream &reset( TQTextStream &s ); // set default flags - -TQ_EXPORT inline TQTSManip qSetW( int w ) -{ - TQTSMFI func = &TQTextStream::width; - return TQTSManip(func,w); -} - -TQ_EXPORT inline TQTSManip qSetFill( int f ) -{ - TQTSMFI func = &TQTextStream::fill; - return TQTSManip(func,f); -} - -TQ_EXPORT inline TQTSManip qSetPrecision( int p ) -{ - TQTSMFI func = &TQTextStream::precision; - return TQTSManip(func,p); -} - -#endif // TQT_NO_TEXTSTREAM -#endif // TQTEXTSTREAM_H diff --git a/src/tools/ntqtl.h b/src/tools/ntqtl.h index 8b8724f9e..712129746 100644 --- a/src/tools/ntqtl.h +++ b/src/tools/ntqtl.h @@ -43,7 +43,7 @@ #ifndef QT_H #include "ntqglobal.h" -#include "ntqtextstream.h" +#include "tqtextstream.h" #include "tqstring.h" #endif // QT_H diff --git a/src/tools/qfeatures.txt b/src/tools/qfeatures.txt index 3c14ef270..fd6cb62cb 100644 --- a/src/tools/qfeatures.txt +++ b/src/tools/qfeatures.txt @@ -194,7 +194,7 @@ SeeAlso: ??? Feature: TEXTSTREAM Section: File I/O Requires: -Name: QTextStream +Name: TQTextStream SeeAlso: ??? Feature: DATASTREAM @@ -993,7 +993,7 @@ SeeAlso: ??? Feature: TEXTVIEW Section: Widgets Requires: TEXTEDIT -Name: QTextView +Name: TQTextView SeeAlso: ??? Feature: TEXTEDIT @@ -1090,7 +1090,7 @@ SeeAlso: ??? Feature: TEXTBROWSER Section: Widgets Requires: TEXTVIEW MIME -Name: QTextBrowser +Name: TQTextBrowser SeeAlso: ??? Feature: LISTBOX @@ -1276,7 +1276,7 @@ SeeAlso: ??? Feature: TEXTCODECPLUGIN Section: Internationalization Requires: COMPONENT TEXTCODEC -Name: QTextCodecPlugin +Name: TQTextCodecPlugin SeeAlso: ??? diff --git a/src/tools/qsettings.cpp b/src/tools/qsettings.cpp index ecaa3f7d6..ebec81889 100644 --- a/src/tools/qsettings.cpp +++ b/src/tools/qsettings.cpp @@ -61,7 +61,7 @@ static inline int qt_open( const char *pathname, int flags, mode_t mode ) #include "ntqfile.h" #include "ntqfileinfo.h" #include "tqmap.h" -#include "ntqtextstream.h" +#include "tqtextstream.h" #include "ntqregexp.h" #include #ifndef NO_ERRNO_H diff --git a/src/tools/qt_tools.pri b/src/tools/qt_tools.pri index 283d7c5ed..54cfd4414 100644 --- a/src/tools/qt_tools.pri +++ b/src/tools/qt_tools.pri @@ -55,7 +55,7 @@ tools { $$TOOLS_H/tqstringlist.h \ $$TOOLS_H/tqstrlist.h \ $$TOOLS_H/tqstrvec.h \ - $$TOOLS_H/ntqtextstream.h \ + $$TOOLS_H/tqtextstream.h \ $$TOOLS_P/qthreadinstance_p.h \ $$TOOLS_H/ntqthreadstorage.h\ $$TOOLS_P/qunicodetables_p.h \ @@ -135,7 +135,7 @@ tools { $$TOOLS_CPP/qsemaphore.cpp \ $$TOOLS_CPP/qsettings.cpp \ $$TOOLS_CPP/tqstringlist.cpp \ - $$TOOLS_CPP/qtextstream.cpp \ + $$TOOLS_CPP/tqtextstream.cpp \ $$TOOLS_CPP/qunicodetables.cpp \ $$TOOLS_CPP/qucom.cpp \ $$TOOLS_CPP/quuid.cpp diff --git a/src/tools/qtextstream.cpp b/src/tools/qtextstream.cpp deleted file mode 100644 index 85059dafc..000000000 --- a/src/tools/qtextstream.cpp +++ /dev/null @@ -1,2632 +0,0 @@ -/**************************************************************************** -** -** Implementation of TQTextStream class -** -** Created : 940922 -** -** 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 "ntqtextstream.h" - -#ifndef TQT_NO_TEXTSTREAM -#include "ntqtextcodec.h" -#include "ntqregexp.h" -#include "ntqbuffer.h" -#include "ntqfile.h" -#include -#include -#include -#ifndef Q_OS_TEMP -#include -#endif - -#if defined(Q_OS_WIN32) -#include "qt_windows.h" -#endif - -/*! - \class TQTextStream ntqtextstream.h - \reentrant - \brief The TQTextStream class provides basic functions for reading - and writing text using a TQIODevice. - - \ingroup io - \ingroup text - \mainclass - - The text stream class has a functional interface that is very - similar to that of the standard C++ iostream class. - - TQt provides several global functions similar to the ones in iostream: - \table - \header \i Function \i Meaning - \row \i bin \i sets the TQTextStream to read/write binary numbers - \row \i oct \i sets the TQTextStream to read/write octal numbers - \row \i dec \i sets the TQTextStream to read/write decimal numbers - \row \i hex \i sets the TQTextStream to read/write hexadecimal numbers - \row \i endl \i forces a line break - \row \i flush \i forces the TQIODevice to flush any buffered data - \row \i ws \i eats any available whitespace (on input) - \row \i reset \i resets the TQTextStream to its default mode (see reset()) - \row \i qSetW(int) \i sets the \link width() field width \endlink - to the given argument - \row \i qSetFill(int) \i sets the \link fill() fill character - \endlink to the given argument - \row \i qSetPrecision(int) \i sets the \link precision() precision - \endlink to the given argument - \endtable - - \warning By default TQTextStream will automatically detect whether - integers in the stream are in decimal, octal, hexadecimal or - binary format when reading from the stream. In particular, a - leading '0' signifies octal, i.e. the sequence "0100" will be - interpreted as 64. - - The TQTextStream class reads and writes text; it is not appropriate - for dealing with binary data (but TQDataStream is). - - By default, output of Unicode text (i.e. TQString) is done using - the local 8-bit encoding. This can be changed using the - setEncoding() method. For input, the TQTextStream will auto-detect - standard Unicode "byte order marked" text files; otherwise the - local 8-bit encoding is used. - - The TQIODevice is set in the constructor, or later using - setDevice(). If the end of the input is reached atEnd() returns - TRUE. Data can be read into variables of the appropriate type - using the operator>>() overloads, or read in its entirety into a - single string using read(), or read a line at a time using - readLine(). Whitespace can be skipped over using skipWhiteSpace(). - You can set flags for the stream using flags() or setf(). The - stream also supports width(), precision() and fill(); use reset() - to reset the defaults. - - \sa TQDataStream -*/ - -/*! - \enum TQTextStream::Encoding - - \value Locale - \value Latin1 - \value Unicode - \value UnicodeNetworkOrder - \value UnicodeReverse - \value RawUnicode - \value UnicodeUTF8 - - See setEncoding() for an explanation of the encodings. -*/ - -/* - \class TQTSManip - - \brief The TQTSManip class is an internal helper class for the - TQTextStream. - - It is generally a very bad idea to use this class directly in - application programs. - - \internal - - This class makes it possible to give the TQTextStream function objects - with arguments, like this: - \code - TQTextStream cout( stdout, IO_WriteOnly ); - cout << setprecision( 8 ); // TQTSManip used here! - cout << 3.14159265358979323846; - \endcode - - The setprecision() function returns a TQTSManip object. - The TQTSManip object contains a pointer to a member function in - TQTextStream and an integer argument. - When serializing a TQTSManip into a TQTextStream, the function - is executed with the argument. -*/ - -/*! \fn TQTSManip::TQTSManip( TQTSMFI m, int a ) - - Constructs a TQTSManip object which will call \a m (a member function - in TQTextStream which accepts a single int) with argument \a a when - TQTSManip::exec() is called. Used internally in e.g. endl: - - \code - s << "some text" << endl << "more text"; - \endcode -*/ - -/*! \fn void TQTSManip::exec( TQTextStream& s ) - - Calls the member function specified in the constructor, for object - \a s. Used internally in e.g. endl: - - \code - s << "some text" << endl << "more text"; - \endcode -*/ - - -/***************************************************************************** - TQTextStream member functions - *****************************************************************************/ - -#if defined(QT_CHECK_STATE) -#undef CHECK_STREAM_PRECOND -#define CHECK_STREAM_PRECOND if ( !dev ) { \ - tqWarning( "TQTextStream: No device" ); \ - return *this; } -#else -#define CHECK_STREAM_PRECOND -#endif - - -#define I_SHORT 0x0010 -#define I_INT 0x0020 -#define I_LONG 0x0030 -#define I_LONGLONG 0x0040 -#define I_TYPE_MASK 0x00f0 - -#define I_BASE_2 TQTS::bin -#define I_BASE_8 TQTS::oct -#define I_BASE_10 TQTS::dec -#define I_BASE_16 TQTS::hex -#define I_BASE_MASK (TQTS::bin | TQTS::oct | TQTS::dec | TQTS::hex) - -#define I_SIGNED 0x0100 -#define I_UNSIGNED 0x0200 -#define I_SIGN_MASK 0x0f00 - - -static const TQChar TQEOF = TQChar((ushort)0xffff); //guaranteed not to be a character. -static const uint getline_buf_size = 256; // bufsize used by ts_getline() - -const int TQTextStream::basefield = I_BASE_MASK; -const int TQTextStream::adjustfield = ( TQTextStream::left | - TQTextStream::right | - TQTextStream::internal ); -const int TQTextStream::floatfield = ( TQTextStream::scientific | - TQTextStream::fixed ); - - -class TQTextStreamPrivate { -public: -#ifndef TQT_NO_TEXTCODEC - TQTextStreamPrivate() - : decoder( 0 ), encoder( 0 ), sourceType( NotSet ) { } - ~TQTextStreamPrivate() { - delete decoder; - delete encoder; - } - TQTextDecoder *decoder; - TQTextEncoder *encoder; -#else - TQTextStreamPrivate() : sourceType( NotSet ) { } - ~TQTextStreamPrivate() { } -#endif - TQString ungetcBuf; - - enum SourceType { NotSet, IODevice, String, ByteArray, File }; - SourceType sourceType; -}; - - -// skips whitespace and returns the first non-whitespace character -TQChar TQTextStream::eat_ws() -{ - TQChar c; - do { c = ts_getc(); } while ( c != TQEOF && ts_isspace(c) ); - return c; -} - -void TQTextStream::init() -{ - // ### ungetcBuf = TQEOF; - dev = 0; - owndev = FALSE; - mapper = 0; - d = new TQTextStreamPrivate; - doUnicodeHeader = TRUE; // autodetect - latin1 = TRUE; // should use locale? - internalOrder = TQChar::networkOrdered(); - networkOrder = TRUE; -} - -/*! - Constructs a data stream that has no IO device. -*/ - -TQTextStream::TQTextStream() -{ - init(); - setEncoding( Locale ); - reset(); - d->sourceType = TQTextStreamPrivate::NotSet; -} - -/*! - Constructs a text stream that uses the IO device \a iod. -*/ - -TQTextStream::TQTextStream( TQIODevice *iod ) -{ - init(); - setEncoding( Locale ); - dev = iod; - reset(); - d->sourceType = TQTextStreamPrivate::IODevice; -} - -// TODO: use special-case handling of this case in TQTextStream, and -// simplify this class to only deal with TQChar or TQString data. -class TQStringBuffer : public TQIODevice { -public: - TQStringBuffer( TQString* str ); - ~TQStringBuffer(); - bool open( int m ); - void close(); - void flush(); - Offset size() const; - Offset at() const; - bool at( Offset pos ); - TQ_LONG readBlock( char *p, TQ_ULONG len ); - TQ_LONG writeBlock( const char *p, TQ_ULONG len ); - int getch(); - int putch( int ch ); - int ungetch( int ch ); -protected: - TQString* s; - -private: - TQStringBuffer( const TQStringBuffer & ); - TQStringBuffer &operator=( const TQStringBuffer & ); -}; - - -TQStringBuffer::TQStringBuffer( TQString* str ) -{ - s = str; -} - -TQStringBuffer::~TQStringBuffer() -{ -} - - -bool TQStringBuffer::open( int m ) -{ - if ( !s ) { -#if defined(QT_CHECK_STATE) - tqWarning( "TQStringBuffer::open: No string" ); -#endif - return FALSE; - } - if ( isOpen() ) { -#if defined(QT_CHECK_STATE) - tqWarning( "TQStringBuffer::open: Buffer already open" ); -#endif - return FALSE; - } - setMode( m ); - if ( m & IO_Truncate ) - s->truncate( 0 ); - - if ( m & IO_Append ) { - ioIndex = s->length()*sizeof(TQChar); - } else { - ioIndex = 0; - } - setState( IO_Open ); - resetStatus(); - return TRUE; -} - -void TQStringBuffer::close() -{ - if ( isOpen() ) { - setFlags( IO_Direct ); - ioIndex = 0; - } -} - -void TQStringBuffer::flush() -{ -} - -TQIODevice::Offset TQStringBuffer::size() const -{ - return s ? s->length()*sizeof(TQChar) : 0; -} - -TQIODevice::Offset TQStringBuffer::at() const -{ - return ioIndex; -} - -bool TQStringBuffer::at( Offset pos ) -{ -#if defined(QT_CHECK_STATE) - if ( !isOpen() ) { - tqWarning( "TQStringBuffer::at: Buffer is not open" ); - return FALSE; - } -#endif - if ( pos >= s->length()*2 ) { -#if defined(QT_CHECK_RANGE) - tqWarning( "TQStringBuffer::at: Index %lu out of range", pos ); -#endif - return FALSE; - } - ioIndex = pos; - return TRUE; -} - - -TQ_LONG TQStringBuffer::readBlock( char *p, TQ_ULONG len ) -{ -#if defined(QT_CHECK_STATE) - TQ_CHECK_PTR( p ); - if ( !isOpen() ) { - tqWarning( "TQStringBuffer::readBlock: Buffer not open" ); - return -1; - } - if ( !isReadable() ) { - tqWarning( "TQStringBuffer::readBlock: Read operation not permitted" ); - return -1; - } -#endif - if ( ioIndex + len > s->length()*sizeof(TQChar) ) { - // overflow - if ( (uint)ioIndex >= s->length()*sizeof(TQChar) ) { - setStatus( IO_ReadError ); - return -1; - } else { - len = s->length()*2 - (uint)ioIndex; - } - } - memcpy( p, ((const char*)(s->unicode()))+ioIndex, len ); - ioIndex += len; - return len; -} - -TQ_LONG TQStringBuffer::writeBlock( const char *p, TQ_ULONG len ) -{ -#if defined(QT_CHECK_NULL) - if ( p == 0 && len != 0 ) - tqWarning( "TQStringBuffer::writeBlock: Null pointer error" ); -#endif -#if defined(QT_CHECK_STATE) - if ( !isOpen() ) { - tqWarning( "TQStringBuffer::writeBlock: Buffer not open" ); - return -1; - } - if ( !isWritable() ) { - tqWarning( "TQStringBuffer::writeBlock: Write operation not permitted" ); - return -1; - } - if ( ioIndex&1 ) { - tqWarning( "TQStringBuffer::writeBlock: non-even index - non Unicode" ); - return -1; - } - if ( len&1 ) { - tqWarning( "TQStringBuffer::writeBlock: non-even length - non Unicode" ); - return -1; - } -#endif - s->replace(ioIndex/2, len/2, (TQChar*)p, len/2); - ioIndex += len; - return len; -} - -int TQStringBuffer::getch() -{ -#if defined(QT_CHECK_STATE) - if ( !isOpen() ) { - tqWarning( "TQStringBuffer::getch: Buffer not open" ); - return -1; - } - if ( !isReadable() ) { - tqWarning( "TQStringBuffer::getch: Read operation not permitted" ); - return -1; - } -#endif - if ( (uint)ioIndex >= s->length()*2 ) { // overflow - setStatus( IO_ReadError ); - return -1; - } - return (int)((const uchar *)s->unicode())[ioIndex++]; -} - -int TQStringBuffer::putch( int ch ) -{ - char c = ch; - if ( writeBlock(&c,1) < 0 ) - return -1; - else - return ch; -} - -int TQStringBuffer::ungetch( int ch ) -{ -#if defined(QT_CHECK_STATE) - if ( !isOpen() ) { - tqWarning( "TQStringBuffer::ungetch: Buffer not open" ); - return -1; - } - if ( !isReadable() ) { - tqWarning( "TQStringBuffer::ungetch: Read operation not permitted" ); - return -1; - } -#endif - if ( ch != -1 ) { // something to do with eof - if ( ioIndex ) - ioIndex--; - else - ch = -1; - } - return ch; -} - - -/*! - Constructs a text stream that operates on the Unicode TQString, \a - str, through an internal device. The \a filemode argument is - passed to the device's open() function; see \l{TQIODevice::mode()}. - - If you set an encoding or codec with setEncoding() or setCodec(), - this setting is ignored for text streams that operate on TQString. - - Example: - \code - TQString str; - TQTextStream ts( &str, IO_WriteOnly ); - ts << "pi = " << 3.14; // str == "pi = 3.14" - \endcode - - Writing data to the text stream will modify the contents of the - string. The string will be expanded when data is written beyond - the end of the string. Note that the string will not be truncated: - \code - TQString str = "pi = 3.14"; - TQTextStream ts( &str, IO_WriteOnly ); - ts << "2+2 = " << 2+2; // str == "2+2 = 414" - \endcode - - Note that because TQString is Unicode, you should not use - readRawBytes() or writeRawBytes() on such a stream. -*/ - -TQTextStream::TQTextStream( TQString* str, int filemode ) -{ - // TODO: optimize for this case as it becomes more common - // (see TQStringBuffer above) - init(); - dev = new TQStringBuffer( str ); - ((TQStringBuffer *)dev)->open( filemode ); - owndev = TRUE; - setEncoding(RawUnicode); - reset(); - d->sourceType = TQTextStreamPrivate::String; -} - -/*! \obsolete - - This constructor is equivalent to the constructor taking a TQString* - parameter. -*/ - -TQTextStream::TQTextStream( TQString& str, int filemode ) -{ - init(); - dev = new TQStringBuffer( &str ); - ((TQStringBuffer *)dev)->open( filemode ); - owndev = TRUE; - setEncoding(RawUnicode); - reset(); - d->sourceType = TQTextStreamPrivate::String; -} - -/*! - Constructs a text stream that operates on the byte array, \a a, - through an internal TQBuffer device. The \a mode argument is passed - to the device's open() function; see \l{TQIODevice::mode()}. - - Example: - \code - TQByteArray array; - TQTextStream ts( array, IO_WriteOnly ); - ts << "pi = " << 3.14 << '\0'; // array == "pi = 3.14" - \endcode - - Writing data to the text stream will modify the contents of the - array. The array will be expanded when data is written beyond the - end of the string. - - Same example, using a TQBuffer: - \code - TQByteArray array; - TQBuffer buf( array ); - buf.open( IO_WriteOnly ); - TQTextStream ts( &buf ); - ts << "pi = " << 3.14 << '\0'; // array == "pi = 3.14" - buf.close(); - \endcode -*/ - -TQTextStream::TQTextStream( TQByteArray a, int mode ) -{ - init(); - dev = new TQBuffer( a ); - ((TQBuffer *)dev)->open( mode ); - owndev = TRUE; - setEncoding( Latin1 ); //### Locale??? - reset(); - d->sourceType = TQTextStreamPrivate::ByteArray; -} - -/*! - Constructs a text stream that operates on an existing file handle - \a fh through an internal TQFile device. The \a mode argument is - passed to the device's open() function; see \l{TQIODevice::mode()}. - - Note that if you create a TQTextStream \c cout or another name that - is also used for another variable of a different type, some - linkers may confuse the two variables, which will often cause - crashes. -*/ - -TQTextStream::TQTextStream( FILE *fh, int mode ) -{ - init(); - setEncoding( Locale ); //### - dev = new TQFile; - ((TQFile *)dev)->open( mode, fh ); - owndev = TRUE; - reset(); - d->sourceType = TQTextStreamPrivate::File; -} - -/*! - Destroys the text stream. - - The destructor does not affect the current IO device. -*/ - -TQTextStream::~TQTextStream() -{ - if ( owndev ) - delete dev; - delete d; -} - -/*! - Positions the read pointer at the first non-whitespace character. -*/ -void TQTextStream::skipWhiteSpace() -{ - ts_ungetc( eat_ws() ); -} - - -/*! - Tries to read \a len characters from the stream and stores them in - \a buf. Returns the number of characters really read. - - \warning There will no TQEOF appended if the read reaches the end - of the file. EOF is reached when the return value does not equal - \a len. -*/ -uint TQTextStream::ts_getbuf( TQChar* buf, uint len ) -{ - if ( len < 1 ) - return 0; - - uint rnum = 0; // the number of TQChars really read - - if ( d && d->ungetcBuf.length() ) { - while ( rnum < len && rnum < d->ungetcBuf.length() ) { - *buf = d->ungetcBuf.constref( rnum ); - buf++; - rnum++; - } - d->ungetcBuf = d->ungetcBuf.mid( rnum ); - if ( rnum >= len ) - return rnum; - } - - // we use dev->ungetch() for one of the bytes of the unicode - // byte-order mark, but a local unget hack for the other byte: - int ungetHack = EOF; - - if ( doUnicodeHeader ) { - doUnicodeHeader = FALSE; // only at the top - int c1 = dev->getch(); - if ( c1 == EOF ) - return rnum; - int c2 = dev->getch(); - if ( c1 == 0xfe && c2 == 0xff ) { - mapper = 0; - latin1 = FALSE; - internalOrder = TQChar::networkOrdered(); - networkOrder = TRUE; - } else if ( c1 == 0xff && c2 == 0xfe ) { - mapper = 0; - latin1 = FALSE; - internalOrder = !TQChar::networkOrdered(); - networkOrder = FALSE; - } else { - if ( c2 != EOF ) { - dev->ungetch( c2 ); - ungetHack = c1; - } else { - /* - A small bug might hide here. If only the first byte - of a file has made it so far, and that first byte - is half of the byte-order mark, then the utfness - will not be detected. - */ - dev->ungetch( c1 ); - } - } - } - -#ifndef TQT_NO_TEXTCODEC - if ( mapper ) { - bool shortRead = FALSE; - if ( !d->decoder ) - d->decoder = mapper->makeDecoder(); - while( rnum < len ) { - TQString s; - bool readBlock = !( len == 1+rnum ); - for (;;) { - // for efficiency: normally read a whole block - if ( readBlock ) { - // guess buffersize; this may be wrong (too small or too - // big). But we can handle this (either iterate reading - // or use ungetcBuf). - // Note that this might cause problems for codecs where - // one byte can result in >1 Unicode Characters if bytes - // are written to the stream in the meantime (loss of - // synchronicity). - uint rlen = len - rnum; - char *cbuf = new char[ rlen ]; - if ( ungetHack != EOF ) { - rlen = 1+dev->readBlock( cbuf+1, rlen-1 ); - cbuf[0] = (char)ungetHack; - ungetHack = EOF; - } else { - rlen = dev->readBlock( cbuf, rlen ); - } - s += d->decoder->toUnicode( cbuf, rlen ); - delete[] cbuf; - // use buffered reading only for the first time, because we - // have to get the stream synchronous again (this is easier - // with single character reading) - readBlock = FALSE; - } - // get stream (and codec) in sync - int c; - if ( ungetHack == EOF ) { - c = dev->getch(); - } else { - c = ungetHack; - ungetHack = EOF; - } - if ( c == EOF ) { - shortRead = TRUE; - break; - } - char b = c; - uint lengthBefore = s.length(); - s += d->decoder->toUnicode( &b, 1 ); - if ( s.length() > lengthBefore ) - break; // it seems we are in sync now - } - uint i = 0; - uint end = TQMIN( len-rnum, s.length() ); - while( i < end ) { - *buf = s.constref(i++); - buf++; - } - rnum += end; - if ( s.length() > i ) { - // could be = but append is clearer - d->ungetcBuf.append( s.mid( i ) ); - } - if ( shortRead ) - return rnum; - } - } else -#endif - if ( latin1 ) { - if ( len == 1+rnum ) { - // use this method for one character because it is more efficient - // (arnt doubts whether it makes a difference, but lets it stand) - int c = (ungetHack == EOF) ? dev->getch() : ungetHack; - if ( c != EOF ) { - *buf = (char)c; - buf++; - rnum++; - } - } else { - if ( ungetHack != EOF ) { - *buf = (char)ungetHack; - buf++; - rnum++; - ungetHack = EOF; - } - char *cbuf = new char[len - rnum]; - while ( !dev->atEnd() && rnum < len ) { - uint rlen = len - rnum; - rlen = dev->readBlock( cbuf, rlen ); - char *it = cbuf; - char *end = cbuf + rlen; - while ( it < end ) { - *buf = *it; - buf++; - it++; - } - rnum += rlen; - } - delete[] cbuf; - } - } else { // UCS-2 or UTF-16 - if ( len == 1+rnum ) { - int c1 = (ungetHack == EOF) ? dev->getch() : ungetHack; - if ( c1 == EOF ) - return rnum; - int c2 = dev->getch(); - if ( c2 == EOF ) - return rnum; - - if ( networkOrder ) { - *buf = TQChar( c2, c1 ); - } else { - *buf = TQChar( c1, c2 ); - } - buf++; - rnum++; - } else { - char *cbuf = new char[ 2*( len - rnum ) ]; // for paranoids: overflow possible - while ( !dev->atEnd() && rnum < len ) { - uint rlen = 2 * ( len-rnum ); - if ( ungetHack != EOF ) { - rlen = 1+dev->readBlock( cbuf+1, rlen-1 ); - cbuf[0] = (char)ungetHack; - ungetHack = EOF; - } else { - rlen = dev->readBlock( cbuf, rlen ); - } - // We can't use an odd number of bytes, so put it back. But - // do it only if we are capable of reading more -- normally - // there should not be an odd number, but the file might be - // truncated or not in UTF-16... - if ( (rlen & 1) == 1 ) - if ( !dev->atEnd() ) - dev->ungetch( cbuf[--rlen] ); - uint i = 0; - if ( networkOrder ) { - while( i < rlen ) { - *buf = TQChar( cbuf[i+1], cbuf[i] ); - buf++; - i+=2; - } - } else { - while( i < rlen ) { - *buf = TQChar( cbuf[i], cbuf[i+1] ); - buf++; - i+=2; - } - } - rnum += i/2; - } - delete[] cbuf; - } - } - return rnum; -} - -/*! - Tries to read one line, but at most len characters from the stream - and stores them in \a buf. - - Returns the number of characters really read. Newlines are not - stripped. - - There will be a TQEOF appended if the read reaches the end of file; - this is different to ts_getbuf(). - - This function works only if a newline (as byte) is also a newline - (as resulting character) since it uses TQIODevice::readLine(). So - use it only for such codecs where this is true! - - This function is (almost) a no-op for UTF 16. Don't use it if - doUnicodeHeader is TRUE! -*/ -uint TQTextStream::ts_getline( TQChar* buf ) -{ - uint rnum=0; // the number of TQChars really read - char cbuf[ getline_buf_size+1 ]; - - if ( d && d->ungetcBuf.length() ) { - while( rnum < getline_buf_size && rnum < d->ungetcBuf.length() ) { - buf[rnum] = d->ungetcBuf.constref(rnum); - rnum++; - } - d->ungetcBuf = d->ungetcBuf.mid( rnum ); - if ( rnum >= getline_buf_size ) - return rnum; - } - -#ifndef TQT_NO_TEXTCODEC - if ( mapper ) { - if ( !d->decoder ) - d->decoder = mapper->makeDecoder(); - TQString s; - bool readBlock = TRUE; - for (;;) { - // for efficiency: try to read a line - if ( readBlock ) { - int rlen = getline_buf_size - rnum; - rlen = dev->readLine( cbuf, rlen+1 ); - if ( rlen == -1 ) - rlen = 0; - s += d->decoder->toUnicode( cbuf, rlen ); - readBlock = FALSE; - } - if ( dev->atEnd() - || s.at( s.length()-1 ) == '\n' - || s.at( s.length()-1 ) == '\r' - ) { - break; - } else { - // get stream (and codec) in sync - int c; - c = dev->getch(); - if ( c == EOF ) { - break; - } - char b = c; - uint lengthBefore = s.length(); - s += d->decoder->toUnicode( &b, 1 ); - if ( s.length() > lengthBefore ) - break; // it seems we are in sync now - } - } - uint i = 0; - while( rnum < getline_buf_size && i < s.length() ) - buf[rnum++] = s.constref(i++); - if ( s.length() > i ) - // could be = but append is clearer - d->ungetcBuf.append( s.mid( i ) ); - if ( rnum < getline_buf_size && dev->atEnd() ) - buf[rnum++] = TQEOF; - } else -#endif - if ( latin1 ) { - int rlen = getline_buf_size - rnum; - rlen = dev->readLine( cbuf, rlen+1 ); - if ( rlen == -1 ) - rlen = 0; - char *end = cbuf+rlen; - char *it = cbuf; - buf +=rnum; - while ( it != end ) { - buf->setCell( *(it++) ); - buf->setRow( 0 ); - buf++; - } - rnum += rlen; - if ( rnum < getline_buf_size && dev->atEnd() ) - buf[1] = TQEOF; - } - return rnum; -} - - -/*! - Puts one character into the stream. -*/ -void TQTextStream::ts_putc( TQChar c ) -{ -#ifndef TQT_NO_TEXTCODEC - if ( mapper ) { - if ( !d->encoder ) - d->encoder = mapper->makeEncoder(); - int len = 1; - TQString s = c; - TQCString block = d->encoder->fromUnicode( s, len ); - dev->writeBlock( block, len ); - } else -#endif - if ( latin1 ) { - if ( c.row() ) - dev->putch( '?' ); // unknown character - else - dev->putch( c.cell() ); - } else { - if ( doUnicodeHeader ) { - doUnicodeHeader = FALSE; - ts_putc( TQChar::byteOrderMark ); - } - if ( internalOrder ) { - // this case is needed by TQStringBuffer - dev->writeBlock( (char*)&c, sizeof(TQChar) ); - } else if ( networkOrder ) { - dev->putch( c.row() ); - dev->putch( c.cell() ); - } else { - dev->putch( c.cell() ); - dev->putch( c.row() ); - } - } -} - -/*! - Puts one character into the stream. -*/ -void TQTextStream::ts_putc( int ch ) -{ - ts_putc( TQChar((ushort)ch) ); -} - -bool TQTextStream::ts_isdigit( TQChar c ) -{ - return c.isDigit(); -} - -bool TQTextStream::ts_isspace( TQChar c ) -{ - return c.isSpace(); -} - -void TQTextStream::ts_ungetc( TQChar c ) -{ - if ( c.unicode() == 0xffff ) - return; - - d->ungetcBuf.prepend( c ); -} - - - -/*! - Reads \a len bytes from the stream into \a s and returns a - reference to the stream. - - The buffer \a s must be preallocated. - - Note that no encoding is done by this function. - - \warning The behavior of this function is undefined unless the - stream's encoding is set to Unicode or Latin1. - - \sa TQIODevice::readBlock() -*/ - -TQTextStream &TQTextStream::readRawBytes( char *s, uint len ) -{ - dev->readBlock( s, len ); - return *this; -} - -/*! - Writes the \a len bytes from \a s to the stream and returns a - reference to the stream. - - Note that no encoding is done by this function. - - \sa TQIODevice::writeBlock() -*/ - -TQTextStream &TQTextStream::writeRawBytes( const char* s, uint len ) -{ - dev->writeBlock( s, len ); - return *this; -} - - -TQTextStream &TQTextStream::writeBlock( const char* p, uint len ) -{ - if ( doUnicodeHeader ) { - doUnicodeHeader = FALSE; - if ( !mapper && !latin1 ) - ts_putc( TQChar::byteOrderMark ); - } - // TQCString and const char * are treated as Latin-1 - if ( !mapper && latin1 ) { - dev->writeBlock( p, len ); - } else if ( !mapper && internalOrder ) { - TQChar *u = new TQChar[len]; - for ( uint i = 0; i < len; i++ ) - u[i] = p[i]; - dev->writeBlock( (char*)u, len * sizeof(TQChar) ); - delete [] u; - } -#ifndef TQT_NO_TEXTCODEC - else if (mapper) { - if (!d->encoder) - d->encoder = mapper->makeEncoder(); - TQString s = TQString::fromLatin1(p, len); - int l = len; - TQCString block = d->encoder->fromUnicode(s, l); - dev->writeBlock(block, l); - } -#endif - else { - for ( uint i = 0; i < len; i++ ) - ts_putc( (uchar)p[i] ); - } - return *this; -} - -TQTextStream &TQTextStream::writeBlock( const TQChar* p, uint len ) -{ -#ifndef TQT_NO_TEXTCODEC - if ( mapper ) { - if ( !d->encoder ) - d->encoder = mapper->makeEncoder(); - TQConstString s( p, len ); - int l = len; - TQCString block = d->encoder->fromUnicode( s.string(), l ); - dev->writeBlock( block, l ); - } else -#endif - if ( latin1 ) { - char *str = TQString::unicodeToLatin1( p, len ); - dev->writeBlock( str, len ); - delete [] str; - } else if ( internalOrder ) { - if ( doUnicodeHeader ) { - doUnicodeHeader = FALSE; - ts_putc( TQChar::byteOrderMark ); - } - dev->writeBlock( (char*)p, sizeof(TQChar)*len ); - } else { - for (uint i=0; isourceType = TQTextStreamPrivate::IODevice; -} - -/*! - Unsets the IO device. Equivalent to setDevice( 0 ). - - \sa device(), setDevice() -*/ - -void TQTextStream::unsetDevice() -{ - setDevice( 0 ); - d->sourceType = TQTextStreamPrivate::NotSet; -} - -/*! - \fn bool TQTextStream::atEnd() const - - Returns TRUE if the IO device has reached the end position (end of - the stream or file) or if there is no IO device set; otherwise - returns FALSE. - - \sa TQIODevice::atEnd() -*/ - -/*!\fn bool TQTextStream::eof() const - - \obsolete - - This function has been renamed to atEnd(). - - \sa TQIODevice::atEnd() -*/ - -/***************************************************************************** - TQTextStream read functions - *****************************************************************************/ - - -/*! - \overload - - Reads a char \a c from the stream and returns a reference to the - stream. Note that whitespace is skipped. -*/ - -TQTextStream &TQTextStream::operator>>( char &c ) -{ - CHECK_STREAM_PRECOND - c = eat_ws(); - return *this; -} - -/*! - Reads a char \a c from the stream and returns a reference to the - stream. Note that whitespace is \e not skipped. -*/ - -TQTextStream &TQTextStream::operator>>( TQChar &c ) -{ - CHECK_STREAM_PRECOND - c = ts_getc(); - return *this; -} - - -ulong TQTextStream::input_bin() -{ - ulong val = 0; - TQChar ch = eat_ws(); - int dv = ch.digitValue(); - while ( dv == 0 || dv == 1 ) { - val = ( val << 1 ) + dv; - ch = ts_getc(); - dv = ch.digitValue(); - } - if ( ch != TQEOF ) - ts_ungetc( ch ); - return val; -} - -ulong TQTextStream::input_oct() -{ - ulong val = 0; - TQChar ch = eat_ws(); - int dv = ch.digitValue(); - while ( dv >= 0 && dv <= 7 ) { - val = ( val << 3 ) + dv; - ch = ts_getc(); - dv = ch.digitValue(); - } - if ( dv == 8 || dv == 9 ) { - while ( ts_isdigit(ch) ) - ch = ts_getc(); - } - if ( ch != TQEOF ) - ts_ungetc( ch ); - return val; -} - -ulong TQTextStream::input_dec() -{ - ulong val = 0; - TQChar ch = eat_ws(); - int dv = ch.digitValue(); - while ( ts_isdigit(ch) ) { - val = val * 10 + dv; - ch = ts_getc(); - dv = ch.digitValue(); - } - if ( ch != TQEOF ) - ts_ungetc( ch ); - return val; -} - -ulong TQTextStream::input_hex() -{ - ulong val = 0; - TQChar ch = eat_ws(); - char c = ch; - while ( isxdigit((uchar) c) ) { - val <<= 4; - if ( ts_isdigit(c) ) - val += c - '0'; - else - val += 10 + tolower( (uchar) c ) - 'a'; - c = ch = ts_getc(); - } - if ( ch != TQEOF ) - ts_ungetc( ch ); - return val; -} - -long TQTextStream::input_int() -{ - long val; - TQChar ch; - char c; - switch ( flags() & basefield ) { - case bin: - val = (long)input_bin(); - break; - case oct: - val = (long)input_oct(); - break; - case dec: - c = ch = eat_ws(); - if ( ch == TQEOF ) { - val = 0; - } else { - if ( !(c == '-' || c == '+') ) - ts_ungetc( ch ); - if ( c == '-' ) { - ulong v = input_dec(); - if ( v ) { // ensure that LONG_MIN can be read - v--; - val = -((long)v) - 1; - } else { - val = 0; - } - } else { - val = (long)input_dec(); - } - } - break; - case hex: - val = (long)input_hex(); - break; - default: - val = 0; - c = ch = eat_ws(); - if ( c == '0' ) { // bin, oct or hex - c = ch = ts_getc(); - if ( tolower((uchar) c) == 'x' ) - val = (long)input_hex(); - else if ( tolower((uchar) c) == 'b' ) - val = (long)input_bin(); - else { // octal - ts_ungetc( ch ); - if ( c >= '0' && c <= '7' ) { - val = (long)input_oct(); - } else { - val = 0; - } - } - } else if ( ts_isdigit(ch) ) { - ts_ungetc( ch ); - val = (long)input_dec(); - } else if ( c == '-' || c == '+' ) { - ulong v = input_dec(); - if ( c == '-' ) { - if ( v ) { // ensure that LONG_MIN can be read - v--; - val = -((long)v) - 1; - } else { - val = 0; - } - } else { - val = (long)v; - } - } - } - return val; -} - -// -// We use a table-driven FSM to parse floating point numbers -// strtod() cannot be used directly since we're reading from a TQIODevice -// - -double TQTextStream::input_double() -{ - const int Init = 0; // states - const int Sign = 1; - const int Mantissa = 2; - const int Dot = 3; - const int Abscissa = 4; - const int ExpMark = 5; - const int ExpSign = 6; - const int Exponent = 7; - const int Done = 8; - - const int InputSign = 1; // input tokens - const int InputDigit = 2; - const int InputDot = 3; - const int InputExp = 4; - - static const uchar table[8][5] = { - /* None InputSign InputDigit InputDot InputExp */ - { 0, Sign, Mantissa, Dot, 0, }, // Init - { 0, 0, Mantissa, Dot, 0, }, // Sign - { Done, Done, Mantissa, Dot, ExpMark,}, // Mantissa - { 0, 0, Abscissa, 0, 0, }, // Dot - { Done, Done, Abscissa, Done, ExpMark,}, // Abscissa - { 0, ExpSign, Exponent, 0, 0, }, // ExpMark - { 0, 0, Exponent, 0, 0, }, // ExpSign - { Done, Done, Exponent, Done, Done } // Exponent - }; - - int state = Init; // parse state - int input; // input token - - char buf[256]; - int i = 0; - TQChar c = eat_ws(); - - for (;;) { - - switch ( c ) { - case '+': - case '-': - input = InputSign; - break; - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - input = InputDigit; - break; - case '.': - input = InputDot; - break; - case 'e': - case 'E': - input = InputExp; - break; - default: - input = 0; - break; - } - - state = table[state][input]; - - if ( state == 0 || state == Done || i > 250 ) { - if ( i > 250 ) { // ignore rest of digits - do { c = ts_getc(); } while ( c != TQEOF && ts_isdigit(c) ); - } - if ( c != TQEOF ) - ts_ungetc( c ); - buf[i] = '\0'; - char *end; - return strtod( buf, &end ); - } - - buf[i++] = c; - c = ts_getc(); - } - -#if !defined(Q_CC_EDG) - return 0.0; -#endif -} - - -/*! - \overload - - Reads a signed \c short integer \a i from the stream and returns a - reference to the stream. See flags() for an explanation of the - expected input format. -*/ - -TQTextStream &TQTextStream::operator>>( signed short &i ) -{ - CHECK_STREAM_PRECOND - i = (signed short)input_int(); - return *this; -} - - -/*! - \overload - - Reads an unsigned \c short integer \a i from the stream and - returns a reference to the stream. See flags() for an explanation - of the expected input format. -*/ - -TQTextStream &TQTextStream::operator>>( unsigned short &i ) -{ - CHECK_STREAM_PRECOND - i = (unsigned short)input_int(); - return *this; -} - - -/*! - \overload - - Reads a signed \c int \a i from the stream and returns a reference - to the stream. See flags() for an explanation of the expected - input format. -*/ - -TQTextStream &TQTextStream::operator>>( signed int &i ) -{ - CHECK_STREAM_PRECOND - i = (signed int)input_int(); - return *this; -} - - -/*! - \overload - - Reads an unsigned \c int \a i from the stream and returns a - reference to the stream. See flags() for an explanation of the - expected input format. -*/ - -TQTextStream &TQTextStream::operator>>( unsigned int &i ) -{ - CHECK_STREAM_PRECOND - i = (unsigned int)input_int(); - return *this; -} - - -/*! - \overload - - Reads a signed \c long int \a i from the stream and returns a - reference to the stream. See flags() for an explanation of the - expected input format. -*/ - -TQTextStream &TQTextStream::operator>>( signed long &i ) -{ - CHECK_STREAM_PRECOND - i = (signed long)input_int(); - return *this; -} - - -/*! - \overload - - Reads an unsigned \c long int \a i from the stream and returns a - reference to the stream. See flags() for an explanation of the - expected input format. -*/ - -TQTextStream &TQTextStream::operator>>( unsigned long &i ) -{ - CHECK_STREAM_PRECOND - i = (unsigned long)input_int(); - return *this; -} - - -/*! - \overload - - Reads a \c float \a f from the stream and returns a reference to - the stream. See flags() for an explanation of the expected input - format. -*/ - -TQTextStream &TQTextStream::operator>>( float &f ) -{ - CHECK_STREAM_PRECOND - f = (float)input_double(); - return *this; -} - - -/*! - \overload - - Reads a \c double \a f from the stream and returns a reference to - the stream. See flags() for an explanation of the expected input - format. -*/ - -TQTextStream &TQTextStream::operator>>( double &f ) -{ - CHECK_STREAM_PRECOND - f = input_double(); - return *this; -} - - -/*! - \overload - - Reads a "word" from the stream into \a s and returns a reference - to the stream. - - A word consists of characters for which isspace() returns FALSE. -*/ - -TQTextStream &TQTextStream::operator>>( char *s ) -{ - CHECK_STREAM_PRECOND - int maxlen = width( 0 ); - TQChar c = eat_ws(); - if ( !maxlen ) - maxlen = -1; - while ( c != TQEOF ) { - if ( ts_isspace(c) || maxlen-- == 0 ) { - ts_ungetc( c ); - break; - } - *s++ = c; - c = ts_getc(); - } - - *s = '\0'; - return *this; -} - -/*! - \overload - - Reads a "word" from the stream into \a str and returns a reference - to the stream. - - A word consists of characters for which isspace() returns FALSE. -*/ - -TQTextStream &TQTextStream::operator>>( TQString &str ) -{ - CHECK_STREAM_PRECOND - str=TQString::fromLatin1(""); - TQChar c = eat_ws(); - - while ( c != TQEOF ) { - if ( ts_isspace(c) ) { - ts_ungetc( c ); - break; - } - str += c; - c = ts_getc(); - } - return *this; -} - -/*! - \overload - - Reads a "word" from the stream into \a str and returns a reference - to the stream. - - A word consists of characters for which isspace() returns FALSE. -*/ - -TQTextStream &TQTextStream::operator>>( TQCString &str ) -{ - CHECK_STREAM_PRECOND - TQCString *dynbuf = 0; - const int buflen = 256; - char buffer[buflen]; - char *s = buffer; - int i = 0; - TQChar c = eat_ws(); - - while ( c != TQEOF ) { - if ( ts_isspace(c) ) { - ts_ungetc( c ); - break; - } - if ( i >= buflen-1 ) { - if ( !dynbuf ) { // create dynamic buffer - dynbuf = new TQCString(buflen*2); - memcpy( dynbuf->data(), s, i ); // copy old data - } else if ( i >= (int)dynbuf->size()-1 ) { - dynbuf->resize( dynbuf->size()*2 ); - } - s = dynbuf->data(); - } - s[i++] = c; - c = ts_getc(); - } - str.resize( i+1 ); - memcpy( str.data(), s, i ); - delete dynbuf; - return *this; -} - - -/*! - Reads a line from the stream and returns a string containing the - text. - - The returned string does not contain any trailing newline or - carriage return. Note that this is different from - TQIODevice::readLine(), which does not strip the newline at the end - of the line. - - On EOF you will get a TQString that is null. On reading an empty - line the returned TQString is empty but not null. - - \sa TQIODevice::readLine() -*/ - -TQString TQTextStream::readLine() -{ -#if defined(QT_CHECK_STATE) - if ( !dev ) { - tqWarning( "TQTextStream::readLine: No device" ); - return TQString::null; - } -#endif - bool readCharByChar = TRUE; - TQString result; -#if 0 - if ( !doUnicodeHeader && ( - (latin1) || - (mapper != 0 && mapper->mibEnum() == 106 ) // UTF 8 - ) ) { - readCharByChar = FALSE; - // use optimized read line - TQChar c[getline_buf_size]; - int pos = 0; - bool eof = FALSE; - - for (;;) { - pos = ts_getline( c ); - if ( pos == 0 ) { - // something went wrong; try fallback - readCharByChar = TRUE; - //dev->resetStatus(); - break; - } - if ( c[pos-1] == TQEOF || c[pos-1] == '\n' ) { - if ( pos>2 && c[pos-1]==TQEOF && c[pos-2]=='\n' ) { - result += TQString( c, pos-2 ); - } else if ( pos > 1 ) { - result += TQString( c, pos-1 ); - } - if ( pos == 1 && c[pos-1] == TQEOF ) - eof = TRUE; - break; - } else { - result += TQString( c, pos ); - } - } - if ( eof && result.isEmpty() ) - return TQString::null; - } -#endif - if ( readCharByChar ) { - const int buf_size = 256; - TQChar c[buf_size]; - int pos = 0; - - c[pos] = ts_getc(); - if ( c[pos] == TQEOF ) - return TQString::null; - - while ( c[pos] != TQEOF && c[pos] != '\n' ) { - if ( c[pos] == '\r' ) { // ( handle mac and dos ) - TQChar nextc = ts_getc(); - if ( nextc != '\n' ) - ts_ungetc( nextc ); - break; - } - pos++; - if ( pos >= buf_size ) { - result += TQString( c, pos ); - pos = 0; - } - c[pos] = ts_getc(); - } - result += TQString( c, pos ); - } - - return result; -} - - -/*! - Reads the entire stream from the current position, and returns a string - containing the text. - - \sa TQIODevice::readLine() -*/ - -TQString TQTextStream::read() -{ -#if defined(QT_CHECK_STATE) - if ( !dev ) { - tqWarning( "TQTextStream::read: No device" ); - return TQString::null; - } -#endif - TQString result; - const uint bufsize = 512; - TQChar buf[bufsize]; - uint i, num, start; - bool skipped_cr = FALSE; - - for (;;) { - num = ts_getbuf(buf,bufsize); - // convert dos (\r\n) and mac (\r) style eol to unix style (\n) - start = 0; - for ( i=0; i>= 1; - if ( !n ) - break; - } - if ( flags() & showbase ) { // show base - *--p = (flags() & uppercase) ? 'B' : 'b'; - *--p = '0'; - } - break; - - case I_BASE_8: // output octal number - p = &buf[74]; - *p = '\0'; - do { - *--p = (char)(n&7) + '0'; - n >>= 3; - } while ( n ); - if ( flags() & showbase ) - *--p = '0'; - break; - - case I_BASE_16: // output hexadecimal number - p = &buf[74]; - *p = '\0'; - hexdigits = (flags() & uppercase) ? - hexdigits_upper : hexdigits_lower; - do { - *--p = hexdigits[(int)n&0xf]; - n >>= 4; - } while ( n ); - if ( flags() & showbase ) { - *--p = (flags() & uppercase) ? 'X' : 'x'; - *--p = '0'; - } - break; - - default: // decimal base is default - p = &buf[74]; - *p = '\0'; - if ( neg ) - n = (unsigned long long)(-(long long)n); - do { - *--p = ((int)(n%10)) + '0'; - n /= 10; - } while ( n ); - if ( neg ) - *--p = '-'; - else if ( flags() & showpos ) - *--p = '+'; - if ( (flags() & internal) && fwidth && !ts_isdigit(*p) ) { - ts_putc( *p ); // special case for internal - ++p; // padding - fwidth--; - return *this << (const char*)p; - } - } - if ( fwidth ) { // adjustment required - if ( !(flags() & left) ) { // but NOT left adjustment - len = tqstrlen(p); - int padlen = fwidth - len; - if ( padlen <= 0 ) { // no padding required - writeBlock( p, len ); - } else if ( padlen < (int)(p-buf) ) { // speeds up padding - memset( p-padlen, (char)fillchar, padlen ); - writeBlock( p-padlen, padlen+len ); - } - else // standard padding - *this << (const char*)p; - } - else - *this << (const char*)p; - fwidth = 0; // reset field width - } - else - writeBlock( p, tqstrlen(p) ); - return *this; -} - - -/*! - \overload - - Writes a \c short integer \a i to the stream and returns a - reference to the stream. -*/ - -TQTextStream &TQTextStream::operator<<( signed short i ) -{ - return output_int( I_SHORT | I_SIGNED, i, i < 0 ); -} - - -/*! - \overload - - Writes an \c unsigned \c short integer \a i to the stream and - returns a reference to the stream. -*/ - -TQTextStream &TQTextStream::operator<<( unsigned short i ) -{ - return output_int( I_SHORT | I_UNSIGNED, i, FALSE ); -} - - -/*! - \overload - - Writes an \c int \a i to the stream and returns a reference to the - stream. -*/ - -TQTextStream &TQTextStream::operator<<( signed int i ) -{ - return output_int( I_INT | I_SIGNED, i, i < 0 ); -} - - -/*! - \overload - - Writes an \c unsigned \c int \a i to the stream and returns a - reference to the stream. -*/ - -TQTextStream &TQTextStream::operator<<( unsigned int i ) -{ - return output_int( I_INT | I_UNSIGNED, i, FALSE ); -} - - -/*! - \overload - - Writes a \c long \c int \a i to the stream and returns a reference - to the stream. -*/ - -TQTextStream &TQTextStream::operator<<( signed long i ) -{ - return output_int( I_LONG | I_SIGNED, i, i < 0 ); -} - - -/*! - \overload - - Writes an \c unsigned \c long \c int \a i to the stream and - returns a reference to the stream. -*/ - -TQTextStream &TQTextStream::operator<<( unsigned long i ) -{ - return output_int( I_LONG | I_UNSIGNED, i, FALSE ); -} - -/*! - \overload - - Writes a \c long long \c int \a i to the stream and returns a reference - to the stream. -*/ - -TQTextStream &TQTextStream::operator<<( signed long long i ) -{ - return output_int( I_LONGLONG | I_SIGNED, i, i < 0 ); -} - - -/*! - \overload - - Writes an \c unsigned \c long \c int \a i to the stream and - returns a reference to the stream. -*/ - -TQTextStream &TQTextStream::operator<<( unsigned long long i ) -{ - return output_int( I_LONGLONG | I_UNSIGNED, i, FALSE ); -} - - -/*! - \overload - - Writes a \c float \a f to the stream and returns a reference to - the stream. -*/ - -TQTextStream &TQTextStream::operator<<( float f ) -{ - return *this << (double)f; -} - -/*! - \overload - - Writes a \c double \a f to the stream and returns a reference to - the stream. -*/ - -TQTextStream &TQTextStream::operator<<( double f ) -{ - CHECK_STREAM_PRECOND - char f_char; - char format[16]; - if ( (flags()&floatfield) == fixed ) - f_char = 'f'; - else if ( (flags()&floatfield) == scientific ) - f_char = (flags() & uppercase) ? 'E' : 'e'; - else - f_char = (flags() & uppercase) ? 'G' : 'g'; - char *fs = format; // generate format string - *fs++ = '%'; // "%.l" - *fs++ = '.'; - int prec = precision(); - if ( prec > 99 ) - prec = 99; - if ( prec >= 10 ) { - *fs++ = prec / 10 + '0'; - *fs++ = prec % 10 + '0'; - } else { - *fs++ = prec + '0'; - } - *fs++ = 'l'; - *fs++ = f_char; - *fs = '\0'; - TQString num; - num.sprintf(format, f); // convert to text - if ( fwidth ) // padding - *this << num.latin1(); - else // just write it - writeBlock(num.latin1(), num.length()); - return *this; -} - - -/*! - \overload - - Writes a string to the stream and returns a reference to the - stream. - - The string \a s is assumed to be Latin1 encoded independent of the - Encoding set for the TQTextStream. -*/ - -TQTextStream &TQTextStream::operator<<( const char* s ) -{ - CHECK_STREAM_PRECOND - char padbuf[48]; - uint len = tqstrlen( s ); // don't write null terminator - if ( fwidth ) { // field width set - int padlen = fwidth - len; - fwidth = 0; // reset width - if ( padlen > 0 ) { - char *ppad; - if ( padlen > 46 ) { // create extra big fill buffer - ppad = new char[padlen]; - TQ_CHECK_PTR( ppad ); - } else { - ppad = padbuf; - } - memset( ppad, (char)fillchar, padlen ); // fill with fillchar - if ( !(flags() & left) ) { - writeBlock( ppad, padlen ); - padlen = 0; - } - writeBlock( s, len ); - if ( padlen ) - writeBlock( ppad, padlen ); - if ( ppad != padbuf ) // delete extra big fill buf - delete[] ppad; - return *this; - } - } - writeBlock( s, len ); - return *this; -} - -/*! - \overload - - Writes \a s to the stream and returns a reference to the stream. - - The string \a s is assumed to be Latin1 encoded independent of the - Encoding set for the TQTextStream. -*/ - -TQTextStream &TQTextStream::operator<<( const TQCString & s ) -{ - return operator<<(s.data()); -} - -/*! - \overload - - Writes \a s to the stream and returns a reference to the stream. -*/ - -TQTextStream &TQTextStream::operator<<( const TQString& s ) -{ - if ( !mapper && latin1 ) - return operator<<(s.latin1()); - CHECK_STREAM_PRECOND - TQString s1 = s; - if ( fwidth ) { // field width set - if ( !(flags() & left) ) { - s1 = s.rightJustify(fwidth, (char)fillchar); - } else { - s1 = s.leftJustify(fwidth, (char)fillchar); - } - fwidth = 0; // reset width - } - writeBlock( s1.unicode(), s1.length() ); - return *this; -} - - -/*! - \overload - - Writes a pointer to the stream and returns a reference to the - stream. - - The \a ptr is output as an unsigned long hexadecimal integer. -*/ - -TQTextStream &TQTextStream::operator<<( void *ptr ) -{ - int f = flags(); - setf( hex, basefield ); - setf( showbase ); - unsetf( uppercase ); - output_int( I_LONG | I_UNSIGNED, (ulong)ptr, FALSE ); - flags( f ); - return *this; -} - - -/*! - \fn int TQTextStream::flags() const - - Returns the current stream flags. The default value is 0. - - \table - \header \i Flag \i Meaning - \row \i \c skipws \i Not currently used; whitespace always skipped - \row \i \c left \i Numeric fields are left-aligned - \row \i \c right - \i Not currently used (by default, numerics are right-aligned) - \row \i \c internal \i Puts any padding spaces between +/- and value - \row \i \c bin \i Output \e and input only in binary - \row \i \c oct \i Output \e and input only in octal - \row \i \c dec \i Output \e and input only in decimal - \row \i \c hex \i Output \e and input only in hexadecimal - \row \i \c showbase - \i Annotates numeric outputs with 0b, 0, or 0x if in \c bin, - \c oct, or \c hex format - \row \i \c showpoint \i Not currently used - \row \i \c uppercase \i Uses 0B and 0X rather than 0b and 0x - \row \i \c showpos \i Shows + for positive numeric values - \row \i \c scientific \i Uses scientific notation for floating point values - \row \i \c fixed \i Uses fixed-point notation for floating point values - \endtable - - Note that unless \c bin, \c oct, \c dec, or \c hex is set, the - input base is octal if the value starts with 0, hexadecimal if it - starts with 0x, binary if it starts with 0b, and decimal - otherwise. - - \sa setf(), unsetf() -*/ - -/*! - \fn int TQTextStream::flags( int f ) - - \overload - - Sets the stream flags to \a f. Returns the previous stream flags. - - \sa setf(), unsetf(), flags() -*/ - -/*! - \fn int TQTextStream::setf( int bits ) - - Sets the stream flag bits \a bits. Returns the previous stream - flags. - - Equivalent to \c{flags( flags() | bits )}. - - \sa setf(), unsetf() -*/ - -/*! - \fn int TQTextStream::setf( int bits, int mask ) - - \overload - - Sets the stream flag bits \a bits with a bit mask \a mask. Returns - the previous stream flags. - - Equivalent to \c{flags( (flags() & ~mask) | (bits & mask) )}. - - \sa setf(), unsetf() -*/ - -/*! - \fn int TQTextStream::unsetf( int bits ) - - Clears the stream flag bits \a bits. Returns the previous stream - flags. - - Equivalent to \c{flags( flags() & ~mask )}. - - \sa setf() -*/ - -/*! - \fn int TQTextStream::width() const - - Returns the field width. The default value is 0. -*/ - -/*! - \fn int TQTextStream::width( int w ) - - \overload - - Sets the field width to \a w. Returns the previous field width. -*/ - -/*! - \fn int TQTextStream::fill() const - - Returns the fill character. The default value is ' ' (space). -*/ - -/*! - \overload int TQTextStream::fill( int f ) - - Sets the fill character to \a f. Returns the previous fill character. -*/ - -/*! - \fn int TQTextStream::precision() const - - Returns the precision. The default value is 6. -*/ - -/*! - \fn int TQTextStream::precision( int p ) - - \overload - - Sets the precision to \a p. Returns the previous precision setting. -*/ - - - /***************************************************************************** - TQTextStream manipulators - *****************************************************************************/ - -TQTextStream &bin( TQTextStream &s ) -{ - s.setf(TQTS::bin,TQTS::basefield); - return s; -} - -TQTextStream &oct( TQTextStream &s ) -{ - s.setf(TQTS::oct,TQTS::basefield); - return s; -} - -TQTextStream &dec( TQTextStream &s ) -{ - s.setf(TQTS::dec,TQTS::basefield); - return s; -} - -TQTextStream &hex( TQTextStream &s ) -{ - s.setf(TQTS::hex,TQTS::basefield); - return s; -} - -TQTextStream &endl( TQTextStream &s ) -{ - return s << '\n'; -} - -TQTextStream &flush( TQTextStream &s ) -{ - if ( s.device() ) - s.device()->flush(); - return s; -} - -TQTextStream &ws( TQTextStream &s ) -{ - s.skipWhiteSpace(); - return s; -} - -TQTextStream &reset( TQTextStream &s ) -{ - s.reset(); - return s; -} - - -/*! - \class TQTextIStream ntqtextstream.h - \reentrant - \brief The TQTextIStream class is a convenience class for input streams. - - \ingroup io - \ingroup text - - This class provides a shorthand for creating simple input - \l{TQTextStream}s without having to pass a \e mode argument to the - constructor. - - This class makes it easy, for example, to write things like this: - \code - TQString data = "123 456"; - int a, b; - TQTextIStream(&data) >> a >> b; - \endcode - - \sa TQTextOStream -*/ - -/*! - \fn TQTextIStream::TQTextIStream( const TQString *s ) - - Constructs a stream to read from the string \a s. -*/ -/*! - \fn TQTextIStream::TQTextIStream( TQByteArray ba ) - - Constructs a stream to read from the array \a ba. -*/ -/*! - \fn TQTextIStream::TQTextIStream( FILE *f ) - - Constructs a stream to read from the file \a f. -*/ - - -/*! - \class TQTextOStream - \reentrant - \brief The TQTextOStream class is a convenience class for output streams. - - \ingroup io - \ingroup text - - This class provides a shorthand for creating simple output - \l{TQTextStream}s without having to pass a \e mode argument to the - constructor. - - This makes it easy for example, to write things like this: - \code - TQString result; - TQTextOStream(&result) << "pi = " << 3.14; - \endcode -*/ - -/*! - \fn TQTextOStream::TQTextOStream( TQString *s ) - - Constructs a stream to write to string \a s. -*/ -/*! - \fn TQTextOStream::TQTextOStream( TQByteArray ba ) - - Constructs a stream to write to the array \a ba. -*/ -/*! - \fn TQTextOStream::TQTextOStream( FILE *f ) - - Constructs a stream to write to the file \a f. -*/ - - - -/*! - Sets the encoding of this stream to \a e, where \a e is one of the - following values: - \table - \header \i Encoding \i Meaning - \row \i Locale - \i Uses local file format (Latin1 if locale is not set), but - autodetecting Unicode(utf16) on input. - \row \i Unicode - \i Uses Unicode(utf16) for input and output. Output will be - written in the order most efficient for the current platform - (i.e. the order used internally in TQString). - \row \i UnicodeUTF8 - \i Using Unicode(utf8) for input and output. If you use it for - input it will autodetect utf16 and use it instead of utf8. - \row \i Latin1 - \i ISO-8859-1. Will not autodetect utf16. - \row \i UnicodeNetworkOrder - \i Uses network order Unicode(utf16) for input and output. - Useful when reading Unicode data that does not start with the - byte order marker. - \row \i UnicodeReverse - \i Uses reverse network order Unicode(utf16) for input and - output. Useful when reading Unicode data that does not start - with the byte order marker or when writing data that should be - read by buggy Windows applications. - \row \i RawUnicode - \i Like Unicode, but does not write the byte order marker nor - does it auto-detect the byte order. Useful only when writing to - non-persistent storage used by a single process. - \endtable - - \c Locale and all Unicode encodings, except \c RawUnicode, will look - at the first two bytes in an input stream to determine the byte - order. The initial byte order marker will be stripped off before - data is read. - - Note that this function should be called before any data is read to - or written from the stream. - - \sa setCodec() -*/ - -void TQTextStream::setEncoding( Encoding e ) -{ - if ( d->sourceType == TQTextStreamPrivate::String ) - return; - - switch ( e ) { - case Unicode: - mapper = 0; - latin1 = FALSE; - doUnicodeHeader = TRUE; - internalOrder = TRUE; - networkOrder = TQChar::networkOrdered(); - break; - case UnicodeUTF8: -#ifndef TQT_NO_TEXTCODEC - mapper = TQTextCodec::codecForMib( 106 ); - latin1 = FALSE; - doUnicodeHeader = TRUE; - internalOrder = TRUE; - networkOrder = TQChar::networkOrdered(); -#else - mapper = 0; - latin1 = TRUE; - doUnicodeHeader = TRUE; -#endif - break; - case UnicodeNetworkOrder: - mapper = 0; - latin1 = FALSE; - doUnicodeHeader = TRUE; - internalOrder = TQChar::networkOrdered(); - networkOrder = TRUE; - break; - case UnicodeReverse: - mapper = 0; - latin1 = FALSE; - doUnicodeHeader = TRUE; - internalOrder = !TQChar::networkOrdered(); - networkOrder = FALSE; - break; - case RawUnicode: - mapper = 0; - latin1 = FALSE; - doUnicodeHeader = FALSE; - internalOrder = TRUE; - networkOrder = TQChar::networkOrdered(); - break; - case Locale: - latin1 = TRUE; // fallback to Latin-1 -#ifndef TQT_NO_TEXTCODEC - mapper = TQTextCodec::codecForLocale(); - // optimized Latin-1 processing -#if defined(Q_OS_WIN32) - if ( GetACP() == 1252 ) - mapper = 0; -#endif - if ( mapper && mapper->mibEnum() == 4 ) -#endif - mapper = 0; - - doUnicodeHeader = TRUE; // If it reads as Unicode, accept it - break; - case Latin1: - mapper = 0; - doUnicodeHeader = FALSE; - latin1 = TRUE; - break; - } -} - - -#ifndef TQT_NO_TEXTCODEC -/*! - Sets the codec for this stream to \a codec. Will not try to - autodetect Unicode. - - Note that this function should be called before any data is read - to/written from the stream. - - \sa setEncoding(), codec() -*/ - -void TQTextStream::setCodec( TQTextCodec *codec ) -{ - if ( d->sourceType == TQTextStreamPrivate::String ) - return; // TQString does not need any codec - mapper = codec; - latin1 = ( codec->mibEnum() == 4 ); - if ( latin1 ) - mapper = 0; - doUnicodeHeader = FALSE; -} - -/*! - Returns the codec actually used for this stream. - - If Unicode is automatically detected in input, a codec with \link - TQTextCodec::name() name() \endlink "ISO-10646-UCS-2" is returned. - - \sa setCodec() -*/ - -TQTextCodec *TQTextStream::codec() -{ - if ( mapper ) { - return mapper; - } else { - // 4 is "ISO 8859-1", 1000 is "ISO-10646-UCS-2" - return TQTextCodec::codecForMib( latin1 ? 4 : 1000 ); - } -} - -#endif - -#endif // TQT_NO_TEXTSTREAM diff --git a/src/tools/tqstring.cpp b/src/tools/tqstring.cpp index a48af12fc..fff59c613 100644 --- a/src/tools/tqstring.cpp +++ b/src/tools/tqstring.cpp @@ -54,7 +54,7 @@ #include "ntqregexp.h" #include "ntqdatastream.h" #ifndef TQT_NO_TEXTCODEC -#include "ntqtextcodec.h" +#include "tqtextcodec.h" #endif #include "ntqlocale.h" #include "qlocale_p.h" diff --git a/src/tools/tqtextstream.cpp b/src/tools/tqtextstream.cpp new file mode 100644 index 000000000..218c9b106 --- /dev/null +++ b/src/tools/tqtextstream.cpp @@ -0,0 +1,2632 @@ +/**************************************************************************** +** +** Implementation of TQTextStream class +** +** Created : 940922 +** +** 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 "tqtextstream.h" + +#ifndef TQT_NO_TEXTSTREAM +#include "tqtextcodec.h" +#include "ntqregexp.h" +#include "ntqbuffer.h" +#include "ntqfile.h" +#include +#include +#include +#ifndef Q_OS_TEMP +#include +#endif + +#if defined(Q_OS_WIN32) +#include "qt_windows.h" +#endif + +/*! + \class TQTextStream tqtextstream.h + \reentrant + \brief The TQTextStream class provides basic functions for reading + and writing text using a TQIODevice. + + \ingroup io + \ingroup text + \mainclass + + The text stream class has a functional interface that is very + similar to that of the standard C++ iostream class. + + TQt provides several global functions similar to the ones in iostream: + \table + \header \i Function \i Meaning + \row \i bin \i sets the TQTextStream to read/write binary numbers + \row \i oct \i sets the TQTextStream to read/write octal numbers + \row \i dec \i sets the TQTextStream to read/write decimal numbers + \row \i hex \i sets the TQTextStream to read/write hexadecimal numbers + \row \i endl \i forces a line break + \row \i flush \i forces the TQIODevice to flush any buffered data + \row \i ws \i eats any available whitespace (on input) + \row \i reset \i resets the TQTextStream to its default mode (see reset()) + \row \i qSetW(int) \i sets the \link width() field width \endlink + to the given argument + \row \i qSetFill(int) \i sets the \link fill() fill character + \endlink to the given argument + \row \i qSetPrecision(int) \i sets the \link precision() precision + \endlink to the given argument + \endtable + + \warning By default TQTextStream will automatically detect whether + integers in the stream are in decimal, octal, hexadecimal or + binary format when reading from the stream. In particular, a + leading '0' signifies octal, i.e. the sequence "0100" will be + interpreted as 64. + + The TQTextStream class reads and writes text; it is not appropriate + for dealing with binary data (but TQDataStream is). + + By default, output of Unicode text (i.e. TQString) is done using + the local 8-bit encoding. This can be changed using the + setEncoding() method. For input, the TQTextStream will auto-detect + standard Unicode "byte order marked" text files; otherwise the + local 8-bit encoding is used. + + The TQIODevice is set in the constructor, or later using + setDevice(). If the end of the input is reached atEnd() returns + TRUE. Data can be read into variables of the appropriate type + using the operator>>() overloads, or read in its entirety into a + single string using read(), or read a line at a time using + readLine(). Whitespace can be skipped over using skipWhiteSpace(). + You can set flags for the stream using flags() or setf(). The + stream also supports width(), precision() and fill(); use reset() + to reset the defaults. + + \sa TQDataStream +*/ + +/*! + \enum TQTextStream::Encoding + + \value Locale + \value Latin1 + \value Unicode + \value UnicodeNetworkOrder + \value UnicodeReverse + \value RawUnicode + \value UnicodeUTF8 + + See setEncoding() for an explanation of the encodings. +*/ + +/* + \class TQTSManip + + \brief The TQTSManip class is an internal helper class for the + TQTextStream. + + It is generally a very bad idea to use this class directly in + application programs. + + \internal + + This class makes it possible to give the TQTextStream function objects + with arguments, like this: + \code + TQTextStream cout( stdout, IO_WriteOnly ); + cout << setprecision( 8 ); // TQTSManip used here! + cout << 3.14159265358979323846; + \endcode + + The setprecision() function returns a TQTSManip object. + The TQTSManip object contains a pointer to a member function in + TQTextStream and an integer argument. + When serializing a TQTSManip into a TQTextStream, the function + is executed with the argument. +*/ + +/*! \fn TQTSManip::TQTSManip( TQTSMFI m, int a ) + + Constructs a TQTSManip object which will call \a m (a member function + in TQTextStream which accepts a single int) with argument \a a when + TQTSManip::exec() is called. Used internally in e.g. endl: + + \code + s << "some text" << endl << "more text"; + \endcode +*/ + +/*! \fn void TQTSManip::exec( TQTextStream& s ) + + Calls the member function specified in the constructor, for object + \a s. Used internally in e.g. endl: + + \code + s << "some text" << endl << "more text"; + \endcode +*/ + + +/***************************************************************************** + TQTextStream member functions + *****************************************************************************/ + +#if defined(QT_CHECK_STATE) +#undef CHECK_STREAM_PRECOND +#define CHECK_STREAM_PRECOND if ( !dev ) { \ + tqWarning( "TQTextStream: No device" ); \ + return *this; } +#else +#define CHECK_STREAM_PRECOND +#endif + + +#define I_SHORT 0x0010 +#define I_INT 0x0020 +#define I_LONG 0x0030 +#define I_LONGLONG 0x0040 +#define I_TYPE_MASK 0x00f0 + +#define I_BASE_2 TQTS::bin +#define I_BASE_8 TQTS::oct +#define I_BASE_10 TQTS::dec +#define I_BASE_16 TQTS::hex +#define I_BASE_MASK (TQTS::bin | TQTS::oct | TQTS::dec | TQTS::hex) + +#define I_SIGNED 0x0100 +#define I_UNSIGNED 0x0200 +#define I_SIGN_MASK 0x0f00 + + +static const TQChar TQEOF = TQChar((ushort)0xffff); //guaranteed not to be a character. +static const uint getline_buf_size = 256; // bufsize used by ts_getline() + +const int TQTextStream::basefield = I_BASE_MASK; +const int TQTextStream::adjustfield = ( TQTextStream::left | + TQTextStream::right | + TQTextStream::internal ); +const int TQTextStream::floatfield = ( TQTextStream::scientific | + TQTextStream::fixed ); + + +class TQTextStreamPrivate { +public: +#ifndef TQT_NO_TEXTCODEC + TQTextStreamPrivate() + : decoder( 0 ), encoder( 0 ), sourceType( NotSet ) { } + ~TQTextStreamPrivate() { + delete decoder; + delete encoder; + } + TQTextDecoder *decoder; + TQTextEncoder *encoder; +#else + TQTextStreamPrivate() : sourceType( NotSet ) { } + ~TQTextStreamPrivate() { } +#endif + TQString ungetcBuf; + + enum SourceType { NotSet, IODevice, String, ByteArray, File }; + SourceType sourceType; +}; + + +// skips whitespace and returns the first non-whitespace character +TQChar TQTextStream::eat_ws() +{ + TQChar c; + do { c = ts_getc(); } while ( c != TQEOF && ts_isspace(c) ); + return c; +} + +void TQTextStream::init() +{ + // ### ungetcBuf = TQEOF; + dev = 0; + owndev = FALSE; + mapper = 0; + d = new TQTextStreamPrivate; + doUnicodeHeader = TRUE; // autodetect + latin1 = TRUE; // should use locale? + internalOrder = TQChar::networkOrdered(); + networkOrder = TRUE; +} + +/*! + Constructs a data stream that has no IO device. +*/ + +TQTextStream::TQTextStream() +{ + init(); + setEncoding( Locale ); + reset(); + d->sourceType = TQTextStreamPrivate::NotSet; +} + +/*! + Constructs a text stream that uses the IO device \a iod. +*/ + +TQTextStream::TQTextStream( TQIODevice *iod ) +{ + init(); + setEncoding( Locale ); + dev = iod; + reset(); + d->sourceType = TQTextStreamPrivate::IODevice; +} + +// TODO: use special-case handling of this case in TQTextStream, and +// simplify this class to only deal with TQChar or TQString data. +class TQStringBuffer : public TQIODevice { +public: + TQStringBuffer( TQString* str ); + ~TQStringBuffer(); + bool open( int m ); + void close(); + void flush(); + Offset size() const; + Offset at() const; + bool at( Offset pos ); + TQ_LONG readBlock( char *p, TQ_ULONG len ); + TQ_LONG writeBlock( const char *p, TQ_ULONG len ); + int getch(); + int putch( int ch ); + int ungetch( int ch ); +protected: + TQString* s; + +private: + TQStringBuffer( const TQStringBuffer & ); + TQStringBuffer &operator=( const TQStringBuffer & ); +}; + + +TQStringBuffer::TQStringBuffer( TQString* str ) +{ + s = str; +} + +TQStringBuffer::~TQStringBuffer() +{ +} + + +bool TQStringBuffer::open( int m ) +{ + if ( !s ) { +#if defined(QT_CHECK_STATE) + tqWarning( "TQStringBuffer::open: No string" ); +#endif + return FALSE; + } + if ( isOpen() ) { +#if defined(QT_CHECK_STATE) + tqWarning( "TQStringBuffer::open: Buffer already open" ); +#endif + return FALSE; + } + setMode( m ); + if ( m & IO_Truncate ) + s->truncate( 0 ); + + if ( m & IO_Append ) { + ioIndex = s->length()*sizeof(TQChar); + } else { + ioIndex = 0; + } + setState( IO_Open ); + resetStatus(); + return TRUE; +} + +void TQStringBuffer::close() +{ + if ( isOpen() ) { + setFlags( IO_Direct ); + ioIndex = 0; + } +} + +void TQStringBuffer::flush() +{ +} + +TQIODevice::Offset TQStringBuffer::size() const +{ + return s ? s->length()*sizeof(TQChar) : 0; +} + +TQIODevice::Offset TQStringBuffer::at() const +{ + return ioIndex; +} + +bool TQStringBuffer::at( Offset pos ) +{ +#if defined(QT_CHECK_STATE) + if ( !isOpen() ) { + tqWarning( "TQStringBuffer::at: Buffer is not open" ); + return FALSE; + } +#endif + if ( pos >= s->length()*2 ) { +#if defined(QT_CHECK_RANGE) + tqWarning( "TQStringBuffer::at: Index %lu out of range", pos ); +#endif + return FALSE; + } + ioIndex = pos; + return TRUE; +} + + +TQ_LONG TQStringBuffer::readBlock( char *p, TQ_ULONG len ) +{ +#if defined(QT_CHECK_STATE) + TQ_CHECK_PTR( p ); + if ( !isOpen() ) { + tqWarning( "TQStringBuffer::readBlock: Buffer not open" ); + return -1; + } + if ( !isReadable() ) { + tqWarning( "TQStringBuffer::readBlock: Read operation not permitted" ); + return -1; + } +#endif + if ( ioIndex + len > s->length()*sizeof(TQChar) ) { + // overflow + if ( (uint)ioIndex >= s->length()*sizeof(TQChar) ) { + setStatus( IO_ReadError ); + return -1; + } else { + len = s->length()*2 - (uint)ioIndex; + } + } + memcpy( p, ((const char*)(s->unicode()))+ioIndex, len ); + ioIndex += len; + return len; +} + +TQ_LONG TQStringBuffer::writeBlock( const char *p, TQ_ULONG len ) +{ +#if defined(QT_CHECK_NULL) + if ( p == 0 && len != 0 ) + tqWarning( "TQStringBuffer::writeBlock: Null pointer error" ); +#endif +#if defined(QT_CHECK_STATE) + if ( !isOpen() ) { + tqWarning( "TQStringBuffer::writeBlock: Buffer not open" ); + return -1; + } + if ( !isWritable() ) { + tqWarning( "TQStringBuffer::writeBlock: Write operation not permitted" ); + return -1; + } + if ( ioIndex&1 ) { + tqWarning( "TQStringBuffer::writeBlock: non-even index - non Unicode" ); + return -1; + } + if ( len&1 ) { + tqWarning( "TQStringBuffer::writeBlock: non-even length - non Unicode" ); + return -1; + } +#endif + s->replace(ioIndex/2, len/2, (TQChar*)p, len/2); + ioIndex += len; + return len; +} + +int TQStringBuffer::getch() +{ +#if defined(QT_CHECK_STATE) + if ( !isOpen() ) { + tqWarning( "TQStringBuffer::getch: Buffer not open" ); + return -1; + } + if ( !isReadable() ) { + tqWarning( "TQStringBuffer::getch: Read operation not permitted" ); + return -1; + } +#endif + if ( (uint)ioIndex >= s->length()*2 ) { // overflow + setStatus( IO_ReadError ); + return -1; + } + return (int)((const uchar *)s->unicode())[ioIndex++]; +} + +int TQStringBuffer::putch( int ch ) +{ + char c = ch; + if ( writeBlock(&c,1) < 0 ) + return -1; + else + return ch; +} + +int TQStringBuffer::ungetch( int ch ) +{ +#if defined(QT_CHECK_STATE) + if ( !isOpen() ) { + tqWarning( "TQStringBuffer::ungetch: Buffer not open" ); + return -1; + } + if ( !isReadable() ) { + tqWarning( "TQStringBuffer::ungetch: Read operation not permitted" ); + return -1; + } +#endif + if ( ch != -1 ) { // something to do with eof + if ( ioIndex ) + ioIndex--; + else + ch = -1; + } + return ch; +} + + +/*! + Constructs a text stream that operates on the Unicode TQString, \a + str, through an internal device. The \a filemode argument is + passed to the device's open() function; see \l{TQIODevice::mode()}. + + If you set an encoding or codec with setEncoding() or setCodec(), + this setting is ignored for text streams that operate on TQString. + + Example: + \code + TQString str; + TQTextStream ts( &str, IO_WriteOnly ); + ts << "pi = " << 3.14; // str == "pi = 3.14" + \endcode + + Writing data to the text stream will modify the contents of the + string. The string will be expanded when data is written beyond + the end of the string. Note that the string will not be truncated: + \code + TQString str = "pi = 3.14"; + TQTextStream ts( &str, IO_WriteOnly ); + ts << "2+2 = " << 2+2; // str == "2+2 = 414" + \endcode + + Note that because TQString is Unicode, you should not use + readRawBytes() or writeRawBytes() on such a stream. +*/ + +TQTextStream::TQTextStream( TQString* str, int filemode ) +{ + // TODO: optimize for this case as it becomes more common + // (see TQStringBuffer above) + init(); + dev = new TQStringBuffer( str ); + ((TQStringBuffer *)dev)->open( filemode ); + owndev = TRUE; + setEncoding(RawUnicode); + reset(); + d->sourceType = TQTextStreamPrivate::String; +} + +/*! \obsolete + + This constructor is equivalent to the constructor taking a TQString* + parameter. +*/ + +TQTextStream::TQTextStream( TQString& str, int filemode ) +{ + init(); + dev = new TQStringBuffer( &str ); + ((TQStringBuffer *)dev)->open( filemode ); + owndev = TRUE; + setEncoding(RawUnicode); + reset(); + d->sourceType = TQTextStreamPrivate::String; +} + +/*! + Constructs a text stream that operates on the byte array, \a a, + through an internal TQBuffer device. The \a mode argument is passed + to the device's open() function; see \l{TQIODevice::mode()}. + + Example: + \code + TQByteArray array; + TQTextStream ts( array, IO_WriteOnly ); + ts << "pi = " << 3.14 << '\0'; // array == "pi = 3.14" + \endcode + + Writing data to the text stream will modify the contents of the + array. The array will be expanded when data is written beyond the + end of the string. + + Same example, using a TQBuffer: + \code + TQByteArray array; + TQBuffer buf( array ); + buf.open( IO_WriteOnly ); + TQTextStream ts( &buf ); + ts << "pi = " << 3.14 << '\0'; // array == "pi = 3.14" + buf.close(); + \endcode +*/ + +TQTextStream::TQTextStream( TQByteArray a, int mode ) +{ + init(); + dev = new TQBuffer( a ); + ((TQBuffer *)dev)->open( mode ); + owndev = TRUE; + setEncoding( Latin1 ); //### Locale??? + reset(); + d->sourceType = TQTextStreamPrivate::ByteArray; +} + +/*! + Constructs a text stream that operates on an existing file handle + \a fh through an internal TQFile device. The \a mode argument is + passed to the device's open() function; see \l{TQIODevice::mode()}. + + Note that if you create a TQTextStream \c cout or another name that + is also used for another variable of a different type, some + linkers may confuse the two variables, which will often cause + crashes. +*/ + +TQTextStream::TQTextStream( FILE *fh, int mode ) +{ + init(); + setEncoding( Locale ); //### + dev = new TQFile; + ((TQFile *)dev)->open( mode, fh ); + owndev = TRUE; + reset(); + d->sourceType = TQTextStreamPrivate::File; +} + +/*! + Destroys the text stream. + + The destructor does not affect the current IO device. +*/ + +TQTextStream::~TQTextStream() +{ + if ( owndev ) + delete dev; + delete d; +} + +/*! + Positions the read pointer at the first non-whitespace character. +*/ +void TQTextStream::skipWhiteSpace() +{ + ts_ungetc( eat_ws() ); +} + + +/*! + Tries to read \a len characters from the stream and stores them in + \a buf. Returns the number of characters really read. + + \warning There will no TQEOF appended if the read reaches the end + of the file. EOF is reached when the return value does not equal + \a len. +*/ +uint TQTextStream::ts_getbuf( TQChar* buf, uint len ) +{ + if ( len < 1 ) + return 0; + + uint rnum = 0; // the number of TQChars really read + + if ( d && d->ungetcBuf.length() ) { + while ( rnum < len && rnum < d->ungetcBuf.length() ) { + *buf = d->ungetcBuf.constref( rnum ); + buf++; + rnum++; + } + d->ungetcBuf = d->ungetcBuf.mid( rnum ); + if ( rnum >= len ) + return rnum; + } + + // we use dev->ungetch() for one of the bytes of the unicode + // byte-order mark, but a local unget hack for the other byte: + int ungetHack = EOF; + + if ( doUnicodeHeader ) { + doUnicodeHeader = FALSE; // only at the top + int c1 = dev->getch(); + if ( c1 == EOF ) + return rnum; + int c2 = dev->getch(); + if ( c1 == 0xfe && c2 == 0xff ) { + mapper = 0; + latin1 = FALSE; + internalOrder = TQChar::networkOrdered(); + networkOrder = TRUE; + } else if ( c1 == 0xff && c2 == 0xfe ) { + mapper = 0; + latin1 = FALSE; + internalOrder = !TQChar::networkOrdered(); + networkOrder = FALSE; + } else { + if ( c2 != EOF ) { + dev->ungetch( c2 ); + ungetHack = c1; + } else { + /* + A small bug might hide here. If only the first byte + of a file has made it so far, and that first byte + is half of the byte-order mark, then the utfness + will not be detected. + */ + dev->ungetch( c1 ); + } + } + } + +#ifndef TQT_NO_TEXTCODEC + if ( mapper ) { + bool shortRead = FALSE; + if ( !d->decoder ) + d->decoder = mapper->makeDecoder(); + while( rnum < len ) { + TQString s; + bool readBlock = !( len == 1+rnum ); + for (;;) { + // for efficiency: normally read a whole block + if ( readBlock ) { + // guess buffersize; this may be wrong (too small or too + // big). But we can handle this (either iterate reading + // or use ungetcBuf). + // Note that this might cause problems for codecs where + // one byte can result in >1 Unicode Characters if bytes + // are written to the stream in the meantime (loss of + // synchronicity). + uint rlen = len - rnum; + char *cbuf = new char[ rlen ]; + if ( ungetHack != EOF ) { + rlen = 1+dev->readBlock( cbuf+1, rlen-1 ); + cbuf[0] = (char)ungetHack; + ungetHack = EOF; + } else { + rlen = dev->readBlock( cbuf, rlen ); + } + s += d->decoder->toUnicode( cbuf, rlen ); + delete[] cbuf; + // use buffered reading only for the first time, because we + // have to get the stream synchronous again (this is easier + // with single character reading) + readBlock = FALSE; + } + // get stream (and codec) in sync + int c; + if ( ungetHack == EOF ) { + c = dev->getch(); + } else { + c = ungetHack; + ungetHack = EOF; + } + if ( c == EOF ) { + shortRead = TRUE; + break; + } + char b = c; + uint lengthBefore = s.length(); + s += d->decoder->toUnicode( &b, 1 ); + if ( s.length() > lengthBefore ) + break; // it seems we are in sync now + } + uint i = 0; + uint end = TQMIN( len-rnum, s.length() ); + while( i < end ) { + *buf = s.constref(i++); + buf++; + } + rnum += end; + if ( s.length() > i ) { + // could be = but append is clearer + d->ungetcBuf.append( s.mid( i ) ); + } + if ( shortRead ) + return rnum; + } + } else +#endif + if ( latin1 ) { + if ( len == 1+rnum ) { + // use this method for one character because it is more efficient + // (arnt doubts whether it makes a difference, but lets it stand) + int c = (ungetHack == EOF) ? dev->getch() : ungetHack; + if ( c != EOF ) { + *buf = (char)c; + buf++; + rnum++; + } + } else { + if ( ungetHack != EOF ) { + *buf = (char)ungetHack; + buf++; + rnum++; + ungetHack = EOF; + } + char *cbuf = new char[len - rnum]; + while ( !dev->atEnd() && rnum < len ) { + uint rlen = len - rnum; + rlen = dev->readBlock( cbuf, rlen ); + char *it = cbuf; + char *end = cbuf + rlen; + while ( it < end ) { + *buf = *it; + buf++; + it++; + } + rnum += rlen; + } + delete[] cbuf; + } + } else { // UCS-2 or UTF-16 + if ( len == 1+rnum ) { + int c1 = (ungetHack == EOF) ? dev->getch() : ungetHack; + if ( c1 == EOF ) + return rnum; + int c2 = dev->getch(); + if ( c2 == EOF ) + return rnum; + + if ( networkOrder ) { + *buf = TQChar( c2, c1 ); + } else { + *buf = TQChar( c1, c2 ); + } + buf++; + rnum++; + } else { + char *cbuf = new char[ 2*( len - rnum ) ]; // for paranoids: overflow possible + while ( !dev->atEnd() && rnum < len ) { + uint rlen = 2 * ( len-rnum ); + if ( ungetHack != EOF ) { + rlen = 1+dev->readBlock( cbuf+1, rlen-1 ); + cbuf[0] = (char)ungetHack; + ungetHack = EOF; + } else { + rlen = dev->readBlock( cbuf, rlen ); + } + // We can't use an odd number of bytes, so put it back. But + // do it only if we are capable of reading more -- normally + // there should not be an odd number, but the file might be + // truncated or not in UTF-16... + if ( (rlen & 1) == 1 ) + if ( !dev->atEnd() ) + dev->ungetch( cbuf[--rlen] ); + uint i = 0; + if ( networkOrder ) { + while( i < rlen ) { + *buf = TQChar( cbuf[i+1], cbuf[i] ); + buf++; + i+=2; + } + } else { + while( i < rlen ) { + *buf = TQChar( cbuf[i], cbuf[i+1] ); + buf++; + i+=2; + } + } + rnum += i/2; + } + delete[] cbuf; + } + } + return rnum; +} + +/*! + Tries to read one line, but at most len characters from the stream + and stores them in \a buf. + + Returns the number of characters really read. Newlines are not + stripped. + + There will be a TQEOF appended if the read reaches the end of file; + this is different to ts_getbuf(). + + This function works only if a newline (as byte) is also a newline + (as resulting character) since it uses TQIODevice::readLine(). So + use it only for such codecs where this is true! + + This function is (almost) a no-op for UTF 16. Don't use it if + doUnicodeHeader is TRUE! +*/ +uint TQTextStream::ts_getline( TQChar* buf ) +{ + uint rnum=0; // the number of TQChars really read + char cbuf[ getline_buf_size+1 ]; + + if ( d && d->ungetcBuf.length() ) { + while( rnum < getline_buf_size && rnum < d->ungetcBuf.length() ) { + buf[rnum] = d->ungetcBuf.constref(rnum); + rnum++; + } + d->ungetcBuf = d->ungetcBuf.mid( rnum ); + if ( rnum >= getline_buf_size ) + return rnum; + } + +#ifndef TQT_NO_TEXTCODEC + if ( mapper ) { + if ( !d->decoder ) + d->decoder = mapper->makeDecoder(); + TQString s; + bool readBlock = TRUE; + for (;;) { + // for efficiency: try to read a line + if ( readBlock ) { + int rlen = getline_buf_size - rnum; + rlen = dev->readLine( cbuf, rlen+1 ); + if ( rlen == -1 ) + rlen = 0; + s += d->decoder->toUnicode( cbuf, rlen ); + readBlock = FALSE; + } + if ( dev->atEnd() + || s.at( s.length()-1 ) == '\n' + || s.at( s.length()-1 ) == '\r' + ) { + break; + } else { + // get stream (and codec) in sync + int c; + c = dev->getch(); + if ( c == EOF ) { + break; + } + char b = c; + uint lengthBefore = s.length(); + s += d->decoder->toUnicode( &b, 1 ); + if ( s.length() > lengthBefore ) + break; // it seems we are in sync now + } + } + uint i = 0; + while( rnum < getline_buf_size && i < s.length() ) + buf[rnum++] = s.constref(i++); + if ( s.length() > i ) + // could be = but append is clearer + d->ungetcBuf.append( s.mid( i ) ); + if ( rnum < getline_buf_size && dev->atEnd() ) + buf[rnum++] = TQEOF; + } else +#endif + if ( latin1 ) { + int rlen = getline_buf_size - rnum; + rlen = dev->readLine( cbuf, rlen+1 ); + if ( rlen == -1 ) + rlen = 0; + char *end = cbuf+rlen; + char *it = cbuf; + buf +=rnum; + while ( it != end ) { + buf->setCell( *(it++) ); + buf->setRow( 0 ); + buf++; + } + rnum += rlen; + if ( rnum < getline_buf_size && dev->atEnd() ) + buf[1] = TQEOF; + } + return rnum; +} + + +/*! + Puts one character into the stream. +*/ +void TQTextStream::ts_putc( TQChar c ) +{ +#ifndef TQT_NO_TEXTCODEC + if ( mapper ) { + if ( !d->encoder ) + d->encoder = mapper->makeEncoder(); + int len = 1; + TQString s = c; + TQCString block = d->encoder->fromUnicode( s, len ); + dev->writeBlock( block, len ); + } else +#endif + if ( latin1 ) { + if ( c.row() ) + dev->putch( '?' ); // unknown character + else + dev->putch( c.cell() ); + } else { + if ( doUnicodeHeader ) { + doUnicodeHeader = FALSE; + ts_putc( TQChar::byteOrderMark ); + } + if ( internalOrder ) { + // this case is needed by TQStringBuffer + dev->writeBlock( (char*)&c, sizeof(TQChar) ); + } else if ( networkOrder ) { + dev->putch( c.row() ); + dev->putch( c.cell() ); + } else { + dev->putch( c.cell() ); + dev->putch( c.row() ); + } + } +} + +/*! + Puts one character into the stream. +*/ +void TQTextStream::ts_putc( int ch ) +{ + ts_putc( TQChar((ushort)ch) ); +} + +bool TQTextStream::ts_isdigit( TQChar c ) +{ + return c.isDigit(); +} + +bool TQTextStream::ts_isspace( TQChar c ) +{ + return c.isSpace(); +} + +void TQTextStream::ts_ungetc( TQChar c ) +{ + if ( c.unicode() == 0xffff ) + return; + + d->ungetcBuf.prepend( c ); +} + + + +/*! + Reads \a len bytes from the stream into \a s and returns a + reference to the stream. + + The buffer \a s must be preallocated. + + Note that no encoding is done by this function. + + \warning The behavior of this function is undefined unless the + stream's encoding is set to Unicode or Latin1. + + \sa TQIODevice::readBlock() +*/ + +TQTextStream &TQTextStream::readRawBytes( char *s, uint len ) +{ + dev->readBlock( s, len ); + return *this; +} + +/*! + Writes the \a len bytes from \a s to the stream and returns a + reference to the stream. + + Note that no encoding is done by this function. + + \sa TQIODevice::writeBlock() +*/ + +TQTextStream &TQTextStream::writeRawBytes( const char* s, uint len ) +{ + dev->writeBlock( s, len ); + return *this; +} + + +TQTextStream &TQTextStream::writeBlock( const char* p, uint len ) +{ + if ( doUnicodeHeader ) { + doUnicodeHeader = FALSE; + if ( !mapper && !latin1 ) + ts_putc( TQChar::byteOrderMark ); + } + // TQCString and const char * are treated as Latin-1 + if ( !mapper && latin1 ) { + dev->writeBlock( p, len ); + } else if ( !mapper && internalOrder ) { + TQChar *u = new TQChar[len]; + for ( uint i = 0; i < len; i++ ) + u[i] = p[i]; + dev->writeBlock( (char*)u, len * sizeof(TQChar) ); + delete [] u; + } +#ifndef TQT_NO_TEXTCODEC + else if (mapper) { + if (!d->encoder) + d->encoder = mapper->makeEncoder(); + TQString s = TQString::fromLatin1(p, len); + int l = len; + TQCString block = d->encoder->fromUnicode(s, l); + dev->writeBlock(block, l); + } +#endif + else { + for ( uint i = 0; i < len; i++ ) + ts_putc( (uchar)p[i] ); + } + return *this; +} + +TQTextStream &TQTextStream::writeBlock( const TQChar* p, uint len ) +{ +#ifndef TQT_NO_TEXTCODEC + if ( mapper ) { + if ( !d->encoder ) + d->encoder = mapper->makeEncoder(); + TQConstString s( p, len ); + int l = len; + TQCString block = d->encoder->fromUnicode( s.string(), l ); + dev->writeBlock( block, l ); + } else +#endif + if ( latin1 ) { + char *str = TQString::unicodeToLatin1( p, len ); + dev->writeBlock( str, len ); + delete [] str; + } else if ( internalOrder ) { + if ( doUnicodeHeader ) { + doUnicodeHeader = FALSE; + ts_putc( TQChar::byteOrderMark ); + } + dev->writeBlock( (char*)p, sizeof(TQChar)*len ); + } else { + for (uint i=0; isourceType = TQTextStreamPrivate::IODevice; +} + +/*! + Unsets the IO device. Equivalent to setDevice( 0 ). + + \sa device(), setDevice() +*/ + +void TQTextStream::unsetDevice() +{ + setDevice( 0 ); + d->sourceType = TQTextStreamPrivate::NotSet; +} + +/*! + \fn bool TQTextStream::atEnd() const + + Returns TRUE if the IO device has reached the end position (end of + the stream or file) or if there is no IO device set; otherwise + returns FALSE. + + \sa TQIODevice::atEnd() +*/ + +/*!\fn bool TQTextStream::eof() const + + \obsolete + + This function has been renamed to atEnd(). + + \sa TQIODevice::atEnd() +*/ + +/***************************************************************************** + TQTextStream read functions + *****************************************************************************/ + + +/*! + \overload + + Reads a char \a c from the stream and returns a reference to the + stream. Note that whitespace is skipped. +*/ + +TQTextStream &TQTextStream::operator>>( char &c ) +{ + CHECK_STREAM_PRECOND + c = eat_ws(); + return *this; +} + +/*! + Reads a char \a c from the stream and returns a reference to the + stream. Note that whitespace is \e not skipped. +*/ + +TQTextStream &TQTextStream::operator>>( TQChar &c ) +{ + CHECK_STREAM_PRECOND + c = ts_getc(); + return *this; +} + + +ulong TQTextStream::input_bin() +{ + ulong val = 0; + TQChar ch = eat_ws(); + int dv = ch.digitValue(); + while ( dv == 0 || dv == 1 ) { + val = ( val << 1 ) + dv; + ch = ts_getc(); + dv = ch.digitValue(); + } + if ( ch != TQEOF ) + ts_ungetc( ch ); + return val; +} + +ulong TQTextStream::input_oct() +{ + ulong val = 0; + TQChar ch = eat_ws(); + int dv = ch.digitValue(); + while ( dv >= 0 && dv <= 7 ) { + val = ( val << 3 ) + dv; + ch = ts_getc(); + dv = ch.digitValue(); + } + if ( dv == 8 || dv == 9 ) { + while ( ts_isdigit(ch) ) + ch = ts_getc(); + } + if ( ch != TQEOF ) + ts_ungetc( ch ); + return val; +} + +ulong TQTextStream::input_dec() +{ + ulong val = 0; + TQChar ch = eat_ws(); + int dv = ch.digitValue(); + while ( ts_isdigit(ch) ) { + val = val * 10 + dv; + ch = ts_getc(); + dv = ch.digitValue(); + } + if ( ch != TQEOF ) + ts_ungetc( ch ); + return val; +} + +ulong TQTextStream::input_hex() +{ + ulong val = 0; + TQChar ch = eat_ws(); + char c = ch; + while ( isxdigit((uchar) c) ) { + val <<= 4; + if ( ts_isdigit(c) ) + val += c - '0'; + else + val += 10 + tolower( (uchar) c ) - 'a'; + c = ch = ts_getc(); + } + if ( ch != TQEOF ) + ts_ungetc( ch ); + return val; +} + +long TQTextStream::input_int() +{ + long val; + TQChar ch; + char c; + switch ( flags() & basefield ) { + case bin: + val = (long)input_bin(); + break; + case oct: + val = (long)input_oct(); + break; + case dec: + c = ch = eat_ws(); + if ( ch == TQEOF ) { + val = 0; + } else { + if ( !(c == '-' || c == '+') ) + ts_ungetc( ch ); + if ( c == '-' ) { + ulong v = input_dec(); + if ( v ) { // ensure that LONG_MIN can be read + v--; + val = -((long)v) - 1; + } else { + val = 0; + } + } else { + val = (long)input_dec(); + } + } + break; + case hex: + val = (long)input_hex(); + break; + default: + val = 0; + c = ch = eat_ws(); + if ( c == '0' ) { // bin, oct or hex + c = ch = ts_getc(); + if ( tolower((uchar) c) == 'x' ) + val = (long)input_hex(); + else if ( tolower((uchar) c) == 'b' ) + val = (long)input_bin(); + else { // octal + ts_ungetc( ch ); + if ( c >= '0' && c <= '7' ) { + val = (long)input_oct(); + } else { + val = 0; + } + } + } else if ( ts_isdigit(ch) ) { + ts_ungetc( ch ); + val = (long)input_dec(); + } else if ( c == '-' || c == '+' ) { + ulong v = input_dec(); + if ( c == '-' ) { + if ( v ) { // ensure that LONG_MIN can be read + v--; + val = -((long)v) - 1; + } else { + val = 0; + } + } else { + val = (long)v; + } + } + } + return val; +} + +// +// We use a table-driven FSM to parse floating point numbers +// strtod() cannot be used directly since we're reading from a TQIODevice +// + +double TQTextStream::input_double() +{ + const int Init = 0; // states + const int Sign = 1; + const int Mantissa = 2; + const int Dot = 3; + const int Abscissa = 4; + const int ExpMark = 5; + const int ExpSign = 6; + const int Exponent = 7; + const int Done = 8; + + const int InputSign = 1; // input tokens + const int InputDigit = 2; + const int InputDot = 3; + const int InputExp = 4; + + static const uchar table[8][5] = { + /* None InputSign InputDigit InputDot InputExp */ + { 0, Sign, Mantissa, Dot, 0, }, // Init + { 0, 0, Mantissa, Dot, 0, }, // Sign + { Done, Done, Mantissa, Dot, ExpMark,}, // Mantissa + { 0, 0, Abscissa, 0, 0, }, // Dot + { Done, Done, Abscissa, Done, ExpMark,}, // Abscissa + { 0, ExpSign, Exponent, 0, 0, }, // ExpMark + { 0, 0, Exponent, 0, 0, }, // ExpSign + { Done, Done, Exponent, Done, Done } // Exponent + }; + + int state = Init; // parse state + int input; // input token + + char buf[256]; + int i = 0; + TQChar c = eat_ws(); + + for (;;) { + + switch ( c ) { + case '+': + case '-': + input = InputSign; + break; + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + input = InputDigit; + break; + case '.': + input = InputDot; + break; + case 'e': + case 'E': + input = InputExp; + break; + default: + input = 0; + break; + } + + state = table[state][input]; + + if ( state == 0 || state == Done || i > 250 ) { + if ( i > 250 ) { // ignore rest of digits + do { c = ts_getc(); } while ( c != TQEOF && ts_isdigit(c) ); + } + if ( c != TQEOF ) + ts_ungetc( c ); + buf[i] = '\0'; + char *end; + return strtod( buf, &end ); + } + + buf[i++] = c; + c = ts_getc(); + } + +#if !defined(Q_CC_EDG) + return 0.0; +#endif +} + + +/*! + \overload + + Reads a signed \c short integer \a i from the stream and returns a + reference to the stream. See flags() for an explanation of the + expected input format. +*/ + +TQTextStream &TQTextStream::operator>>( signed short &i ) +{ + CHECK_STREAM_PRECOND + i = (signed short)input_int(); + return *this; +} + + +/*! + \overload + + Reads an unsigned \c short integer \a i from the stream and + returns a reference to the stream. See flags() for an explanation + of the expected input format. +*/ + +TQTextStream &TQTextStream::operator>>( unsigned short &i ) +{ + CHECK_STREAM_PRECOND + i = (unsigned short)input_int(); + return *this; +} + + +/*! + \overload + + Reads a signed \c int \a i from the stream and returns a reference + to the stream. See flags() for an explanation of the expected + input format. +*/ + +TQTextStream &TQTextStream::operator>>( signed int &i ) +{ + CHECK_STREAM_PRECOND + i = (signed int)input_int(); + return *this; +} + + +/*! + \overload + + Reads an unsigned \c int \a i from the stream and returns a + reference to the stream. See flags() for an explanation of the + expected input format. +*/ + +TQTextStream &TQTextStream::operator>>( unsigned int &i ) +{ + CHECK_STREAM_PRECOND + i = (unsigned int)input_int(); + return *this; +} + + +/*! + \overload + + Reads a signed \c long int \a i from the stream and returns a + reference to the stream. See flags() for an explanation of the + expected input format. +*/ + +TQTextStream &TQTextStream::operator>>( signed long &i ) +{ + CHECK_STREAM_PRECOND + i = (signed long)input_int(); + return *this; +} + + +/*! + \overload + + Reads an unsigned \c long int \a i from the stream and returns a + reference to the stream. See flags() for an explanation of the + expected input format. +*/ + +TQTextStream &TQTextStream::operator>>( unsigned long &i ) +{ + CHECK_STREAM_PRECOND + i = (unsigned long)input_int(); + return *this; +} + + +/*! + \overload + + Reads a \c float \a f from the stream and returns a reference to + the stream. See flags() for an explanation of the expected input + format. +*/ + +TQTextStream &TQTextStream::operator>>( float &f ) +{ + CHECK_STREAM_PRECOND + f = (float)input_double(); + return *this; +} + + +/*! + \overload + + Reads a \c double \a f from the stream and returns a reference to + the stream. See flags() for an explanation of the expected input + format. +*/ + +TQTextStream &TQTextStream::operator>>( double &f ) +{ + CHECK_STREAM_PRECOND + f = input_double(); + return *this; +} + + +/*! + \overload + + Reads a "word" from the stream into \a s and returns a reference + to the stream. + + A word consists of characters for which isspace() returns FALSE. +*/ + +TQTextStream &TQTextStream::operator>>( char *s ) +{ + CHECK_STREAM_PRECOND + int maxlen = width( 0 ); + TQChar c = eat_ws(); + if ( !maxlen ) + maxlen = -1; + while ( c != TQEOF ) { + if ( ts_isspace(c) || maxlen-- == 0 ) { + ts_ungetc( c ); + break; + } + *s++ = c; + c = ts_getc(); + } + + *s = '\0'; + return *this; +} + +/*! + \overload + + Reads a "word" from the stream into \a str and returns a reference + to the stream. + + A word consists of characters for which isspace() returns FALSE. +*/ + +TQTextStream &TQTextStream::operator>>( TQString &str ) +{ + CHECK_STREAM_PRECOND + str=TQString::fromLatin1(""); + TQChar c = eat_ws(); + + while ( c != TQEOF ) { + if ( ts_isspace(c) ) { + ts_ungetc( c ); + break; + } + str += c; + c = ts_getc(); + } + return *this; +} + +/*! + \overload + + Reads a "word" from the stream into \a str and returns a reference + to the stream. + + A word consists of characters for which isspace() returns FALSE. +*/ + +TQTextStream &TQTextStream::operator>>( TQCString &str ) +{ + CHECK_STREAM_PRECOND + TQCString *dynbuf = 0; + const int buflen = 256; + char buffer[buflen]; + char *s = buffer; + int i = 0; + TQChar c = eat_ws(); + + while ( c != TQEOF ) { + if ( ts_isspace(c) ) { + ts_ungetc( c ); + break; + } + if ( i >= buflen-1 ) { + if ( !dynbuf ) { // create dynamic buffer + dynbuf = new TQCString(buflen*2); + memcpy( dynbuf->data(), s, i ); // copy old data + } else if ( i >= (int)dynbuf->size()-1 ) { + dynbuf->resize( dynbuf->size()*2 ); + } + s = dynbuf->data(); + } + s[i++] = c; + c = ts_getc(); + } + str.resize( i+1 ); + memcpy( str.data(), s, i ); + delete dynbuf; + return *this; +} + + +/*! + Reads a line from the stream and returns a string containing the + text. + + The returned string does not contain any trailing newline or + carriage return. Note that this is different from + TQIODevice::readLine(), which does not strip the newline at the end + of the line. + + On EOF you will get a TQString that is null. On reading an empty + line the returned TQString is empty but not null. + + \sa TQIODevice::readLine() +*/ + +TQString TQTextStream::readLine() +{ +#if defined(QT_CHECK_STATE) + if ( !dev ) { + tqWarning( "TQTextStream::readLine: No device" ); + return TQString::null; + } +#endif + bool readCharByChar = TRUE; + TQString result; +#if 0 + if ( !doUnicodeHeader && ( + (latin1) || + (mapper != 0 && mapper->mibEnum() == 106 ) // UTF 8 + ) ) { + readCharByChar = FALSE; + // use optimized read line + TQChar c[getline_buf_size]; + int pos = 0; + bool eof = FALSE; + + for (;;) { + pos = ts_getline( c ); + if ( pos == 0 ) { + // something went wrong; try fallback + readCharByChar = TRUE; + //dev->resetStatus(); + break; + } + if ( c[pos-1] == TQEOF || c[pos-1] == '\n' ) { + if ( pos>2 && c[pos-1]==TQEOF && c[pos-2]=='\n' ) { + result += TQString( c, pos-2 ); + } else if ( pos > 1 ) { + result += TQString( c, pos-1 ); + } + if ( pos == 1 && c[pos-1] == TQEOF ) + eof = TRUE; + break; + } else { + result += TQString( c, pos ); + } + } + if ( eof && result.isEmpty() ) + return TQString::null; + } +#endif + if ( readCharByChar ) { + const int buf_size = 256; + TQChar c[buf_size]; + int pos = 0; + + c[pos] = ts_getc(); + if ( c[pos] == TQEOF ) + return TQString::null; + + while ( c[pos] != TQEOF && c[pos] != '\n' ) { + if ( c[pos] == '\r' ) { // ( handle mac and dos ) + TQChar nextc = ts_getc(); + if ( nextc != '\n' ) + ts_ungetc( nextc ); + break; + } + pos++; + if ( pos >= buf_size ) { + result += TQString( c, pos ); + pos = 0; + } + c[pos] = ts_getc(); + } + result += TQString( c, pos ); + } + + return result; +} + + +/*! + Reads the entire stream from the current position, and returns a string + containing the text. + + \sa TQIODevice::readLine() +*/ + +TQString TQTextStream::read() +{ +#if defined(QT_CHECK_STATE) + if ( !dev ) { + tqWarning( "TQTextStream::read: No device" ); + return TQString::null; + } +#endif + TQString result; + const uint bufsize = 512; + TQChar buf[bufsize]; + uint i, num, start; + bool skipped_cr = FALSE; + + for (;;) { + num = ts_getbuf(buf,bufsize); + // convert dos (\r\n) and mac (\r) style eol to unix style (\n) + start = 0; + for ( i=0; i>= 1; + if ( !n ) + break; + } + if ( flags() & showbase ) { // show base + *--p = (flags() & uppercase) ? 'B' : 'b'; + *--p = '0'; + } + break; + + case I_BASE_8: // output octal number + p = &buf[74]; + *p = '\0'; + do { + *--p = (char)(n&7) + '0'; + n >>= 3; + } while ( n ); + if ( flags() & showbase ) + *--p = '0'; + break; + + case I_BASE_16: // output hexadecimal number + p = &buf[74]; + *p = '\0'; + hexdigits = (flags() & uppercase) ? + hexdigits_upper : hexdigits_lower; + do { + *--p = hexdigits[(int)n&0xf]; + n >>= 4; + } while ( n ); + if ( flags() & showbase ) { + *--p = (flags() & uppercase) ? 'X' : 'x'; + *--p = '0'; + } + break; + + default: // decimal base is default + p = &buf[74]; + *p = '\0'; + if ( neg ) + n = (unsigned long long)(-(long long)n); + do { + *--p = ((int)(n%10)) + '0'; + n /= 10; + } while ( n ); + if ( neg ) + *--p = '-'; + else if ( flags() & showpos ) + *--p = '+'; + if ( (flags() & internal) && fwidth && !ts_isdigit(*p) ) { + ts_putc( *p ); // special case for internal + ++p; // padding + fwidth--; + return *this << (const char*)p; + } + } + if ( fwidth ) { // adjustment required + if ( !(flags() & left) ) { // but NOT left adjustment + len = tqstrlen(p); + int padlen = fwidth - len; + if ( padlen <= 0 ) { // no padding required + writeBlock( p, len ); + } else if ( padlen < (int)(p-buf) ) { // speeds up padding + memset( p-padlen, (char)fillchar, padlen ); + writeBlock( p-padlen, padlen+len ); + } + else // standard padding + *this << (const char*)p; + } + else + *this << (const char*)p; + fwidth = 0; // reset field width + } + else + writeBlock( p, tqstrlen(p) ); + return *this; +} + + +/*! + \overload + + Writes a \c short integer \a i to the stream and returns a + reference to the stream. +*/ + +TQTextStream &TQTextStream::operator<<( signed short i ) +{ + return output_int( I_SHORT | I_SIGNED, i, i < 0 ); +} + + +/*! + \overload + + Writes an \c unsigned \c short integer \a i to the stream and + returns a reference to the stream. +*/ + +TQTextStream &TQTextStream::operator<<( unsigned short i ) +{ + return output_int( I_SHORT | I_UNSIGNED, i, FALSE ); +} + + +/*! + \overload + + Writes an \c int \a i to the stream and returns a reference to the + stream. +*/ + +TQTextStream &TQTextStream::operator<<( signed int i ) +{ + return output_int( I_INT | I_SIGNED, i, i < 0 ); +} + + +/*! + \overload + + Writes an \c unsigned \c int \a i to the stream and returns a + reference to the stream. +*/ + +TQTextStream &TQTextStream::operator<<( unsigned int i ) +{ + return output_int( I_INT | I_UNSIGNED, i, FALSE ); +} + + +/*! + \overload + + Writes a \c long \c int \a i to the stream and returns a reference + to the stream. +*/ + +TQTextStream &TQTextStream::operator<<( signed long i ) +{ + return output_int( I_LONG | I_SIGNED, i, i < 0 ); +} + + +/*! + \overload + + Writes an \c unsigned \c long \c int \a i to the stream and + returns a reference to the stream. +*/ + +TQTextStream &TQTextStream::operator<<( unsigned long i ) +{ + return output_int( I_LONG | I_UNSIGNED, i, FALSE ); +} + +/*! + \overload + + Writes a \c long long \c int \a i to the stream and returns a reference + to the stream. +*/ + +TQTextStream &TQTextStream::operator<<( signed long long i ) +{ + return output_int( I_LONGLONG | I_SIGNED, i, i < 0 ); +} + + +/*! + \overload + + Writes an \c unsigned \c long \c int \a i to the stream and + returns a reference to the stream. +*/ + +TQTextStream &TQTextStream::operator<<( unsigned long long i ) +{ + return output_int( I_LONGLONG | I_UNSIGNED, i, FALSE ); +} + + +/*! + \overload + + Writes a \c float \a f to the stream and returns a reference to + the stream. +*/ + +TQTextStream &TQTextStream::operator<<( float f ) +{ + return *this << (double)f; +} + +/*! + \overload + + Writes a \c double \a f to the stream and returns a reference to + the stream. +*/ + +TQTextStream &TQTextStream::operator<<( double f ) +{ + CHECK_STREAM_PRECOND + char f_char; + char format[16]; + if ( (flags()&floatfield) == fixed ) + f_char = 'f'; + else if ( (flags()&floatfield) == scientific ) + f_char = (flags() & uppercase) ? 'E' : 'e'; + else + f_char = (flags() & uppercase) ? 'G' : 'g'; + char *fs = format; // generate format string + *fs++ = '%'; // "%.l" + *fs++ = '.'; + int prec = precision(); + if ( prec > 99 ) + prec = 99; + if ( prec >= 10 ) { + *fs++ = prec / 10 + '0'; + *fs++ = prec % 10 + '0'; + } else { + *fs++ = prec + '0'; + } + *fs++ = 'l'; + *fs++ = f_char; + *fs = '\0'; + TQString num; + num.sprintf(format, f); // convert to text + if ( fwidth ) // padding + *this << num.latin1(); + else // just write it + writeBlock(num.latin1(), num.length()); + return *this; +} + + +/*! + \overload + + Writes a string to the stream and returns a reference to the + stream. + + The string \a s is assumed to be Latin1 encoded independent of the + Encoding set for the TQTextStream. +*/ + +TQTextStream &TQTextStream::operator<<( const char* s ) +{ + CHECK_STREAM_PRECOND + char padbuf[48]; + uint len = tqstrlen( s ); // don't write null terminator + if ( fwidth ) { // field width set + int padlen = fwidth - len; + fwidth = 0; // reset width + if ( padlen > 0 ) { + char *ppad; + if ( padlen > 46 ) { // create extra big fill buffer + ppad = new char[padlen]; + TQ_CHECK_PTR( ppad ); + } else { + ppad = padbuf; + } + memset( ppad, (char)fillchar, padlen ); // fill with fillchar + if ( !(flags() & left) ) { + writeBlock( ppad, padlen ); + padlen = 0; + } + writeBlock( s, len ); + if ( padlen ) + writeBlock( ppad, padlen ); + if ( ppad != padbuf ) // delete extra big fill buf + delete[] ppad; + return *this; + } + } + writeBlock( s, len ); + return *this; +} + +/*! + \overload + + Writes \a s to the stream and returns a reference to the stream. + + The string \a s is assumed to be Latin1 encoded independent of the + Encoding set for the TQTextStream. +*/ + +TQTextStream &TQTextStream::operator<<( const TQCString & s ) +{ + return operator<<(s.data()); +} + +/*! + \overload + + Writes \a s to the stream and returns a reference to the stream. +*/ + +TQTextStream &TQTextStream::operator<<( const TQString& s ) +{ + if ( !mapper && latin1 ) + return operator<<(s.latin1()); + CHECK_STREAM_PRECOND + TQString s1 = s; + if ( fwidth ) { // field width set + if ( !(flags() & left) ) { + s1 = s.rightJustify(fwidth, (char)fillchar); + } else { + s1 = s.leftJustify(fwidth, (char)fillchar); + } + fwidth = 0; // reset width + } + writeBlock( s1.unicode(), s1.length() ); + return *this; +} + + +/*! + \overload + + Writes a pointer to the stream and returns a reference to the + stream. + + The \a ptr is output as an unsigned long hexadecimal integer. +*/ + +TQTextStream &TQTextStream::operator<<( void *ptr ) +{ + int f = flags(); + setf( hex, basefield ); + setf( showbase ); + unsetf( uppercase ); + output_int( I_LONG | I_UNSIGNED, (ulong)ptr, FALSE ); + flags( f ); + return *this; +} + + +/*! + \fn int TQTextStream::flags() const + + Returns the current stream flags. The default value is 0. + + \table + \header \i Flag \i Meaning + \row \i \c skipws \i Not currently used; whitespace always skipped + \row \i \c left \i Numeric fields are left-aligned + \row \i \c right + \i Not currently used (by default, numerics are right-aligned) + \row \i \c internal \i Puts any padding spaces between +/- and value + \row \i \c bin \i Output \e and input only in binary + \row \i \c oct \i Output \e and input only in octal + \row \i \c dec \i Output \e and input only in decimal + \row \i \c hex \i Output \e and input only in hexadecimal + \row \i \c showbase + \i Annotates numeric outputs with 0b, 0, or 0x if in \c bin, + \c oct, or \c hex format + \row \i \c showpoint \i Not currently used + \row \i \c uppercase \i Uses 0B and 0X rather than 0b and 0x + \row \i \c showpos \i Shows + for positive numeric values + \row \i \c scientific \i Uses scientific notation for floating point values + \row \i \c fixed \i Uses fixed-point notation for floating point values + \endtable + + Note that unless \c bin, \c oct, \c dec, or \c hex is set, the + input base is octal if the value starts with 0, hexadecimal if it + starts with 0x, binary if it starts with 0b, and decimal + otherwise. + + \sa setf(), unsetf() +*/ + +/*! + \fn int TQTextStream::flags( int f ) + + \overload + + Sets the stream flags to \a f. Returns the previous stream flags. + + \sa setf(), unsetf(), flags() +*/ + +/*! + \fn int TQTextStream::setf( int bits ) + + Sets the stream flag bits \a bits. Returns the previous stream + flags. + + Equivalent to \c{flags( flags() | bits )}. + + \sa setf(), unsetf() +*/ + +/*! + \fn int TQTextStream::setf( int bits, int mask ) + + \overload + + Sets the stream flag bits \a bits with a bit mask \a mask. Returns + the previous stream flags. + + Equivalent to \c{flags( (flags() & ~mask) | (bits & mask) )}. + + \sa setf(), unsetf() +*/ + +/*! + \fn int TQTextStream::unsetf( int bits ) + + Clears the stream flag bits \a bits. Returns the previous stream + flags. + + Equivalent to \c{flags( flags() & ~mask )}. + + \sa setf() +*/ + +/*! + \fn int TQTextStream::width() const + + Returns the field width. The default value is 0. +*/ + +/*! + \fn int TQTextStream::width( int w ) + + \overload + + Sets the field width to \a w. Returns the previous field width. +*/ + +/*! + \fn int TQTextStream::fill() const + + Returns the fill character. The default value is ' ' (space). +*/ + +/*! + \overload int TQTextStream::fill( int f ) + + Sets the fill character to \a f. Returns the previous fill character. +*/ + +/*! + \fn int TQTextStream::precision() const + + Returns the precision. The default value is 6. +*/ + +/*! + \fn int TQTextStream::precision( int p ) + + \overload + + Sets the precision to \a p. Returns the previous precision setting. +*/ + + + /***************************************************************************** + TQTextStream manipulators + *****************************************************************************/ + +TQTextStream &bin( TQTextStream &s ) +{ + s.setf(TQTS::bin,TQTS::basefield); + return s; +} + +TQTextStream &oct( TQTextStream &s ) +{ + s.setf(TQTS::oct,TQTS::basefield); + return s; +} + +TQTextStream &dec( TQTextStream &s ) +{ + s.setf(TQTS::dec,TQTS::basefield); + return s; +} + +TQTextStream &hex( TQTextStream &s ) +{ + s.setf(TQTS::hex,TQTS::basefield); + return s; +} + +TQTextStream &endl( TQTextStream &s ) +{ + return s << '\n'; +} + +TQTextStream &flush( TQTextStream &s ) +{ + if ( s.device() ) + s.device()->flush(); + return s; +} + +TQTextStream &ws( TQTextStream &s ) +{ + s.skipWhiteSpace(); + return s; +} + +TQTextStream &reset( TQTextStream &s ) +{ + s.reset(); + return s; +} + + +/*! + \class TQTextIStream tqtextstream.h + \reentrant + \brief The TQTextIStream class is a convenience class for input streams. + + \ingroup io + \ingroup text + + This class provides a shorthand for creating simple input + \l{TQTextStream}s without having to pass a \e mode argument to the + constructor. + + This class makes it easy, for example, to write things like this: + \code + TQString data = "123 456"; + int a, b; + TQTextIStream(&data) >> a >> b; + \endcode + + \sa TQTextOStream +*/ + +/*! + \fn TQTextIStream::TQTextIStream( const TQString *s ) + + Constructs a stream to read from the string \a s. +*/ +/*! + \fn TQTextIStream::TQTextIStream( TQByteArray ba ) + + Constructs a stream to read from the array \a ba. +*/ +/*! + \fn TQTextIStream::TQTextIStream( FILE *f ) + + Constructs a stream to read from the file \a f. +*/ + + +/*! + \class TQTextOStream + \reentrant + \brief The TQTextOStream class is a convenience class for output streams. + + \ingroup io + \ingroup text + + This class provides a shorthand for creating simple output + \l{TQTextStream}s without having to pass a \e mode argument to the + constructor. + + This makes it easy for example, to write things like this: + \code + TQString result; + TQTextOStream(&result) << "pi = " << 3.14; + \endcode +*/ + +/*! + \fn TQTextOStream::TQTextOStream( TQString *s ) + + Constructs a stream to write to string \a s. +*/ +/*! + \fn TQTextOStream::TQTextOStream( TQByteArray ba ) + + Constructs a stream to write to the array \a ba. +*/ +/*! + \fn TQTextOStream::TQTextOStream( FILE *f ) + + Constructs a stream to write to the file \a f. +*/ + + + +/*! + Sets the encoding of this stream to \a e, where \a e is one of the + following values: + \table + \header \i Encoding \i Meaning + \row \i Locale + \i Uses local file format (Latin1 if locale is not set), but + autodetecting Unicode(utf16) on input. + \row \i Unicode + \i Uses Unicode(utf16) for input and output. Output will be + written in the order most efficient for the current platform + (i.e. the order used internally in TQString). + \row \i UnicodeUTF8 + \i Using Unicode(utf8) for input and output. If you use it for + input it will autodetect utf16 and use it instead of utf8. + \row \i Latin1 + \i ISO-8859-1. Will not autodetect utf16. + \row \i UnicodeNetworkOrder + \i Uses network order Unicode(utf16) for input and output. + Useful when reading Unicode data that does not start with the + byte order marker. + \row \i UnicodeReverse + \i Uses reverse network order Unicode(utf16) for input and + output. Useful when reading Unicode data that does not start + with the byte order marker or when writing data that should be + read by buggy Windows applications. + \row \i RawUnicode + \i Like Unicode, but does not write the byte order marker nor + does it auto-detect the byte order. Useful only when writing to + non-persistent storage used by a single process. + \endtable + + \c Locale and all Unicode encodings, except \c RawUnicode, will look + at the first two bytes in an input stream to determine the byte + order. The initial byte order marker will be stripped off before + data is read. + + Note that this function should be called before any data is read to + or written from the stream. + + \sa setCodec() +*/ + +void TQTextStream::setEncoding( Encoding e ) +{ + if ( d->sourceType == TQTextStreamPrivate::String ) + return; + + switch ( e ) { + case Unicode: + mapper = 0; + latin1 = FALSE; + doUnicodeHeader = TRUE; + internalOrder = TRUE; + networkOrder = TQChar::networkOrdered(); + break; + case UnicodeUTF8: +#ifndef TQT_NO_TEXTCODEC + mapper = TQTextCodec::codecForMib( 106 ); + latin1 = FALSE; + doUnicodeHeader = TRUE; + internalOrder = TRUE; + networkOrder = TQChar::networkOrdered(); +#else + mapper = 0; + latin1 = TRUE; + doUnicodeHeader = TRUE; +#endif + break; + case UnicodeNetworkOrder: + mapper = 0; + latin1 = FALSE; + doUnicodeHeader = TRUE; + internalOrder = TQChar::networkOrdered(); + networkOrder = TRUE; + break; + case UnicodeReverse: + mapper = 0; + latin1 = FALSE; + doUnicodeHeader = TRUE; + internalOrder = !TQChar::networkOrdered(); + networkOrder = FALSE; + break; + case RawUnicode: + mapper = 0; + latin1 = FALSE; + doUnicodeHeader = FALSE; + internalOrder = TRUE; + networkOrder = TQChar::networkOrdered(); + break; + case Locale: + latin1 = TRUE; // fallback to Latin-1 +#ifndef TQT_NO_TEXTCODEC + mapper = TQTextCodec::codecForLocale(); + // optimized Latin-1 processing +#if defined(Q_OS_WIN32) + if ( GetACP() == 1252 ) + mapper = 0; +#endif + if ( mapper && mapper->mibEnum() == 4 ) +#endif + mapper = 0; + + doUnicodeHeader = TRUE; // If it reads as Unicode, accept it + break; + case Latin1: + mapper = 0; + doUnicodeHeader = FALSE; + latin1 = TRUE; + break; + } +} + + +#ifndef TQT_NO_TEXTCODEC +/*! + Sets the codec for this stream to \a codec. Will not try to + autodetect Unicode. + + Note that this function should be called before any data is read + to/written from the stream. + + \sa setEncoding(), codec() +*/ + +void TQTextStream::setCodec( TQTextCodec *codec ) +{ + if ( d->sourceType == TQTextStreamPrivate::String ) + return; // TQString does not need any codec + mapper = codec; + latin1 = ( codec->mibEnum() == 4 ); + if ( latin1 ) + mapper = 0; + doUnicodeHeader = FALSE; +} + +/*! + Returns the codec actually used for this stream. + + If Unicode is automatically detected in input, a codec with \link + TQTextCodec::name() name() \endlink "ISO-10646-UCS-2" is returned. + + \sa setCodec() +*/ + +TQTextCodec *TQTextStream::codec() +{ + if ( mapper ) { + return mapper; + } else { + // 4 is "ISO 8859-1", 1000 is "ISO-10646-UCS-2" + return TQTextCodec::codecForMib( latin1 ? 4 : 1000 ); + } +} + +#endif + +#endif // TQT_NO_TEXTSTREAM diff --git a/src/tools/tqtextstream.h b/src/tools/tqtextstream.h new file mode 100644 index 000000000..ab2366b39 --- /dev/null +++ b/src/tools/tqtextstream.h @@ -0,0 +1,341 @@ +/**************************************************************************** +** +** Definition of TQTextStream class +** +** Created : 940922 +** +** 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 TQTEXTSTREAM_H +#define TQTEXTSTREAM_H + +#ifndef QT_H +#include "ntqiodevice.h" +#include "tqstring.h" +#include +#endif // QT_H + +#ifndef TQT_NO_TEXTSTREAM +class TQTextCodec; +class TQTextDecoder; + +class TQTextStreamPrivate; + +class TQ_EXPORT TQTextStream // text stream class +{ +public: + enum Encoding { Locale, Latin1, Unicode, UnicodeNetworkOrder, + UnicodeReverse, RawUnicode, UnicodeUTF8 }; + + void setEncoding( Encoding ); +#ifndef TQT_NO_TEXTCODEC + void setCodec( TQTextCodec* ); + TQTextCodec *codec(); +#endif + + TQTextStream(); + TQTextStream( TQIODevice * ); + TQTextStream( TQString*, int mode ); + TQTextStream( TQString&, int mode ); // obsolete + TQTextStream( TQByteArray, int mode ); + TQTextStream( FILE *, int mode ); + virtual ~TQTextStream(); + + TQIODevice *device() const; + void setDevice( TQIODevice * ); + void unsetDevice(); + + bool atEnd() const; + bool eof() const; + + TQTextStream &operator>>( TQChar & ); + TQTextStream &operator>>( char & ); + TQTextStream &operator>>( signed short & ); + TQTextStream &operator>>( unsigned short & ); + TQTextStream &operator>>( signed int & ); + TQTextStream &operator>>( unsigned int & ); + TQTextStream &operator>>( signed long & ); + TQTextStream &operator>>( unsigned long & ); + TQTextStream &operator>>( float & ); + TQTextStream &operator>>( double & ); + TQTextStream &operator>>( char * ); + TQTextStream &operator>>( TQString & ); + TQTextStream &operator>>( TQCString & ); + + TQTextStream &operator<<( TQChar ); + TQTextStream &operator<<( char ); + TQTextStream &operator<<( signed short ); + TQTextStream &operator<<( unsigned short ); + TQTextStream &operator<<( signed int ); + TQTextStream &operator<<( unsigned int ); + TQTextStream &operator<<( signed long ); + TQTextStream &operator<<( unsigned long ); + TQTextStream &operator<<( signed long long ); + TQTextStream &operator<<( unsigned long long ); + TQTextStream &operator<<( float ); + TQTextStream &operator<<( double ); + TQTextStream &operator<<( const char* ); + TQTextStream &operator<<( const TQString & ); + TQTextStream &operator<<( const TQCString & ); + TQTextStream &operator<<( void * ); // any pointer + + TQTextStream &readRawBytes( char *, uint len ); + TQTextStream &writeRawBytes( const char* , uint len ); + + TQString readLine(); + TQString read(); + void skipWhiteSpace(); + + enum { + skipws = 0x0001, // skip whitespace on input + left = 0x0002, // left-adjust output + right = 0x0004, // right-adjust output + internal = 0x0008, // pad after sign + bin = 0x0010, // binary format integer + oct = 0x0020, // octal format integer + dec = 0x0040, // decimal format integer + hex = 0x0080, // hex format integer + showbase = 0x0100, // show base indicator + showpoint = 0x0200, // force decimal point (float) + uppercase = 0x0400, // upper-case hex output + showpos = 0x0800, // add '+' to positive integers + scientific= 0x1000, // scientific float output + fixed = 0x2000 // fixed float output + }; + + static const int basefield; // bin | oct | dec | hex + static const int adjustfield; // left | right | internal + static const int floatfield; // scientific | fixed + + int flags() const; + int flags( int f ); + int setf( int bits ); + int setf( int bits, int mask ); + int unsetf( int bits ); + + void reset(); + + int width() const; + int width( int ); + int fill() const; + int fill( int ); + int precision() const; + int precision( int ); + +private: + long input_int(); + void init(); + TQTextStream &output_int( int, unsigned long long, bool ); + + TQIODevice *dev; + + int fflags; + int fwidth; + int fillchar; + int fprec; + bool doUnicodeHeader; + bool owndev; + TQTextCodec *mapper; + TQTextStreamPrivate * d; + TQChar unused1; // ### remove in TQt 4.0 + bool latin1; + bool internalOrder; + bool networkOrder; + void *unused2; // ### remove in TQt 4.0 + + TQChar eat_ws(); + uint ts_getline( TQChar* ); + void ts_ungetc( TQChar ); + TQChar ts_getc(); + uint ts_getbuf( TQChar*, uint ); + void ts_putc(int); + void ts_putc(TQChar); + bool ts_isspace(TQChar); + bool ts_isdigit(TQChar); + ulong input_bin(); + ulong input_oct(); + ulong input_dec(); + ulong input_hex(); + double input_double(); + TQTextStream &writeBlock( const char* p, uint len ); + TQTextStream &writeBlock( const TQChar* p, uint len ); + +private: // Disabled copy constructor and operator= +#if defined(TQ_DISABLE_COPY) + TQTextStream( const TQTextStream & ); + TQTextStream &operator=( const TQTextStream & ); +#endif +}; + +typedef TQTextStream TQTS; + +class TQ_EXPORT TQTextIStream : public TQTextStream { +public: + TQTextIStream( const TQString* s ) : + TQTextStream((TQString*)s,IO_ReadOnly) { } + TQTextIStream( TQByteArray ba ) : + TQTextStream(ba,IO_ReadOnly) { } + TQTextIStream( FILE *f ) : + TQTextStream(f,IO_ReadOnly) { } + +private: // Disabled copy constructor and operator= +#if defined(TQ_DISABLE_COPY) + TQTextIStream( const TQTextIStream & ); + TQTextIStream &operator=( const TQTextIStream & ); +#endif +}; + +class TQ_EXPORT TQTextOStream : public TQTextStream { +public: + TQTextOStream( TQString* s ) : + TQTextStream(s,IO_WriteOnly) { } + TQTextOStream( TQByteArray ba ) : + TQTextStream(ba,IO_WriteOnly) { } + TQTextOStream( FILE *f ) : + TQTextStream(f,IO_WriteOnly) { } + +private: // Disabled copy constructor and operator= +#if defined(TQ_DISABLE_COPY) + TQTextOStream( const TQTextOStream & ); + TQTextOStream &operator=( const TQTextOStream & ); +#endif +}; + +/***************************************************************************** + TQTextStream inline functions + *****************************************************************************/ + +inline TQIODevice *TQTextStream::device() const +{ return dev; } + +inline bool TQTextStream::atEnd() const +{ return dev ? dev->atEnd() : FALSE; } + +inline bool TQTextStream::eof() const +{ return atEnd(); } + +inline int TQTextStream::flags() const +{ return fflags; } + +inline int TQTextStream::flags( int f ) +{ int oldf = fflags; fflags = f; return oldf; } + +inline int TQTextStream::setf( int bits ) +{ int oldf = fflags; fflags |= bits; return oldf; } + +inline int TQTextStream::setf( int bits, int mask ) +{ int oldf = fflags; fflags = (fflags & ~mask) | (bits & mask); return oldf; } + +inline int TQTextStream::unsetf( int bits ) +{ int oldf = fflags; fflags &= ~bits; return oldf; } + +inline int TQTextStream::width() const +{ return fwidth; } + +inline int TQTextStream::width( int w ) +{ int oldw = fwidth; fwidth = w; return oldw; } + +inline int TQTextStream::fill() const +{ return fillchar; } + +inline int TQTextStream::fill( int f ) +{ int oldc = fillchar; fillchar = f; return oldc; } + +inline int TQTextStream::precision() const +{ return fprec; } + +inline int TQTextStream::precision( int p ) +{ int oldp = fprec; fprec = p; return oldp; } + +/*! + Returns one character from the stream, or EOF. +*/ +inline TQChar TQTextStream::ts_getc() +{ TQChar r; return ( ts_getbuf( &r,1 ) == 1 ? r : TQChar((ushort)0xffff) ); } + +/***************************************************************************** + TQTextStream manipulators + *****************************************************************************/ + +typedef TQTextStream & (*TQTSFUNC)(TQTextStream &);// manipulator function +typedef int (TQTextStream::*TQTSMFI)(int); // manipulator w/int argument + +class TQ_EXPORT TQTSManip { // text stream manipulator +public: + TQTSManip( TQTSMFI m, int a ) { mf=m; arg=a; } + void exec( TQTextStream &s ) { (s.*mf)(arg); } +private: + TQTSMFI mf; // TQTextStream member function + int arg; // member function argument +}; + +TQ_EXPORT inline TQTextStream &operator>>( TQTextStream &s, TQTSFUNC f ) +{ return (*f)( s ); } + +TQ_EXPORT inline TQTextStream &operator<<( TQTextStream &s, TQTSFUNC f ) +{ return (*f)( s ); } + +TQ_EXPORT inline TQTextStream &operator<<( TQTextStream &s, TQTSManip m ) +{ m.exec(s); return s; } + +TQ_EXPORT TQTextStream &bin( TQTextStream &s ); // set bin notation +TQ_EXPORT TQTextStream &oct( TQTextStream &s ); // set oct notation +TQ_EXPORT TQTextStream &dec( TQTextStream &s ); // set dec notation +TQ_EXPORT TQTextStream &hex( TQTextStream &s ); // set hex notation +TQ_EXPORT TQTextStream &endl( TQTextStream &s ); // insert EOL ('\n') +TQ_EXPORT TQTextStream &flush( TQTextStream &s ); // flush output +TQ_EXPORT TQTextStream &ws( TQTextStream &s ); // eat whitespace on input +TQ_EXPORT TQTextStream &reset( TQTextStream &s ); // set default flags + +TQ_EXPORT inline TQTSManip qSetW( int w ) +{ + TQTSMFI func = &TQTextStream::width; + return TQTSManip(func,w); +} + +TQ_EXPORT inline TQTSManip qSetFill( int f ) +{ + TQTSMFI func = &TQTextStream::fill; + return TQTSManip(func,f); +} + +TQ_EXPORT inline TQTSManip qSetPrecision( int p ) +{ + TQTSMFI func = &TQTextStream::precision; + return TQTSManip(func,p); +} + +#endif // TQT_NO_TEXTSTREAM +#endif // TQTEXTSTREAM_H diff --git a/src/widgets/ntqdockarea.h b/src/widgets/ntqdockarea.h index 441f4b828..f70f61fe5 100644 --- a/src/widgets/ntqdockarea.h +++ b/src/widgets/ntqdockarea.h @@ -48,7 +48,7 @@ #include "ntqlayout.h" #include "tqvaluelist.h" #include "ntqguardedptr.h" -#include "ntqtextstream.h" +#include "tqtextstream.h" #endif // QT_H #ifndef TQT_NO_MAINWINDOW diff --git a/src/widgets/ntqmainwindow.h b/src/widgets/ntqmainwindow.h index 73265436a..548bbae88 100644 --- a/src/widgets/ntqmainwindow.h +++ b/src/widgets/ntqmainwindow.h @@ -45,7 +45,7 @@ #include "tqwidget.h" #include "ntqtoolbar.h" #include "tqptrlist.h" -#include "ntqtextstream.h" +#include "tqtextstream.h" #endif // QT_H #ifndef TQT_NO_MAINWINDOW diff --git a/src/widgets/ntqmultilineedit.h b/src/widgets/ntqmultilineedit.h index bbf22d8bd..1f53dc38f 100644 --- a/src/widgets/ntqmultilineedit.h +++ b/src/widgets/ntqmultilineedit.h @@ -42,7 +42,7 @@ #define TQMULTILINEEDIT_H #ifndef QT_H -#include "ntqtextedit.h" +#include "tqtextedit.h" #endif // QT_H #ifndef TQT_NO_MULTILINEEDIT diff --git a/src/widgets/ntqtextbrowser.h b/src/widgets/ntqtextbrowser.h deleted file mode 100644 index c9ac4ae9e..000000000 --- a/src/widgets/ntqtextbrowser.h +++ /dev/null @@ -1,107 +0,0 @@ -/**************************************************************************** -** -** Definition of the TQTextBrowser class -** -** Created : 990101 -** -** Copyright (C) 1992-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 TQTEXTBROWSER_H -#define TQTEXTBROWSER_H - -#ifndef QT_H -#include "tqptrlist.h" -#include "ntqpixmap.h" -#include "ntqcolor.h" -#include "ntqtextedit.h" -#endif // QT_H - -#ifndef TQT_NO_TEXTBROWSER - -class TQTextBrowserData; - -class TQ_EXPORT TQTextBrowser : public TQTextEdit -{ - TQ_OBJECT - TQ_PROPERTY( TQString source READ source WRITE setSource ) - TQ_OVERRIDE( int undoDepth DESIGNABLE false SCRIPTABLE false ) - TQ_OVERRIDE( bool overwriteMode DESIGNABLE false SCRIPTABLE false ) - TQ_OVERRIDE( bool modified SCRIPTABLE false) - TQ_OVERRIDE( bool readOnly DESIGNABLE false SCRIPTABLE false ) - TQ_OVERRIDE( bool undoRedoEnabled DESIGNABLE false SCRIPTABLE false ) - -public: - TQTextBrowser( TQWidget* parent=0, const char* name=0 ); - ~TQTextBrowser(); - - TQString source() const; - -public slots: - virtual void setSource(const TQString& name); - virtual void backward(); - virtual void forward(); - virtual void home(); - virtual void reload(); - void setText( const TQString &txt ) { setText( txt, TQString::null ); } - virtual void setText( const TQString &txt, const TQString &context ); - -signals: - void backwardAvailable( bool ); - void forwardAvailable( bool ); - void sourceChanged( const TQString& ); - void highlighted( const TQString& ); - void linkClicked( const TQString& ); - void anchorClicked( const TQString&, const TQString& ); - -protected: - void keyPressEvent( TQKeyEvent * e); - -private: - void popupDetail( const TQString& contents, const TQPoint& pos ); - bool linksEnabled() const { return TRUE; } - void emitHighlighted( const TQString &s ); - void emitLinkClicked( const TQString &s ); - TQTextBrowserData *d; - -private: // Disabled copy constructor and operator= -#if defined(TQ_DISABLE_COPY) - TQTextBrowser( const TQTextBrowser & ); - TQTextBrowser& operator=( const TQTextBrowser & ); -#endif -}; - -#endif // TQT_NO_TEXTBROWSER - -#endif // TQTEXTBROWSER_H diff --git a/src/widgets/ntqtextedit.h b/src/widgets/ntqtextedit.h deleted file mode 100644 index 40906dbfc..000000000 --- a/src/widgets/ntqtextedit.h +++ /dev/null @@ -1,613 +0,0 @@ -/**************************************************************************** -** -** Definition of the TQTextEdit class -** -** Created : 990101 -** -** Copyright (C) 1992-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 TQTEXTEDIT_H -#define TQTEXTEDIT_H - -#ifndef QT_H -#include "ntqscrollview.h" -#include "ntqstylesheet.h" -#include "tqptrvector.h" -#include "tqvaluelist.h" -#include "tqptrlist.h" -#endif // QT_H - -#ifndef TQT_NO_TEXTEDIT -// uncomment below to enable optimization mode - also uncomment the -// optimDoAutoScroll() private slot since moc ignores #ifdefs.. -#define QT_TEXTEDIT_OPTIMIZATION - -class TQPainter; -class TQTextDocument; -class TQTextCursor; -class TQKeyEvent; -class TQResizeEvent; -class TQMouseEvent; -class TQTimer; -class TQTextString; -class TQTextCommand; -class TQTextParagraph; -class TQTextFormat; -class TQFont; -class TQColor; -class TQTextEdit; -class TQTextBrowser; -class TQTextString; -struct TQUndoRedoInfoPrivate; -class TQPopupMenu; -class TQTextEditPrivate; -class TQSyntaxHighlighter; - -#ifdef QT_TEXTEDIT_OPTIMIZATION -class TQTextEditOptimPrivate -{ -public: - // Note: no left-tag has any value for leftTag or parent, and - // no right-tag has any formatting flags set. - enum TagType { Color = 0, Format = 1 }; - struct Tag { - TagType type:2; - bool bold:1; - bool italic:1; - bool underline:1; - int line; - int index; - Tag * leftTag; // ptr to left-tag in a left-right tag pair - Tag * parent; // ptr to parent left-tag in a nested tag - Tag * prev; - Tag * next; - TQString tag; - }; - TQTextEditOptimPrivate() - { - len = numLines = maxLineWidth = 0; - selStart.line = selStart.index = -1; - selEnd.line = selEnd.index = -1; - search.line = search.index = 0; - tags = lastTag = 0; - } - void clearTags() - { - Tag * itr = tags; - while ( tags ) { - itr = tags; - tags = tags->next; - delete itr; - } - tags = lastTag = 0; - tagIndex.clear(); - } - ~TQTextEditOptimPrivate() - { - clearTags(); - } - int len; - int numLines; - int maxLineWidth; - struct Selection { - int line; - int index; - }; - Selection selStart, selEnd, search; - Tag * tags, * lastTag; - TQMap lines; - TQMap tagIndex; -}; -#endif - -class TQ_EXPORT TQTextEdit : public TQScrollView -{ - friend class TQTextBrowser; - friend class TQSyntaxHighlighter; - - TQ_OBJECT - TQ_ENUMS( WordWrap WrapPolicy ) - TQ_SETS( AutoFormatting ) - TQ_PROPERTY( TextFormat textFormat READ textFormat WRITE setTextFormat ) - TQ_PROPERTY( TQString text READ text WRITE setText ) - TQ_PROPERTY( TQBrush paper READ paper WRITE setPaper ) - TQ_PROPERTY( bool linkUnderline READ linkUnderline WRITE setLinkUnderline ) - TQ_PROPERTY( TQString documentTitle READ documentTitle ) - TQ_PROPERTY( int length READ length ) - TQ_PROPERTY( WordWrap wordWrap READ wordWrap WRITE setWordWrap ) - TQ_PROPERTY( int wrapColumnOrWidth READ wrapColumnOrWidth WRITE setWrapColumnOrWidth ) - TQ_PROPERTY( WrapPolicy wrapPolicy READ wrapPolicy WRITE setWrapPolicy ) - TQ_PROPERTY( bool hasSelectedText READ hasSelectedText ) - TQ_PROPERTY( TQString selectedText READ selectedText ) - TQ_PROPERTY( int undoDepth READ undoDepth WRITE setUndoDepth ) - TQ_PROPERTY( bool overwriteMode READ isOverwriteMode WRITE setOverwriteMode ) - TQ_PROPERTY( bool modified READ isModified WRITE setModified DESIGNABLE false ) - TQ_PROPERTY( bool readOnly READ isReadOnly WRITE setReadOnly ) - TQ_PROPERTY( bool undoRedoEnabled READ isUndoRedoEnabled WRITE setUndoRedoEnabled ) - TQ_PROPERTY( int tabStopWidth READ tabStopWidth WRITE setTabStopWidth ) - TQ_PROPERTY( bool tabChangesFocus READ tabChangesFocus WRITE setTabChangesFocus ) - TQ_PROPERTY( AutoFormatting autoFormatting READ autoFormatting WRITE setAutoFormatting ) - -public: - enum WordWrap { - NoWrap, - WidgetWidth, - FixedPixelWidth, - FixedColumnWidth - }; - - enum WrapPolicy { - AtWordBoundary, - AtWhiteSpace = AtWordBoundary, // AtWhiteSpace is deprecated - Anywhere, - AtWordOrDocumentBoundary - }; - - enum AutoFormatting { - AutoNone = 0, - AutoBulletList = 0x00000001, - AutoAll = 0xffffffff - }; - - enum KeyboardAction { - ActionBackspace, - ActionDelete, - ActionReturn, - ActionKill, - ActionWordBackspace, - ActionWordDelete - }; - - enum CursorAction { - MoveBackward, - MoveForward, - MoveWordBackward, - MoveWordForward, - MoveUp, - MoveDown, - MoveLineStart, - MoveLineEnd, - MoveHome, - MoveEnd, - MovePgUp, - MovePgDown - }; - - enum VerticalAlignment { - AlignNormal, - AlignSuperScript, - AlignSubScript - }; - - enum TextInsertionFlags { - RedoIndentation = 0x0001, - CheckNewLines = 0x0002, - RemoveSelected = 0x0004, - AsIMCompositionText = 0x0008, // internal use - WithIMSelection = 0x0010 // internal use - }; - - TQTextEdit( const TQString& text, const TQString& context = TQString::null, - TQWidget* parent=0, const char* name=0); - TQTextEdit( TQWidget* parent=0, const char* name=0 ); - virtual ~TQTextEdit(); - void setPalette( const TQPalette & ); - - TQString text() const; - TQString text( int para ) const; - TextFormat textFormat() const; - TQString context() const; - TQString documentTitle() const; - - void getSelection( int *paraFrom, int *indexFrom, - int *paraTo, int *indexTo, int selNum = 0 ) const; - virtual bool find( const TQString &expr, bool cs, bool wo, bool forward = TRUE, - int *para = 0, int *index = 0 ); - - int paragraphs() const; - int lines() const; - int linesOfParagraph( int para ) const; - int lineOfChar( int para, int chr ); - int length() const; - TQRect paragraphRect( int para ) const; - int paragraphAt( const TQPoint &pos ) const; - int charAt( const TQPoint &pos, int *para ) const; - int paragraphLength( int para ) const; - - TQStyleSheet* styleSheet() const; -#ifndef TQT_NO_MIME - TQMimeSourceFactory* mimeSourceFactory() const; -#endif - TQBrush paper() const; - bool linkUnderline() const; - - int heightForWidth( int w ) const; - - bool hasSelectedText() const; - TQString selectedText() const; - bool isUndoAvailable() const; - bool isRedoAvailable() const; - - WordWrap wordWrap() const; - int wrapColumnOrWidth() const; - WrapPolicy wrapPolicy() const; - - int tabStopWidth() const; - - TQString anchorAt( const TQPoint& pos ); - TQString anchorAt( const TQPoint& pos, AnchorAttribute a ); - - TQSize sizeHint() const; - - bool isReadOnly() const { return readOnly; } - - void getCursorPosition( int *parag, int *index ) const; - - bool isModified() const; - bool italic() const; - bool bold() const; - bool underline() const; - TQString family() const; - int pointSize() const; - TQColor color() const; - TQFont font() const; - TQFont currentFont() const; - int alignment() const; - int undoDepth() const; - - // do not use, will go away - virtual bool getFormat( int para, int index, TQFont *font, TQColor *color, VerticalAlignment *verticalAlignment ); - // do not use, will go away - virtual bool getParagraphFormat( int para, TQFont *font, TQColor *color, - VerticalAlignment *verticalAlignment, int *alignment, - TQStyleSheetItem::DisplayMode *displayMode, - TQStyleSheetItem::ListStyle *listStyle, - int *listDepth ); - - - bool isOverwriteMode() const { return overWrite; } - TQColor paragraphBackgroundColor( int para ) const; - - bool isUndoRedoEnabled() const; - bool eventFilter( TQObject *o, TQEvent *e ); - bool tabChangesFocus() const; - - void setAutoFormatting( uint features ); - uint autoFormatting() const; - TQSyntaxHighlighter *syntaxHighlighter() const; - -public slots: - void setEnabled( bool ); -#ifndef TQT_NO_MIME - virtual void setMimeSourceFactory( TQMimeSourceFactory* factory ); -#endif - virtual void setStyleSheet( TQStyleSheet* styleSheet ); - virtual void scrollToAnchor( const TQString& name ); - virtual void setPaper( const TQBrush& pap ); - virtual void setLinkUnderline( bool ); - - virtual void setWordWrap( WordWrap mode ); - virtual void setWrapColumnOrWidth( int ); - virtual void setWrapPolicy( WrapPolicy policy ); - - virtual void copy(); - virtual void append( const TQString& text ); - - void setText( const TQString &txt ) { setText( txt, TQString::null ); } - virtual void setText( const TQString &txt, const TQString &context ); - virtual void setTextFormat( TextFormat f ); - - virtual void selectAll( bool select = TRUE ); - virtual void setTabStopWidth( int ts ); - virtual void zoomIn( int range ); - virtual void zoomIn() { zoomIn( 1 ); } - virtual void zoomOut( int range ); - virtual void zoomOut() { zoomOut( 1 ); } - virtual void zoomTo( int size ); - - virtual void sync(); - virtual void setReadOnly( bool b ); - - virtual void undo(); - virtual void redo(); - virtual void cut(); - virtual void paste(); -#ifndef TQT_NO_CLIPBOARD - virtual void pasteSubType( const TQCString &subtype ); -#endif - virtual void clear(); - virtual void del(); - virtual void indent(); - virtual void setItalic( bool b ); - virtual void setBold( bool b ); - virtual void setUnderline( bool b ); - virtual void setFamily( const TQString &f ); - virtual void setPointSize( int s ); - virtual void setColor( const TQColor &c ); - virtual void setFont( const TQFont &f ); - virtual void setVerticalAlignment( VerticalAlignment a ); - virtual void setAlignment( int a ); - - // do not use, will go away - virtual void setParagType( TQStyleSheetItem::DisplayMode dm, TQStyleSheetItem::ListStyle listStyle ); - - virtual void setCursorPosition( int parag, int index ); - virtual void setSelection( int parag_from, int index_from, int parag_to, int index_to, int selNum = 0 ); - virtual void setSelectionAttributes( int selNum, const TQColor &back, bool invertText ); - virtual void setModified( bool m ); - virtual void resetFormat(); - virtual void setUndoDepth( int d ); - virtual void setFormat( TQTextFormat *f, int flags ); - virtual void ensureCursorVisible(); - virtual void placeCursor( const TQPoint &pos, TQTextCursor *c = 0 ); - virtual void moveCursor( CursorAction action, bool select ); - virtual void doKeyboardAction( KeyboardAction action ); - virtual void removeSelectedText( int selNum = 0 ); - virtual void removeSelection( int selNum = 0 ); - virtual void setCurrentFont( const TQFont &f ); - virtual void setOverwriteMode( bool b ) { overWrite = b; } - - virtual void scrollToBottom(); - - void insert( const TQString &text, uint insertionFlags = CheckNewLines | RemoveSelected ); // ## virtual in 4.0 - - // obsolete - virtual void insert( const TQString &text, bool, bool = TRUE, bool = TRUE ); - - virtual void insertAt( const TQString &text, int para, int index ); - virtual void removeParagraph( int para ); - virtual void insertParagraph( const TQString &text, int para ); - - virtual void setParagraphBackgroundColor( int para, const TQColor &bg ); - virtual void clearParagraphBackground( int para ); - - virtual void setUndoRedoEnabled( bool b ); - void setTabChangesFocus( bool b ); // ### make virtual in 4.0 - -#ifdef QT_TEXTEDIT_OPTIMIZATION - void polish(); - void setMaxLogLines( int numLines ); - int maxLogLines(); -#endif - -signals: - void textChanged(); - void selectionChanged(); - void copyAvailable( bool ); - void undoAvailable( bool yes ); - void redoAvailable( bool yes ); - void currentFontChanged( const TQFont &f ); - void currentColorChanged( const TQColor &c ); - void currentAlignmentChanged( int a ); - void currentVerticalAlignmentChanged( VerticalAlignment a ); - void cursorPositionChanged( TQTextCursor *c ); - void cursorPositionChanged( int para, int pos ); - void returnPressed(); - void modificationChanged( bool m ); - void clicked( int parag, int index ); - void doubleClicked( int parag, int index ); - -protected: - void repaintChanged(); - void updateStyles(); - void drawContents( TQPainter *p, int cx, int cy, int cw, int ch ); - bool event( TQEvent *e ); - void keyPressEvent( TQKeyEvent *e ); - void resizeEvent( TQResizeEvent *e ); - void viewportResizeEvent( TQResizeEvent* ); - void contentsMousePressEvent( TQMouseEvent *e ); - void contentsMouseMoveEvent( TQMouseEvent *e ); - void contentsMouseReleaseEvent( TQMouseEvent *e ); - void contentsMouseDoubleClickEvent( TQMouseEvent *e ); -#ifndef TQT_NO_WHEELEVENT - void contentsWheelEvent( TQWheelEvent *e ); -#endif - void imStartEvent( TQIMEvent * ); - void imComposeEvent( TQIMEvent * ); - void imEndEvent( TQIMEvent * ); -#ifndef TQT_NO_DRAGANDDROP - void contentsDragEnterEvent( TQDragEnterEvent *e ); - void contentsDragMoveEvent( TQDragMoveEvent *e ); - void contentsDragLeaveEvent( TQDragLeaveEvent *e ); - void contentsDropEvent( TQDropEvent *e ); -#endif - void contentsContextMenuEvent( TQContextMenuEvent *e ); - bool sendMouseEventToInputContext( TQMouseEvent *e ); - bool focusNextPrevChild( bool next ); - TQTextDocument *document() const; - TQTextCursor *textCursor() const; - void setDocument( TQTextDocument *doc ); - virtual TQPopupMenu *createPopupMenu( const TQPoint& pos ); - virtual TQPopupMenu *createPopupMenu(); - void drawCursor( bool visible ); - - void windowActivationChange( bool ); - -protected slots: - virtual void doChangeInterval(); - void sliderReleased(); // ### make virtual in 4.0 - -private slots: - void formatMore(); - void doResize(); - void autoScrollTimerDone(); - void blinkCursor(); - void setModified(); - void startDrag(); - void documentWidthChanged( int w ); - void clipboardChanged(); - -private: - struct TQ_EXPORT UndoRedoInfo { - enum Type { Invalid, Insert, Delete, Backspace, Return, RemoveSelected, Format, Style, IME }; - - UndoRedoInfo( TQTextDocument *dc ); - ~UndoRedoInfo(); - void clear(); - bool valid() const; - - TQUndoRedoInfoPrivate *d; - int id; - int index; - int eid; - int eindex; - TQTextFormat *format; - int flags; - Type type; - TQTextDocument *doc; - TQByteArray styleInformation; - }; - -private: - void updateCursor( const TQPoint & pos ); - void handleMouseMove( const TQPoint& pos ); - void drawContents( TQPainter * ); - virtual bool linksEnabled() const { return FALSE; } - void init(); - void checkUndoRedoInfo( UndoRedoInfo::Type t ); - void updateCurrentFormat(); - bool handleReadOnlyKeyEvent( TQKeyEvent *e ); - void makeParagVisible( TQTextParagraph *p ); - void normalCopy(); - void copyToClipboard(); -#ifndef TQT_NO_MIME - TQCString pickSpecial(TQMimeSource* ms, bool always_ask, const TQPoint&); - TQTextDrag *dragObject( TQWidget *parent = 0 ) const; -#endif -#ifndef TQT_NO_MIMECLIPBOARD - void pasteSpecial(const TQPoint&); -#endif - void setFontInternal( const TQFont &f ); - - virtual void emitHighlighted( const TQString & ) {} - virtual void emitLinkClicked( const TQString & ) {} - - void readFormats( TQTextCursor &c1, TQTextCursor &c2, TQTextString &text, bool fillStyles = FALSE ); - void clearUndoRedo(); - void paintDocument( bool drawAll, TQPainter *p, int cx = -1, int cy = -1, int cw = -1, int ch = -1 ); - void moveCursor( CursorAction action ); - void ensureFormatted( TQTextParagraph *p ); - void placeCursor( const TQPoint &pos, TQTextCursor *c, bool link ); - void updateMicroFocusHint(); - -#ifdef QT_TEXTEDIT_OPTIMIZATION - bool checkOptimMode(); - TQString optimText() const; - void optimSetText( const TQString &str ); - void optimAppend( const TQString &str ); - void optimInsert( const TQString &str, int line, int index ); - void optimDrawContents( TQPainter * p, int cx, int cy, int cw, int ch ); - void optimMousePressEvent( TQMouseEvent * e ); - void optimMouseReleaseEvent( TQMouseEvent * e ); - void optimMouseMoveEvent( TQMouseEvent * e ); - int optimCharIndex( const TQString &str, int mx ) const; - void optimSelectAll(); - void optimRemoveSelection(); - void optimSetSelection( int startLine, int startIdx, int endLine, - int endIdx ); - bool optimHasSelection() const; - TQString optimSelectedText() const; - bool optimFind( const TQString & str, bool, bool, bool, int *, int * ); - void optimParseTags( TQString * str, int lineNo = -1, int indexOffset = 0 ); - TQTextEditOptimPrivate::Tag * optimPreviousLeftTag( int line ); - void optimSetTextFormat( TQTextDocument *, TQTextCursor *, TQTextFormat * f, - int, int, TQTextEditOptimPrivate::Tag * t ); - TQTextEditOptimPrivate::Tag * optimAppendTag( int index, const TQString & tag ); - TQTextEditOptimPrivate::Tag * optimInsertTag( int line, int index, const TQString & tag ); - void optimCheckLimit( const TQString& str ); - bool optimHasBoldMetrics( int line ); - -private slots: - void optimDoAutoScroll(); -#endif // QT_TEXTEDIT_OPTIMIZATION - -private: -#ifndef TQT_NO_CLIPBOARD - void pasteSubType( const TQCString &subtype, TQMimeSource *m ); -#endif - -private: - TQTextDocument *doc; - TQTextCursor *cursor; - TQTimer *formatTimer, *scrollTimer, *changeIntervalTimer, *blinkTimer, *dragStartTimer; - TQTextParagraph *lastFormatted; - int interval; - UndoRedoInfo undoRedoInfo; - TQTextFormat *currentFormat; - int currentAlignment; - TQPoint oldMousePos, mousePos; - TQPoint dragStartPos; - TQString onLink; - WordWrap wrapMode; - WrapPolicy wPolicy; - int wrapWidth; - TQString pressedLink; - TQTextEditPrivate *d; - bool inDoubleClick : 1; - bool mousePressed : 1; - bool cursorVisible : 1; - bool blinkCursorVisible : 1; - bool noop: 1; //< Removed; keep as padding for binary compat or reuse if needed - bool modified : 1; - bool mightStartDrag : 1; - bool inDnD : 1; - bool readOnly : 1; - bool undoEnabled : 1; - bool overWrite : 1; - -private: // Disabled copy constructor and operator= -#if defined(TQ_DISABLE_COPY) - TQTextEdit( const TQTextEdit & ); - TQTextEdit &operator=( const TQTextEdit & ); -#endif -}; - -inline TQTextDocument *TQTextEdit::document() const -{ - return doc; -} - -inline TQTextCursor *TQTextEdit::textCursor() const -{ - return cursor; -} - -inline void TQTextEdit::setCurrentFont( const TQFont &f ) -{ - TQTextEdit::setFontInternal( f ); -} - -#endif //TQT_NO_TEXTEDIT -#endif //TQTEXTVIEW_H diff --git a/src/widgets/ntqtextview.h b/src/widgets/ntqtextview.h deleted file mode 100644 index 2d0d73cfe..000000000 --- a/src/widgets/ntqtextview.h +++ /dev/null @@ -1,74 +0,0 @@ -/**************************************************************************** -** -** Definition of the TQTextView class -** -** Created : 990101 -** -** Copyright (C) 1992-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 TQTEXTVIEW_H -#define TQTEXTVIEW_H - -#ifndef QT_H -#include "ntqtextedit.h" -#endif // QT_H - -#ifndef TQT_NO_TEXTVIEW - -class TQ_EXPORT TQTextView : public TQTextEdit -{ - TQ_OBJECT - TQ_OVERRIDE( int undoDepth DESIGNABLE false SCRIPTABLE false ) - TQ_OVERRIDE( bool overwriteMode DESIGNABLE false SCRIPTABLE false ) - TQ_OVERRIDE( bool modified SCRIPTABLE false) - TQ_OVERRIDE( bool readOnly DESIGNABLE false SCRIPTABLE false ) - TQ_OVERRIDE( bool undoRedoEnabled DESIGNABLE false SCRIPTABLE false ) - -public: - TQTextView( const TQString& text, const TQString& context = TQString::null, - TQWidget* parent=0, const char* name=0); - TQTextView( TQWidget* parent=0, const char* name=0 ); - - virtual ~TQTextView(); - -private: -#if defined(TQ_DISABLE_COPY) // Disabled copy constructor and operator= - TQTextView( const TQTextView & ); - TQTextView &operator=( const TQTextView & ); -#endif -}; - -#endif //TQT_NO_TEXTVIEW -#endif //TQTEXTVIEW_H diff --git a/src/widgets/qcheckbox.cpp b/src/widgets/qcheckbox.cpp index 970ed5785..0ef6529b0 100644 --- a/src/widgets/qcheckbox.cpp +++ b/src/widgets/qcheckbox.cpp @@ -45,7 +45,7 @@ #include "ntqpixmap.h" #include "ntqpixmapcache.h" #include "ntqbitmap.h" -#include "ntqtextstream.h" +#include "tqtextstream.h" #include "ntqapplication.h" #include "ntqstyle.h" diff --git a/src/widgets/qiconview.cpp b/src/widgets/qiconview.cpp index 36e1529c3..71baf927d 100644 --- a/src/widgets/qiconview.cpp +++ b/src/widgets/qiconview.cpp @@ -59,7 +59,7 @@ #include "ntqtimer.h" #include "ntqcursor.h" #include "ntqapplication.h" -#include "ntqtextedit.h" +#include "tqtextedit.h" #include "ntqmemarray.h" #include "tqptrlist.h" #include "ntqvbox.h" diff --git a/src/widgets/qlineedit.cpp b/src/widgets/qlineedit.cpp index 6ed133729..3894e35e6 100644 --- a/src/widgets/qlineedit.cpp +++ b/src/widgets/qlineedit.cpp @@ -61,7 +61,7 @@ #include "ntqstyle.h" #include "ntqwhatsthis.h" #include "../kernel/qinternal_p.h" -#include "private/qtextlayout_p.h" +#include "private/tqtextlayout_p.h" #include "tqvaluevector.h" #if defined(Q_OS_LINUX) #include diff --git a/src/widgets/qradiobutton.cpp b/src/widgets/qradiobutton.cpp index f6e48df6e..b5de6b8d9 100644 --- a/src/widgets/qradiobutton.cpp +++ b/src/widgets/qradiobutton.cpp @@ -46,7 +46,7 @@ #include "ntqpixmap.h" #include "ntqpixmapcache.h" #include "ntqbitmap.h" -#include "ntqtextstream.h" +#include "tqtextstream.h" #include "ntqapplication.h" #include "ntqstyle.h" diff --git a/src/widgets/qsyntaxhighlighter.cpp b/src/widgets/qsyntaxhighlighter.cpp index 814cc5a96..8cd8ba2a8 100644 --- a/src/widgets/qsyntaxhighlighter.cpp +++ b/src/widgets/qsyntaxhighlighter.cpp @@ -43,7 +43,7 @@ #ifndef TQT_NO_SYNTAXHIGHLIGHTER #include "../kernel/qrichtext_p.h" -#include "ntqtextedit.h" +#include "tqtextedit.h" #include "ntqtimer.h" /*! diff --git a/src/widgets/qt_widgets.pri b/src/widgets/qt_widgets.pri index 8be28d1cf..263c0e473 100644 --- a/src/widgets/qt_widgets.pri +++ b/src/widgets/qt_widgets.pri @@ -59,9 +59,9 @@ widgets { $$WIDGETS_H/tqwidgetstack.h \ $$WIDGETS_H/ntqaction.h \ $$WIDGETS_H/ntqdatetimeedit.h \ - $$WIDGETS_H/ntqtextview.h \ - $$WIDGETS_H/ntqtextbrowser.h \ - $$WIDGETS_H/ntqtextedit.h \ + $$WIDGETS_H/tqtextview.h \ + $$WIDGETS_H/tqtextbrowser.h \ + $$WIDGETS_H/tqtextedit.h \ $$WIDGETS_P/tqwidgetinterface_p.h \ $$WIDGETS_H/tqwidgetplugin.h @@ -122,9 +122,9 @@ widgets { $$WIDGETS_CPP/qaction.cpp \ $$WIDGETS_CPP/qdatetimeedit.cpp \ $$WIDGETS_CPP/qeffects.cpp \ - $$WIDGETS_CPP/qtextview.cpp \ - $$WIDGETS_CPP/qtextbrowser.cpp \ - $$WIDGETS_CPP/qtextedit.cpp \ + $$WIDGETS_CPP/tqtextview.cpp \ + $$WIDGETS_CPP/tqtextbrowser.cpp \ + $$WIDGETS_CPP/tqtextedit.cpp \ $$WIDGETS_CPP/tqwidgetplugin.cpp !embedded:mac:SOURCES += $$WIDGETS_CPP/qmenubar_mac.cpp } diff --git a/src/widgets/qtextbrowser.cpp b/src/widgets/qtextbrowser.cpp deleted file mode 100644 index 23b2452f6..000000000 --- a/src/widgets/qtextbrowser.cpp +++ /dev/null @@ -1,555 +0,0 @@ -/**************************************************************************** -** -** Implementation of the TQTextBrowser class -** -** Created : 990101 -** -** Copyright (C) 1992-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 "ntqtextbrowser.h" -#ifndef TQT_NO_TEXTBROWSER -#include "../kernel/qrichtext_p.h" - -#include "ntqapplication.h" -#include "ntqlayout.h" -#include "ntqpainter.h" - -#include "tqvaluestack.h" -#include "stdio.h" -#include "ntqfile.h" -#include "ntqtextstream.h" -#include "ntqlayout.h" -#include "ntqbitmap.h" -#include "ntqtimer.h" -#include "tqimage.h" -#include "ntqsimplerichtext.h" -#include "ntqdragobject.h" -#include "ntqurl.h" -#include "ntqcursor.h" - -/*! - \class TQTextBrowser ntqtextbrowser.h - \brief The TQTextBrowser class provides a rich text browser with hypertext navigation. - - \ingroup advanced - \ingroup helpsystem - \ingroup text - \mainclass - - This class extends TQTextEdit (in read-only mode), adding some - navigation functionality so that users can follow links in - hypertext documents. The contents of TQTextEdit is set with - setText(), but TQTextBrowser has an additional function, - setSource(), which makes it possible to set the text to a named - document. The name is looked up in the text view's mime source - factory. If a document name ends with an anchor (for example, "\c - #anchor"), the text browser automatically scrolls to that position - (using scrollToAnchor()). When the user clicks on a hyperlink, the - browser will call setSource() itself, with the link's \c href - value as argument. You can track the current source by connetion - to the sourceChanged() signal. - - TQTextBrowser provides backward() and forward() slots which you can - use to implement Back and Forward buttons. The home() slot sets - the text to the very first document displayed. The linkClicked() - signal is emitted when the user clicks a link. - - By using TQTextEdit::setMimeSourceFactory() you can provide your - own subclass of TQMimeSourceFactory. This makes it possible to - access data from anywhere, for example from a network or from a - database. See TQMimeSourceFactory::data() for details. - - If you intend using the mime factory to read the data directly - from the file system, you may have to specify the encoding for the - file extension you are using. For example: - \code - mimeSourceFactory()->setExtensionType("qml", "text/utf8"); - \endcode - This is to ensure that the factory is able to resolve the document - names. - - TQTextBrowser interprets the tags it processes in accordance with - the default style sheet. Change the style sheet with - \l{setStyleSheet()}; see TQStyleSheet for details. - - If you want to provide your users with editable rich text use - TQTextEdit. If you want a text browser without hypertext navigation - use TQTextEdit, and use TQTextEdit::setReadOnly() to disable - editing. If you just need to display a small piece of rich text - use TQSimpleRichText or TQLabel. - - -*/ - -class TQTextBrowserData -{ -public: - TQTextBrowserData():textOrSourceChanged(FALSE) {} - - TQValueStack stack; - TQValueStack forwardStack; - TQString home; - TQString curmain; - TQString curmark; - - /*flag necessary to give the linkClicked() signal some meaningful - semantics when somebody connected to it calls setText() or - setSource() */ - bool textOrSourceChanged; -}; - - -/*! - Constructs an empty TQTextBrowser called \a name, with parent \a - parent. -*/ -TQTextBrowser::TQTextBrowser(TQWidget *parent, const char *name) - : TQTextEdit( parent, name ) -{ - setReadOnly( TRUE ); - d = new TQTextBrowserData; - - viewport()->setMouseTracking( TRUE ); -} - -/*! - \reimp -*/ -TQTextBrowser::~TQTextBrowser() -{ - delete d; -} - - -/*! - \property TQTextBrowser::source - \brief the name of the displayed document. - - This is a TQString::null if no document is displayed or if the - source is unknown. - - Setting this property uses the mimeSourceFactory() to lookup the - named document. It also checks for optional anchors and scrolls - the document accordingly. - - If the first tag in the document is \c{}, the - document is displayed as a popup rather than as new document in - the browser window itself. Otherwise, the document is displayed - normally in the text browser with the text set to the contents of - the named document with setText(). - - If you are using the filesystem access capabilities of the mime - source factory, you must ensure that the factory knows about the - encoding of specified files; otherwise no data will be available. - The default factory handles a couple of common file extensions - such as \c *.html and \c *.txt with reasonable defaults. See - TQMimeSourceFactory::data() for details. -*/ - -TQString TQTextBrowser::source() const -{ - if ( d->stack.isEmpty() ) - return TQString::null; - else - return d->stack.top(); -} - -/*! - \property TQTextBrowser::undoDepth - \brief This text browser's undo depth. -*/ - -/*! - \property TQTextBrowser::overwriteMode - \brief This text browser's overwrite mode. -*/ - -/*! - \property TQTextBrowser::modified - \brief Whether the contents have been modified. -*/ - -/*! - \property TQTextBrowser::readOnly - \brief Whether the contents are read only. -*/ - -/*! - \property TQTextBrowser::undoRedoEnabled - \brief Whether undo and redo are enabled. -*/ - - - -/*! - Reloads the current set source. -*/ - -void TQTextBrowser::reload() -{ - TQString s = d->curmain; - d->curmain = ""; - setSource( s ); -} - - -void TQTextBrowser::setSource(const TQString& name) -{ -#ifndef TQT_NO_CURSOR - if ( isVisible() ) - tqApp->setOverrideCursor( waitCursor ); -#endif - d->textOrSourceChanged = TRUE; - TQString source = name; - TQString mark; - int hash = name.find('#'); - if ( hash != -1) { - source = name.left( hash ); - mark = name.mid( hash+1 ); - } - - if ( source.left(5) == "file:" ) - source = source.mid(6); - - TQString url = mimeSourceFactory()->makeAbsolute( source, context() ); - TQString txt; - bool dosettext = FALSE; - - if ( !source.isEmpty() && url != d->curmain ) { - const TQMimeSource* m = - mimeSourceFactory()->data( source, context() ); - if ( !m ){ - tqWarning("TQTextBrowser: no mimesource for %s", source.latin1() ); - } - else { - if ( !TQTextDrag::decode( m, txt ) ) { - tqWarning("TQTextBrowser: cannot decode %s", source.latin1() ); - } - } - if ( isVisible() ) { - TQString firstTag = txt.left( txt.find( '>' ) + 1 ); - if ( firstTag.left( 3 ) == "restoreOverrideCursor(); -#endif - return; - } - } - - d->curmain = url; - dosettext = TRUE; - } - - d->curmark = mark; - - if ( !mark.isEmpty() ) { - url += "#"; - url += mark; - } - if ( !d->home ) - d->home = url; - - if ( d->stack.isEmpty() || d->stack.top() != url) - d->stack.push( url ); - - int stackCount = (int)d->stack.count(); - if ( d->stack.top() == url ) - stackCount--; - emit backwardAvailable( stackCount > 0 ); - stackCount = (int)d->forwardStack.count(); - if ( d->forwardStack.isEmpty() || d->forwardStack.top() == url ) - stackCount--; - emit forwardAvailable( stackCount > 0 ); - - if ( dosettext ) - TQTextEdit::setText( txt, url ); - - if ( !mark.isEmpty() ) - scrollToAnchor( mark ); - else - setContentsPos( 0, 0 ); - -#ifndef TQT_NO_CURSOR - if ( isVisible() ) - tqApp->restoreOverrideCursor(); -#endif - - emit sourceChanged( url ); -} - -/*! - \fn void TQTextBrowser::backwardAvailable(bool available) - - This signal is emitted when the availability of backward() - changes. \a available is FALSE when the user is at home(); - otherwise it is TRUE. -*/ - -/*! - \fn void TQTextBrowser::forwardAvailable(bool available) - - This signal is emitted when the availability of forward() changes. - \a available is TRUE after the user navigates backward() and FALSE - when the user navigates or goes forward(). -*/ - -/*! - \fn void TQTextBrowser::sourceChanged( const TQString& src) - - This signal is emitted when the mime source has changed, \a src - being the new source. - - Source changes happen both programmatically when calling - setSource(), forward(), backword() or home() or when the user - clicks on links or presses the equivalent key sequences. -*/ - -/*! \fn void TQTextBrowser::highlighted (const TQString &link) - - This signal is emitted when the user has selected but not - activated a link in the document. \a link is the value of the \c - href i.e. the name of the target document. -*/ - -/*! - \fn void TQTextBrowser::linkClicked( const TQString& link) - - This signal is emitted when the user clicks a link. The \a link is - the value of the \c href i.e. the name of the target document. - - The \a link will be the absolute location of the document, based - on the value of the anchor's href tag and the current context of - the document. - - \sa anchorClicked(), context() -*/ - -/*! - \fn void TQTextBrowser::anchorClicked( const TQString& name, const TQString &link) - - This signal is emitted when the user clicks an anchor. The \a link is - the value of the \c href i.e. the name of the target document. The \a name - is the name of the anchor. - - \sa linkClicked() -*/ - -/*! - Changes the document displayed to the previous document in the - list of documents built by navigating links. Does nothing if there - is no previous document. - - \sa forward(), backwardAvailable() -*/ -void TQTextBrowser::backward() -{ - if ( d->stack.count() <= 1) - return; - d->forwardStack.push( d->stack.pop() ); - setSource( d->stack.pop() ); - emit forwardAvailable( TRUE ); -} - -/*! - Changes the document displayed to the next document in the list of - documents built by navigating links. Does nothing if there is no - next document. - - \sa backward(), forwardAvailable() -*/ -void TQTextBrowser::forward() -{ - if ( d->forwardStack.isEmpty() ) - return; - setSource( d->forwardStack.pop() ); - emit forwardAvailable( !d->forwardStack.isEmpty() ); -} - -/*! - Changes the document displayed to be the first document the - browser displayed. -*/ -void TQTextBrowser::home() -{ - if (!d->home.isNull() ) - setSource( d->home ); -} - -/*! - The event \a e is used to provide the following keyboard shortcuts: - \table - \header \i Keypress \i Action - \row \i Alt+Left Arrow \i \l backward() - \row \i Alt+Right Arrow \i \l forward() - \row \i Alt+Up Arrow \i \l home() - \endtable -*/ -void TQTextBrowser::keyPressEvent( TQKeyEvent * e ) -{ - if ( e->state() & AltButton ) { - switch (e->key()) { - case Key_Right: - forward(); - return; - case Key_Left: - backward(); - return; - case Key_Up: - home(); - return; - } - } - TQTextEdit::keyPressEvent(e); -} - -class TQTextDetailPopup : public TQWidget -{ -public: - TQTextDetailPopup() - : TQWidget ( 0, "automatic TQText detail widget", WType_Popup | WDestructiveClose ) - { - } - -protected: - - void mousePressEvent( TQMouseEvent*) - { - close(); - } -}; - - -void TQTextBrowser::popupDetail( const TQString& contents, const TQPoint& pos ) -{ - - const int shadowWidth = 6; // also used as '5' and '6' and even '8' below - const int vMargin = 8; - const int hMargin = 12; - - TQWidget* popup = new TQTextDetailPopup; - popup->setBackgroundMode( TQWidget::NoBackground ); - - TQSimpleRichText* doc = new TQSimpleRichText( contents, popup->font() ); - doc->adjustSize(); - TQRect r( 0, 0, doc->width(), doc->height() ); - - int w = r.width() + 2*hMargin; - int h = r.height() + 2*vMargin; - - popup->resize( w + shadowWidth, h + shadowWidth ); - - // okay, now to find a suitable location - //###### we need a global fancy popup positioning somewhere - popup->move(pos - popup->rect().center()); - if (popup->geometry().right() > TQApplication::desktop()->width()) - popup->move( TQApplication::desktop()->width() - popup->width(), - popup->y() ); - if (popup->geometry().bottom() > TQApplication::desktop()->height()) - popup->move( popup->x(), - TQApplication::desktop()->height() - popup->height() ); - if ( popup->x() < 0 ) - popup->move( 0, popup->y() ); - if ( popup->y() < 0 ) - popup->move( popup->x(), 0 ); - - - popup->show(); - - // now for super-clever shadow stuff. super-clever mostly in - // how many window system problems it skirts around. - - TQPainter p( popup ); - p.setPen( TQApplication::palette().active().foreground() ); - p.drawRect( 0, 0, w, h ); - p.setPen( TQApplication::palette().active().mid() ); - p.setBrush( TQColor( 255, 255, 240 ) ); - p.drawRect( 1, 1, w-2, h-2 ); - p.setPen( black ); - - doc->draw( &p, hMargin, vMargin, r, popup->colorGroup(), 0 ); - delete doc; - - p.drawPoint( w + 5, 6 ); - p.drawLine( w + 3, 6, - w + 5, 8 ); - p.drawLine( w + 1, 6, - w + 5, 10 ); - int i; - for( i=7; i < h; i += 2 ) - p.drawLine( w, i, - w + 5, i + 5 ); - for( i = w - i + h; i > 6; i -= 2 ) - p.drawLine( i, h, - i + 5, h + 5 ); - for( ; i > 0 ; i -= 2 ) - p.drawLine( 6, h + 6 - i, - i + 5, h + 5 ); -} - -/*! - \fn void TQTextBrowser::setText( const TQString &txt ) - - \overload - - Sets the text to \a txt. -*/ - -/*! - \reimp -*/ - -void TQTextBrowser::setText( const TQString &txt, const TQString &context ) -{ - d->textOrSourceChanged = TRUE; - d->curmark = ""; - d->curmain = ""; - TQTextEdit::setText( txt, context ); -} - -void TQTextBrowser::emitHighlighted( const TQString &s ) -{ - emit highlighted( s ); -} - -void TQTextBrowser::emitLinkClicked( const TQString &s ) -{ - d->textOrSourceChanged = FALSE; - emit linkClicked( s ); - if ( !d->textOrSourceChanged ) - setSource( s ); -} - -#endif // TQT_NO_TEXTBROWSER diff --git a/src/widgets/qtextedit.cpp b/src/widgets/qtextedit.cpp deleted file mode 100644 index 0fb328bf9..000000000 --- a/src/widgets/qtextedit.cpp +++ /dev/null @@ -1,7474 +0,0 @@ -/**************************************************************************** -** -** Implementation of the TQTextEdit class -** -** Created : 990101 -** -** Copyright (C) 1992-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 "ntqtextedit.h" - -#ifndef TQT_NO_TEXTEDIT - -// Keep this position to avoid patch rejection -#ifndef TQT_NO_IM -#include "ntqinputcontext.h" -#endif - -#include "../kernel/qrichtext_p.h" -#include "ntqpainter.h" -#include "ntqpen.h" -#include "ntqbrush.h" -#include "ntqpixmap.h" -#include "ntqfont.h" -#include "ntqcolor.h" -#include "ntqstyle.h" -#include "ntqsize.h" -#include "ntqevent.h" -#include "ntqtimer.h" -#include "ntqapplication.h" -#include "ntqlistbox.h" -#include "ntqvbox.h" -#include "ntqapplication.h" -#include "ntqclipboard.h" -#include "ntqcolordialog.h" -#include "ntqfontdialog.h" -#include "ntqstylesheet.h" -#include "ntqdragobject.h" -#include "ntqurl.h" -#include "ntqcursor.h" -#include "ntqregexp.h" -#include "ntqpopupmenu.h" -#include "tqptrstack.h" -#include "ntqmetaobject.h" -#include "ntqtextbrowser.h" -#include -#include "private/qsyntaxhighlighter_p.h" -#include - -#ifndef TQT_NO_ACCEL -#include -#define ACCEL_KEY(k) "\t" + TQString(TQKeySequence( TQt::CTRL | TQt::Key_ ## k )) -#else -#define ACCEL_KEY(k) "\t" + TQString("Ctrl+" #k) -#endif - -#ifdef QT_TEXTEDIT_OPTIMIZATION -#define LOGOFFSET(i) d->logOffset + i -#endif - -struct TQUndoRedoInfoPrivate -{ - TQTextString text; -}; - -class TQTextEditPrivate -{ -public: - TQTextEditPrivate() - :preeditStart(-1),preeditLength(-1),ensureCursorVisibleInShowEvent(FALSE), - tabChangesFocus(FALSE), -#ifndef TQT_NO_CLIPBOARD - clipboard_mode( TQClipboard::Clipboard ), -#endif -#ifdef QT_TEXTEDIT_OPTIMIZATION - od(0), optimMode(FALSE), - maxLogLines(-1), - logOffset(0), -#endif - autoFormatting( (uint)TQTextEdit::AutoAll ) - { - for ( int i=0; i<7; i++ ) - id[i] = 0; - } - int id[ 7 ]; - int preeditStart; - int preeditLength; - bool composeMode() const { return ( preeditLength > 0 ); } - - uint ensureCursorVisibleInShowEvent : 1; - uint tabChangesFocus : 1; - TQString scrollToAnchor; // used to deferr scrollToAnchor() until the show event when we are resized - TQString pressedName; - TQString onName; -#ifndef TQT_NO_CLIPBOARD - TQClipboard::Mode clipboard_mode; -#endif - TQTimer *trippleClickTimer; - TQPoint trippleClickPoint; -#ifdef QT_TEXTEDIT_OPTIMIZATION - TQTextEditOptimPrivate * od; - bool optimMode : 1; - int maxLogLines; - int logOffset; -#endif - uint autoFormatting; -}; - -#ifndef TQT_NO_MIME -class TQRichTextDrag : public TQTextDrag -{ -public: - TQRichTextDrag( TQWidget *dragSource = 0, const char *name = 0 ); - - void setPlainText( const TQString &txt ) { setText( txt ); } - void setRichText( const TQString &txt ) { richTxt = txt; } - - virtual TQByteArray encodedData( const char *mime ) const; - virtual const char* format( int i ) const; - - static bool decode( TQMimeSource *e, TQString &str, const TQCString &mimetype, - const TQCString &subtype ); - static bool canDecode( TQMimeSource* e ); - -private: - TQString richTxt; - -}; - -TQRichTextDrag::TQRichTextDrag( TQWidget *dragSource, const char *name ) - : TQTextDrag( dragSource, name ) -{ -} - -TQByteArray TQRichTextDrag::encodedData( const char *mime ) const -{ - if ( qstrcmp( "application/x-qrichtext", mime ) == 0 ) { - return richTxt.utf8(); // #### perhaps we should use USC2 instead? - } else - return TQTextDrag::encodedData( mime ); -} - -bool TQRichTextDrag::decode( TQMimeSource *e, TQString &str, const TQCString &mimetype, - const TQCString &subtype ) -{ - if ( mimetype == "application/x-qrichtext" ) { - // do richtext decode - const char *mime; - int i; - for ( i = 0; ( mime = e->format( i ) ); ++i ) { - if ( qstrcmp( "application/x-qrichtext", mime ) != 0 ) - continue; - str = TQString::fromUtf8( e->encodedData( mime ) ); - return TRUE; - } - return FALSE; - } - - // do a regular text decode - TQCString subt = subtype; - return TQTextDrag::decode( e, str, subt ); -} - -bool TQRichTextDrag::canDecode( TQMimeSource* e ) -{ - if ( e->provides( "application/x-qrichtext" ) ) - return TRUE; - return TQTextDrag::canDecode( e ); -} - -const char* TQRichTextDrag::format( int i ) const -{ - if ( TQTextDrag::format( i ) ) - return TQTextDrag::format( i ); - if ( TQTextDrag::format( i-1 ) ) - return "application/x-qrichtext"; - return 0; -} - -#endif - -static bool block_set_alignment = FALSE; - -/*! - \class TQTextEdit ntqtextedit.h - \brief The TQTextEdit widget provides a powerful single-page rich text editor. - - \ingroup basic - \ingroup text - \mainclass - - \tableofcontents - - \section1 Introduction and Concepts - - TQTextEdit is an advanced WYSIWYG viewer/editor supporting rich - text formatting using HTML-style tags. It is optimized to handle - large documents and to respond quickly to user input. - - TQTextEdit has four modes of operation: - \table - \header \i Mode \i Command \i Notes - \row \i Plain Text Editor \i setTextFormat(PlainText) - \i Set text with setText(); text() returns plain text. Text - attributes (e.g. colors) can be set, but plain text is always - returned. - \row \i Rich Text Editor \i setTextFormat(RichText) - \i Set text with setText(); text() returns rich text. Rich - text editing is fairly limited. You can't set margins or - insert images for example (although you can read and - correctly display files that have margins set and that - include images). This mode is mostly useful for editing small - amounts of rich text. 1. - \row \i Text Viewer \i setReadOnly(TRUE) - \i Set text with setText() or append() (which has no undo - history so is faster and uses less memory); text() returns - plain or rich text depending on the textFormat(). This mode - can correctly display a large subset of HTML tags. - \row \i Log Viewer \i setTextFormat(LogText) - \i Append text using append(). The widget is set to be read - only and rich text support is disabled although a few HTML - tags (for color, bold, italic and underline) may be used. - (See \link #logtextmode LogText mode\endlink for details.) - \endtable - - 1.A more complete API that supports setting - margins, images, etc., is planned for a later TQt release. - - TQTextEdit can be used as a syntax highlighting editor when used in - conjunction with TQSyntaxHighlighter. - - We recommend that you always call setTextFormat() to set the mode - you want to use. If you use \c AutoText then setText() and - append() will try to determine whether the text they are given is - plain text or rich text. If you use \c RichText then setText() and - append() will assume that the text they are given is rich text. - insert() simply inserts the text it is given. - - TQTextEdit works on paragraphs and characters. A paragraph is a - formatted string which is word-wrapped to fit into the width of - the widget. By default when reading plain text, one newline - signify a paragraph. A document consists of zero or more - paragraphs, indexed from 0. Characters are indexed on a - per-paragraph basis, also indexed from 0. The words in the - paragraph are aligned in accordance with the paragraph's - alignment(). Paragraphs are separated by hard line breaks. Each - character within a paragraph has its own attributes, for example, - font and color. - - The text edit documentation uses the following concepts: - \list - \i \e{current format} -- - this is the format at the current cursor position, \e and it - is the format of the selected text if any. - \i \e{current paragraph} -- the paragraph which contains the - cursor. - \endlist - - TQTextEdit can display images (using TQMimeSourceFactory), lists and - tables. If the text is too large to view within the text edit's - viewport, scrollbars will appear. The text edit can load both - plain text and HTML files (a subset of HTML 3.2 and 4). The - rendering style and the set of valid tags are defined by a - styleSheet(). Custom tags can be created and placed in a custom - style sheet. Change the style sheet with \l{setStyleSheet()}; see - TQStyleSheet for details. The images identified by image tags are - displayed if they can be interpreted using the text edit's - \l{TQMimeSourceFactory}; see setMimeSourceFactory(). - - If you want a text browser with more navigation use TQTextBrowser. - If you just need to display a small piece of rich text use TQLabel - or TQSimpleRichText. - - If you create a new TQTextEdit, and want to allow the user to edit - rich text, call setTextFormat(TQt::RichText) to ensure that the - text is treated as rich text. (Rich text uses HTML tags to set - text formatting attributes. See TQStyleSheet for information on the - HTML tags that are supported.). If you don't call setTextFormat() - explicitly the text edit will guess from the text itself whether - it is rich text or plain text. This means that if the text looks - like HTML or XML it will probably be interpreted as rich text, so - you should call setTextFormat(TQt::PlainText) to preserve such - text. - - Note that we do not intend to add a full-featured web browser - widget to TQt (because that would easily double TQt's size and only - a few applications would benefit from it). The rich - text support in TQt is designed to provide a fast, portable and - efficient way to add reasonable online help facilities to - applications, and to provide a basis for rich text editors. - - \section1 Using TQTextEdit as a Display Widget - - TQTextEdit can display a large HTML subset, including tables and - images. - - The text is set or replaced using setText() which deletes any - existing text and replaces it with the text passed in the - setText() call. If you call setText() with legacy HTML (with - setTextFormat(RichText) in force), and then call text(), the text - that is returned may have different markup, but will render the - same. Text can be inserted with insert(), paste(), pasteSubType() - and append(). Text that is appended does not go into the undo - history; this makes append() faster and consumes less memory. Text - can also be cut(). The entire text is deleted with clear() and the - selected text is deleted with removeSelectedText(). Selected - (marked) text can also be deleted with del() (which will delete - the character to the right of the cursor if no text is selected). - - Loading and saving text is achieved using setText() and text(), - for example: - \code - TQFile file( fileName ); // Read the text from a file - if ( file.open( IO_ReadOnly ) ) { - TQTextStream stream( &file ); - textEdit->setText( stream.read() ); - } - - TQFile file( fileName ); // Write the text to a file - if ( file.open( IO_WriteOnly ) ) { - TQTextStream stream( &file ); - stream << textEdit->text(); - textEdit->setModified( FALSE ); - } - \endcode - - By default the text edit wraps words at whitespace to fit within - the text edit widget. The setWordWrap() function is used to - specify the kind of word wrap you want, or \c NoWrap if you don't - want any wrapping. Call setWordWrap() to set a fixed pixel width - \c FixedPixelWidth, or character column (e.g. 80 column) \c - FixedColumnWidth with the pixels or columns specified with - setWrapColumnOrWidth(). If you use word wrap to the widget's width - \c WidgetWidth, you can specify whether to break on whitespace or - anywhere with setWrapPolicy(). - - The background color is set differently than other widgets, using - setPaper(). You specify a brush style which could be a plain color - or a complex pixmap. - - Hypertext links are automatically underlined; this can be changed - with setLinkUnderline(). The tab stop width is set with - setTabStopWidth(). - - The zoomIn() and zoomOut() functions can be used to resize the - text by increasing (decreasing for zoomOut()) the point size used. - Images are not affected by the zoom functions. - - The lines() function returns the number of lines in the text and - paragraphs() returns the number of paragraphs. The number of lines - within a particular paragraph is returned by linesOfParagraph(). - The length of the entire text in characters is returned by - length(). - - You can scroll to an anchor in the text, e.g. - \c{} with scrollToAnchor(). The find() function - can be used to find and select a given string within the text. - - A read-only TQTextEdit provides the same functionality as the - (obsolete) TQTextView. (TQTextView is still supplied for - compatibility with old code.) - - \section2 Read-only key bindings - - When TQTextEdit is used read-only the key-bindings are limited to - navigation, and text may only be selected with the mouse: - \table - \header \i Keypresses \i Action - \row \i UpArrow \i Move one line up - \row \i DownArrow \i Move one line down - \row \i LeftArrow \i Move one character left - \row \i RightArrow \i Move one character right - \row \i PageUp \i Move one (viewport) page up - \row \i PageDown \i Move one (viewport) page down - \row \i Home \i Move to the beginning of the text - \row \i End \i Move to the end of the text - \row \i Shift+Wheel - \i Scroll the page horizontally (the Wheel is the mouse wheel) - \row \i Ctrl+Wheel \i Zoom the text - \endtable - - The text edit may be able to provide some meta-information. For - example, the documentTitle() function will return the text from - within HTML \c{} tags. - - The text displayed in a text edit has a \e context. The context is - a path which the text edit's TQMimeSourceFactory uses to resolve - the locations of files and images. It is passed to the - mimeSourceFactory() when quering data. (See TQTextEdit() and - \l{context()}.) - - \target logtextmode - \section2 Using TQTextEdit in LogText Mode - - Setting the text format to \c LogText puts the widget in a special - mode which is optimized for very large texts. Editing, word wrap, - and rich text support are disabled in this mode (the widget is - explicitly made read-only). This allows the text to be stored in a - different, more memory efficient manner. However, a certain degree - of text formatting is supported through the use of formatting tags. - A tag is delimited by \c < and \c {>}. The characters \c {<}, \c > - and \c & are escaped by using \c {<}, \c {>} and \c {&}. - A tag pair consists of a left and a right tag (or open/close tags). - Left-tags mark the starting point for formatting, while right-tags - mark the ending point. A right-tag always start with a \c / before - the tag keyword. For example \c <b> and \c </b> are a tag pair. - Tags can be nested, but they have to be closed in the same order as - they are opened. For example, \c <b><u></u></b> is valid, while \c - <b><u></b></u> will output an error message. - - By using tags it is possible to change the color, bold, italic and - underline settings for a piece of text. A color can be specified - by using the HTML font tag \c {<font color=colorname>}. The color - name can be one of the color names from the X11 color database, or - a RGB hex value (e.g \c {#00ff00}). Example of valid color tags: - \c {<font color=red>}, \c {<font color="light blue">}, \c {<font - color="#223344">}. Bold, italic and underline settings can be - specified by the tags \c {<b>}, \c <i> and \c {<u>}. Note that a - tag does not necessarily have to be closed. A valid example: - \code - This is <font color=red>red</font> while <b>this</b> is <font color=blue>blue</font>. - <font color=green><font color=yellow>Yellow,</font> and <u>green</u>. - \endcode - - Stylesheets can also be used in LogText mode. To create and use a - custom tag, you could do the following: - \code - TQTextEdit * log = new TQTextEdit( this ); - log->setTextFormat( TQt::LogText ); - TQStyleSheetItem * item = new TQStyleSheetItem( log->styleSheet(), "mytag" ); - item->setColor( "red" ); - item->setFontWeight( TQFont::Bold ); - item->setFontUnderline( TRUE ); - log->append( "This is a <mytag>custom tag</mytag>!" ); - \endcode - Note that only the color, bold, underline and italic attributes of - a TQStyleSheetItem is used in LogText mode. - - Note that you can use setMaxLogLines() to limit the number of - lines the widget can hold in LogText mode. - - There are a few things that you need to be aware of when the - widget is in this mode: - \list - \i Functions that deal with rich text formatting and cursor - movement will not work or return anything valid. - \i Lines are equivalent to paragraphs. - \endlist - - \section1 Using TQTextEdit as an Editor - - All the information about using TQTextEdit as a display widget also - applies here. - - The current format's attributes are set with setItalic(), - setBold(), setUnderline(), setFamily() (font family), - setPointSize(), setColor() and setCurrentFont(). The current - paragraph's alignment is set with setAlignment(). - - Use setSelection() to select text. The setSelectionAttributes() - function is used to indicate how selected text should be - displayed. Use hasSelectedText() to find out if any text is - selected. The currently selected text's position is available - using getSelection() and the selected text itself is returned by - selectedText(). The selection can be copied to the clipboard with - copy(), or cut to the clipboard with cut(). It can be deleted with - removeSelectedText(). The entire text can be selected (or - unselected) using selectAll(). TQTextEdit supports multiple - selections. Most of the selection functions operate on the default - selection, selection 0. If the user presses a non-selecting key, - e.g. a cursor key without also holding down Shift, all selections - are cleared. - - Set and get the position of the cursor with setCursorPosition() - and getCursorPosition() respectively. When the cursor is moved, - the signals currentFontChanged(), currentColorChanged() and - currentAlignmentChanged() are emitted to reflect the font, color - and alignment at the new cursor position. - - If the text changes, the textChanged() signal is emitted, and if - the user inserts a new line by pressing Return or Enter, - returnPressed() is emitted. The isModified() function will return - TRUE if the text has been modified. - - TQTextEdit provides command-based undo and redo. To set the depth - of the command history use setUndoDepth() which defaults to 100 - steps. To undo or redo the last operation call undo() or redo(). - The signals undoAvailable() and redoAvailable() indicate whether - the undo and redo operations can be executed. - - The indent() function is used to reindent a paragraph. It is - useful for code editors, for example in \link designer-manual.book - TQt Designer\endlink's code editor \e{Ctrl+I} invokes the indent() - function. - - \section2 Editing key bindings - - The list of key-bindings which are implemented for editing: - \table - \header \i Keypresses \i Action - \row \i Backspace \i Delete the character to the left of the cursor - \row \i Delete \i Delete the character to the right of the cursor - \row \i Ctrl+A \i Move the cursor to the beginning of the line - \row \i Ctrl+B \i Move the cursor one character left - \row \i Ctrl+C \i Copy the marked text to the clipboard (also - Ctrl+Insert under Windows) - \row \i Ctrl+D \i Delete the character to the right of the cursor - \row \i Ctrl+E \i Move the cursor to the end of the line - \row \i Ctrl+F \i Move the cursor one character right - \row \i Ctrl+H \i Delete the character to the left of the cursor - \row \i Ctrl+K \i Delete to end of line - \row \i Ctrl+N \i Move the cursor one line down - \row \i Ctrl+P \i Move the cursor one line up - \row \i Ctrl+V \i Paste the clipboard text into line edit - (also Shift+Insert under Windows) - \row \i Ctrl+X \i Cut the marked text, copy to clipboard - (also Shift+Delete under Windows) - \row \i Ctrl+Z \i Undo the last operation - \row \i Ctrl+Y \i Redo the last operation - \row \i LeftArrow \i Move the cursor one character left - \row \i Ctrl+LeftArrow \i Move the cursor one word left - \row \i RightArrow \i Move the cursor one character right - \row \i Ctrl+RightArrow \i Move the cursor one word right - \row \i UpArrow \i Move the cursor one line up - \row \i Ctrl+UpArrow \i Move the cursor one word up - \row \i DownArrow \i Move the cursor one line down - \row \i Ctrl+Down Arrow \i Move the cursor one word down - \row \i PageUp \i Move the cursor one page up - \row \i PageDown \i Move the cursor one page down - \row \i Home \i Move the cursor to the beginning of the line - \row \i Ctrl+Home \i Move the cursor to the beginning of the text - \row \i End \i Move the cursor to the end of the line - \row \i Ctrl+End \i Move the cursor to the end of the text - \row \i Shift+Wheel \i Scroll the page horizontally - (the Wheel is the mouse wheel) - \row \i Ctrl+Wheel \i Zoom the text - \endtable - - To select (mark) text hold down the Shift key whilst pressing one - of the movement keystrokes, for example, \e{Shift+Right Arrow} - will select the character to the right, and \e{Shift+Ctrl+Right - Arrow} will select the word to the right, etc. - - By default the text edit widget operates in insert mode so all - text that the user enters is inserted into the text edit and any - text to the right of the cursor is moved out of the way. The mode - can be changed to overwrite, where new text overwrites any text to - the right of the cursor, using setOverwriteMode(). -*/ - -/*! - \enum TQTextEdit::AutoFormatting - - \value AutoNone Do not perform any automatic formatting - \value AutoBulletList Only automatically format bulletted lists - \value AutoAll Apply all available autoformatting -*/ - - -/*! - \enum TQTextEdit::KeyboardAction - - This enum is used by doKeyboardAction() to specify which action - should be executed: - - \value ActionBackspace Delete the character to the left of the - cursor. - - \value ActionDelete Delete the character to the right of the - cursor. - - \value ActionReturn Split the paragraph at the cursor position. - - \value ActionKill If the cursor is not at the end of the - paragraph, delete the text from the cursor position until the end - of the paragraph. If the cursor is at the end of the paragraph, - delete the hard line break at the end of the paragraph: this will - cause this paragraph to be joined with the following paragraph. - - \value ActionWordBackspace Delete the word to the left of the - cursor position. - - \value ActionWordDelete Delete the word to the right of the - cursor position - -*/ - -/*! - \enum TQTextEdit::VerticalAlignment - - This enum is used to set the vertical alignment of the text. - - \value AlignNormal Normal alignment - \value AlignSuperScript Superscript - \value AlignSubScript Subscript -*/ - -/*! - \enum TQTextEdit::TextInsertionFlags - - \internal - - \value RedoIndentation - \value CheckNewLines - \value RemoveSelected -*/ - - -/*! - \fn void TQTextEdit::copyAvailable(bool yes) - - This signal is emitted when text is selected or de-selected in the - text edit. - - When text is selected this signal will be emitted with \a yes set - to TRUE. If no text has been selected or if the selected text is - de-selected this signal is emitted with \a yes set to FALSE. - - If \a yes is TRUE then copy() can be used to copy the selection to - the clipboard. If \a yes is FALSE then copy() does nothing. - - \sa selectionChanged() -*/ - - -/*! - \fn void TQTextEdit::textChanged() - - This signal is emitted whenever the text in the text edit changes. - - \sa setText() append() -*/ - -/*! - \fn void TQTextEdit::selectionChanged() - - This signal is emitted whenever the selection changes. - - \sa setSelection() copyAvailable() -*/ - -/*! \fn TQTextDocument *TQTextEdit::document() const - - \internal - - This function returns the TQTextDocument which is used by the text - edit. -*/ - -/*! \fn void TQTextEdit::setDocument( TQTextDocument *doc ) - - \internal - - This function sets the TQTextDocument which should be used by the text - edit to \a doc. This can be used, for example, if you want to - display a document using multiple views. You would create a - TQTextDocument and set it to the text edits which should display it. - You would need to connect to the textChanged() and - selectionChanged() signals of all the text edits and update them all - accordingly (preferably with a slight delay for efficiency reasons). -*/ - -/*! - \enum TQTextEdit::CursorAction - - This enum is used by moveCursor() to specify in which direction - the cursor should be moved: - - \value MoveBackward Moves the cursor one character backward - - \value MoveWordBackward Moves the cursor one word backward - - \value MoveForward Moves the cursor one character forward - - \value MoveWordForward Moves the cursor one word forward - - \value MoveUp Moves the cursor up one line - - \value MoveDown Moves the cursor down one line - - \value MoveLineStart Moves the cursor to the beginning of the line - - \value MoveLineEnd Moves the cursor to the end of the line - - \value MoveHome Moves the cursor to the beginning of the document - - \value MoveEnd Moves the cursor to the end of the document - - \value MovePgUp Moves the cursor one viewport page up - - \value MovePgDown Moves the cursor one viewport page down -*/ - -/*! - \enum TQt::AnchorAttribute - - An anchor has one or more of the following attributes: - - \value AnchorName the name attribute of the anchor. This attribute is - used when scrolling to an anchor in the document. - - \value AnchorHref the href attribute of the anchor. This attribute is - used when a link is clicked to determine what content to load. -*/ - -/*! - \property TQTextEdit::overwriteMode - \brief the text edit's overwrite mode - - If FALSE (the default) characters entered by the user are inserted - with any characters to the right being moved out of the way. If - TRUE, the editor is in overwrite mode, i.e. characters entered by - the user overwrite any characters to the right of the cursor - position. -*/ - -/*! - \fn void TQTextEdit::setCurrentFont( const TQFont &f ) - - Sets the font of the current format to \a f. - - If the widget is in \c LogText mode this function will do - nothing. Use setFont() instead. - - \sa currentFont() setPointSize() setFamily() -*/ - -/*! - \property TQTextEdit::undoDepth - \brief the depth of the undo history - - The maximum number of steps in the undo/redo history. The default - is 100. - - \sa undo() redo() -*/ - -/*! - \fn void TQTextEdit::undoAvailable( bool yes ) - - This signal is emitted when the availability of undo changes. If - \a yes is TRUE, then undo() will work until undoAvailable( FALSE ) - is next emitted. - - \sa undo() undoDepth() -*/ - -/*! - \fn void TQTextEdit::modificationChanged( bool m ) - - This signal is emitted when the modification status of the - document has changed. If \a m is TRUE, the document was modified, - otherwise the modification state has been reset to unmodified. - - \sa modified -*/ - -/*! - \fn void TQTextEdit::redoAvailable( bool yes ) - - This signal is emitted when the availability of redo changes. If - \a yes is TRUE, then redo() will work until redoAvailable( FALSE ) - is next emitted. - - \sa redo() undoDepth() -*/ - -/*! - \fn void TQTextEdit::currentFontChanged( const TQFont &f ) - - This signal is emitted if the font of the current format has - changed. - - The new font is \a f. - - \sa setCurrentFont() -*/ - -/*! - \fn void TQTextEdit::currentColorChanged( const TQColor &c ) - - This signal is emitted if the color of the current format has - changed. - - The new color is \a c. - - \sa setColor() -*/ - -/*! - \fn void TQTextEdit::currentVerticalAlignmentChanged( VerticalAlignment a ) - - This signal is emitted if the vertical alignment of the current - format has changed. - - The new vertical alignment is \a a. - - \sa setVerticalAlignment() -*/ - -/*! - \fn void TQTextEdit::currentAlignmentChanged( int a ) - - This signal is emitted if the alignment of the current paragraph - has changed. - - The new alignment is \a a. - - \sa setAlignment() -*/ - -/*! - \fn void TQTextEdit::cursorPositionChanged( TQTextCursor *c ) - - \internal -*/ - -/*! - \fn void TQTextEdit::cursorPositionChanged( int para, int pos ) - - This signal is emitted if the position of the cursor has changed. - \a para contains the paragraph index and \a pos contains the - character position within the paragraph. - - \sa setCursorPosition() -*/ - -/*! - \fn void TQTextEdit::clicked( int para, int pos ) - - This signal is emitted when the mouse is clicked on the paragraph - \a para at character position \a pos. - - \sa doubleClicked() -*/ - -/*! \fn void TQTextEdit::doubleClicked( int para, int pos ) - - This signal is emitted when the mouse is double-clicked on the - paragraph \a para at character position \a pos. - - \sa clicked() -*/ - - -/*! - \fn void TQTextEdit::returnPressed() - - This signal is emitted if the user pressed the Return or the Enter - key. -*/ - -/*! - \fn TQTextCursor *TQTextEdit::textCursor() const - - Returns the text edit's text cursor. - - \warning TQTextCursor is not in the public API, but in special - circumstances you might wish to use it. -*/ - -/*! - Constructs an empty TQTextEdit called \a name, with parent \a - parent. -*/ - -TQTextEdit::TQTextEdit( TQWidget *parent, const char *name ) - : TQScrollView( parent, name, WStaticContents | WNoAutoErase ), - doc( new TQTextDocument( 0 ) ), undoRedoInfo( doc ) -{ - init(); -} - -/*! - Constructs a TQTextEdit called \a name, with parent \a parent. The - text edit will display the text \a text using context \a context. - - The \a context is a path which the text edit's TQMimeSourceFactory - uses to resolve the locations of files and images. It is passed to - the mimeSourceFactory() when quering data. - - For example if the text contains an image tag, - \c{<img src="image.png">}, and the context is "path/to/look/in", the - TQMimeSourceFactory will try to load the image from - "path/to/look/in/image.png". If the tag was - \c{<img src="/image.png">}, the context will not be used (because - TQMimeSourceFactory recognizes that we have used an absolute path) - and will try to load "/image.png". The context is applied in exactly - the same way to \e hrefs, for example, - \c{<a href="target.html">Target</a>}, would resolve to - "path/to/look/in/target.html". -*/ - -TQTextEdit::TQTextEdit( const TQString& text, const TQString& context, - TQWidget *parent, const char *name) - : TQScrollView( parent, name, WStaticContents | WNoAutoErase ), - doc( new TQTextDocument( 0 ) ), undoRedoInfo( doc ) -{ - init(); - setText( text, context ); -} - -/*! - \reimp -*/ - -TQTextEdit::~TQTextEdit() -{ - delete undoRedoInfo.d; - undoRedoInfo.d = 0; - delete cursor; - delete doc; -#ifdef QT_TEXTEDIT_OPTIMIZATION - if ( d->optimMode ) - delete d->od; -#endif - delete d; -} - -void TQTextEdit::init() -{ - d = new TQTextEditPrivate; - doc->formatCollection()->setPaintDevice( this ); - undoEnabled = TRUE; - readOnly = TRUE; - setReadOnly( FALSE ); - setFrameStyle( LineEditPanel | Sunken ); - connect( doc, TQ_SIGNAL( minimumWidthChanged(int) ), - this, TQ_SLOT( documentWidthChanged(int) ) ); - - mousePressed = FALSE; - inDoubleClick = FALSE; - modified = FALSE; - onLink = TQString::null; - d->onName = TQString::null; - overWrite = FALSE; - wrapMode = WidgetWidth; - wrapWidth = -1; - wPolicy = AtWhiteSpace; - mightStartDrag = FALSE; - inDnD = FALSE; - doc->setFormatter( new TQTextFormatterBreakWords ); - doc->formatCollection()->defaultFormat()->setFont( TQScrollView::font() ); - doc->formatCollection()->defaultFormat()->setColor( colorGroup().color( TQColorGroup::Text ) ); - currentFormat = doc->formatCollection()->defaultFormat(); - currentAlignment = TQt::AlignAuto; - - setBackgroundMode( PaletteBase ); - viewport()->setBackgroundMode( PaletteBase ); - viewport()->setAcceptDrops( TRUE ); - resizeContents( 0, doc->lastParagraph() ? - ( doc->lastParagraph()->paragId() + 1 ) * doc->formatCollection()->defaultFormat()->height() : 0 ); - - setKeyCompression( TRUE ); - viewport()->setMouseTracking( TRUE ); -#ifndef TQT_NO_CURSOR - viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); -#endif - cursor = new TQTextCursor( doc ); - - formatTimer = new TQTimer( this ); - connect( formatTimer, TQ_SIGNAL( timeout() ), - this, TQ_SLOT( formatMore() ) ); - lastFormatted = doc->firstParagraph(); - - scrollTimer = new TQTimer( this ); - connect( scrollTimer, TQ_SIGNAL( timeout() ), - this, TQ_SLOT( autoScrollTimerDone() ) ); - - interval = 0; - changeIntervalTimer = new TQTimer( this ); - connect( changeIntervalTimer, TQ_SIGNAL( timeout() ), - this, TQ_SLOT( doChangeInterval() ) ); - - cursorVisible = TRUE; - blinkTimer = new TQTimer( this ); - connect( blinkTimer, TQ_SIGNAL( timeout() ), - this, TQ_SLOT( blinkCursor() ) ); - -#ifndef TQT_NO_DRAGANDDROP - dragStartTimer = new TQTimer( this ); - connect( dragStartTimer, TQ_SIGNAL( timeout() ), - this, TQ_SLOT( startDrag() ) ); -#endif - - d->trippleClickTimer = new TQTimer( this ); - - formatMore(); - - blinkCursorVisible = FALSE; - - viewport()->setFocusProxy( this ); - viewport()->setFocusPolicy( WheelFocus ); - setInputMethodEnabled( TRUE ); - viewport()->installEventFilter( this ); - connect( this, TQ_SIGNAL(horizontalSliderReleased()), this, TQ_SLOT(sliderReleased()) ); - connect( this, TQ_SIGNAL(verticalSliderReleased()), this, TQ_SLOT(sliderReleased()) ); - installEventFilter( this ); -} - -void TQTextEdit::paintDocument( bool drawAll, TQPainter *p, int cx, int cy, int cw, int ch ) -{ -#ifdef QT_TEXTEDIT_OPTIMIZATION - Q_ASSERT( !d->optimMode ); - if ( d->optimMode ) - return; -#endif - - bool drawCur = hasFocus() || viewport()->hasFocus(); - if (( hasSelectedText() && !style().styleHint( TQStyle::SH_BlinkCursorWhenTextSelected ) ) || - isReadOnly() || !cursorVisible || doc->hasSelection( TQTextDocument::IMSelectionText )) - drawCur = FALSE; - TQColorGroup g = colorGroup(); - const TQColorGroup::ColorRole backRole = TQPalette::backgroundRoleFromMode(backgroundMode()); - if ( doc->paper() ) - g.setBrush( backRole, *doc->paper() ); - - if ( contentsY() < doc->y() ) { - p->fillRect( contentsX(), contentsY(), visibleWidth(), doc->y(), - g.brush( backRole ) ); - } - if ( drawAll && doc->width() - contentsX() < cx + cw ) { - p->fillRect( doc->width() - contentsX(), cy, cx + cw - doc->width() + contentsX(), ch, - g.brush( backRole ) ); - } - - p->setBrushOrigin( -contentsX(), -contentsY() ); - - lastFormatted = doc->draw( p, cx, cy, cw, ch, g, !drawAll, drawCur, cursor ); - - if ( lastFormatted == doc->lastParagraph() ) - resizeContents( contentsWidth(), doc->height() ); - - if ( contentsHeight() < visibleHeight() && ( !doc->lastParagraph() || doc->lastParagraph()->isValid() ) && drawAll ) - p->fillRect( 0, contentsHeight(), visibleWidth(), - visibleHeight() - contentsHeight(), g.brush( backRole ) ); -} - -/*! - \reimp -*/ - -void TQTextEdit::drawContents( TQPainter *p, int cx, int cy, int cw, int ch ) -{ -#ifdef QT_TEXTEDIT_OPTIMIZATION - if ( d->optimMode ) { - optimDrawContents( p, cx, cy, cw, ch ); - return; - } -#endif - paintDocument( TRUE, p, cx, cy, cw, ch ); - int v; - p->setPen( foregroundColor() ); - if ( document()->isPageBreakEnabled() && ( v = document()->flow()->pageSize() ) > 0 ) { - int l = int(cy / v) * v; - while ( l < cy + ch ) { - p->drawLine( cx, l, cx + cw - 1, l ); - l += v; - } - } - - // This invocation is required to follow dragging of active window - // by the showed candidate window. - updateMicroFocusHint(); -} - -/*! - \reimp -*/ - -void TQTextEdit::drawContents( TQPainter *p ) -{ - if ( horizontalScrollBar()->isVisible() && - verticalScrollBar()->isVisible() ) { - const TQRect verticalRect = verticalScrollBar()->geometry(); - const TQRect horizontalRect = horizontalScrollBar()->geometry(); - - TQRect cornerRect; - cornerRect.setTop( verticalRect.bottom() ); - cornerRect.setBottom( horizontalRect.bottom() ); - cornerRect.setLeft( verticalRect.left() ); - cornerRect.setRight( verticalRect.right() ); - - p->fillRect( cornerRect, colorGroup().background() ); - } -} - -/*! - \reimp -*/ - -bool TQTextEdit::event( TQEvent *e ) -{ - if ( e->type() == TQEvent::AccelOverride && !isReadOnly() ) { - TQKeyEvent* ke = (TQKeyEvent*) e; - switch((int)(ke->state())) { - case NoButton: - case Keypad: - case ShiftButton: - if ( ke->key() < Key_Escape ) { - ke->accept(); - } else { - switch ( ke->key() ) { - case Key_Return: - case Key_Enter: - case Key_Delete: - case Key_Home: - case Key_End: - case Key_Backspace: - case Key_Left: - case Key_Right: - ke->accept(); - default: - break; - } - } - break; - - case ControlButton: - case ControlButton|ShiftButton: - case ControlButton|Keypad: - case ControlButton|ShiftButton|Keypad: - switch ( ke->key() ) { - case Key_Tab: - case Key_Backtab: - ke->ignore(); - break; -// Those are too frequently used for application functionality -/* case Key_A: - case Key_B: - case Key_D: - case Key_E: - case Key_F: - case Key_H: - case Key_I: - case Key_K: - case Key_N: - case Key_P: - case Key_T: -*/ - case Key_C: - case Key_V: - case Key_X: - case Key_Y: - case Key_Z: - case Key_Left: - case Key_Right: - case Key_Up: - case Key_Down: - case Key_Home: - case Key_End: -#if defined (TQ_WS_WIN) - case Key_Insert: - case Key_Delete: -#endif - ke->accept(); - default: - break; - } - break; - - default: - switch ( ke->key() ) { -#if defined (TQ_WS_WIN) - case Key_Insert: - ke->accept(); -#endif - default: - break; - } - break; - } - } - - if ( e->type() == TQEvent::Show ) { - if ( -#ifdef QT_TEXTEDIT_OPTIMIZATION - !d->optimMode && -#endif - d->ensureCursorVisibleInShowEvent ) { - ensureCursorVisible(); - d->ensureCursorVisibleInShowEvent = FALSE; - } - if ( !d->scrollToAnchor.isEmpty() ) { - scrollToAnchor( d->scrollToAnchor ); - d->scrollToAnchor = TQString::null; - } - } - return TQWidget::event( e ); -} - -/*! - Processes the key event, \a e. By default key events are used to - provide keyboard navigation and text editing. -*/ - -void TQTextEdit::keyPressEvent( TQKeyEvent *e ) -{ - changeIntervalTimer->stop(); - interval = 10; - bool unknownKey = FALSE; - if ( isReadOnly() ) { - if ( !handleReadOnlyKeyEvent( e ) ) - TQScrollView::keyPressEvent( e ); - changeIntervalTimer->start( 100, TRUE ); - return; - } - - - bool selChanged = FALSE; - for ( int i = 1; i < doc->numSelections(); ++i ) // start with 1 as we don't want to remove the Standard-Selection - selChanged = doc->removeSelection( i ) || selChanged; - - if ( selChanged ) { - cursor->paragraph()->document()->nextDoubleBuffered = TRUE; - repaintChanged(); - } - - bool clearUndoRedoInfo = TRUE; - - - switch ( e->key() ) { - case Key_Left: - case Key_Right: { - // a bit hacky, but can't change this without introducing new enum values for move and keeping the - // correct semantics and movement for BiDi and non BiDi text. - CursorAction a; - if ( cursor->paragraph()->string()->isRightToLeft() == (e->key() == Key_Right) ) - a = e->state() & ControlButton ? MoveWordBackward : MoveBackward; - else - a = e->state() & ControlButton ? MoveWordForward : MoveForward; - moveCursor( a, e->state() & ShiftButton ); - break; - } - case Key_Up: - moveCursor( e->state() & ControlButton ? MovePgUp : MoveUp, e->state() & ShiftButton ); - break; - case Key_Down: - moveCursor( e->state() & ControlButton ? MovePgDown : MoveDown, e->state() & ShiftButton ); - break; - case Key_Home: - moveCursor( e->state() & ControlButton ? MoveHome : MoveLineStart, e->state() & ShiftButton ); - break; - case Key_End: - moveCursor( e->state() & ControlButton ? MoveEnd : MoveLineEnd, e->state() & ShiftButton ); - break; - case Key_Prior: - moveCursor( MovePgUp, e->state() & ShiftButton ); - break; - case Key_Next: - moveCursor( MovePgDown, e->state() & ShiftButton ); - break; - case Key_Return: case Key_Enter: - if ( doc->hasSelection( TQTextDocument::Standard, FALSE ) ) - removeSelectedText(); - if ( textFormat() == TQt::RichText && ( e->state() & ControlButton ) ) { - // Ctrl-Enter inserts a line break in rich text mode - insert( TQString( TQChar( 0x2028) ), TRUE, FALSE ); - } else { -#ifndef TQT_NO_CURSOR - viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); -#endif - clearUndoRedoInfo = FALSE; - doKeyboardAction( ActionReturn ); - emit returnPressed(); - } - break; - case Key_Delete: -#if defined (TQ_WS_WIN) - if ( e->state() & ShiftButton ) { - cut(); - break; - } else -#endif - if ( doc->hasSelection( TQTextDocument::Standard, TRUE ) ) { - removeSelectedText(); - break; - } - doKeyboardAction( e->state() & ControlButton ? ActionWordDelete - : ActionDelete ); - clearUndoRedoInfo = FALSE; - - break; - case Key_Insert: - if ( e->state() & ShiftButton ) - paste(); -#if defined (TQ_WS_WIN) - else if ( e->state() & ControlButton ) - copy(); -#endif - else - setOverwriteMode( !isOverwriteMode() ); - break; - case Key_Backspace: -#if defined (TQ_WS_WIN) - if ( e->state() & AltButton ) { - if (e->state() & ControlButton ) { - break; - } else if ( e->state() & ShiftButton ) { - redo(); - break; - } else { - undo(); - break; - } - } else -#endif - if ( doc->hasSelection( TQTextDocument::Standard, TRUE ) ) { - removeSelectedText(); - break; - } - - doKeyboardAction( e->state() & ControlButton ? ActionWordBackspace - : ActionBackspace ); - clearUndoRedoInfo = FALSE; - break; - case Key_F16: // Copy key on Sun keyboards - copy(); - break; - case Key_F18: // Paste key on Sun keyboards - paste(); - break; - case Key_F20: // Cut key on Sun keyboards - cut(); - break; - case Key_Direction_L: - if ( doc->textFormat() == TQt::PlainText ) { - // change the whole doc - TQTextParagraph *p = doc->firstParagraph(); - while ( p ) { - p->setDirection( TQChar::DirL ); - p->setAlignment( TQt::AlignLeft ); - p->invalidate( 0 ); - p = p->next(); - } - } else { - if ( !cursor->paragraph() || cursor->paragraph()->direction() == TQChar::DirL ) - return; - cursor->paragraph()->setDirection( TQChar::DirL ); - if ( cursor->paragraph()->length() <= 1&& - ( (cursor->paragraph()->alignment() & (TQt::AlignLeft | TQt::AlignRight) ) != 0 ) ) - setAlignment( TQt::AlignLeft ); - } - repaintChanged(); - break; - case Key_Direction_R: - if ( doc->textFormat() == TQt::PlainText ) { - // change the whole doc - TQTextParagraph *p = doc->firstParagraph(); - while ( p ) { - p->setDirection( TQChar::DirR ); - p->setAlignment( TQt::AlignRight ); - p->invalidate( 0 ); - p = p->next(); - } - } else { - if ( !cursor->paragraph() || cursor->paragraph()->direction() == TQChar::DirR ) - return; - cursor->paragraph()->setDirection( TQChar::DirR ); - if ( cursor->paragraph()->length() <= 1&& - ( (cursor->paragraph()->alignment() & (TQt::AlignLeft | TQt::AlignRight) ) != 0 ) ) - setAlignment( TQt::AlignRight ); - } - repaintChanged(); - break; - default: { - if ( e->text().length() && - ( ( !( e->state() & ControlButton ) && -#ifndef Q_OS_MACX - !( e->state() & AltButton ) && -#endif - !( e->state() & MetaButton ) ) || - ( ( (e->state()&ControlButton) | AltButton ) == (ControlButton|AltButton) ) ) && - ( !e->ascii() || e->ascii() >= 32 || e->text() == "\t" ) ) { - clearUndoRedoInfo = FALSE; - if ( e->key() == Key_Tab ) { - if ( d->tabChangesFocus ) { - e->ignore(); - break; - } - if ( textFormat() == TQt::RichText && cursor->index() == 0 - && ( cursor->paragraph()->isListItem() || cursor->paragraph()->listDepth() ) ) { - clearUndoRedo(); - undoRedoInfo.type = UndoRedoInfo::Style; - undoRedoInfo.id = cursor->paragraph()->paragId(); - undoRedoInfo.eid = undoRedoInfo.id; - undoRedoInfo.styleInformation = TQTextStyleCommand::readStyleInformation( doc, undoRedoInfo.id, undoRedoInfo.eid ); - cursor->paragraph()->setListDepth( cursor->paragraph()->listDepth() +1 ); - clearUndoRedo(); - drawCursor( FALSE ); - repaintChanged(); - drawCursor( TRUE ); - break; - } - } else if ( e->key() == Key_BackTab ) { - if ( d->tabChangesFocus ) { - e->ignore(); - break; - } - } - - if ( ( autoFormatting() & AutoBulletList ) && - textFormat() == TQt::RichText && cursor->index() == 0 - && !cursor->paragraph()->isListItem() - && ( e->text()[0] == '-' || e->text()[0] == '*' ) ) { - clearUndoRedo(); - undoRedoInfo.type = UndoRedoInfo::Style; - undoRedoInfo.id = cursor->paragraph()->paragId(); - undoRedoInfo.eid = undoRedoInfo.id; - undoRedoInfo.styleInformation = TQTextStyleCommand::readStyleInformation( doc, undoRedoInfo.id, undoRedoInfo.eid ); - setParagType( TQStyleSheetItem::DisplayListItem, TQStyleSheetItem::ListDisc ); - clearUndoRedo(); - drawCursor( FALSE ); - repaintChanged(); - drawCursor( TRUE ); - break; - } - if (overWrite && !cursor->atParagEnd() && !doc->hasSelection(TQTextDocument::Standard)) { - doKeyboardAction(ActionDelete); - clearUndoRedoInfo = FALSE; - } - TQString t = e->text(); -#ifdef TQ_WS_X11 - extern bool tqt_hebrew_keyboard_hack; - if ( tqt_hebrew_keyboard_hack ) { - // the X11 keyboard layout is broken and does not reverse - // braces correctly. This is a hack to get halfway correct - // behaviour - TQTextParagraph *p = cursor->paragraph(); - if ( p && p->string() && p->string()->isRightToLeft() ) { - TQChar *c = (TQChar *)t.unicode(); - int l = t.length(); - while( l-- ) { - if ( c->mirrored() ) - *c = c->mirroredChar(); - c++; - } - } - } -#endif - insert( t, TRUE, FALSE ); - break; - } else if ( e->state() & ControlButton ) { - switch ( e->key() ) { - case Key_C: case Key_F16: // Copy key on Sun keyboards - copy(); - break; - case Key_V: - paste(); - break; - case Key_X: - cut(); - break; - case Key_I: case Key_T: case Key_Tab: - if ( !d->tabChangesFocus ) - indent(); - break; - case Key_A: -#if defined(TQ_WS_X11) - moveCursor( MoveLineStart, e->state() & ShiftButton ); -#else - selectAll( TRUE ); -#endif - break; - case Key_B: - moveCursor( MoveBackward, e->state() & ShiftButton ); - break; - case Key_F: - moveCursor( MoveForward, e->state() & ShiftButton ); - break; - case Key_D: - if ( doc->hasSelection( TQTextDocument::Standard ) ) { - removeSelectedText(); - break; - } - doKeyboardAction( ActionDelete ); - clearUndoRedoInfo = FALSE; - break; - case Key_H: - if ( doc->hasSelection( TQTextDocument::Standard ) ) { - removeSelectedText(); - break; - } - if ( !cursor->paragraph()->prev() && - cursor->atParagStart() ) - break; - - doKeyboardAction( ActionBackspace ); - clearUndoRedoInfo = FALSE; - break; - case Key_E: - moveCursor( MoveLineEnd, e->state() & ShiftButton ); - break; - case Key_N: - moveCursor( MoveDown, e->state() & ShiftButton ); - break; - case Key_P: - moveCursor( MoveUp, e->state() & ShiftButton ); - break; - case Key_Z: - if(e->state() & ShiftButton) - redo(); - else - undo(); - break; - case Key_Y: - redo(); - break; - case Key_K: - doKeyboardAction( ActionKill ); - break; -#if defined(TQ_WS_WIN) - case Key_Insert: - copy(); - break; - case Key_Delete: - del(); - break; -#endif - default: - unknownKey = FALSE; - break; - } - } else { - unknownKey = TRUE; - } - } - } - - emit cursorPositionChanged( cursor ); - emit cursorPositionChanged( cursor->paragraph()->paragId(), cursor->index() ); - if ( clearUndoRedoInfo ) - clearUndoRedo(); - changeIntervalTimer->start( 100, TRUE ); - if ( unknownKey ) - e->ignore(); -} - -/*! - This function is not intended as polymorphic usage. Just a shared code - fragment that calls TQWidget::sendMouseEventToInputContext() easily for this - class. - */ -bool TQTextEdit::sendMouseEventToInputContext( TQMouseEvent *e ) -{ -#ifndef TQT_NO_IM - if ( d->composeMode() ) { - TQTextCursor c( doc ); - if ( c.place( e->pos(), doc->firstParagraph(), FALSE, FALSE, FALSE ) ) { - int mousePos = c.index() - d->preeditStart; - if ( cursor->globalY() == c.globalY() && - mousePos >= 0 && mousePos < d->preeditLength ) { - TQWidget::sendMouseEventToInputContext( mousePos, e->type(), - e->button(), e->state() ); - } - } else if ( e->type() != TQEvent::MouseMove ) { - // send button events on out of preedit - TQWidget::sendMouseEventToInputContext( -1, e->type(), - e->button(), e->state() ); - } - return TRUE; - } -#endif - return FALSE; -} - - -/*! - \reimp -*/ -void TQTextEdit::imStartEvent( TQIMEvent *e ) -{ - if ( isReadOnly() ) { - e->ignore(); - return; - } - - if ( hasSelectedText() ) - removeSelectedText(); - d->preeditStart = cursor->index(); - clearUndoRedo(); - undoRedoInfo.type = UndoRedoInfo::IME; -} - -/*! - \reimp -*/ -void TQTextEdit::imComposeEvent( TQIMEvent *e ) -{ - if ( isReadOnly() ) { - e->ignore(); - return; - } - - doc->removeSelection( TQTextDocument::IMCompositionText ); - doc->removeSelection( TQTextDocument::IMSelectionText ); - - if ( d->composeMode() && cursor->paragraph() ) - cursor->paragraph()->remove( d->preeditStart, d->preeditLength ); - cursor->setIndex( d->preeditStart ); - d->preeditLength = e->text().length(); - - int sellen = e->selectionLength(); - uint insertionFlags = CheckNewLines | RemoveSelected | AsIMCompositionText; - if ( sellen > 0 ) { - insertionFlags |= WithIMSelection; - } - insert( e->text(), insertionFlags ); - // insert can trigger an imEnd event as it emits a textChanged signal, so better - // be careful - if(d->preeditStart != -1) { - cursor->setIndex( d->preeditStart + d->preeditLength ); - TQTextCursor c = *cursor; - cursor->setIndex( d->preeditStart ); - doc->setSelectionStart( TQTextDocument::IMCompositionText, *cursor ); - doc->setSelectionEnd( TQTextDocument::IMCompositionText, c ); - - cursor->setIndex( d->preeditStart + e->cursorPos() ); - - if ( sellen > 0 ) { - cursor->setIndex( d->preeditStart + e->cursorPos() + sellen ); - c = *cursor; - cursor->setIndex( d->preeditStart + e->cursorPos() ); - doc->setSelectionStart( TQTextDocument::IMSelectionText, *cursor ); - doc->setSelectionEnd( TQTextDocument::IMSelectionText, c ); -#if 0 - // Disabled for Asian input method that shows candidate - // window. This behavior is same as TQt/E 2.3.7 which supports - // Asian input methods. Asian input methods need start point - // of IM selection text to place candidate window as adjacent - // to the selection text. - cursor->setIndex( d->preeditStart + d->preeditLength ); -#endif - } - } - - updateMicroFocusHint(); - repaintChanged(); -} - -/*! - \reimp -*/ -void TQTextEdit::imEndEvent( TQIMEvent *e ) -{ - if ( isReadOnly() ) { - e->ignore(); - return; - } - - doc->removeSelection( TQTextDocument::IMCompositionText ); - doc->removeSelection( TQTextDocument::IMSelectionText ); - - if (undoRedoInfo.type == UndoRedoInfo::IME) - undoRedoInfo.type = UndoRedoInfo::Invalid; - - if ( d->composeMode() && cursor->paragraph() ) - cursor->paragraph()->remove( d->preeditStart, d->preeditLength ); - if ( d->preeditStart >= 0 ) { - cursor->setIndex( d->preeditStart ); - //TODO: TQt 4 we should use the new virtual insert function - insert( e->text(), FALSE ); - } - d->preeditStart = d->preeditLength = -1; - - repaintChanged(); -} - - -static bool qtextedit_ignore_readonly = FALSE; - -/*! - Executes keyboard action \a action. This is normally called by a - key event handler. -*/ - -void TQTextEdit::doKeyboardAction( KeyboardAction action ) -{ - if ( isReadOnly() && !qtextedit_ignore_readonly ) - return; - - if ( cursor->nestedDepth() != 0 ) // #### for 3.0, disable editing of tables as this is not advanced enough - return; - - lastFormatted = cursor->paragraph(); - drawCursor( FALSE ); - bool doUpdateCurrentFormat = TRUE; - - switch ( action ) { - case ActionWordDelete: - case ActionDelete: - if ( action == ActionDelete && !cursor->atParagEnd() ) { - if ( undoEnabled ) { - checkUndoRedoInfo( UndoRedoInfo::Delete ); - if ( !undoRedoInfo.valid() ) { - undoRedoInfo.id = cursor->paragraph()->paragId(); - undoRedoInfo.index = cursor->index(); - undoRedoInfo.d->text = TQString::null; - } - int idx = cursor->index(); - do { - undoRedoInfo.d->text.insert( undoRedoInfo.d->text.length(), cursor->paragraph()->at( idx++ ), TRUE ); - } while ( !cursor->paragraph()->string()->validCursorPosition( idx ) ); - } - cursor->remove(); - } else { - clearUndoRedo(); - doc->setSelectionStart( TQTextDocument::Temp, *cursor ); - if ( action == ActionWordDelete && !cursor->atParagEnd() ) { - cursor->gotoNextWord(); - } else { - cursor->gotoNextLetter(); - } - doc->setSelectionEnd( TQTextDocument::Temp, *cursor ); - removeSelectedText( TQTextDocument::Temp ); - } - break; - case ActionWordBackspace: - case ActionBackspace: - if ( textFormat() == TQt::RichText - && (cursor->paragraph()->isListItem() - || cursor->paragraph()->listDepth() ) - && cursor->index() == 0 ) { - if ( undoEnabled ) { - clearUndoRedo(); - undoRedoInfo.type = UndoRedoInfo::Style; - undoRedoInfo.id = cursor->paragraph()->paragId(); - undoRedoInfo.eid = undoRedoInfo.id; - undoRedoInfo.styleInformation = TQTextStyleCommand::readStyleInformation( doc, undoRedoInfo.id, undoRedoInfo.eid ); - } - int ldepth = cursor->paragraph()->listDepth(); - if ( cursor->paragraph()->isListItem() && ldepth == 1 ) { - cursor->paragraph()->setListItem( FALSE ); - } else if ( TQMAX( ldepth, 1 ) == 1 ) { - cursor->paragraph()->setListItem( FALSE ); - cursor->paragraph()->setListDepth( 0 ); - } else { - cursor->paragraph()->setListDepth( ldepth - 1 ); - } - clearUndoRedo(); - lastFormatted = cursor->paragraph(); - repaintChanged(); - drawCursor( TRUE ); - return; - } - - if ( action == ActionBackspace && !cursor->atParagStart() ) { - if ( undoEnabled ) { - checkUndoRedoInfo( UndoRedoInfo::Delete ); - if ( !undoRedoInfo.valid() ) { - undoRedoInfo.id = cursor->paragraph()->paragId(); - undoRedoInfo.index = cursor->index(); - undoRedoInfo.d->text = TQString::null; - } - undoRedoInfo.d->text.insert( 0, cursor->paragraph()->at( cursor->index()-1 ), TRUE ); - undoRedoInfo.index = cursor->index()-1; - } - cursor->removePreviousChar(); - lastFormatted = cursor->paragraph(); - } else if ( cursor->paragraph()->prev() - || (action == ActionWordBackspace - && !cursor->atParagStart()) ) { - clearUndoRedo(); - doc->setSelectionStart( TQTextDocument::Temp, *cursor ); - if ( action == ActionWordBackspace && !cursor->atParagStart() ) { - cursor->gotoPreviousWord(); - } else { - cursor->gotoPreviousLetter(); - } - doc->setSelectionEnd( TQTextDocument::Temp, *cursor ); - removeSelectedText( TQTextDocument::Temp ); - } - break; - case ActionReturn: - if ( undoEnabled ) { - checkUndoRedoInfo( UndoRedoInfo::Return ); - if ( !undoRedoInfo.valid() ) { - undoRedoInfo.id = cursor->paragraph()->paragId(); - undoRedoInfo.index = cursor->index(); - undoRedoInfo.d->text = TQString::null; - } - undoRedoInfo.d->text += "\n"; - } - cursor->splitAndInsertEmptyParagraph(); - if ( cursor->paragraph()->prev() ) { - lastFormatted = cursor->paragraph()->prev(); - lastFormatted->invalidate( 0 ); - } - doUpdateCurrentFormat = FALSE; - break; - case ActionKill: - clearUndoRedo(); - doc->setSelectionStart( TQTextDocument::Temp, *cursor ); - if ( cursor->atParagEnd() ) - cursor->gotoNextLetter(); - else - cursor->setIndex( cursor->paragraph()->length() - 1 ); - doc->setSelectionEnd( TQTextDocument::Temp, *cursor ); - removeSelectedText( TQTextDocument::Temp ); - break; - } - - formatMore(); - repaintChanged(); - ensureCursorVisible(); - drawCursor( TRUE ); - updateMicroFocusHint(); - if ( doUpdateCurrentFormat ) - updateCurrentFormat(); - setModified(); - emit textChanged(); -} - -void TQTextEdit::readFormats( TQTextCursor &c1, TQTextCursor &c2, TQTextString &text, bool fillStyles ) -{ -#ifndef TQT_NO_DATASTREAM - TQDataStream styleStream( undoRedoInfo.styleInformation, IO_WriteOnly ); -#endif - c2.restoreState(); - c1.restoreState(); - int lastIndex = text.length(); - if ( c1.paragraph() == c2.paragraph() ) { - for ( int i = c1.index(); i < c2.index(); ++i ) - text.insert( lastIndex + i - c1.index(), c1.paragraph()->at( i ), TRUE ); -#ifndef TQT_NO_DATASTREAM - if ( fillStyles ) { - styleStream << (int) 1; - c1.paragraph()->writeStyleInformation( styleStream ); - } -#endif - } else { - int i; - for ( i = c1.index(); i < c1.paragraph()->length()-1; ++i ) - text.insert( lastIndex++, c1.paragraph()->at( i ), TRUE ); - int num = 2; // start and end, being different - text += "\n"; lastIndex++; - - if (c1.paragraph()->next() != c2.paragraph()) { - num += text.appendParagraphs(c1.paragraph()->next(), c2.paragraph()); - lastIndex = text.length(); - } - - for ( i = 0; i < c2.index(); ++i ) - text.insert( i + lastIndex, c2.paragraph()->at( i ), TRUE ); -#ifndef TQT_NO_DATASTREAM - if ( fillStyles ) { - styleStream << num; - for ( TQTextParagraph *p = c1.paragraph(); --num >= 0; p = p->next() ) - p->writeStyleInformation( styleStream ); - } -#endif - } -} - -/*! - Removes the selection \a selNum (by default 0). This does not - remove the selected text. - - \sa removeSelectedText() -*/ - -void TQTextEdit::removeSelection( int selNum ) -{ - doc->removeSelection( selNum ); - repaintChanged(); -} - -/*! - Deletes the text of selection \a selNum (by default, the default - selection, 0). If there is no selected text nothing happens. - - \sa selectedText removeSelection() -*/ - -void TQTextEdit::removeSelectedText( int selNum ) -{ - if(selNum != 0) - resetInputContext(); - - TQTextCursor c1 = doc->selectionStartCursor( selNum ); - c1.restoreState(); - TQTextCursor c2 = doc->selectionEndCursor( selNum ); - c2.restoreState(); - - // ### no support for editing tables yet, plus security for broken selections - if ( c1.nestedDepth() || c2.nestedDepth() ) - return; - - for ( int i = 0; i < (int)doc->numSelections(); ++i ) { - if ( i == selNum ) - continue; - doc->removeSelection( i ); - } - - drawCursor( FALSE ); - if ( undoEnabled ) { - checkUndoRedoInfo( UndoRedoInfo::RemoveSelected ); - if ( !undoRedoInfo.valid() ) { - doc->selectionStart( selNum, undoRedoInfo.id, undoRedoInfo.index ); - undoRedoInfo.d->text = TQString::null; - } - readFormats( c1, c2, undoRedoInfo.d->text, TRUE ); - } - - doc->removeSelectedText( selNum, cursor ); - if ( cursor->isValid() ) { - lastFormatted = 0; // make sync a noop - ensureCursorVisible(); - lastFormatted = cursor->paragraph(); - formatMore(); - repaintContents( FALSE ); - ensureCursorVisible(); - drawCursor( TRUE ); - clearUndoRedo(); -#if defined(TQ_WS_WIN) - // there seems to be a problem with repainting or erasing the area - // of the scrollview which is not the contents on windows - if ( contentsHeight() < visibleHeight() ) - viewport()->repaint( 0, contentsHeight(), visibleWidth(), visibleHeight() - contentsHeight(), TRUE ); -#endif -#ifndef TQT_NO_CURSOR - viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); -#endif - updateMicroFocusHint(); - } else { - delete cursor; - cursor = new TQTextCursor( doc ); - drawCursor( TRUE ); - repaintContents( TRUE ); - } - setModified(); - emit textChanged(); - emit selectionChanged(); - emit copyAvailable( doc->hasSelection( TQTextDocument::Standard ) ); -} - -/*! - Moves the text cursor according to \a action. This is normally - used by some key event handler. \a select specifies whether the - text between the current cursor position and the new position - should be selected. -*/ - -void TQTextEdit::moveCursor( CursorAction action, bool select ) -{ -#ifdef QT_TEXTEDIT_OPTIMIZATION - if ( d->optimMode ) - return; -#endif -#ifdef TQ_WS_MACX - TQTextCursor c1 = *cursor; - TQTextCursor c2; -#endif - drawCursor( FALSE ); - if ( select ) { - if ( !doc->hasSelection( TQTextDocument::Standard ) ) - doc->setSelectionStart( TQTextDocument::Standard, *cursor ); - moveCursor( action ); -#ifdef TQ_WS_MACX - c2 = *cursor; - if (c1 == c2) - if (action == MoveDown || action == MovePgDown) - moveCursor( MoveEnd ); - else if (action == MoveUp || action == MovePgUp) - moveCursor( MoveHome ); -#endif - if ( doc->setSelectionEnd( TQTextDocument::Standard, *cursor ) ) { - cursor->paragraph()->document()->nextDoubleBuffered = TRUE; - repaintChanged(); - } else { - drawCursor( TRUE ); - } - ensureCursorVisible(); - emit selectionChanged(); - emit copyAvailable( doc->hasSelection( TQTextDocument::Standard ) ); - } else { -#ifdef TQ_WS_MACX - TQTextCursor cStart = doc->selectionStartCursor( TQTextDocument::Standard ); - TQTextCursor cEnd = doc->selectionEndCursor( TQTextDocument::Standard ); - bool redraw = doc->removeSelection( TQTextDocument::Standard ); - if (redraw && action == MoveDown) - *cursor = cEnd; - else if (redraw && action == MoveUp) - *cursor = cStart; - if (redraw && action == MoveForward) - *cursor = cEnd; - else if (redraw && action == MoveBackward) - *cursor = cStart; - else - moveCursor( action ); - c2 = *cursor; - if (c1 == c2) - if (action == MoveDown) - moveCursor( MoveEnd ); - else if (action == MoveUp) - moveCursor( MoveHome ); -#else - bool redraw = doc->removeSelection( TQTextDocument::Standard ); - moveCursor( action ); -#endif - if ( !redraw ) { - ensureCursorVisible(); - drawCursor( TRUE ); - } else { - cursor->paragraph()->document()->nextDoubleBuffered = TRUE; - repaintChanged(); - ensureCursorVisible(); - drawCursor( TRUE ); -#ifndef TQT_NO_CURSOR - viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); -#endif - } - if ( redraw ) { - emit copyAvailable( doc->hasSelection( TQTextDocument::Standard ) ); - emit selectionChanged(); - } - } - - drawCursor( TRUE ); - updateCurrentFormat(); - updateMicroFocusHint(); -} - -/*! - \overload -*/ - -void TQTextEdit::moveCursor( CursorAction action ) -{ - resetInputContext(); - switch ( action ) { - case MoveBackward: - cursor->gotoPreviousLetter(); - break; - case MoveWordBackward: - cursor->gotoPreviousWord(); - break; - case MoveForward: - cursor->gotoNextLetter(); - break; - case MoveWordForward: - cursor->gotoNextWord(); - break; - case MoveUp: - cursor->gotoUp(); - break; - case MovePgUp: - cursor->gotoPageUp( visibleHeight() ); - break; - case MoveDown: - cursor->gotoDown(); - break; - case MovePgDown: - cursor->gotoPageDown( visibleHeight() ); - break; - case MoveLineStart: - cursor->gotoLineStart(); - break; - case MoveHome: - cursor->gotoHome(); - break; - case MoveLineEnd: - cursor->gotoLineEnd(); - break; - case MoveEnd: - ensureFormatted( doc->lastParagraph() ); - cursor->gotoEnd(); - break; - } - updateMicroFocusHint(); - updateCurrentFormat(); -} - -/*! - \reimp -*/ - -void TQTextEdit::resizeEvent( TQResizeEvent *e ) -{ - TQScrollView::resizeEvent( e ); - if ( doc->visibleWidth() == 0 ) - doResize(); -} - -/*! - \reimp -*/ - -void TQTextEdit::viewportResizeEvent( TQResizeEvent *e ) -{ - TQScrollView::viewportResizeEvent( e ); - if ( e->oldSize().width() != e->size().width() ) { - bool stayAtBottom = e->oldSize().height() != e->size().height() && - contentsY() > 0 && contentsY() >= doc->height() - e->oldSize().height(); - doResize(); - if ( stayAtBottom ) - scrollToBottom(); - } -} - -/*! - Ensures that the cursor is visible by scrolling the text edit if - necessary. - - \sa setCursorPosition() -*/ - -void TQTextEdit::ensureCursorVisible() -{ - // Not visible or the user is draging the window, so don't position to caret yet - if ( !isUpdatesEnabled() || !isVisible() || isHorizontalSliderPressed() || isVerticalSliderPressed() ) { - d->ensureCursorVisibleInShowEvent = TRUE; - return; - } - sync(); - TQTextStringChar *chr = cursor->paragraph()->at( cursor->index() ); - int h = cursor->paragraph()->lineHeightOfChar( cursor->index() ); - int x = cursor->paragraph()->rect().x() + chr->x + cursor->offsetX(); - int y = 0; int dummy; - cursor->paragraph()->lineHeightOfChar( cursor->index(), &dummy, &y ); - y += cursor->paragraph()->rect().y() + cursor->offsetY(); - int w = 1; - ensureVisible( x, y + h / 2, w, h / 2 + 2 ); -} - -/*! - \internal -*/ -void TQTextEdit::sliderReleased() -{ - if ( d->ensureCursorVisibleInShowEvent && isVisible() ) { - d->ensureCursorVisibleInShowEvent = FALSE; - ensureCursorVisible(); - } -} - -/*! - \internal -*/ -void TQTextEdit::drawCursor( bool visible ) -{ - if ( !isUpdatesEnabled() || - !viewport()->isUpdatesEnabled() || - !cursor->paragraph() || - !cursor->paragraph()->isValid() || - ( !style().styleHint( TQStyle::SH_BlinkCursorWhenTextSelected ) && - ( d->optimMode ? optimHasSelection() : doc->hasSelection( TQTextDocument::Standard, TRUE ))) || - ( visible && !hasFocus() && !viewport()->hasFocus() && !inDnD ) || - doc->hasSelection( TQTextDocument::IMSelectionText ) || - isReadOnly() ) - return; - - // Asian users regard selection text as cursor on candidate - // selection phase of input method, so ordinary cursor should be - // invisible if IM selection text exists. - if ( doc->hasSelection( TQTextDocument::IMSelectionText ) ) { - visible = FALSE; - } - - TQPainter p( viewport() ); - TQRect r( cursor->topParagraph()->rect() ); - cursor->paragraph()->setChanged( TRUE ); - p.translate( -contentsX() + cursor->totalOffsetX(), -contentsY() + cursor->totalOffsetY() ); - TQPixmap *pix = 0; - TQColorGroup cg( colorGroup() ); - const TQColorGroup::ColorRole backRole = TQPalette::backgroundRoleFromMode(backgroundMode()); - if ( cursor->paragraph()->background() ) - cg.setBrush( backRole, *cursor->paragraph()->background() ); - else if ( doc->paper() ) - cg.setBrush( backRole, *doc->paper() ); - p.setBrushOrigin( -contentsX(), -contentsY() ); - cursor->paragraph()->document()->nextDoubleBuffered = TRUE; - if ( !cursor->nestedDepth() ) { - int h = cursor->paragraph()->lineHeightOfChar( cursor->index() ); - int dist = 5; - if ( ( cursor->paragraph()->alignment() & TQt::AlignJustify ) == TQt::AlignJustify ) - dist = 50; - int x = r.x() - cursor->totalOffsetX() + cursor->x() - dist; - x = TQMAX( x, 0 ); - p.setClipRect( TQRect( x - contentsX(), - r.y() - cursor->totalOffsetY() + cursor->y() - contentsY(), 2 * dist, h ) ); - doc->drawParagraph( &p, cursor->paragraph(), x, - r.y() - cursor->totalOffsetY() + cursor->y(), 2 * dist, h, pix, cg, visible, cursor ); - } else { - doc->drawParagraph( &p, cursor->paragraph(), r.x() - cursor->totalOffsetX(), - r.y() - cursor->totalOffsetY(), r.width(), r.height(), - pix, cg, visible, cursor ); - } - cursorVisible = visible; -} - -enum { - IdUndo = 0, - IdRedo = 1, - IdCut = 2, - IdCopy = 3, - IdPaste = 4, - IdClear = 5, - IdSelectAll = 6 -}; - -/*! - \reimp -*/ -#ifndef TQT_NO_WHEELEVENT -void TQTextEdit::contentsWheelEvent( TQWheelEvent *e ) -{ - if ( isReadOnly() ) { - if ( e->state() & ControlButton ) { - if ( e->delta() > 0 ) - zoomOut(); - else if ( e->delta() < 0 ) - zoomIn(); - return; - } - } - TQScrollView::contentsWheelEvent( e ); -} -#endif - -/*! - \reimp -*/ - -void TQTextEdit::contentsMousePressEvent( TQMouseEvent *e ) -{ -#ifdef QT_TEXTEDIT_OPTIMIZATION - if ( d->optimMode ) { - optimMousePressEvent( e ); - return; - } -#endif - - if ( sendMouseEventToInputContext( e ) ) - return; - - if ( d->trippleClickTimer->isActive() && - ( e->globalPos() - d->trippleClickPoint ).manhattanLength() < - TQApplication::startDragDistance() ) { - TQTextCursor c1 = *cursor; - TQTextCursor c2 = *cursor; - c1.gotoLineStart(); - c2.gotoLineEnd(); - doc->setSelectionStart( TQTextDocument::Standard, c1 ); - doc->setSelectionEnd( TQTextDocument::Standard, c2 ); - *cursor = c2; - repaintChanged(); - mousePressed = TRUE; - return; - } - - clearUndoRedo(); - TQTextCursor oldCursor = *cursor; - TQTextCursor c = *cursor; - mousePos = e->pos(); - mightStartDrag = FALSE; - pressedLink = TQString::null; - d->pressedName = TQString::null; - - if ( e->button() == LeftButton ) { - mousePressed = TRUE; - drawCursor( FALSE ); - placeCursor( e->pos() ); - ensureCursorVisible(); - - if ( isReadOnly() && linksEnabled() ) { - TQTextCursor c = *cursor; - placeCursor( e->pos(), &c, TRUE ); - if ( c.paragraph() && c.paragraph()->at( c.index() ) && - c.paragraph()->at( c.index() )->isAnchor() ) { - pressedLink = c.paragraph()->at( c.index() )->anchorHref(); - d->pressedName = c.paragraph()->at( c.index() )->anchorName(); - } - } - -#ifndef TQT_NO_DRAGANDDROP - if ( doc->inSelection( TQTextDocument::Standard, e->pos() ) ) { - mightStartDrag = TRUE; - drawCursor( TRUE ); - dragStartTimer->start( TQApplication::startDragTime(), TRUE ); - dragStartPos = e->pos(); - return; - } -#endif - - bool redraw = FALSE; - if ( doc->hasSelection( TQTextDocument::Standard ) ) { - if ( !( e->state() & ShiftButton ) ) { - redraw = doc->removeSelection( TQTextDocument::Standard ); - doc->setSelectionStart( TQTextDocument::Standard, *cursor ); - } else { - redraw = doc->setSelectionEnd( TQTextDocument::Standard, *cursor ) || redraw; - } - } else { - if ( isReadOnly() || !( e->state() & ShiftButton ) ) { - doc->setSelectionStart( TQTextDocument::Standard, *cursor ); - } else { - doc->setSelectionStart( TQTextDocument::Standard, c ); - redraw = doc->setSelectionEnd( TQTextDocument::Standard, *cursor ) || redraw; - } - } - - for ( int i = 1; i < doc->numSelections(); ++i ) // start with 1 as we don't want to remove the Standard-Selection - redraw = doc->removeSelection( i ) || redraw; - - if ( !redraw ) { - drawCursor( TRUE ); - } else { - repaintChanged(); -#ifndef TQT_NO_CURSOR - viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); -#endif - } - } else if ( e->button() == MidButton ) { - bool redraw = doc->removeSelection( TQTextDocument::Standard ); - if ( !redraw ) { - drawCursor( TRUE ); - } else { - repaintChanged(); -#ifndef TQT_NO_CURSOR - viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); -#endif - } - } - - if ( *cursor != oldCursor ) - updateCurrentFormat(); -} - -/*! - \reimp -*/ - -void TQTextEdit::contentsMouseMoveEvent( TQMouseEvent *e ) -{ -#ifdef QT_TEXTEDIT_OPTIMIZATION - if ( d->optimMode ) { - optimMouseMoveEvent( e ); - return; - } -#endif - if ( sendMouseEventToInputContext( e ) ) { - // don't return from here to avoid cursor vanishing - } else if ( mousePressed ) { -#ifndef TQT_NO_DRAGANDDROP - if ( mightStartDrag ) { - dragStartTimer->stop(); - if ( ( e->pos() - dragStartPos ).manhattanLength() > TQApplication::startDragDistance() ) { - TQGuardedPtr<TQTextEdit> guard( this ); - startDrag(); - if (guard.isNull()) // we got deleted during the dnd - return; - } -#ifndef TQT_NO_CURSOR - if ( !isReadOnly() ) - viewport()->setCursor( ibeamCursor ); -#endif - return; - } -#endif - mousePos = e->pos(); - handleMouseMove( mousePos ); - oldMousePos = mousePos; - } - -#ifndef TQT_NO_CURSOR - if ( !isReadOnly() && !mousePressed ) { - if ( doc->hasSelection( TQTextDocument::Standard ) && doc->inSelection( TQTextDocument::Standard, e->pos() ) ) - viewport()->setCursor( arrowCursor ); - else - viewport()->setCursor( ibeamCursor ); - } -#endif - updateCursor( e->pos() ); -} - -void TQTextEdit::copyToClipboard() -{ -#ifndef TQT_NO_CLIPBOARD - if (TQApplication::clipboard()->supportsSelection()) { - d->clipboard_mode = TQClipboard::Selection; - - // don't listen to selection changes - disconnect( TQApplication::clipboard(), TQ_SIGNAL(selectionChanged()), this, 0); - copy(); - // listen to selection changes - connect( TQApplication::clipboard(), TQ_SIGNAL(selectionChanged()), - this, TQ_SLOT(clipboardChanged()) ); - - d->clipboard_mode = TQClipboard::Clipboard; - } -#endif -} - -/*! - \reimp -*/ - -void TQTextEdit::contentsMouseReleaseEvent( TQMouseEvent * e ) -{ - if ( !inDoubleClick && !d->composeMode() ) { // could be the release of a dblclick - int para = 0; - int index = charAt( e->pos(), ¶ ); - emit clicked( para, index ); - } -#ifdef QT_TEXTEDIT_OPTIMIZATION - if ( d->optimMode ) { - optimMouseReleaseEvent( e ); - return; - } -#endif - if ( sendMouseEventToInputContext( e ) ) - return; - TQTextCursor oldCursor = *cursor; - if ( scrollTimer->isActive() ) - scrollTimer->stop(); -#ifndef TQT_NO_DRAGANDDROP - if ( dragStartTimer->isActive() ) - dragStartTimer->stop(); - if ( mightStartDrag ) { - selectAll( FALSE ); - mousePressed = FALSE; - } -#endif - bool mouseWasPressed = mousePressed; - if ( mousePressed ) { - mousePressed = FALSE; - copyToClipboard(); - } -#ifndef TQT_NO_CLIPBOARD - else if ( e->button() == MidButton && !isReadOnly() ) { - // only do middle-click pasting on systems that have selections (ie. X11) - if (TQApplication::clipboard()->supportsSelection()) { - drawCursor( FALSE ); - placeCursor( e->pos() ); - ensureCursorVisible(); - doc->setSelectionStart( TQTextDocument::Standard, oldCursor ); - bool redraw = FALSE; - if ( doc->hasSelection( TQTextDocument::Standard ) ) { - redraw = doc->removeSelection( TQTextDocument::Standard ); - doc->setSelectionStart( TQTextDocument::Standard, *cursor ); - } else { - doc->setSelectionStart( TQTextDocument::Standard, *cursor ); - } - // start with 1 as we don't want to remove the Standard-Selection - for ( int i = 1; i < doc->numSelections(); ++i ) - redraw = doc->removeSelection( i ) || redraw; - if ( !redraw ) { - drawCursor( TRUE ); - } else { - repaintChanged(); -#ifndef TQT_NO_CURSOR - viewport()->setCursor( ibeamCursor ); -#endif - } - d->clipboard_mode = TQClipboard::Selection; - paste(); - d->clipboard_mode = TQClipboard::Clipboard; - } - } -#endif - emit cursorPositionChanged( cursor ); - emit cursorPositionChanged( cursor->paragraph()->paragId(), cursor->index() ); - if ( oldCursor != *cursor ) - updateCurrentFormat(); - inDoubleClick = FALSE; - -#ifndef TQT_NO_NETWORKPROTOCOL - if ( ( (!onLink.isEmpty() && onLink == pressedLink) - || (!d->onName.isEmpty() && d->onName == d->pressedName)) - && linksEnabled() && mouseWasPressed ) { - if (!onLink.isEmpty()) { - TQUrl u( doc->context(), onLink, TRUE ); - emitLinkClicked( u.toString( FALSE, FALSE ) ); - } - if (::tqt_cast<TQTextBrowser*>(this)) { // change for 4.0 - TQConnectionList *clist = receivers( - "anchorClicked(const TQString&,const TQString&)"); - if (!signalsBlocked() && clist) { - TQUObject o[3]; - static_QUType_TQString.set(o+1, d->onName); - static_QUType_TQString.set(o+2, onLink); - activate_signal( clist, o); - } - } - - // emitting linkClicked() may result in that the cursor winds - // up hovering over a different valid link - check this and - // set the appropriate cursor shape - updateCursor( e->pos() ); - } -#endif - drawCursor( TRUE ); - if ( !doc->hasSelection( TQTextDocument::Standard, TRUE ) ) - doc->removeSelection( TQTextDocument::Standard ); - - emit copyAvailable( doc->hasSelection( TQTextDocument::Standard ) ); - emit selectionChanged(); -} - -/*! - \reimp -*/ - -void TQTextEdit::contentsMouseDoubleClickEvent( TQMouseEvent * e ) -{ - if ( e->button() != TQt::LeftButton && !d->composeMode() ) { - e->ignore(); - return; - } - int para = 0; - int index = charAt( e->pos(), ¶ ); -#ifdef QT_TEXTEDIT_OPTIMIZATION - if ( d->optimMode ) { - TQString str = d->od->lines[ LOGOFFSET(para) ]; - int startIdx = index, endIdx = index, i; - if ( !str[ index ].isSpace() ) { - i = startIdx; - // find start of word - while ( i >= 0 && !str[ i ].isSpace() ) { - startIdx = i--; - } - i = endIdx; - // find end of word.. - while ( (uint) i < str.length() && !str[ i ].isSpace() ) { - endIdx = ++i; - } - // ..and start of next - while ( (uint) i < str.length() && str[ i ].isSpace() ) { - endIdx = ++i; - } - optimSetSelection( para, startIdx, para, endIdx ); - repaintContents( FALSE ); - } - } else -#endif - { - if ( sendMouseEventToInputContext( e ) ) - return; - - TQTextCursor c1 = *cursor; - TQTextCursor c2 = *cursor; -#if defined(Q_OS_MAC) - TQTextParagraph *para = cursor->paragraph(); - if ( cursor->isValid() ) { - if ( para->at( cursor->index() )->c.isLetterOrNumber() ) { - while ( c1.index() > 0 && - c1.paragraph()->at( c1.index()-1 )->c.isLetterOrNumber() ) - c1.gotoPreviousLetter(); - while ( c2.paragraph()->at( c2.index() )->c.isLetterOrNumber() && - !c2.atParagEnd() ) - c2.gotoNextLetter(); - } else if ( para->at( cursor->index() )->c.isSpace() ) { - while ( c1.index() > 0 && - c1.paragraph()->at( c1.index()-1 )->c.isSpace() ) - c1.gotoPreviousLetter(); - while ( c2.paragraph()->at( c2.index() )->c.isSpace() && - !c2.atParagEnd() ) - c2.gotoNextLetter(); - } else if ( !c2.atParagEnd() ) { - c2.gotoNextLetter(); - } - } -#else - if ( cursor->index() > 0 && !cursor->paragraph()->at( cursor->index()-1 )->c.isSpace() ) - c1.gotoPreviousWord(); - if ( !cursor->paragraph()->at( cursor->index() )->c.isSpace() && !cursor->atParagEnd() ) - c2.gotoNextWord(); -#endif - doc->setSelectionStart( TQTextDocument::Standard, c1 ); - doc->setSelectionEnd( TQTextDocument::Standard, c2 ); - - *cursor = c2; - - repaintChanged(); - - d->trippleClickTimer->start( tqApp->doubleClickInterval(), TRUE ); - d->trippleClickPoint = e->globalPos(); - } - inDoubleClick = TRUE; - mousePressed = TRUE; - emit doubleClicked( para, index ); -} - -#ifndef TQT_NO_DRAGANDDROP - -/*! - \reimp -*/ - -void TQTextEdit::contentsDragEnterEvent( TQDragEnterEvent *e ) -{ - if ( isReadOnly() || !TQTextDrag::canDecode( e ) ) { - e->ignore(); - return; - } - e->acceptAction(); - inDnD = TRUE; -} - -/*! - \reimp -*/ - -void TQTextEdit::contentsDragMoveEvent( TQDragMoveEvent *e ) -{ - if ( isReadOnly() || !TQTextDrag::canDecode( e ) ) { - e->ignore(); - return; - } - drawCursor( FALSE ); - placeCursor( e->pos(), cursor ); - drawCursor( TRUE ); - e->acceptAction(); -} - -/*! - \reimp -*/ - -void TQTextEdit::contentsDragLeaveEvent( TQDragLeaveEvent * ) -{ - drawCursor( FALSE ); - inDnD = FALSE; -} - -/*! - \reimp -*/ - -void TQTextEdit::contentsDropEvent( TQDropEvent *e ) -{ - if ( isReadOnly() ) - return; - inDnD = FALSE; - e->acceptAction(); - bool intern = FALSE; - if ( TQRichTextDrag::canDecode( e ) ) { - bool hasSel = doc->hasSelection( TQTextDocument::Standard ); - bool internalDrag = e->source() == this || e->source() == viewport(); - int dropId, dropIndex; - TQTextCursor insertCursor = *cursor; - dropId = cursor->paragraph()->paragId(); - dropIndex = cursor->index(); - if ( hasSel && internalDrag ) { - TQTextCursor c1, c2; - int selStartId, selStartIndex; - int selEndId, selEndIndex; - c1 = doc->selectionStartCursor( TQTextDocument::Standard ); - c1.restoreState(); - c2 = doc->selectionEndCursor( TQTextDocument::Standard ); - c2.restoreState(); - selStartId = c1.paragraph()->paragId(); - selStartIndex = c1.index(); - selEndId = c2.paragraph()->paragId(); - selEndIndex = c2.index(); - if ( ( ( dropId > selStartId ) || - ( dropId == selStartId && dropIndex > selStartIndex ) ) && - ( ( dropId < selEndId ) || - ( dropId == selEndId && dropIndex <= selEndIndex ) ) ) - insertCursor = c1; - if ( dropId == selEndId && dropIndex > selEndIndex ) { - insertCursor = c1; - if ( selStartId == selEndId ) { - insertCursor.setIndex( dropIndex - - ( selEndIndex - selStartIndex ) ); - } else { - insertCursor.setIndex( dropIndex - selEndIndex + - selStartIndex ); - } - } - } - - if ( internalDrag && e->action() == TQDropEvent::Move ) { - removeSelectedText(); - intern = TRUE; - doc->removeSelection( TQTextDocument::Standard ); - } else { - doc->removeSelection( TQTextDocument::Standard ); -#ifndef TQT_NO_CURSOR - viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); -#endif - } - drawCursor( FALSE ); - cursor->setParagraph( insertCursor.paragraph() ); - cursor->setIndex( insertCursor.index() ); - drawCursor( TRUE ); - if ( !cursor->nestedDepth() ) { - TQString subType = "plain"; - if ( textFormat() != PlainText ) { - if ( e->provides( "application/x-qrichtext" ) ) - subType = "x-qrichtext"; - } -#ifndef TQT_NO_CLIPBOARD - pasteSubType( subType.latin1(), e ); -#endif - // emit appropriate signals. - emit selectionChanged(); - emit cursorPositionChanged( cursor ); - emit cursorPositionChanged( cursor->paragraph()->paragId(), cursor->index() ); - } else { - if ( intern ) - undo(); - e->ignore(); - } - } -} - -#endif - -/*! - \reimp -*/ -void TQTextEdit::contentsContextMenuEvent( TQContextMenuEvent *e ) -{ - e->accept(); -#ifndef TQT_NO_IM - if ( d->composeMode() ) - return; -#endif - - clearUndoRedo(); - mousePressed = FALSE; - -#ifndef TQT_NO_POPUPMENU - TQGuardedPtr<TQTextEdit> that = this; - TQGuardedPtr<TQPopupMenu> popup = createPopupMenu( e->pos() ); - if ( !popup ) - popup = createPopupMenu(); - if ( !popup ) - return; - - int r = popup->exec( e->globalPos() ); - delete popup; - if (!that) - return; - - if ( r == d->id[ IdClear ] ) - clear(); - else if ( r == d->id[ IdSelectAll ] ) { - selectAll(); -#ifndef TQT_NO_CLIPBOARD - // if the clipboard support selections, put the newly selected text into - // the clipboard - if (TQApplication::clipboard()->supportsSelection()) { - d->clipboard_mode = TQClipboard::Selection; - - // don't listen to selection changes - disconnect( TQApplication::clipboard(), TQ_SIGNAL(selectionChanged()), this, 0); - copy(); - // listen to selection changes - connect( TQApplication::clipboard(), TQ_SIGNAL(selectionChanged()), - this, TQ_SLOT(clipboardChanged()) ); - - d->clipboard_mode = TQClipboard::Clipboard; - } -#endif - } else if ( r == d->id[ IdUndo ] ) - undo(); - else if ( r == d->id[ IdRedo ] ) - redo(); -#ifndef TQT_NO_CLIPBOARD - else if ( r == d->id[ IdCut ] ) - cut(); - else if ( r == d->id[ IdCopy ] ) - copy(); - else if ( r == d->id[ IdPaste ] ) - paste(); -#endif -#endif -} - - -void TQTextEdit::autoScrollTimerDone() -{ - if ( mousePressed ) - handleMouseMove( viewportToContents( viewport()->mapFromGlobal( TQCursor::pos() ) ) ); -} - -void TQTextEdit::handleMouseMove( const TQPoint& pos ) -{ - if ( !mousePressed ) - return; - - if ( (!scrollTimer->isActive() && pos.y() < contentsY()) || pos.y() > contentsY() + visibleHeight() ) - scrollTimer->start( 100, FALSE ); - else if ( scrollTimer->isActive() && pos.y() >= contentsY() && pos.y() <= contentsY() + visibleHeight() ) - scrollTimer->stop(); - - drawCursor( FALSE ); - TQTextCursor oldCursor = *cursor; - - placeCursor( pos ); - - if ( inDoubleClick ) { - TQTextCursor cl = *cursor; - cl.gotoPreviousWord(); - TQTextCursor cr = *cursor; - cr.gotoNextWord(); - - int diff = TQABS( oldCursor.paragraph()->at( oldCursor.index() )->x - mousePos.x() ); - int ldiff = TQABS( cl.paragraph()->at( cl.index() )->x - mousePos.x() ); - int rdiff = TQABS( cr.paragraph()->at( cr.index() )->x - mousePos.x() ); - - - if ( cursor->paragraph()->lineStartOfChar( cursor->index() ) != - oldCursor.paragraph()->lineStartOfChar( oldCursor.index() ) ) - diff = 0xFFFFFF; - - if ( rdiff < diff && rdiff < ldiff ) - *cursor = cr; - else if ( ldiff < diff && ldiff < rdiff ) - *cursor = cl; - else - *cursor = oldCursor; - - } - ensureCursorVisible(); - - bool redraw = FALSE; - if ( doc->hasSelection( TQTextDocument::Standard ) ) { - redraw = doc->setSelectionEnd( TQTextDocument::Standard, *cursor ) || redraw; - } - - if ( !redraw ) { - drawCursor( TRUE ); - } else { - repaintChanged(); - drawCursor( TRUE ); - } - - if ( currentFormat && currentFormat->key() != cursor->paragraph()->at( cursor->index() )->format()->key() ) { - currentFormat->removeRef(); - currentFormat = doc->formatCollection()->format( cursor->paragraph()->at( cursor->index() )->format() ); - if ( currentFormat->isMisspelled() ) { - currentFormat->removeRef(); - currentFormat = doc->formatCollection()->format( currentFormat->font(), currentFormat->color() ); - } - emit currentFontChanged( currentFormat->font() ); - emit currentColorChanged( currentFormat->color() ); - emit currentVerticalAlignmentChanged( (VerticalAlignment)currentFormat->vAlign() ); - } - - if ( currentAlignment != cursor->paragraph()->alignment() ) { - currentAlignment = cursor->paragraph()->alignment(); - block_set_alignment = TRUE; - emit currentAlignmentChanged( currentAlignment ); - block_set_alignment = FALSE; - } -} - -/*! \internal */ - -void TQTextEdit::placeCursor( const TQPoint &pos, TQTextCursor *c, bool link ) -{ -#ifdef QT_TEXTEDIT_OPTIMIZATION - if ( d->optimMode ) - return; -#endif - if ( !c ) - c = cursor; - - resetInputContext(); - c->restoreState(); - TQTextParagraph *s = doc->firstParagraph(); - c->place( pos, s, link ); - updateMicroFocusHint(); -} - - -void TQTextEdit::updateMicroFocusHint() -{ - TQTextCursor c( *cursor ); -#if 0 - // Disabled for Asian input method that shows candidate - // window. This behavior is same as TQt/E 2.3.7 which supports - // Asian input methods. Asian input methods need start point of IM - // selection text to place candidate window as adjacent to the - // selection text. - if ( d->preeditStart != -1 ) { - c.setIndex( d->preeditStart ); - if(doc->hasSelection(TQTextDocument::IMSelectionText)) { - int para, index; - doc->selectionStart(TQTextDocument::IMSelectionText, para, index); - c.setIndex(index); - } - } -#endif - - if ( hasFocus() || viewport()->hasFocus() ) { - int h = c.paragraph()->lineHeightOfChar( cursor->index() ); - if ( !readOnly ) { - TQFont f = c.paragraph()->at( c.index() )->format()->font(); - setMicroFocusHint( c.x() - contentsX() + frameWidth(), - c.y() + cursor->paragraph()->rect().y() - contentsY() + frameWidth(), 0, h, TRUE, &f ); - } - } -} - - - -void TQTextEdit::formatMore() -{ - if ( !lastFormatted ) - return; - - int bottom = contentsHeight(); - int lastTop = -1; - int lastBottom = -1; - int to = 20; - bool firstVisible = FALSE; - TQRect cr( contentsX(), contentsY(), visibleWidth(), visibleHeight() ); - for ( int i = 0; lastFormatted && - ( i < to || ( firstVisible && lastTop < contentsY()+height() ) ); - i++ ) { - lastFormatted->format(); - lastTop = lastFormatted->rect().top(); - lastBottom = lastFormatted->rect().bottom(); - if ( i == 0 ) - firstVisible = lastBottom < cr.bottom(); - bottom = TQMAX( bottom, lastBottom ); - lastFormatted = lastFormatted->next(); - } - - if ( bottom > contentsHeight() ) { - resizeContents( contentsWidth(), TQMAX( doc->height(), bottom ) ); - } else if ( !lastFormatted && lastBottom < contentsHeight() ) { - resizeContents( contentsWidth(), TQMAX( doc->height(), lastBottom ) ); - if ( contentsHeight() < visibleHeight() ) - updateContents( 0, contentsHeight(), visibleWidth(), - visibleHeight() - contentsHeight() ); - } - - if ( lastFormatted ) - formatTimer->start( interval, TRUE ); - else - interval = TQMAX( 0, interval ); -} - -void TQTextEdit::doResize() -{ -#ifdef QT_TEXTEDIT_OPTIMIZATION - if ( !d->optimMode ) -#endif - { - if ( wrapMode == FixedPixelWidth ) - return; - doc->setMinimumWidth( -1 ); - resizeContents( 0, 0 ); - doc->setWidth( visibleWidth() ); - doc->invalidate(); - lastFormatted = doc->firstParagraph(); - interval = 0; - formatMore(); - } - repaintContents( FALSE ); -} - -/*! \internal */ - -void TQTextEdit::doChangeInterval() -{ - interval = 0; -} - -/*! - \reimp -*/ - -bool TQTextEdit::eventFilter( TQObject *o, TQEvent *e ) -{ -#ifdef QT_TEXTEDIT_OPTIMIZATION - if ( !d->optimMode && (o == this || o == viewport()) ) { -#else - if ( o == this || o == viewport() ) { -#endif - if ( e->type() == TQEvent::FocusIn ) { - if ( TQApplication::cursorFlashTime() > 0 ) - blinkTimer->start( TQApplication::cursorFlashTime() / 2 ); - drawCursor( TRUE ); - updateMicroFocusHint(); - } else if ( e->type() == TQEvent::FocusOut ) { - blinkTimer->stop(); - drawCursor( FALSE ); - } - } - - if ( o == this && e->type() == TQEvent::PaletteChange ) { - TQColor old( viewport()->colorGroup().color( TQColorGroup::Text ) ); - if ( old != colorGroup().color( TQColorGroup::Text ) ) { - TQColor c( colorGroup().color( TQColorGroup::Text ) ); - doc->setMinimumWidth( -1 ); - doc->setDefaultFormat( doc->formatCollection()->defaultFormat()->font(), c ); - lastFormatted = doc->firstParagraph(); - formatMore(); - repaintChanged(); - } - } - - return TQScrollView::eventFilter( o, e ); -} - -/*! - \obsolete - */ -void TQTextEdit::insert( const TQString &text, bool indent, - bool checkNewLine, bool removeSelected ) -{ - uint f = 0; - if ( indent ) - f |= RedoIndentation; - if ( checkNewLine ) - f |= CheckNewLines; - if ( removeSelected ) - f |= RemoveSelected; - insert( text, f ); -} - -/*! - Inserts \a text at the current cursor position. - - The \a insertionFlags define how the text is inserted. If \c - RedoIndentation is set, the paragraph is re-indented. If \c - CheckNewLines is set, newline characters in \a text result in hard - line breaks (i.e. new paragraphs). If \c checkNewLine is not set, - the behaviour of the editor is undefined if the \a text contains - newlines. (It is not possible to change TQTextEdit's newline handling - behavior, but you can use TQString::replace() to preprocess text - before inserting it.) If \c RemoveSelected is set, any selected - text (in selection 0) is removed before the text is inserted. - - The default flags are \c CheckNewLines | \c RemoveSelected. - - If the widget is in \c LogText mode this function will do nothing. - - \sa paste() pasteSubType() -*/ - - -void TQTextEdit::insert( const TQString &text, uint insertionFlags ) -{ -#ifdef QT_TEXTEDIT_OPTIMIZATION - if ( d->optimMode ) - return; -#endif - - if ( cursor->nestedDepth() != 0 ) // #### for 3.0, disable editing of tables as this is not advanced enough - return; - - bool indent = insertionFlags & RedoIndentation; - bool checkNewLine = insertionFlags & CheckNewLines; - bool removeSelected = insertionFlags & RemoveSelected; - bool imComposition = insertionFlags & AsIMCompositionText; - bool imSelection = insertionFlags & WithIMSelection; - TQString txt( text ); - drawCursor( FALSE ); - if ( !isReadOnly() && doc->hasSelection( TQTextDocument::Standard ) && removeSelected ) - removeSelectedText(); - TQTextCursor c2 = *cursor; - int oldLen = 0; - - if ( undoEnabled && !isReadOnly() && undoRedoInfo.type != UndoRedoInfo::IME ) { - checkUndoRedoInfo( UndoRedoInfo::Insert ); - - if (undoRedoInfo.valid() && undoRedoInfo.index + undoRedoInfo.d->text.length() != cursor->index()) { - clearUndoRedo(); - undoRedoInfo.type = UndoRedoInfo::Insert; - } - - if ( !undoRedoInfo.valid() ) { - undoRedoInfo.id = cursor->paragraph()->paragId(); - undoRedoInfo.index = cursor->index(); - undoRedoInfo.d->text = TQString::null; - } - oldLen = undoRedoInfo.d->text.length(); - } - - lastFormatted = checkNewLine && cursor->paragraph()->prev() ? - cursor->paragraph()->prev() : cursor->paragraph(); - TQTextCursor oldCursor = *cursor; - cursor->insert( txt, checkNewLine ); - if ( doc->useFormatCollection() && !doc->preProcessor() ) { - doc->setSelectionStart( TQTextDocument::Temp, oldCursor ); - doc->setSelectionEnd( TQTextDocument::Temp, *cursor ); - doc->setFormat( TQTextDocument::Temp, currentFormat, TQTextFormat::Format ); - doc->removeSelection( TQTextDocument::Temp ); - } - - if ( indent && ( txt == "{" || txt == "}" || txt == ":" || txt == "#" ) ) - cursor->indent(); - formatMore(); - repaintChanged(); - ensureCursorVisible(); - // Asian users regard selection text as cursor on candidate - // selection phase of input method, so ordinary cursor should be - // invisible if IM selection text exists. - drawCursor( !imSelection ); - - if ( undoEnabled && !isReadOnly() && undoRedoInfo.type != UndoRedoInfo::IME ) { - undoRedoInfo.d->text += txt; - if ( !doc->preProcessor() ) { - for ( int i = 0; i < (int)txt.length(); ++i ) { - if ( txt[ i ] != '\n' && c2.paragraph()->at( c2.index() )->format() ) { - c2.paragraph()->at( c2.index() )->format()->addRef(); - undoRedoInfo.d->text. - setFormat( oldLen + i, - c2.paragraph()->at( c2.index() )->format(), TRUE ); - } - c2.gotoNextLetter(); - } - } - } - - if ( !removeSelected ) { - doc->setSelectionStart( TQTextDocument::Standard, oldCursor ); - doc->setSelectionEnd( TQTextDocument::Standard, *cursor ); - repaintChanged(); - } - // updateMicroFocusHint() should not be invoked here when this - // function is invoked from imComposeEvent() because cursor - // postion is incorrect yet. imComposeEvent() invokes - // updateMicroFocusHint() later. - if ( !imComposition ) { - updateMicroFocusHint(); - } - setModified(); - emit textChanged(); -} - -/*! - Inserts \a text in the paragraph \a para at position \a index. -*/ - -void TQTextEdit::insertAt( const TQString &text, int para, int index ) -{ -#ifdef QT_TEXTEDIT_OPTIMIZATION - if ( d->optimMode ) { - optimInsert( text, para, index ); - return; - } -#endif - resetInputContext(); - TQTextParagraph *p = doc->paragAt( para ); - if ( !p ) - return; - removeSelection( TQTextDocument::Standard ); - TQTextCursor tmp = *cursor; - cursor->setParagraph( p ); - cursor->setIndex( index ); - insert( text, FALSE, TRUE, FALSE ); - *cursor = tmp; - removeSelection( TQTextDocument::Standard ); -} - -/*! - Inserts \a text as a new paragraph at position \a para. If \a para - is -1, the text is appended. Use append() if the append operation - is performance critical. -*/ - -void TQTextEdit::insertParagraph( const TQString &text, int para ) -{ -#ifdef QT_TEXTEDIT_OPTIMIZATION - if ( d->optimMode ) { - optimInsert( text + "\n", para, 0 ); - return; - } -#endif - resetInputContext(); - for ( int i = 0; i < (int)doc->numSelections(); ++i ) - doc->removeSelection( i ); - - TQTextParagraph *p = doc->paragAt( para ); - - bool append = !p; - if ( !p ) - p = doc->lastParagraph(); - - TQTextCursor old = *cursor; - drawCursor( FALSE ); - - cursor->setParagraph( p ); - cursor->setIndex( 0 ); - clearUndoRedo(); - qtextedit_ignore_readonly = TRUE; - if ( append && cursor->paragraph()->length() > 1 ) { - cursor->setIndex( cursor->paragraph()->length() - 1 ); - doKeyboardAction( ActionReturn ); - } - insert( text, FALSE, TRUE, TRUE ); - doKeyboardAction( ActionReturn ); - qtextedit_ignore_readonly = FALSE; - - drawCursor( FALSE ); - *cursor = old; - drawCursor( TRUE ); - - repaintChanged(); -} - -/*! - Removes the paragraph \a para. -*/ - -void TQTextEdit::removeParagraph( int para ) -{ -#ifdef QT_TEXTEDIT_OPTIMIZATION - if ( d->optimMode ) - return; -#endif - resetInputContext(); - TQTextParagraph *p = doc->paragAt( para ); - if ( !p ) - return; - - for ( int i = 0; i < doc->numSelections(); ++i ) - doc->removeSelection( i ); - - TQTextCursor start( doc ); - TQTextCursor end( doc ); - start.setParagraph( p ); - start.setIndex( 0 ); - end.setParagraph( p ); - end.setIndex( p->length() - 1 ); - - if ( !(p == doc->firstParagraph() && p == doc->lastParagraph()) ) { - if ( p->next() ) { - end.setParagraph( p->next() ); - end.setIndex( 0 ); - } else if ( p->prev() ) { - start.setParagraph( p->prev() ); - start.setIndex( p->prev()->length() - 1 ); - } - } - - doc->setSelectionStart( TQTextDocument::Temp, start ); - doc->setSelectionEnd( TQTextDocument::Temp, end ); - removeSelectedText( TQTextDocument::Temp ); -} - -/*! - Undoes the last operation. - - If there is no operation to undo, i.e. there is no undo step in - the undo/redo history, nothing happens. - - \sa undoAvailable() redo() undoDepth() -*/ - -void TQTextEdit::undo() -{ - clearUndoRedo(); - if ( isReadOnly() || !doc->commands()->isUndoAvailable() || !undoEnabled ) - return; - - resetInputContext(); - for ( int i = 0; i < (int)doc->numSelections(); ++i ) - doc->removeSelection( i ); - -#ifndef TQT_NO_CURSOR - viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); -#endif - - clearUndoRedo(); - drawCursor( FALSE ); - TQTextCursor *c = doc->undo( cursor ); - if ( !c ) { - drawCursor( TRUE ); - return; - } - lastFormatted = 0; - repaintChanged(); - ensureCursorVisible(); - drawCursor( TRUE ); - updateMicroFocusHint(); - setModified(); - // ### If we get back to a completely blank textedit, it - // is possible that cursor is invalid and further actions - // might not fix the problem, so reset the cursor here. - // This is copied from removeSeletedText(), it might be - // okay to just call that. - if ( !cursor->isValid() ) { - delete cursor; - cursor = new TQTextCursor( doc ); - drawCursor( TRUE ); - repaintContents( TRUE ); - } - emit undoAvailable( isUndoAvailable() ); - emit redoAvailable( isRedoAvailable() ); - emit textChanged(); -} - -/*! - Redoes the last operation. - - If there is no operation to redo, i.e. there is no redo step in - the undo/redo history, nothing happens. - - \sa redoAvailable() undo() undoDepth() -*/ - -void TQTextEdit::redo() -{ - if ( isReadOnly() || !doc->commands()->isRedoAvailable() || !undoEnabled ) - return; - - resetInputContext(); - for ( int i = 0; i < (int)doc->numSelections(); ++i ) - doc->removeSelection( i ); - -#ifndef TQT_NO_CURSOR - viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); -#endif - - clearUndoRedo(); - drawCursor( FALSE ); - TQTextCursor *c = doc->redo( cursor ); - if ( !c ) { - drawCursor( TRUE ); - return; - } - lastFormatted = 0; - ensureCursorVisible(); - repaintChanged(); - ensureCursorVisible(); - drawCursor( TRUE ); - updateMicroFocusHint(); - setModified(); - emit undoAvailable( isUndoAvailable() ); - emit redoAvailable( isRedoAvailable() ); - emit textChanged(); -} - -/*! - Pastes the text from the clipboard into the text edit at the - current cursor position. Only plain text is pasted. - - If there is no text in the clipboard nothing happens. - - \sa pasteSubType() cut() TQTextEdit::copy() -*/ - -void TQTextEdit::paste() -{ -#ifndef TQT_NO_MIMECLIPBOARD - if ( isReadOnly() ) - return; - TQString subType = "plain"; - if ( textFormat() != PlainText ) { - TQMimeSource *m = TQApplication::clipboard()->data( d->clipboard_mode ); - if ( !m ) - return; - if ( m->provides( "application/x-qrichtext" ) ) - subType = "x-qrichtext"; - } - - pasteSubType( subType.latin1() ); - updateMicroFocusHint(); -#endif -} - -void TQTextEdit::checkUndoRedoInfo( UndoRedoInfo::Type t ) -{ - if ( undoRedoInfo.valid() && t != undoRedoInfo.type ) { - clearUndoRedo(); - } - undoRedoInfo.type = t; -} - -/*! - Repaints any paragraphs that have changed. - - Although used extensively internally you shouldn't need to call - this yourself. -*/ - -void TQTextEdit::repaintChanged() -{ - if ( !isUpdatesEnabled() || !viewport()->isUpdatesEnabled() ) - return; - - TQPainter p( viewport() ); -#ifdef QT_TEXTEDIT_OPTIMIZATION - if ( d->optimMode ) { - optimDrawContents( &p, contentsX(), contentsY(), visibleWidth(), visibleHeight() ); - return; - } -#endif - p.translate( -contentsX(), -contentsY() ); - paintDocument( FALSE, &p, contentsX(), contentsY(), visibleWidth(), visibleHeight() ); -} - -#ifndef TQT_NO_MIME -TQTextDrag *TQTextEdit::dragObject( TQWidget *parent ) const -{ - if ( !doc->hasSelection( TQTextDocument::Standard ) || - doc->selectedText( TQTextDocument::Standard ).isEmpty() ) - return 0; - if ( textFormat() != RichText ) - return new TQTextDrag( doc->selectedText( TQTextDocument::Standard ), parent ); - TQRichTextDrag *drag = new TQRichTextDrag( parent ); - drag->setPlainText( doc->selectedText( TQTextDocument::Standard ) ); - drag->setRichText( doc->selectedText( TQTextDocument::Standard, TRUE ) ); - return drag; -} -#endif - -/*! - Copies the selected text (from selection 0) to the clipboard and - deletes it from the text edit. - - If there is no selected text (in selection 0) nothing happens. - - \sa TQTextEdit::copy() paste() pasteSubType() -*/ - -void TQTextEdit::cut() -{ - if ( isReadOnly() ) - return; - resetInputContext(); - normalCopy(); - removeSelectedText(); - updateMicroFocusHint(); -} - -void TQTextEdit::normalCopy() -{ -#ifndef TQT_NO_MIME - TQTextDrag *drag = dragObject(); - if ( !drag ) - return; -#ifndef TQT_NO_MIMECLIPBOARD - TQApplication::clipboard()->setData( drag, d->clipboard_mode ); -#endif // TQT_NO_MIMECLIPBOARD -#endif // TQT_NO_MIME -} - -/*! - Copies any selected text (from selection 0) to the clipboard. - - \sa hasSelectedText() copyAvailable() -*/ - -void TQTextEdit::copy() -{ -#ifndef TQT_NO_CLIPBOARD -# ifdef QT_TEXTEDIT_OPTIMIZATION - if ( d->optimMode && optimHasSelection() ) - TQApplication::clipboard()->setText( optimSelectedText(), d->clipboard_mode ); - else - normalCopy(); -# else - normalCopy(); -# endif -#endif -} - -/*! - \internal - - Re-indents the current paragraph. -*/ - -void TQTextEdit::indent() -{ - if ( isReadOnly() ) - return; - - drawCursor( FALSE ); - if ( !doc->hasSelection( TQTextDocument::Standard ) ) - cursor->indent(); - else - doc->indentSelection( TQTextDocument::Standard ); - repaintChanged(); - drawCursor( TRUE ); - setModified(); - emit textChanged(); -} - -/*! - Reimplemented to allow tabbing through links. If \a n is TRUE the - tab moves the focus to the next child; if \a n is FALSE the tab - moves the focus to the previous child. Returns TRUE if the focus - was moved; otherwise returns FALSE. - */ - -bool TQTextEdit::focusNextPrevChild( bool n ) -{ - if ( !isReadOnly() || !linksEnabled() ) - return FALSE; - bool b = doc->focusNextPrevChild( n ); - repaintChanged(); - if ( b ) { - TQTextParagraph *p = doc->focusIndicator.parag; - int start = doc->focusIndicator.start; - int len = doc->focusIndicator.len; - - int y = p->rect().y(); - while ( p - && len == 0 - && p->at( start )->isCustom() - && p->at( start )->customItem()->isNested() ) { - - TQTextTable *t = (TQTextTable*)p->at( start )->customItem(); - TQPtrList<TQTextTableCell> cells = t->tableCells(); - TQTextTableCell *c; - for ( c = cells.first(); c; c = cells.next() ) { - TQTextDocument *cellDoc = c->richText(); - if ( cellDoc->hasFocusParagraph() ) { - y += c->geometry().y() + c->verticalAlignmentOffset(); - - p = cellDoc->focusIndicator.parag; - start = cellDoc->focusIndicator.start; - len = cellDoc->focusIndicator.len; - if ( p ) - y += p->rect().y(); - - break; - } - } - } - setContentsPos( contentsX(), TQMIN( y, contentsHeight() - visibleHeight() ) ); - } - return b; -} - -/*! - \internal - - This functions sets the current format to \a f. Only the fields of \a - f which are specified by the \a flags are used. -*/ - -void TQTextEdit::setFormat( TQTextFormat *f, int flags ) -{ - if ( doc->hasSelection( TQTextDocument::Standard ) ) { - drawCursor( FALSE ); - TQTextCursor c1 = doc->selectionStartCursor( TQTextDocument::Standard ); - c1.restoreState(); - TQTextCursor c2 = doc->selectionEndCursor( TQTextDocument::Standard ); - c2.restoreState(); - if ( undoEnabled ) { - clearUndoRedo(); - undoRedoInfo.type = UndoRedoInfo::Format; - undoRedoInfo.id = c1.paragraph()->paragId(); - undoRedoInfo.index = c1.index(); - undoRedoInfo.eid = c2.paragraph()->paragId(); - undoRedoInfo.eindex = c2.index(); - readFormats( c1, c2, undoRedoInfo.d->text ); - undoRedoInfo.format = f; - undoRedoInfo.flags = flags; - clearUndoRedo(); - } - doc->setFormat( TQTextDocument::Standard, f, flags ); - repaintChanged(); - formatMore(); - drawCursor( TRUE ); - setModified(); - emit textChanged(); - } - if ( currentFormat && currentFormat->key() != f->key() ) { - currentFormat->removeRef(); - currentFormat = doc->formatCollection()->format( f ); - if ( currentFormat->isMisspelled() ) { - currentFormat->removeRef(); - currentFormat = doc->formatCollection()->format( currentFormat->font(), - currentFormat->color() ); - } - emit currentFontChanged( currentFormat->font() ); - emit currentColorChanged( currentFormat->color() ); - emit currentVerticalAlignmentChanged( (VerticalAlignment)currentFormat->vAlign() ); - if ( cursor->index() == cursor->paragraph()->length() - 1 ) { - currentFormat->addRef(); - cursor->paragraph()->string()->setFormat( cursor->index(), currentFormat, TRUE ); - if ( cursor->paragraph()->length() == 1 ) { - cursor->paragraph()->invalidate( 0 ); - cursor->paragraph()->format(); - repaintChanged(); - } - } - } -} - -/*! - \reimp -*/ - -void TQTextEdit::setPalette( const TQPalette &p ) -{ - TQScrollView::setPalette( p ); - if ( textFormat() == PlainText ) { - TQTextFormat *f = doc->formatCollection()->defaultFormat(); - f->setColor( colorGroup().text() ); - updateContents(); - } -} - -/*! \internal - \warning In TQt 3.1 we will provide a cleaer API for the - functionality which is provided by this function and in TQt 4.0 this - function will go away. - - Sets the paragraph style of the current paragraph - to \a dm. If \a dm is TQStyleSheetItem::DisplayListItem, the - type of the list item is set to \a listStyle. - - \sa setAlignment() -*/ - -void TQTextEdit::setParagType( TQStyleSheetItem::DisplayMode dm, - TQStyleSheetItem::ListStyle listStyle ) -{ - if ( isReadOnly() ) - return; - - drawCursor( FALSE ); - TQTextParagraph *start = cursor->paragraph(); - TQTextParagraph *end = start; - if ( doc->hasSelection( TQTextDocument::Standard ) ) { - start = doc->selectionStartCursor( TQTextDocument::Standard ).topParagraph(); - end = doc->selectionEndCursor( TQTextDocument::Standard ).topParagraph(); - if ( end->paragId() < start->paragId() ) - return; // do not trust our selections - } - - clearUndoRedo(); - undoRedoInfo.type = UndoRedoInfo::Style; - undoRedoInfo.id = start->paragId(); - undoRedoInfo.eid = end->paragId(); - undoRedoInfo.styleInformation = TQTextStyleCommand::readStyleInformation( doc, undoRedoInfo.id, undoRedoInfo.eid ); - - while ( start != end->next() ) { - start->setListStyle( listStyle ); - if ( dm == TQStyleSheetItem::DisplayListItem ) { - start->setListItem( TRUE ); - if( start->listDepth() == 0 ) - start->setListDepth( 1 ); - } else if ( start->isListItem() ) { - start->setListItem( FALSE ); - start->setListDepth( TQMAX( start->listDepth()-1, 0 ) ); - } - start = start->next(); - } - - clearUndoRedo(); - repaintChanged(); - formatMore(); - drawCursor( TRUE ); - setModified(); - emit textChanged(); -} - -/*! - Sets the alignment of the current paragraph to \a a. Valid - alignments are \c TQt::AlignLeft, \c TQt::AlignRight, - \c TQt::AlignJustify and \c TQt::AlignCenter (which centers - horizontally). -*/ - -void TQTextEdit::setAlignment( int a ) -{ - if ( isReadOnly() || block_set_alignment ) - return; - - drawCursor( FALSE ); - TQTextParagraph *start = cursor->paragraph(); - TQTextParagraph *end = start; - if ( doc->hasSelection( TQTextDocument::Standard ) ) { - start = doc->selectionStartCursor( TQTextDocument::Standard ).topParagraph(); - end = doc->selectionEndCursor( TQTextDocument::Standard ).topParagraph(); - if ( end->paragId() < start->paragId() ) - return; // do not trust our selections - } - - clearUndoRedo(); - undoRedoInfo.type = UndoRedoInfo::Style; - undoRedoInfo.id = start->paragId(); - undoRedoInfo.eid = end->paragId(); - undoRedoInfo.styleInformation = TQTextStyleCommand::readStyleInformation( doc, undoRedoInfo.id, undoRedoInfo.eid ); - - while ( start != end->next() ) { - start->setAlignment( a ); - start = start->next(); - } - - clearUndoRedo(); - repaintChanged(); - formatMore(); - drawCursor( TRUE ); - if ( currentAlignment != a ) { - currentAlignment = a; - emit currentAlignmentChanged( currentAlignment ); - } - setModified(); - emit textChanged(); -} - -void TQTextEdit::updateCurrentFormat() -{ - int i = cursor->index(); - if ( i > 0 ) - --i; - if ( doc->useFormatCollection() && - ( !currentFormat || currentFormat->key() != cursor->paragraph()->at( i )->format()->key() ) ) { - if ( currentFormat ) - currentFormat->removeRef(); - currentFormat = doc->formatCollection()->format( cursor->paragraph()->at( i )->format() ); - if ( currentFormat->isMisspelled() ) { - currentFormat->removeRef(); - currentFormat = doc->formatCollection()->format( currentFormat->font(), currentFormat->color() ); - } - emit currentFontChanged( currentFormat->font() ); - emit currentColorChanged( currentFormat->color() ); - emit currentVerticalAlignmentChanged( (VerticalAlignment)currentFormat->vAlign() ); - } - - if ( currentAlignment != cursor->paragraph()->alignment() ) { - currentAlignment = cursor->paragraph()->alignment(); - block_set_alignment = TRUE; - emit currentAlignmentChanged( currentAlignment ); - block_set_alignment = FALSE; - } -} - -/*! - If \a b is TRUE sets the current format to italic; otherwise sets - the current format to non-italic. - - \sa italic() -*/ - -void TQTextEdit::setItalic( bool b ) -{ - TQTextFormat f( *currentFormat ); - f.setItalic( b ); - TQTextFormat *f2 = doc->formatCollection()->format( &f ); - setFormat(f2, TQTextFormat::Italic ); -} - -/*! - If \a b is TRUE sets the current format to bold; otherwise sets - the current format to non-bold. - - \sa bold() -*/ - -void TQTextEdit::setBold( bool b ) -{ - TQTextFormat f( *currentFormat ); - f.setBold( b ); - TQTextFormat *f2 = doc->formatCollection()->format( &f ); - setFormat( f2, TQTextFormat::Bold ); -} - -/*! - If \a b is TRUE sets the current format to underline; otherwise - sets the current format to non-underline. - - \sa underline() -*/ - -void TQTextEdit::setUnderline( bool b ) -{ - TQTextFormat f( *currentFormat ); - f.setUnderline( b ); - TQTextFormat *f2 = doc->formatCollection()->format( &f ); - setFormat( f2, TQTextFormat::Underline ); -} - -/*! - Sets the font family of the current format to \a fontFamily. - - \sa family() setCurrentFont() -*/ - -void TQTextEdit::setFamily( const TQString &fontFamily ) -{ - TQTextFormat f( *currentFormat ); - f.setFamily( fontFamily ); - TQTextFormat *f2 = doc->formatCollection()->format( &f ); - setFormat( f2, TQTextFormat::Family ); -} - -/*! - Sets the point size of the current format to \a s. - - Note that if \a s is zero or negative, the behaviour of this - function is not defined. - - \sa pointSize() setCurrentFont() setFamily() -*/ - -void TQTextEdit::setPointSize( int s ) -{ - TQTextFormat f( *currentFormat ); - f.setPointSize( s ); - TQTextFormat *f2 = doc->formatCollection()->format( &f ); - setFormat( f2, TQTextFormat::Size ); -} - -/*! - Sets the color of the current format, i.e. of the text, to \a c. - - \sa color() setPaper() -*/ - -void TQTextEdit::setColor( const TQColor &c ) -{ - TQTextFormat f( *currentFormat ); - f.setColor( c ); - TQTextFormat *f2 = doc->formatCollection()->format( &f ); - setFormat( f2, TQTextFormat::Color ); -} - -/*! - Sets the vertical alignment of the current format, i.e. of the - text, to \a a. - - \sa color() setPaper() -*/ - -void TQTextEdit::setVerticalAlignment( VerticalAlignment a ) -{ - TQTextFormat f( *currentFormat ); - f.setVAlign( (TQTextFormat::VerticalAlignment)a ); - TQTextFormat *f2 = doc->formatCollection()->format( &f ); - setFormat( f2, TQTextFormat::VAlign ); -} - -void TQTextEdit::setFontInternal( const TQFont &f_ ) -{ - TQTextFormat f( *currentFormat ); - f.setFont( f_ ); - TQTextFormat *f2 = doc->formatCollection()->format( &f ); - setFormat( f2, TQTextFormat::Font ); -} - - -TQString TQTextEdit::text() const -{ -#ifdef QT_TEXTEDIT_OPTIMIZATION - if ( d->optimMode ) - return optimText(); -#endif - - TQTextParagraph *p = doc->firstParagraph(); - if ( !p || (!p->next() && p->length() <= 1) ) - return TQString::fromLatin1(""); - - if ( isReadOnly() ) - return doc->originalText(); - return doc->text(); -} - -/*! - \overload - - Returns the text of paragraph \a para. - - If textFormat() is \c RichText the text will contain HTML - formatting tags. -*/ - -TQString TQTextEdit::text( int para ) const -{ -#ifdef QT_TEXTEDIT_OPTIMIZATION - if ( d->optimMode && (d->od->numLines >= para) ) { - TQString paraStr = d->od->lines[ LOGOFFSET(para) ]; - if ( paraStr.isEmpty() ) - paraStr = "\n"; - return paraStr; - } else -#endif - return doc->text( para ); -} - -/*! - \overload - - Changes the text of the text edit to the string \a text and the - context to \a context. Any previous text is removed. - - \a text may be interpreted either as plain text or as rich text, - depending on the textFormat(). The default setting is \c AutoText, - i.e. the text edit auto-detects the format from \a text. - - For rich text the rendering style and available tags are defined - by a styleSheet(); see TQStyleSheet for details. - - The optional \a context is a path which the text edit's - TQMimeSourceFactory uses to resolve the locations of files and - images. (See \l{TQTextEdit::TQTextEdit()}.) It is passed to the text - edit's TQMimeSourceFactory when quering data. - - Note that the undo/redo history is cleared by this function. - - \sa text(), setTextFormat() -*/ - -void TQTextEdit::setText( const TQString &text, const TQString &context ) -{ -#ifdef QT_TEXTEDIT_OPTIMIZATION - if ( d->optimMode ) { - optimSetText( text ); - return; - } -#endif - resetInputContext(); - if ( !isModified() && isReadOnly() && - this->context() == context && this->text() == text ) - return; - - emit undoAvailable( FALSE ); - emit redoAvailable( FALSE ); - undoRedoInfo.clear(); - doc->commands()->clear(); - - lastFormatted = 0; - int oldCursorPos = cursor->index(); - int oldCursorPar = cursor->paragraph()->paragId(); - cursor->restoreState(); - delete cursor; - doc->setText( text, context ); - - if ( wrapMode == FixedPixelWidth ) { - resizeContents( wrapWidth, 0 ); - doc->setWidth( wrapWidth ); - doc->setMinimumWidth( wrapWidth ); - } else { - doc->setMinimumWidth( -1 ); - resizeContents( 0, 0 ); - } - - lastFormatted = doc->firstParagraph(); - cursor = new TQTextCursor( doc ); - updateContents(); - - if ( isModified() ) - setModified( FALSE ); - emit textChanged(); - if ( cursor->index() != oldCursorPos || cursor->paragraph()->paragId() != oldCursorPar ) { - emit cursorPositionChanged( cursor ); - emit cursorPositionChanged( cursor->paragraph()->paragId(), cursor->index() ); - } - formatMore(); - updateCurrentFormat(); - d->scrollToAnchor = TQString::null; -} - -/*! - \property TQTextEdit::text - \brief the text edit's text - - There is no default text. - - On setting, any previous text is deleted. - - The text may be interpreted either as plain text or as rich text, - depending on the textFormat(). The default setting is \c AutoText, - i.e. the text edit auto-detects the format of the text. - - For richtext, calling text() on an editable TQTextEdit will cause - the text to be regenerated from the textedit. This may mean that - the TQString returned may not be exactly the same as the one that - was set. - - \sa textFormat -*/ - - -/*! - \property TQTextEdit::readOnly - \brief whether the text edit is read-only - - In a read-only text edit the user can only navigate through the - text and select text; modifying the text is not possible. - - This property's default is FALSE. -*/ - -/*! - Finds the next occurrence of the string, \a expr. Returns TRUE if - \a expr was found; otherwise returns FALSE. - - If \a para and \a index are both 0 the search begins from the - current cursor position. If \a para and \a index are both not 0, - the search begins from the \a *index character position in the - \a *para paragraph. - - If \a cs is TRUE the search is case sensitive, otherwise it is - case insensitive. If \a wo is TRUE the search looks for whole word - matches only; otherwise it searches for any matching text. If \a - forward is TRUE (the default) the search works forward from the - starting position to the end of the text, otherwise it works - backwards to the beginning of the text. - - If \a expr is found the function returns TRUE. If \a index and \a - para are not 0, the number of the paragraph in which the first - character of the match was found is put into \a *para, and the - index position of that character within the paragraph is put into - \a *index. - - If \a expr is not found the function returns FALSE. If \a index - and \a para are not 0 and \a expr is not found, \a *index - and \a *para are undefined. - - Please note that this function will make the next occurrence of - the string (if found) the current selection, and will thus - modify the cursor position. - - Using the \a para and \a index parameters will not work correctly - in case the document contains tables. -*/ - -bool TQTextEdit::find( const TQString &expr, bool cs, bool wo, bool forward, - int *para, int *index ) -{ -#ifdef QT_TEXTEDIT_OPTIMIZATION - if ( d->optimMode ) - return optimFind( expr, cs, wo, forward, para, index ); -#endif - drawCursor( FALSE ); -#ifndef TQT_NO_CURSOR - viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); -#endif - TQTextCursor findcur = *cursor; - if ( para && index ) { - if ( doc->paragAt( *para ) ) - findcur.gotoPosition( doc->paragAt(*para), *index ); - else - findcur.gotoEnd(); - } else if ( doc->hasSelection( TQTextDocument::Standard ) ){ - // maks sure we do not find the same selection again - if ( forward ) - findcur.gotoNextLetter(); - else - findcur.gotoPreviousLetter(); - } else if (!forward && findcur.index() == 0 && findcur.paragraph() == findcur.topParagraph()) { - findcur.gotoEnd(); - } - removeSelection( TQTextDocument::Standard ); - bool found = doc->find( findcur, expr, cs, wo, forward ); - if ( found ) { - if ( para ) - *para = findcur.paragraph()->paragId(); - if ( index ) - *index = findcur.index(); - *cursor = findcur; - repaintChanged(); - ensureCursorVisible(); - } - drawCursor( TRUE ); - if (found) { - emit cursorPositionChanged( cursor ); - emit cursorPositionChanged( cursor->paragraph()->paragId(), cursor->index() ); - } - return found; -} - -void TQTextEdit::blinkCursor() -{ - if ( !cursorVisible ) - return; - bool cv = cursorVisible; - blinkCursorVisible = !blinkCursorVisible; - drawCursor( blinkCursorVisible ); - cursorVisible = cv; -} - -/*! - Sets the cursor to position \a index in paragraph \a para. - - \sa getCursorPosition() -*/ - -void TQTextEdit::setCursorPosition( int para, int index ) -{ - TQTextParagraph *p = doc->paragAt( para ); - if ( !p ) - return; - - resetInputContext(); - if ( index > p->length() - 1 ) - index = p->length() - 1; - - drawCursor( FALSE ); - cursor->setParagraph( p ); - cursor->setIndex( index ); - ensureCursorVisible(); - drawCursor( TRUE ); - updateCurrentFormat(); - emit cursorPositionChanged( cursor ); - emit cursorPositionChanged( cursor->paragraph()->paragId(), cursor->index() ); -} - -/*! - This function sets the \a *para and \a *index parameters to the - current cursor position. \a para and \a index must not be 0. - - \sa setCursorPosition() -*/ - -void TQTextEdit::getCursorPosition( int *para, int *index ) const -{ - if ( !para || !index ) - return; - *para = cursor->paragraph()->paragId(); - *index = cursor->index(); -} - -/*! - Sets a selection which starts at position \a indexFrom in - paragraph \a paraFrom and ends at position \a indexTo in paragraph - \a paraTo. - - Any existing selections which have a different id (\a selNum) are - left alone, but if an existing selection has the same id as \a - selNum it is removed and replaced by this selection. - - Uses the selection settings of selection \a selNum. If \a selNum - is 0, this is the default selection. - - The cursor is moved to the end of the selection if \a selNum is 0, - otherwise the cursor position remains unchanged. - - \sa getSelection() selectedText -*/ - -void TQTextEdit::setSelection( int paraFrom, int indexFrom, - int paraTo, int indexTo, int selNum ) -{ -#ifdef QT_TEXTEDIT_OPTIMIZATION - if (d->optimMode) { - optimSetSelection(paraFrom, indexFrom, paraTo, indexTo); - repaintContents(FALSE); - return; - } -#endif - resetInputContext(); - if ( doc->hasSelection( selNum ) ) { - doc->removeSelection( selNum ); - repaintChanged(); - } - if ( selNum > doc->numSelections() - 1 ) - doc->addSelection( selNum ); - TQTextParagraph *p1 = doc->paragAt( paraFrom ); - if ( !p1 ) - return; - TQTextParagraph *p2 = doc->paragAt( paraTo ); - if ( !p2 ) - return; - - if ( indexFrom > p1->length() - 1 ) - indexFrom = p1->length() - 1; - if ( indexTo > p2->length() - 1 ) - indexTo = p2->length() - 1; - - drawCursor( FALSE ); - TQTextCursor c = *cursor; - TQTextCursor oldCursor = *cursor; - c.setParagraph( p1 ); - c.setIndex( indexFrom ); - cursor->setParagraph( p2 ); - cursor->setIndex( indexTo ); - doc->setSelectionStart( selNum, c ); - doc->setSelectionEnd( selNum, *cursor ); - repaintChanged(); - ensureCursorVisible(); - if ( selNum != TQTextDocument::Standard ) - *cursor = oldCursor; - drawCursor( TRUE ); -} - -/*! - If there is a selection, \a *paraFrom is set to the number of the - paragraph in which the selection begins and \a *paraTo is set to - the number of the paragraph in which the selection ends. (They - could be the same.) \a *indexFrom is set to the index at which the - selection begins within \a *paraFrom, and \a *indexTo is set to - the index at which the selection ends within \a *paraTo. - - If there is no selection, \a *paraFrom, \a *indexFrom, \a *paraTo - and \a *indexTo are all set to -1. - - If \a paraFrom, \a indexFrom, \a paraTo or \a indexTo is 0 this - function does nothing. - - The \a selNum is the number of the selection (multiple selections - are supported). It defaults to 0 (the default selection). - - \sa setSelection() selectedText -*/ - -void TQTextEdit::getSelection( int *paraFrom, int *indexFrom, - int *paraTo, int *indexTo, int selNum ) const -{ - if ( !paraFrom || !paraTo || !indexFrom || !indexTo ) - return; -#ifdef QT_TEXTEDIT_OPTIMIZATION - if (d->optimMode) { - *paraFrom = d->od->selStart.line; - *paraTo = d->od->selEnd.line; - *indexFrom = d->od->selStart.index; - *indexTo = d->od->selEnd.index; - return; - } -#endif - if ( !doc->hasSelection( selNum ) ) { - *paraFrom = -1; - *indexFrom = -1; - *paraTo = -1; - *indexTo = -1; - return; - } - - doc->selectionStart( selNum, *paraFrom, *indexFrom ); - doc->selectionEnd( selNum, *paraTo, *indexTo ); -} - -/*! - \property TQTextEdit::textFormat - \brief the text format: rich text, plain text, log text or auto text. - - The text format is one of the following: - \list - \i PlainText - all characters, except newlines, are displayed - verbatim, including spaces. Whenever a newline appears in the text - the text edit inserts a hard line break and begins a new - paragraph. - \i RichText - rich text rendering. The available styles are - defined in the default stylesheet TQStyleSheet::defaultSheet(). - \i LogText - optimized mode for very large texts. Supports a very - limited set of formatting tags (color, bold, underline and italic - settings). - \i AutoText - this is the default. The text edit autodetects which - rendering style is best, \c PlainText or \c RichText. This is done - by using the TQStyleSheet::mightBeRichText() function. - \endlist -*/ - -void TQTextEdit::setTextFormat( TextFormat format ) -{ - doc->setTextFormat( format ); -#ifdef QT_TEXTEDIT_OPTIMIZATION - checkOptimMode(); -#endif -} - -TQt::TextFormat TQTextEdit::textFormat() const -{ - return doc->textFormat(); -} - -/*! - Returns the number of paragraphs in the text; an empty textedit is always - considered to have one paragraph, so 1 is returned in this case. -*/ - -int TQTextEdit::paragraphs() const -{ -#ifdef QT_TEXTEDIT_OPTIMIZATION - if ( d->optimMode ) { - return d->od->numLines; - } -#endif - return doc->lastParagraph()->paragId() + 1; -} - -/*! - Returns the number of lines in paragraph \a para, or -1 if there - is no paragraph with index \a para. -*/ - -int TQTextEdit::linesOfParagraph( int para ) const -{ -#ifdef QT_TEXTEDIT_OPTIMIZATION - if ( d->optimMode ) { - if ( d->od->numLines >= para ) - return 1; - else - return -1; - } -#endif - TQTextParagraph *p = doc->paragAt( para ); - if ( !p ) - return -1; - return p->lines(); -} - -/*! - Returns the length of the paragraph \a para (i.e. the number of - characters), or -1 if there is no paragraph with index \a para. - - This function ignores newlines. -*/ - -int TQTextEdit::paragraphLength( int para ) const -{ -#ifdef QT_TEXTEDIT_OPTIMIZATION - if ( d->optimMode ) { - if ( d->od->numLines >= para ) { - if ( d->od->lines[ LOGOFFSET(para) ].isEmpty() ) // CR - return 1; - else - return d->od->lines[ LOGOFFSET(para) ].length(); - } - return -1; - } -#endif - TQTextParagraph *p = doc->paragAt( para ); - if ( !p ) - return -1; - return p->length() - 1; -} - -/*! - Returns the number of lines in the text edit; this could be 0. - - \warning This function may be slow. Lines change all the time - during word wrapping, so this function has to iterate over all the - paragraphs and get the number of lines from each one individually. -*/ - -int TQTextEdit::lines() const -{ -#ifdef QT_TEXTEDIT_OPTIMIZATION - if ( d->optimMode ) { - return d->od->numLines; - } -#endif - TQTextParagraph *p = doc->firstParagraph(); - int l = 0; - while ( p ) { - l += p->lines(); - p = p->next(); - } - - return l; -} - -/*! - Returns the line number of the line in paragraph \a para in which - the character at position \a index appears. The \a index position is - relative to the beginning of the paragraph. If there is no such - paragraph or no such character at the \a index position (e.g. the - index is out of range) -1 is returned. -*/ - -int TQTextEdit::lineOfChar( int para, int index ) -{ - TQTextParagraph *p = doc->paragAt( para ); - if ( !p ) - return -1; - - int idx, line; - TQTextStringChar *c = p->lineStartOfChar( index, &idx, &line ); - if ( !c ) - return -1; - - return line; -} - -void TQTextEdit::setModified( bool m ) -{ - bool oldModified = modified; - modified = m; - if ( modified && doc->oTextValid ) - doc->invalidateOriginalText(); - if ( oldModified != modified ) - emit modificationChanged( modified ); -} - -/*! - \property TQTextEdit::modified - \brief whether the document has been modified by the user -*/ - -bool TQTextEdit::isModified() const -{ - return modified; -} - -void TQTextEdit::setModified() -{ - if ( !isModified() ) - setModified( TRUE ); -} - -/*! - Returns TRUE if the current format is italic; otherwise returns FALSE. - - \sa setItalic() -*/ - -bool TQTextEdit::italic() const -{ - return currentFormat->font().italic(); -} - -/*! - Returns TRUE if the current format is bold; otherwise returns FALSE. - - \sa setBold() -*/ - -bool TQTextEdit::bold() const -{ - return currentFormat->font().bold(); -} - -/*! - Returns TRUE if the current format is underlined; otherwise returns - FALSE. - - \sa setUnderline() -*/ - -bool TQTextEdit::underline() const -{ - return currentFormat->font().underline(); -} - -/*! - Returns the font family of the current format. - - \sa setFamily() setCurrentFont() setPointSize() -*/ - -TQString TQTextEdit::family() const -{ - return currentFormat->font().family(); -} - -/*! - Returns the point size of the font of the current format. - - \sa setFamily() setCurrentFont() setPointSize() -*/ - -int TQTextEdit::pointSize() const -{ - return currentFormat->font().pointSize(); -} - -/*! - Returns the color of the current format. - - \sa setColor() setPaper() -*/ - -TQColor TQTextEdit::color() const -{ - return currentFormat->color(); -} - -/*! - \obsolete - - Returns TQScrollView::font() - - \warning In previous versions this function returned the font of - the current format. This lead to confusion. Please use - currentFont() instead. -*/ - -TQFont TQTextEdit::font() const -{ - return TQScrollView::font(); -} - -/*! - Returns the font of the current format. - - \sa setCurrentFont() setFamily() setPointSize() -*/ - -TQFont TQTextEdit::currentFont() const -{ - return currentFormat->font(); -} - - -/*! - Returns the alignment of the current paragraph. - - \sa setAlignment() -*/ - -int TQTextEdit::alignment() const -{ - return currentAlignment; -} - -void TQTextEdit::startDrag() -{ -#ifndef TQT_NO_DRAGANDDROP - mousePressed = FALSE; - inDoubleClick = FALSE; - TQDragObject *drag = dragObject( viewport() ); - if ( !drag ) - return; - if ( isReadOnly() ) { - drag->dragCopy(); - } else { - if ( drag->drag() && TQDragObject::target() != this && TQDragObject::target() != viewport() ) - removeSelectedText(); - } -#endif -} - -/*! - If \a select is TRUE (the default), all the text is selected as - selection 0. If \a select is FALSE any selected text is - unselected, i.e. the default selection (selection 0) is cleared. - - \sa selectedText -*/ - -void TQTextEdit::selectAll( bool select ) -{ -#ifdef QT_TEXTEDIT_OPTIMIZATION - if ( d->optimMode ) { - if ( select ) - optimSelectAll(); - else - optimRemoveSelection(); - return; - } -#endif - if ( !select ) - doc->removeSelection( TQTextDocument::Standard ); - else - doc->selectAll( TQTextDocument::Standard ); - repaintChanged(); - emit copyAvailable( doc->hasSelection( TQTextDocument::Standard ) ); - emit selectionChanged(); -#ifndef TQT_NO_CURSOR - viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); -#endif -} - -void TQTextEdit::UndoRedoInfo::clear() -{ - if ( valid() ) { - if ( type == Insert || type == Return ) - doc->addCommand( new TQTextInsertCommand( doc, id, index, d->text.rawData(), styleInformation ) ); - else if ( type == Format ) - doc->addCommand( new TQTextFormatCommand( doc, id, index, eid, eindex, d->text.rawData(), format, flags ) ); - else if ( type == Style ) - doc->addCommand( new TQTextStyleCommand( doc, id, eid, styleInformation ) ); - else if ( type != Invalid ) { - doc->addCommand( new TQTextDeleteCommand( doc, id, index, d->text.rawData(), styleInformation ) ); - } - } - type = Invalid; - d->text = TQString::null; - id = -1; - index = -1; - styleInformation = TQByteArray(); -} - - -/*! - If there is some selected text (in selection 0) it is deleted. If - there is no selected text (in selection 0) the character to the - right of the text cursor is deleted. - - \sa removeSelectedText() cut() -*/ - -void TQTextEdit::del() -{ - if ( doc->hasSelection( TQTextDocument::Standard ) ) { - removeSelectedText(); - return; - } - - doKeyboardAction( ActionDelete ); -} - - -TQTextEdit::UndoRedoInfo::UndoRedoInfo( TQTextDocument *dc ) - : type( Invalid ), doc( dc ) -{ - d = new TQUndoRedoInfoPrivate; - d->text = TQString::null; - id = -1; - index = -1; -} - -TQTextEdit::UndoRedoInfo::~UndoRedoInfo() -{ - delete d; -} - -bool TQTextEdit::UndoRedoInfo::valid() const -{ - return id >= 0 && type != Invalid; -} - -/*! - \internal - - Resets the current format to the default format. -*/ - -void TQTextEdit::resetFormat() -{ - setAlignment( TQt::AlignAuto ); - setParagType( TQStyleSheetItem::DisplayBlock, TQStyleSheetItem::ListDisc ); - setFormat( doc->formatCollection()->defaultFormat(), TQTextFormat::Format ); -} - -/*! - Returns the TQStyleSheet which is being used by this text edit. - - \sa setStyleSheet() -*/ - -TQStyleSheet* TQTextEdit::styleSheet() const -{ - return doc->styleSheet(); -} - -/*! - Sets the stylesheet to use with this text edit to \a styleSheet. - Changes will only take effect for new text added with setText() or - append(). - - \sa styleSheet() -*/ - -void TQTextEdit::setStyleSheet( TQStyleSheet* styleSheet ) -{ - doc->setStyleSheet( styleSheet ); -} - -/*! - \property TQTextEdit::paper - \brief the background (paper) brush. - - The brush that is currently used to draw the background of the - text edit. The initial setting is an empty brush. -*/ - -void TQTextEdit::setPaper( const TQBrush& pap ) -{ - doc->setPaper( new TQBrush( pap ) ); - - if ( pap.pixmap() ) { - viewport()->setBackgroundPixmap( *pap.pixmap() ); - } else { - setPaletteBackgroundColor( pap.color() ); - viewport()->setPaletteBackgroundColor( pap.color() ); - } - -#ifdef QT_TEXTEDIT_OPTIMIZATION - // force a repaint of the entire viewport - using updateContents() - // would clip the coords to the content size - if (d->optimMode) - repaintContents(contentsX(), contentsY(), viewport()->width(), viewport()->height()); - else -#endif - updateContents(); -} - -TQBrush TQTextEdit::paper() const -{ - if ( doc->paper() ) - return *doc->paper(); - return TQBrush( colorGroup().base() ); -} - -/*! - \property TQTextEdit::linkUnderline - \brief whether hypertext links will be underlined - - If TRUE (the default) hypertext links will be displayed - underlined. If FALSE links will not be displayed underlined. -*/ - -void TQTextEdit::setLinkUnderline( bool b ) -{ - if ( doc->underlineLinks() == b ) - return; - doc->setUnderlineLinks( b ); - repaintChanged(); -} - -bool TQTextEdit::linkUnderline() const -{ - return doc->underlineLinks(); -} - -/*! - Sets the text edit's mimesource factory to \a factory. See - TQMimeSourceFactory for further details. - - \sa mimeSourceFactory() - */ - -#ifndef TQT_NO_MIME -void TQTextEdit::setMimeSourceFactory( TQMimeSourceFactory* factory ) -{ - doc->setMimeSourceFactory( factory ); -} - -/*! - Returns the TQMimeSourceFactory which is being used by this text - edit. - - \sa setMimeSourceFactory() -*/ - -TQMimeSourceFactory* TQTextEdit::mimeSourceFactory() const -{ - return doc->mimeSourceFactory(); -} -#endif - -/*! - Returns how many pixels high the text edit needs to be to display - all the text if the text edit is \a w pixels wide. -*/ - -int TQTextEdit::heightForWidth( int w ) const -{ - int oldw = doc->width(); - doc->doLayout( 0, w ); - int h = doc->height(); - doc->setWidth( oldw ); - doc->invalidate(); - ( (TQTextEdit*)this )->formatMore(); - return h; -} - -/*! - Appends a new paragraph with \a text to the end of the text edit. Note that - the undo/redo history is cleared by this function, and no undo - history is kept for appends which makes them faster than - insert()s. If you want to append text which is added to the - undo/redo history as well, use insertParagraph(). -*/ - -void TQTextEdit::append( const TQString &text ) -{ -#ifdef QT_TEXTEDIT_OPTIMIZATION - if ( d->optimMode ) { - optimAppend( text ); - return; - } -#endif - // flush and clear the undo/redo stack if necessary - undoRedoInfo.clear(); - doc->commands()->clear(); - - doc->removeSelection( TQTextDocument::Standard ); - TextFormat f = doc->textFormat(); - if ( f == AutoText ) { - if ( TQStyleSheet::mightBeRichText( text ) ) - f = RichText; - else - f = PlainText; - } - - drawCursor( FALSE ); - TQTextCursor oldc( *cursor ); - ensureFormatted( doc->lastParagraph() ); - bool atBottom = contentsY() >= contentsHeight() - visibleHeight(); - cursor->gotoEnd(); - if ( cursor->index() > 0 ) - cursor->splitAndInsertEmptyParagraph(); - TQTextCursor oldCursor2 = *cursor; - - if ( f == TQt::PlainText ) { - cursor->insert( text, TRUE ); - if ( doc->useFormatCollection() && !doc->preProcessor() && - currentFormat != cursor->paragraph()->at( cursor->index() )->format() ) { - doc->setSelectionStart( TQTextDocument::Temp, oldCursor2 ); - doc->setSelectionEnd( TQTextDocument::Temp, *cursor ); - doc->setFormat( TQTextDocument::Temp, currentFormat, TQTextFormat::Format ); - doc->removeSelection( TQTextDocument::Temp ); - } - } else { - cursor->paragraph()->setListItem( FALSE ); - cursor->paragraph()->setListDepth( 0 ); - if ( cursor->paragraph()->prev() ) - cursor->paragraph()->prev()->invalidate(0); // vertical margins might have to change - doc->setRichTextInternal( text ); - } - formatMore(); - repaintChanged(); - if ( atBottom ) - scrollToBottom(); - *cursor = oldc; - if ( !isReadOnly() ) - cursorVisible = TRUE; - setModified(); - emit textChanged(); -} - -/*! - \property TQTextEdit::hasSelectedText - \brief whether some text is selected in selection 0 -*/ - -bool TQTextEdit::hasSelectedText() const -{ -#ifdef QT_TEXTEDIT_OPTIMIZATION - if ( d->optimMode ) - return optimHasSelection(); - else -#endif - return doc->hasSelection( TQTextDocument::Standard ); -} - -/*! - \property TQTextEdit::selectedText - \brief The selected text (from selection 0) or an empty string if - there is no currently selected text (in selection 0). - - The text is always returned as \c PlainText if the textFormat() is - \c PlainText or \c AutoText, otherwise it is returned as HTML. - - \sa hasSelectedText -*/ - -TQString TQTextEdit::selectedText() const -{ -#ifdef QT_TEXTEDIT_OPTIMIZATION - if ( d->optimMode ) - return optimSelectedText(); - else -#endif - return doc->selectedText( TQTextDocument::Standard, textFormat() == RichText ); -} - -bool TQTextEdit::handleReadOnlyKeyEvent( TQKeyEvent *e ) -{ - switch( e->key() ) { - case Key_Down: - setContentsPos( contentsX(), contentsY() + 10 ); - break; - case Key_Up: - setContentsPos( contentsX(), contentsY() - 10 ); - break; - case Key_Left: - setContentsPos( contentsX() - 10, contentsY() ); - break; - case Key_Right: - setContentsPos( contentsX() + 10, contentsY() ); - break; - case Key_PageUp: - setContentsPos( contentsX(), contentsY() - visibleHeight() ); - break; - case Key_PageDown: - setContentsPos( contentsX(), contentsY() + visibleHeight() ); - break; - case Key_Home: - setContentsPos( contentsX(), 0 ); - break; - case Key_End: - setContentsPos( contentsX(), contentsHeight() - visibleHeight() ); - break; - case Key_F16: // Copy key on Sun keyboards - copy(); - break; -#ifndef TQT_NO_NETWORKPROTOCOL - case Key_Return: - case Key_Enter: - case Key_Space: { - if (!doc->focusIndicator.href.isEmpty() - || !doc->focusIndicator.name.isEmpty()) { - if (!doc->focusIndicator.href.isEmpty()) { - TQUrl u( doc->context(), doc->focusIndicator.href, TRUE ); - emitLinkClicked( u.toString( FALSE, FALSE ) ); - } - if (!doc->focusIndicator.name.isEmpty()) { - if (::tqt_cast<TQTextBrowser*>(this)) { // change for 4.0 - TQConnectionList *clist = receivers( - "anchorClicked(const TQString&,const TQString&)"); - if (!signalsBlocked() && clist) { - TQUObject o[3]; - static_QUType_TQString.set(o+1, - doc->focusIndicator.name); - static_QUType_TQString.set(o+2, - doc->focusIndicator.href); - activate_signal( clist, o); - } - } - } -#ifndef TQT_NO_CURSOR - viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); -#endif - } - } break; -#endif - default: - if ( e->state() & ControlButton ) { - switch ( e->key() ) { - case Key_C: case Key_F16: // Copy key on Sun keyboards - copy(); - break; -#ifdef TQ_WS_WIN - case Key_Insert: - copy(); - break; - case Key_A: - selectAll(); - break; -#endif - } - - } - return FALSE; - } - return TRUE; -} - -/*! - Returns the context of the text edit. The context is a path which - the text edit's TQMimeSourceFactory uses to resolve the locations - of files and images. - - \sa text -*/ - -TQString TQTextEdit::context() const -{ - return doc->context(); -} - -/*! - \property TQTextEdit::documentTitle - \brief the title of the document parsed from the text. - - For \c PlainText the title will be an empty string. For \c - RichText the title will be the text between the \c{<title>} tags, - if present, otherwise an empty string. -*/ - -TQString TQTextEdit::documentTitle() const -{ - return doc->attributes()[ "title" ]; -} - -void TQTextEdit::makeParagVisible( TQTextParagraph *p ) -{ - setContentsPos( contentsX(), TQMIN( p->rect().y(), contentsHeight() - visibleHeight() ) ); -} - -/*! - Scrolls the text edit to make the text at the anchor called \a - name visible, if it can be found in the document. If the anchor - isn't found no scrolling will occur. An anchor is defined using - the HTML anchor tag, e.g. \c{<a name="target">}. -*/ - -void TQTextEdit::scrollToAnchor( const TQString& name ) -{ - if ( !isVisible() ) { - d->scrollToAnchor = name; - return; - } - if ( name.isEmpty() ) - return; - sync(); - TQTextCursor cursor( doc ); - TQTextParagraph* last = doc->lastParagraph(); - for (;;) { - TQTextStringChar* c = cursor.paragraph()->at( cursor.index() ); - if( c->isAnchor() ) { - TQString a = c->anchorName(); - if ( a == name || - (a.contains( '#' ) && TQStringList::split( '#', a ).contains( name ) ) ) { - setContentsPos( contentsX(), TQMIN( cursor.paragraph()->rect().top() + cursor.totalOffsetY(), contentsHeight() - visibleHeight() ) ); - break; - } - } - if ( cursor.paragraph() == last && cursor.atParagEnd() ) - break; - cursor.gotoNextLetter(); - } -} - -/*! - \overload - - If there is an anchor at position \a pos (in contents - coordinates), its \c href is returned, otherwise TQString::null is - returned. -*/ - -TQString TQTextEdit::anchorAt( const TQPoint& pos ) -{ - return anchorAt(pos, AnchorHref); -} - -/*! - If there is an anchor at position \a pos (in contents - coordinates), the text for attribute \a attr is returned, - otherwise TQString::null is returned. -*/ - -TQString TQTextEdit::anchorAt( const TQPoint& pos, AnchorAttribute attr ) -{ - TQTextCursor c( doc ); - placeCursor( pos, &c ); - switch(attr) { - case AnchorName: - return c.paragraph()->at( c.index() )->anchorName(); - case AnchorHref: - return c.paragraph()->at( c.index() )->anchorHref(); - } - // incase the compiler is really dumb about determining if a function - // returns something :) - return TQString::null; -} - -void TQTextEdit::documentWidthChanged( int w ) -{ - resizeContents( TQMAX( visibleWidth(), w), contentsHeight() ); -} - -/*! \internal - - This function does nothing -*/ - -void TQTextEdit::updateStyles() -{ -} - -void TQTextEdit::setDocument( TQTextDocument *dc ) -{ - if ( dc == 0 ) { - tqWarning( "Q3TextEdit::setDocument() called with null Q3TextDocument pointer" ); - return; - } - if ( dc == doc ) - return; - resetInputContext(); - doc = dc; - delete cursor; - cursor = new TQTextCursor( doc ); - clearUndoRedo(); - undoRedoInfo.doc = doc; - lastFormatted = 0; -} - -#ifndef TQT_NO_CLIPBOARD - -/*! - Pastes the text with format \a subtype from the clipboard into the - text edit at the current cursor position. The \a subtype can be - "plain" or "html". - - If there is no text with format \a subtype in the clipboard - nothing happens. - - \sa paste() cut() TQTextEdit::copy() -*/ - -void TQTextEdit::pasteSubType( const TQCString &subtype ) -{ -#ifndef TQT_NO_MIMECLIPBOARD - TQMimeSource *m = TQApplication::clipboard()->data( d->clipboard_mode ); - pasteSubType( subtype, m ); -#endif -} - -/*! \internal */ - -void TQTextEdit::pasteSubType( const TQCString& subtype, TQMimeSource *m ) -{ -#ifndef TQT_NO_MIME - TQCString st = subtype; - if ( subtype != "x-qrichtext" ) - st.prepend( "text/" ); - else - st.prepend( "application/" ); - if ( !m ) - return; - if ( doc->hasSelection( TQTextDocument::Standard ) ) - removeSelectedText(); - if ( !TQRichTextDrag::canDecode( m ) ) - return; - TQString t; - if ( !TQRichTextDrag::decode( m, t, st.data(), subtype ) ) - return; - if ( st == "application/x-qrichtext" ) { - int start; - if ( (start = t.find( "<!--StartFragment-->" )) != -1 ) { - start += 20; - int end = t.find( "<!--EndFragment-->" ); - TQTextCursor oldC = *cursor; - - // during the setRichTextInternal() call the cursors - // paragraph might get joined with the provious one, so - // the cursors one would get deleted and oldC.paragraph() - // would be a dnagling pointer. To avoid that try to go - // one letter back and later go one forward again. - oldC.gotoPreviousLetter(); - bool couldGoBack = oldC != *cursor; - // first para might get deleted, so remember to reset it - bool wasAtFirst = oldC.paragraph() == doc->firstParagraph(); - - if ( start < end ) - t = t.mid( start, end - start ); - else - t = t.mid( start ); - lastFormatted = cursor->paragraph(); - if ( lastFormatted->prev() ) - lastFormatted = lastFormatted->prev(); - doc->setRichTextInternal( t, cursor ); - - // the first para might have been deleted in - // setRichTextInternal(). To be sure, reset it if - // necessary. - if ( wasAtFirst ) { - int index = oldC.index(); - oldC.setParagraph( doc->firstParagraph() ); - oldC.setIndex( index ); - } - - // if we went back one letter before (see last comment), - // go one forward to point to the right position - if ( couldGoBack ) - oldC.gotoNextLetter(); - - if ( undoEnabled && !isReadOnly() ) { - doc->setSelectionStart( TQTextDocument::Temp, oldC ); - doc->setSelectionEnd( TQTextDocument::Temp, *cursor ); - - checkUndoRedoInfo( UndoRedoInfo::Insert ); - if ( !undoRedoInfo.valid() ) { - undoRedoInfo.id = oldC.paragraph()->paragId(); - undoRedoInfo.index = oldC.index(); - undoRedoInfo.d->text = TQString::null; - } - int oldLen = undoRedoInfo.d->text.length(); - if ( !doc->preProcessor() ) { - TQString txt = doc->selectedText( TQTextDocument::Temp ); - undoRedoInfo.d->text += txt; - for ( int i = 0; i < (int)txt.length(); ++i ) { - if ( txt[ i ] != '\n' && oldC.paragraph()->at( oldC.index() )->format() ) { - oldC.paragraph()->at( oldC.index() )->format()->addRef(); - undoRedoInfo.d->text. - setFormat( oldLen + i, oldC.paragraph()->at( oldC.index() )->format(), TRUE ); - } - oldC.gotoNextLetter(); - } - } - undoRedoInfo.clear(); - removeSelection( TQTextDocument::Temp ); - } - - formatMore(); - setModified(); - emit textChanged(); - repaintChanged(); - ensureCursorVisible(); - return; - } - } else { -#if defined(Q_OS_WIN32) - // Need to convert CRLF to LF - t.replace( "\r\n", "\n" ); -#elif defined(Q_OS_MAC) - //need to convert CR to LF - t.replace( '\r', '\n' ); -#endif - TQChar *uc = (TQChar *)t.unicode(); - for ( int i=0; (uint) i<t.length(); i++ ) { - if ( uc[ i ] < ' ' && uc[ i ] != '\n' && uc[ i ] != '\t' ) - uc[ i ] = ' '; - } - if ( !t.isEmpty() ) - insert( t, FALSE, TRUE ); - } -#endif //TQT_NO_MIME -} - -#ifndef TQT_NO_MIMECLIPBOARD -/*! - Prompts the user to choose a type from a list of text types - available, then copies text from the clipboard (if there is any) - into the text edit at the current text cursor position. Any - selected text (in selection 0) is first deleted. -*/ -void TQTextEdit::pasteSpecial( const TQPoint& pt ) -{ - TQCString st = pickSpecial( TQApplication::clipboard()->data( d->clipboard_mode ), - TRUE, pt ); - if ( !st.isEmpty() ) - pasteSubType( st ); -} -#endif -#ifndef TQT_NO_MIME -TQCString TQTextEdit::pickSpecial( TQMimeSource* ms, bool always_ask, const TQPoint& pt ) -{ - if ( ms ) { -#ifndef TQT_NO_POPUPMENU - TQPopupMenu popup( this, "qt_pickspecial_menu" ); - TQString fmt; - int n = 0; - TQDict<void> done; - for (int i = 0; !( fmt = ms->format( i ) ).isNull(); i++) { - int semi = fmt.find( ";" ); - if ( semi >= 0 ) - fmt = fmt.left( semi ); - if ( fmt.left( 5 ) == "text/" ) { - fmt = fmt.mid( 5 ); - if ( !done.find( fmt ) ) { - done.insert( fmt,(void*)1 ); - popup.insertItem( fmt, i ); - n++; - } - } - } - if ( n ) { - int i = n ==1 && !always_ask ? popup.idAt( 0 ) : popup.exec( pt ); - if ( i >= 0 ) - return popup.text(i).latin1(); - } -#else - TQString fmt; - for (int i = 0; !( fmt = ms->format( i ) ).isNull(); i++) { - int semi = fmt.find( ";" ); - if ( semi >= 0 ) - fmt = fmt.left( semi ); - if ( fmt.left( 5 ) == "text/" ) { - fmt = fmt.mid( 5 ); - return fmt.latin1(); - } - } -#endif - } - return TQCString(); -} -#endif // TQT_NO_MIME -#endif // TQT_NO_CLIPBOARD - -/*! - \enum TQTextEdit::WordWrap - - This enum defines the TQTextEdit's word wrap modes. - - \value NoWrap Do not wrap the text. - - \value WidgetWidth Wrap the text at the current width of the - widget (this is the default). Wrapping is at whitespace by - default; this can be changed with setWrapPolicy(). - - \value FixedPixelWidth Wrap the text at a fixed number of pixels - from the widget's left side. The number of pixels is set with - wrapColumnOrWidth(). - - \value FixedColumnWidth Wrap the text at a fixed number of - character columns from the widget's left side. The number of - characters is set with wrapColumnOrWidth(). This is useful if you - need formatted text that can also be displayed gracefully on - devices with monospaced fonts, for example a standard VT100 - terminal, where you might set wrapColumnOrWidth() to 80. - - \sa setWordWrap() wordWrap() -*/ - -/*! - \property TQTextEdit::wordWrap - \brief the word wrap mode - - The default mode is \c WidgetWidth which causes words to be - wrapped at the right edge of the text edit. Wrapping occurs at - whitespace, keeping whole words intact. If you want wrapping to - occur within words use setWrapPolicy(). If you set a wrap mode of - \c FixedPixelWidth or \c FixedColumnWidth you should also call - setWrapColumnOrWidth() with the width you want. - - \sa WordWrap, wrapColumnOrWidth, wrapPolicy, -*/ - -void TQTextEdit::setWordWrap( WordWrap mode ) -{ - if ( wrapMode == mode ) - return; - wrapMode = mode; - switch ( mode ) { - case NoWrap: - document()->formatter()->setWrapEnabled( FALSE ); - document()->formatter()->setWrapAtColumn( -1 ); - doc->setWidth( visibleWidth() ); - doc->setMinimumWidth( -1 ); - doc->invalidate(); - updateContents(); - lastFormatted = doc->firstParagraph(); - interval = 0; - formatMore(); - break; - case WidgetWidth: - document()->formatter()->setWrapEnabled( TRUE ); - document()->formatter()->setWrapAtColumn( -1 ); - doResize(); - break; - case FixedPixelWidth: - document()->formatter()->setWrapEnabled( TRUE ); - document()->formatter()->setWrapAtColumn( -1 ); - if ( wrapWidth < 0 ) - wrapWidth = 200; - setWrapColumnOrWidth( wrapWidth ); - break; - case FixedColumnWidth: - if ( wrapWidth < 0 ) - wrapWidth = 80; - document()->formatter()->setWrapEnabled( TRUE ); - document()->formatter()->setWrapAtColumn( wrapWidth ); - setWrapColumnOrWidth( wrapWidth ); - break; - } -#ifdef QT_TEXTEDIT_OPTIMIZATION - checkOptimMode(); -#endif -} - -TQTextEdit::WordWrap TQTextEdit::wordWrap() const -{ - return wrapMode; -} - -/*! - \property TQTextEdit::wrapColumnOrWidth - \brief the position (in pixels or columns depending on the wrap mode) where text will be wrapped - - If the wrap mode is \c FixedPixelWidth, the value is the number of - pixels from the left edge of the text edit at which text should be - wrapped. If the wrap mode is \c FixedColumnWidth, the value is the - column number (in character columns) from the left edge of the - text edit at which text should be wrapped. - - \sa wordWrap -*/ -void TQTextEdit::setWrapColumnOrWidth( int value ) -{ - wrapWidth = value; - if ( wrapMode == FixedColumnWidth ) { - document()->formatter()->setWrapAtColumn( wrapWidth ); - resizeContents( 0, 0 ); - doc->setWidth( visibleWidth() ); - doc->setMinimumWidth( -1 ); - } else if (wrapMode == FixedPixelWidth ) { - document()->formatter()->setWrapAtColumn( -1 ); - resizeContents( wrapWidth, 0 ); - doc->setWidth( wrapWidth ); - doc->setMinimumWidth( wrapWidth ); - } else { - return; - } - doc->invalidate(); - updateContents(); - lastFormatted = doc->firstParagraph(); - interval = 0; - formatMore(); -} - -int TQTextEdit::wrapColumnOrWidth() const -{ - if ( wrapMode == WidgetWidth ) - return visibleWidth(); - return wrapWidth; -} - - -/*! - \enum TQTextEdit::WrapPolicy - - This enum defines where text can be wrapped in word wrap mode. - - \value AtWhiteSpace Don't use this deprecated value (it is a - synonym for \c AtWordBoundary which you should use instead). - \value Anywhere Break anywhere, including within words. - \value AtWordBoundary Break lines at word boundaries, e.g. spaces or - newlines - \value AtWordOrDocumentBoundary Break lines at whitespace, e.g. - spaces or newlines if possible. Break it anywhere otherwise. - - \sa setWrapPolicy() -*/ - -/*! - \property TQTextEdit::wrapPolicy - \brief the word wrap policy, at whitespace or anywhere - - Defines where text can be wrapped when word wrap mode is not \c - NoWrap. The choices are \c AtWordBoundary (the default), \c - Anywhere and \c AtWordOrDocumentBoundary - - \sa wordWrap -*/ - -void TQTextEdit::setWrapPolicy( WrapPolicy policy ) -{ - if ( wPolicy == policy ) - return; - wPolicy = policy; - TQTextFormatter *formatter; - if ( policy == AtWordBoundary || policy == AtWordOrDocumentBoundary ) { - formatter = new TQTextFormatterBreakWords; - formatter->setAllowBreakInWords( policy == AtWordOrDocumentBoundary ); - } else { - formatter = new TQTextFormatterBreakInWords; - } - formatter->setWrapAtColumn( document()->formatter()->wrapAtColumn() ); - formatter->setWrapEnabled( document()->formatter()->isWrapEnabled( 0 ) ); - document()->setFormatter( formatter ); - doc->invalidate(); - updateContents(); - lastFormatted = doc->firstParagraph(); - interval = 0; - formatMore(); -} - -TQTextEdit::WrapPolicy TQTextEdit::wrapPolicy() const -{ - return wPolicy; -} - -/*! - Deletes all the text in the text edit. - - \sa cut() removeSelectedText() setText() -*/ - -void TQTextEdit::clear() -{ -#ifdef QT_TEXTEDIT_OPTIMIZATION - if ( d->optimMode ) { - optimSetText(""); - } else -#endif - { - // make clear undoable - doc->selectAll( TQTextDocument::Temp ); - removeSelectedText( TQTextDocument::Temp ); - setContentsPos( 0, 0 ); - if ( cursor->isValid() ) - cursor->restoreState(); - doc->clear( TRUE ); - delete cursor; - cursor = new TQTextCursor( doc ); - lastFormatted = 0; - } - updateContents(); - - emit cursorPositionChanged( cursor ); - emit cursorPositionChanged( cursor->paragraph()->paragId(), cursor->index() ); -} - -int TQTextEdit::undoDepth() const -{ - return document()->undoDepth(); -} - -/*! - \property TQTextEdit::length - \brief the number of characters in the text -*/ - -int TQTextEdit::length() const -{ -#ifdef QT_TEXTEDIT_OPTIMIZATION - if ( d->optimMode ) - return d->od->len; - else -#endif - return document()->length(); -} - -/*! - \property TQTextEdit::tabStopWidth - \brief the tab stop width in pixels -*/ - -int TQTextEdit::tabStopWidth() const -{ - return document()->tabStopWidth(); -} - -void TQTextEdit::setUndoDepth( int d ) -{ - document()->setUndoDepth( d ); -} - -void TQTextEdit::setTabStopWidth( int ts ) -{ - document()->setTabStops( ts ); - doc->invalidate(); - lastFormatted = doc->firstParagraph(); - interval = 0; - formatMore(); - updateContents(); -} - -/*! - \reimp -*/ - -TQSize TQTextEdit::sizeHint() const -{ - // cf. TQScrollView::sizeHint() - constPolish(); - int f = 2 * frameWidth(); - int h = fontMetrics().height(); - TQSize sz( f, f ); - return sz.expandedTo( TQSize(12 * h, 8 * h) ); -} - -void TQTextEdit::clearUndoRedo() -{ - if ( !undoEnabled ) - return; - undoRedoInfo.clear(); - emit undoAvailable( doc->commands()->isUndoAvailable() ); - emit redoAvailable( doc->commands()->isRedoAvailable() ); -} - -/*! \internal - \warning In TQt 3.1 we will provide a cleaer API for the - functionality which is provided by this function and in TQt 4.0 this - function will go away. - - This function gets the format of the character at position \a - index in paragraph \a para. Sets \a font to the character's font, \a - color to the character's color and \a verticalAlignment to the - character's vertical alignment. - - Returns FALSE if \a para or \a index is out of range otherwise - returns TRUE. -*/ - -bool TQTextEdit::getFormat( int para, int index, TQFont *font, TQColor *color, VerticalAlignment *verticalAlignment ) -{ - if ( !font || !color ) - return FALSE; - TQTextParagraph *p = doc->paragAt( para ); - if ( !p ) - return FALSE; - if ( index < 0 || index >= p->length() ) - return FALSE; - *font = p->at( index )->format()->font(); - *color = p->at( index )->format()->color(); - *verticalAlignment = (VerticalAlignment)p->at( index )->format()->vAlign(); - return TRUE; -} - -/*! \internal - \warning In TQt 3.1 we will provide a cleaer API for the - functionality which is provided by this function and in TQt 4.0 this - function will go away. - - This function gets the format of the paragraph \a para. Sets \a - font to the paragraphs's font, \a color to the paragraph's color, \a - verticalAlignment to the paragraph's vertical alignment, \a - alignment to the paragraph's alignment, \a displayMode to the - paragraph's display mode, \a listStyle to the paragraph's list style - (if the display mode is TQStyleSheetItem::DisplayListItem) and \a - listDepth to the depth of the list (if the display mode is - TQStyleSheetItem::DisplayListItem). - - Returns FALSE if \a para is out of range otherwise returns TRUE. -*/ - -bool TQTextEdit::getParagraphFormat( int para, TQFont *font, TQColor *color, - VerticalAlignment *verticalAlignment, int *alignment, - TQStyleSheetItem::DisplayMode *displayMode, - TQStyleSheetItem::ListStyle *listStyle, - int *listDepth ) -{ - if ( !font || !color || !alignment || !displayMode || !listStyle ) - return FALSE; - TQTextParagraph *p = doc->paragAt( para ); - if ( !p ) - return FALSE; - *font = p->at(0)->format()->font(); - *color = p->at(0)->format()->color(); - *verticalAlignment = (VerticalAlignment)p->at(0)->format()->vAlign(); - *alignment = p->alignment(); - *displayMode = p->isListItem() ? TQStyleSheetItem::DisplayListItem : TQStyleSheetItem::DisplayBlock; - *listStyle = p->listStyle(); - *listDepth = p->listDepth(); - return TRUE; -} - - - -/*! - This function is called to create a right mouse button popup menu - at the document position \a pos. If you want to create a custom - popup menu, reimplement this function and return the created popup - menu. Ownership of the popup menu is transferred to the caller. - - \warning The TQPopupMenu ID values 0-7 are reserved, and they map to the - standard operations. When inserting items into your custom popup menu, be - sure to specify ID values larger than 7. -*/ - -TQPopupMenu *TQTextEdit::createPopupMenu( const TQPoint& pos ) -{ - Q_UNUSED( pos ) -#ifndef TQT_NO_POPUPMENU - TQPopupMenu *popup = new TQPopupMenu( this, "qt_edit_menu" ); - if ( !isReadOnly() ) { - d->id[ IdUndo ] = popup->insertItem( tr( "&Undo" ) + ACCEL_KEY( Z ) ); - d->id[ IdRedo ] = popup->insertItem( tr( "&Redo" ) + ACCEL_KEY( Y ) ); - popup->insertSeparator(); - } -#ifndef TQT_NO_CLIPBOARD - if ( !isReadOnly() ) - d->id[ IdCut ] = popup->insertItem( tr( "Cu&t" ) + ACCEL_KEY( X ) ); - d->id[ IdCopy ] = popup->insertItem( tr( "&Copy" ) + ACCEL_KEY( C ) ); - if ( !isReadOnly() ) - d->id[ IdPaste ] = popup->insertItem( tr( "&Paste" ) + ACCEL_KEY( V ) ); -#endif - if ( !isReadOnly() ) { - d->id[ IdClear ] = popup->insertItem( tr( "Clear" ) ); - popup->insertSeparator(); - } -#if defined(TQ_WS_X11) - d->id[ IdSelectAll ] = popup->insertItem( tr( "Select All" ) ); -#else - d->id[ IdSelectAll ] = popup->insertItem( tr( "Select All" ) + ACCEL_KEY( A ) ); -#endif - -#ifndef TQT_NO_IM - TQInputContext *qic = getInputContext(); - if ( qic ) - qic->addMenusTo( popup ); -#endif - - popup->setItemEnabled( d->id[ IdUndo ], !isReadOnly() && doc->commands()->isUndoAvailable() ); - popup->setItemEnabled( d->id[ IdRedo ], !isReadOnly() && doc->commands()->isRedoAvailable() ); -#ifndef TQT_NO_CLIPBOARD - popup->setItemEnabled( d->id[ IdCut ], !isReadOnly() && doc->hasSelection( TQTextDocument::Standard, TRUE ) ); -#ifdef QT_TEXTEDIT_OPTIMIZATION - popup->setItemEnabled( d->id[ IdCopy ], d->optimMode ? optimHasSelection() : doc->hasSelection( TQTextDocument::Standard, TRUE ) ); -#else - popup->setItemEnabled( d->id[ IdCopy ], doc->hasSelection( TQTextDocument::Standard, TRUE ) ); -#endif - popup->setItemEnabled( d->id[ IdPaste ], !isReadOnly() && !TQApplication::clipboard()->text( d->clipboard_mode ).isEmpty() ); -#endif - const bool isEmptyDocument = (length() == 0); - popup->setItemEnabled( d->id[ IdClear ], !isReadOnly() && !isEmptyDocument ); - popup->setItemEnabled( d->id[ IdSelectAll ], !isEmptyDocument ); - return popup; -#else - return 0; -#endif -} - -/*! \overload - \obsolete - This function is called to create a right mouse button popup menu. - If you want to create a custom popup menu, reimplement this function - and return the created popup menu. Ownership of the popup menu is - transferred to the caller. - - This function is only called if createPopupMenu( const TQPoint & ) - returns 0. -*/ - -TQPopupMenu *TQTextEdit::createPopupMenu() -{ - return 0; -} - -/*! - \reimp -*/ - -void TQTextEdit::setFont( const TQFont &f ) -{ -#ifdef QT_TEXTEDIT_OPTIMIZATION - if ( d->optimMode ) { - TQScrollView::setFont( f ); - doc->setDefaultFormat( f, doc->formatCollection()->defaultFormat()->color() ); - // recalculate the max string width - TQFontMetrics fm(f); - int i, sw; - d->od->maxLineWidth = 0; - for ( i = 0; i < d->od->numLines; i++ ) { - sw = fm.width(d->od->lines[LOGOFFSET(i)]); - if (d->od->maxLineWidth < sw) - d->od->maxLineWidth = sw; - } - resizeContents(d->od->maxLineWidth + 4, d->od->numLines * fm.lineSpacing() + 1); - return; - } -#endif - TQScrollView::setFont( f ); - doc->setMinimumWidth( -1 ); - doc->setDefaultFormat( f, doc->formatCollection()->defaultFormat()->color() ); - lastFormatted = doc->firstParagraph(); - formatMore(); - repaintChanged(); -} - -/*! - \fn TQTextEdit::zoomIn() - - \overload - - Zooms in on the text by making the base font size one point - larger and recalculating all font sizes to be the new size. This - does not change the size of any images. - - \sa zoomOut() -*/ - -/*! - \fn TQTextEdit::zoomOut() - - \overload - - Zooms out on the text by making the base font size one point - smaller and recalculating all font sizes to be the new size. This - does not change the size of any images. - - \sa zoomIn() -*/ - - -/*! - Zooms in on the text by making the base font size \a range - points larger and recalculating all font sizes to be the new size. - This does not change the size of any images. - - \sa zoomOut() -*/ - -void TQTextEdit::zoomIn( int range ) -{ - TQFont f( TQScrollView::font() ); - TQFontInfo fi(f); - if (fi.pointSize() <= 0) { - f.setPixelSize( fi.pixelSize() + range ); - } else { - f.setPointSize( fi.pointSize() + range ); - } - setFont( f ); -} - -/*! - Zooms out on the text by making the base font size \a range points - smaller and recalculating all font sizes to be the new size. This - does not change the size of any images. - - \sa zoomIn() -*/ - -void TQTextEdit::zoomOut( int range ) -{ - TQFont f( TQScrollView::font() ); - TQFontInfo fi(f); - if (fi.pointSize() <= 0) { - f.setPixelSize( TQMAX( 1, fi.pixelSize() - range ) ); - } else { - f.setPointSize( TQMAX( 1, fi.pointSize() - range ) ); - } - setFont( f ); -} - -/*! - Zooms the text by making the base font size \a size points and - recalculating all font sizes to be the new size. This does not - change the size of any images. -*/ - -void TQTextEdit::zoomTo( int size ) -{ - TQFont f( TQScrollView::font() ); - f.setPointSize( size ); - setFont( f ); -} - -/*! - TQTextEdit is optimized for large amounts text. One of its - optimizations is to format only the visible text, formatting the rest - on demand, e.g. as the user scrolls, so you don't usually need to - call this function. - - In some situations you may want to force the whole text - to be formatted. For example, if after calling setText(), you wanted - to know the height of the document (using contentsHeight()), you - would call this function first. -*/ - -void TQTextEdit::sync() -{ -#ifdef QT_TEXTEDIT_OPTIMIZATION - if ( d->optimMode ) { - TQFontMetrics fm( TQScrollView::font() ); - resizeContents( d->od->maxLineWidth + 4, d->od->numLines * fm.lineSpacing() + 1 ); - } else -#endif - { - while ( lastFormatted ) { - lastFormatted->format(); - lastFormatted = lastFormatted->next(); - } - resizeContents( contentsWidth(), doc->height() ); - } - updateScrollBars(); -} - -/*! - \reimp -*/ - -void TQTextEdit::setEnabled( bool b ) -{ - TQScrollView::setEnabled( b ); - if ( textFormat() == PlainText ) { - TQTextFormat *f = doc->formatCollection()->defaultFormat(); - f->setColor( colorGroup().text() ); - updateContents(); - } -} - -/*! - Sets the background color of selection number \a selNum to \a back - and specifies whether the text of this selection should be - inverted with \a invertText. - - This only works for \a selNum > 0. The default selection (\a - selNum == 0) gets its attributes from the text edit's - colorGroup(). -*/ - -void TQTextEdit::setSelectionAttributes( int selNum, const TQColor &back, bool invertText ) -{ - if ( selNum < 1 ) - return; - if ( selNum > doc->numSelections() ) - doc->addSelection( selNum ); - doc->setSelectionColor( selNum, back ); - doc->setInvertSelectionText( selNum, invertText ); -} - -/*! - \reimp -*/ -void TQTextEdit::windowActivationChange( bool oldActive ) -{ - if ( oldActive && scrollTimer ) - scrollTimer->stop(); - if ( palette().active() != palette().inactive() ) - updateContents(); - TQScrollView::windowActivationChange( oldActive ); -} - -void TQTextEdit::setReadOnly( bool b ) -{ - if ( (bool) readOnly == b ) - return; - readOnly = b; -#ifndef TQT_NO_CURSOR - if ( readOnly ) - viewport()->setCursor( arrowCursor ); - else - viewport()->setCursor( ibeamCursor ); - setInputMethodEnabled( !readOnly ); -#endif -#ifdef QT_TEXTEDIT_OPTIMIZATION - checkOptimMode(); -#endif -} - -/*! - Scrolls to the bottom of the document and does formatting if - required. -*/ - -void TQTextEdit::scrollToBottom() -{ - sync(); - setContentsPos( contentsX(), contentsHeight() - visibleHeight() ); -} - -/*! - Returns the rectangle of the paragraph \a para in contents - coordinates, or an invalid rectangle if \a para is out of range. -*/ - -TQRect TQTextEdit::paragraphRect( int para ) const -{ - TQTextEdit *that = (TQTextEdit *)this; - that->sync(); - TQTextParagraph *p = doc->paragAt( para ); - if ( !p ) - return TQRect( -1, -1, -1, -1 ); - return p->rect(); -} - -/*! - Returns the paragraph which is at position \a pos (in contents - coordinates). -*/ - -int TQTextEdit::paragraphAt( const TQPoint &pos ) const -{ -#ifdef QT_TEXTEDIT_OPTIMIZATION - if ( d->optimMode ) { - TQFontMetrics fm( TQScrollView::font() ); - int parag = pos.y() / fm.lineSpacing(); - if ( parag <= d->od->numLines ) - return parag; - else - return 0; - } -#endif - TQTextCursor c( doc ); - c.place( pos, doc->firstParagraph() ); - if ( c.paragraph() ) - return c.paragraph()->paragId(); - return -1; // should never happen.. -} - -/*! - Returns the index of the character (relative to its paragraph) at - position \a pos (in contents coordinates). If \a para is not 0, - \a *para is set to the character's paragraph. -*/ - -int TQTextEdit::charAt( const TQPoint &pos, int *para ) const -{ -#ifdef QT_TEXTEDIT_OPTIMIZATION - if ( d->optimMode ) { - int par = paragraphAt( pos ); - if ( para ) - *para = par; - return optimCharIndex( d->od->lines[ LOGOFFSET(par) ], pos.x() ); - } -#endif - TQTextCursor c( doc ); - c.place( pos, doc->firstParagraph() ); - if ( c.paragraph() ) { - if ( para ) - *para = c.paragraph()->paragId(); - return c.index(); - } - return -1; // should never happen.. -} - -/*! - Sets the background color of the paragraph \a para to \a bg. -*/ - -void TQTextEdit::setParagraphBackgroundColor( int para, const TQColor &bg ) -{ - TQTextParagraph *p = doc->paragAt( para ); - if ( !p ) - return; - p->setBackgroundColor( bg ); - repaintChanged(); -} - -/*! - Clears the background color of the paragraph \a para, so that the - default color is used again. -*/ - -void TQTextEdit::clearParagraphBackground( int para ) -{ - TQTextParagraph *p = doc->paragAt( para ); - if ( !p ) - return; - p->clearBackgroundColor(); - repaintChanged(); -} - -/*! - Returns the background color of the paragraph \a para or an - invalid color if \a para is out of range or the paragraph has no - background set -*/ - -TQColor TQTextEdit::paragraphBackgroundColor( int para ) const -{ - TQTextParagraph *p = doc->paragAt( para ); - if ( !p ) - return TQColor(); - TQColor *c = p->backgroundColor(); - if ( c ) - return *c; - return TQColor(); -} - -/*! - \property TQTextEdit::undoRedoEnabled - \brief whether undo/redo is enabled - - When changing this property, the undo/redo history is cleared. - - The default is TRUE. -*/ - -void TQTextEdit::setUndoRedoEnabled( bool b ) -{ - undoRedoInfo.clear(); - doc->commands()->clear(); - - undoEnabled = b; -} - -bool TQTextEdit::isUndoRedoEnabled() const -{ - return undoEnabled; -} - -/*! - Returns TRUE if undo is available; otherwise returns FALSE. -*/ - -bool TQTextEdit::isUndoAvailable() const -{ - return undoEnabled && (doc->commands()->isUndoAvailable() || undoRedoInfo.valid()); -} - -/*! - Returns TRUE if redo is available; otherwise returns FALSE. -*/ - -bool TQTextEdit::isRedoAvailable() const -{ - return undoEnabled && doc->commands()->isRedoAvailable(); -} - -void TQTextEdit::ensureFormatted( TQTextParagraph *p ) -{ - while ( !p->isValid() ) { - if ( !lastFormatted ) - return; - formatMore(); - } -} - -/*! \internal */ -void TQTextEdit::updateCursor( const TQPoint & pos ) -{ - if ( isReadOnly() && linksEnabled() ) { - TQTextCursor c = *cursor; - placeCursor( pos, &c, TRUE ); - -#ifndef TQT_NO_NETWORKPROTOCOL - bool insideParagRect = TRUE; - if (c.paragraph() == doc->lastParagraph() - && c.paragraph()->rect().y() + c.paragraph()->rect().height() < pos.y()) - insideParagRect = FALSE; - if (insideParagRect && c.paragraph() && c.paragraph()->at( c.index() ) && - c.paragraph()->at( c.index() )->isAnchor()) { - if (!c.paragraph()->at( c.index() )->anchorHref().isEmpty() - && c.index() < c.paragraph()->length() - 1 ) - onLink = c.paragraph()->at( c.index() )->anchorHref(); - else - onLink = TQString::null; - - if (!c.paragraph()->at( c.index() )->anchorName().isEmpty() - && c.index() < c.paragraph()->length() - 1 ) - d->onName = c.paragraph()->at( c.index() )->anchorName(); - else - d->onName = TQString::null; - - if (!c.paragraph()->at( c.index() )->anchorHref().isEmpty() ) { -#ifndef TQT_NO_CURSOR - viewport()->setCursor( onLink.isEmpty() ? arrowCursor : pointingHandCursor ); -#endif - TQUrl u( doc->context(), onLink, TRUE ); - emitHighlighted( u.toString( FALSE, FALSE ) ); - } - } else { -#ifndef TQT_NO_CURSOR - viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); -#endif - onLink = TQString::null; - emitHighlighted( TQString::null ); - } -#endif - } -} - -/*! - Places the cursor \a c at the character which is closest to position - \a pos (in contents coordinates). If \a c is 0, the default text - cursor is used. - - \sa setCursorPosition() -*/ -void TQTextEdit::placeCursor( const TQPoint &pos, TQTextCursor *c ) -{ - placeCursor( pos, c, FALSE ); -} - -/*! \internal */ -void TQTextEdit::clipboardChanged() -{ -#ifndef TQT_NO_CLIPBOARD - // don't listen to selection changes - disconnect( TQApplication::clipboard(), TQ_SIGNAL(selectionChanged()), this, 0); -#endif - selectAll(FALSE); -} - -/*! \property TQTextEdit::tabChangesFocus - \brief whether TAB changes focus or is accepted as input - - In some occasions text edits should not allow the user to input - tabulators or change indentation using the TAB key, as this breaks - the focus chain. The default is FALSE. - -*/ - -void TQTextEdit::setTabChangesFocus( bool b ) -{ - d->tabChangesFocus = b; -} - -bool TQTextEdit::tabChangesFocus() const -{ - return d->tabChangesFocus; -} - -#ifdef QT_TEXTEDIT_OPTIMIZATION -/* Implementation of optimized LogText mode follows */ - -static void tqSwap( int * a, int * b ) -{ - if ( !a || !b ) - return; - int tmp = *a; - *a = *b; - *b = tmp; -} - -/*! \internal */ -bool TQTextEdit::checkOptimMode() -{ - bool oldMode = d->optimMode; - if ( textFormat() == LogText ) { - setReadOnly( TRUE ); - d->optimMode = TRUE; - } else { - d->optimMode = FALSE; - } - - // when changing mode - try to keep selections and text - if ( oldMode != d->optimMode ) { - if ( d->optimMode ) { - d->od = new TQTextEditOptimPrivate; - connect( scrollTimer, TQ_SIGNAL( timeout() ), this, TQ_SLOT( optimDoAutoScroll() ) ); - disconnect( doc, TQ_SIGNAL( minimumWidthChanged(int) ), this, TQ_SLOT( documentWidthChanged(int) ) ); - disconnect( scrollTimer, TQ_SIGNAL( timeout() ), this, TQ_SLOT( autoScrollTimerDone() ) ); - disconnect( formatTimer, TQ_SIGNAL( timeout() ), this, TQ_SLOT( formatMore() ) ); - optimSetText( doc->originalText() ); - doc->clear(TRUE); - delete cursor; - cursor = new TQTextCursor( doc ); - } else { - disconnect( scrollTimer, TQ_SIGNAL( timeout() ), this, TQ_SLOT( optimDoAutoScroll() ) ); - connect( doc, TQ_SIGNAL( minimumWidthChanged(int) ), this, TQ_SLOT( documentWidthChanged(int) ) ); - connect( scrollTimer, TQ_SIGNAL( timeout() ), this, TQ_SLOT( autoScrollTimerDone() ) ); - connect( formatTimer, TQ_SIGNAL( timeout() ), this, TQ_SLOT( formatMore() ) ); - setText( optimText() ); - delete d->od; - d->od = 0; - } - } - return d->optimMode; -} - -/*! \internal */ -TQString TQTextEdit::optimText() const -{ - TQString str, tmp; - - if ( d->od->len == 0 ) - return str; - - // concatenate all strings - int i; - int offset; - TQMapConstIterator<int,TQTextEditOptimPrivate::Tag *> it; - TQTextEditOptimPrivate::Tag * ftag = 0; - for ( i = 0; i < d->od->numLines; i++ ) { - if ( d->od->lines[ LOGOFFSET(i) ].isEmpty() ) { // CR lines are empty - str += "\n"; - } else { - tmp = d->od->lines[ LOGOFFSET(i) ] + "\n"; - // inject the tags for this line - if ( (it = d->od->tagIndex.find( LOGOFFSET(i) )) != d->od->tagIndex.end() ) - ftag = it.data(); - offset = 0; - while ( ftag && ftag->line == i ) { - tmp.insert( ftag->index + offset, "<" + ftag->tag + ">" ); - offset += ftag->tag.length() + 2; // 2 -> the '<' and '>' chars - ftag = ftag->next; - } - str += tmp; - } - } - return str; -} - -/*! \internal */ -void TQTextEdit::optimSetText( const TQString &str ) -{ - optimRemoveSelection(); -// this is just too slow - but may have to go in due to compatibility reasons -// if ( str == optimText() ) -// return; - d->od->numLines = 0; - d->od->lines.clear(); - d->od->maxLineWidth = 0; - d->od->len = 0; - d->od->clearTags(); - TQFontMetrics fm( TQScrollView::font() ); - if ( !(str.isEmpty() || str.isNull() || d->maxLogLines == 0) ) { - TQStringList strl = TQStringList::split( '\n', str, TRUE ); - int lWidth = 0; - for ( TQStringList::Iterator it = strl.begin(); it != strl.end(); ++it ) { - optimParseTags( &*it ); - optimCheckLimit( *it ); - lWidth = fm.width( *it ); - if ( lWidth > d->od->maxLineWidth ) - d->od->maxLineWidth = lWidth; - } - } - resizeContents( d->od->maxLineWidth + 4, d->od->numLines * fm.lineSpacing() + 1 ); - repaintContents(); - emit textChanged(); -} - -/*! \internal - - Append \a tag to the tag list. -*/ -TQTextEditOptimPrivate::Tag * TQTextEdit::optimAppendTag( int index, const TQString & tag ) -{ - TQTextEditOptimPrivate::Tag * t = new TQTextEditOptimPrivate::Tag, * tmp; - - if ( d->od->tags == 0 ) - d->od->tags = t; - t->bold = t->italic = t->underline = FALSE; - t->line = d->od->numLines; - t->index = index; - t->tag = tag; - t->leftTag = 0; - t->parent = 0; - t->prev = d->od->lastTag; - if ( d->od->lastTag ) - d->od->lastTag->next = t; - t->next = 0; - d->od->lastTag = t; - tmp = d->od->tagIndex[ LOGOFFSET(t->line) ]; - if ( !tmp || (tmp && tmp->index > t->index) ) { - d->od->tagIndex.replace( LOGOFFSET(t->line), t ); - } - return t; -} - - /*! \internal - - Insert \a tag in the tag - according to line and index numbers -*/ - -TQTextEditOptimPrivate::Tag *TQTextEdit::optimInsertTag(int line, int index, const TQString &tag) -{ - TQTextEditOptimPrivate::Tag *t = new TQTextEditOptimPrivate::Tag, *tmp; - - if (d->od->tags == 0) - d->od->tags = t; - t->bold = t->italic = t->underline = FALSE; - t->line = line; - t->index = index; - t->tag = tag; - t->leftTag = 0; - t->parent = 0; - t->next = 0; - t->prev = 0; - - // find insertion pt. in tag struct. - TQMap<int,TQTextEditOptimPrivate::Tag *>::ConstIterator it; - if ((it = d->od->tagIndex.find(LOGOFFSET(line))) != d->od->tagIndex.end()) { - tmp = *it; - if (tmp->index >= index) { // the exisiting tag may be placed AFTER the one we want to insert - tmp = tmp->prev; - } else { - while (tmp && tmp->next && tmp->next->line == line && tmp->next->index <= index) - tmp = tmp->next; - } - } else { - tmp = d->od->tags; - while (tmp && tmp->next && tmp->next->line < line) - tmp = tmp->next; - if (tmp == d->od->tags) - tmp = 0; - } - - t->prev = tmp; - t->next = tmp ? tmp->next : 0; - if (t->next) - t->next->prev = t; - if (tmp) - tmp->next = t; - - tmp = d->od->tagIndex[LOGOFFSET(t->line)]; - if (!tmp || (tmp && tmp->index >= t->index)) { - d->od->tagIndex.replace(LOGOFFSET(t->line), t); - } - return t; -} - - -/*! \internal - - Find tags in \a line, remove them from \a line and put them in a - structure. - - A tag is delimited by '<' and '>'. The characters '<', '>' and '&' - are escaped by using '<', '>' and '&'. Left-tags marks - the starting point for formatting, while right-tags mark the ending - point. A right-tag is the same as a left-tag, but with a '/' - appearing before the tag keyword. E.g a valid left-tag: <b>, and - a valid right-tag: </b>. Tags can be nested, but they have to be - closed in the same order as they are opened. E.g: - <font color=red><font color=blue>blue</font>red</font> - is valid, while: - <font color=red><b>bold red</font> just bold</b> - is invalid since the font tag is - closed before the bold tag. Note that a tag does not have to be - closed: '<font color=blue>Lots of text - and then some..' is perfectly valid for - setting all text appearing after the tag to blue. A tag can be used - to change the color of a piece of text, or set one of the following - formatting attributes: bold, italic and underline. These attributes - are set using the <b>, <i> and <u> tags. Example of valid tags: - <font color=red>, </font>, <b>, <u>, <i>, </i>. - Example of valid text: - This is some <font color=red>red text</font>, while this is some <font color=green>green - text</font>. <font color=blue><font color=yellow>This is yellow</font>, while this is - blue.</font> - - Note that only the color attribute of the HTML font tag is supported. - - Limitations: - 1. A tag cannot span several lines. - 2. Very limited error checking - mismatching left/right-tags is the - only thing that is detected. - -*/ -void TQTextEdit::optimParseTags( TQString * line, int lineNo, int indexOffset ) -{ - int len = line->length(); - int i, startIndex = -1, endIndex = -1, escIndex = -1; - int state = 0; // 0 = outside tag, 1 = inside tag - bool tagOpen, tagClose; - int bold = 0, italic = 0, underline = 0; - TQString tagStr; - TQPtrStack<TQTextEditOptimPrivate::Tag> tagStack; - - for ( i = 0; i < len; i++ ) { - tagOpen = (*line)[i] == '<'; - tagClose = (*line)[i] == '>'; - - // handle '<' and '>' and '&' - if ( (*line)[i] == '&' ) { - escIndex = i; - continue; - } else if ( escIndex != -1 && (*line)[i] == ';' ) { - TQString esc = line->mid( escIndex, i - escIndex + 1 ); - TQString c; - if ( esc == "<" ) - c = '<'; - else if ( esc == ">" ) - c = '>'; - else if ( esc == "&" ) - c = '&'; - line->replace( escIndex, i - escIndex + 1, c ); - len = line->length(); - i -= i-escIndex; - escIndex = -1; - continue; - } - - if ( state == 0 && tagOpen ) { - state = 1; - startIndex = i; - continue; - } - if ( state == 1 && tagClose ) { - state = 0; - endIndex = i; - if ( !tagStr.isEmpty() ) { - TQTextEditOptimPrivate::Tag * tag, * cur, * tmp; - bool format = TRUE; - - if ( tagStr == "b" ) - bold++; - else if ( tagStr == "/b" ) - bold--; - else if ( tagStr == "i" ) - italic++; - else if ( tagStr == "/i" ) - italic--; - else if ( tagStr == "u" ) - underline++; - else if ( tagStr == "/u" ) - underline--; - else - format = FALSE; - if ( lineNo > -1 ) - tag = optimInsertTag( lineNo, startIndex + indexOffset, tagStr ); - else - tag = optimAppendTag( startIndex, tagStr ); - // everything that is not a b, u or i tag is considered - // to be a color tag. - tag->type = format ? TQTextEditOptimPrivate::Format - : TQTextEditOptimPrivate::Color; - if ( tagStr[0] == '/' ) { - // this is a right-tag - search for the left-tag - // and possible parent tag - cur = tag->prev; - if ( !cur ) { -#ifdef QT_CHECK_RANGE - tqWarning( "TQTextEdit::optimParseTags: no left-tag for '<%s>' in line %d.", tag->tag.ascii(), tag->line + 1 ); -#endif - return; // something is wrong - give up - } - while ( cur ) { - if ( cur->leftTag ) { // push right-tags encountered - tagStack.push( cur ); - } else { - tmp = tagStack.pop(); - if ( !tmp ) { - if ( (("/" + cur->tag) == tag->tag) || - (tag->tag == "/font" && cur->tag.left(4) == "font") ) { - // set up the left and parent of this tag - tag->leftTag = cur; - tmp = cur->prev; - if ( tmp && tmp->parent ) { - tag->parent = tmp->parent; - } else if ( tmp && !tmp->leftTag ) { - tag->parent = tmp; - } - break; - } else if ( !cur->leftTag ) { -#ifdef QT_CHECK_RANGE - tqWarning( "TQTextEdit::optimParseTags: mismatching %s-tag for '<%s>' in line %d.", cur->tag[0] == '/' ? "left" : "right", cur->tag.ascii(), cur->line + 1 ); -#endif - return; // something is amiss - give up - } - } - } - cur = cur->prev; - } - } else { - tag->bold = bold > 0; - tag->italic = italic > 0; - tag->underline = underline > 0; - tmp = tag->prev; - while ( tmp && tmp->leftTag ) { - tmp = tmp->leftTag->parent; - } - if ( tmp ) { - tag->bold |= tmp->bold; - tag->italic |= tmp->italic; - tag->underline |= tmp->underline; - } - } - } - if ( startIndex != -1 ) { - int l = (endIndex == -1) ? - line->length() - startIndex : endIndex - startIndex; - line->remove( startIndex, l+1 ); - len = line->length(); - i -= l+1; - } - tagStr = ""; - continue; - } - - if ( state == 1 ) { - tagStr += (*line)[i]; - } - } -} - -// calculate the width of a string in pixels inc. tabs -static int qStrWidth(const TQString& str, int tabWidth, const TQFontMetrics& fm) -{ - int tabs = str.contains('\t'); - - if (!tabs) - return fm.width(str); - - int newIdx = 0; - int lastIdx = 0; - int strWidth = 0; - int tn; - for (tn = 1; tn <= tabs; ++tn) { - newIdx = str.find('\t', newIdx); - strWidth += fm.width(str.mid(lastIdx, newIdx - lastIdx)); - if (strWidth >= tn * tabWidth) { - int u = tn; - while (strWidth >= u * tabWidth) - ++u; - strWidth = u * tabWidth; - } else { - strWidth = tn * tabWidth; - } - lastIdx = ++newIdx; - } - if ((int)str.length() > newIdx) - strWidth += fm.width(str.mid(newIdx)); - return strWidth; -} - -bool TQTextEdit::optimHasBoldMetrics(int line) -{ - TQTextEditOptimPrivate::Tag *t; - TQMapConstIterator<int,TQTextEditOptimPrivate::Tag *> it; - if ((it = d->od->tagIndex.find(line)) != d->od->tagIndex.end()) { - t = *it; - while (t && t->line == line) { - if (t->bold) - return TRUE; - t = t->next; - } - } else if ((t = optimPreviousLeftTag(line)) && t->bold) { - return TRUE; - } - return FALSE; -} - -/*! \internal - - Append \a str to the current text buffer. Parses each line to find - formatting tags. -*/ -void TQTextEdit::optimAppend( const TQString &str ) -{ - if ( str.isEmpty() || str.isNull() || d->maxLogLines == 0 ) - return; - - TQStringList strl = TQStringList::split( '\n', str, TRUE ); - TQStringList::Iterator it = strl.begin(); - - TQFontMetrics fm(TQScrollView::font()); - int lWidth = 0; - - for ( ; it != strl.end(); ++it ) { - optimParseTags( &*it ); - optimCheckLimit( *it ); - if (optimHasBoldMetrics(d->od->numLines-1)) { - TQFont fnt = TQScrollView::font(); - fnt.setBold(TRUE); - fm = TQFontMetrics(fnt); - } - lWidth = qStrWidth(*it, tabStopWidth(), fm) + 4; - if ( lWidth > d->od->maxLineWidth ) - d->od->maxLineWidth = lWidth; - } - bool scrollToEnd = contentsY() >= contentsHeight() - visibleHeight(); - resizeContents( d->od->maxLineWidth + 4, d->od->numLines * fm.lineSpacing() + 1 ); - if ( scrollToEnd ) { - updateScrollBars(); - ensureVisible( contentsX(), contentsHeight(), 0, 0 ); - } - // when a max log size is set, the text may not be redrawn because - // the size of the viewport may not have changed - if ( d->maxLogLines > -1 ) - viewport()->update(); - emit textChanged(); -} - - -static void qStripTags(TQString *line) -{ - int len = line->length(); - int i, startIndex = -1, endIndex = -1, escIndex = -1; - int state = 0; // 0 = outside tag, 1 = inside tag - bool tagOpen, tagClose; - - for ( i = 0; i < len; i++ ) { - tagOpen = (*line)[i] == '<'; - tagClose = (*line)[i] == '>'; - - // handle '<' and '>' and '&' - if ( (*line)[i] == '&' ) { - escIndex = i; - continue; - } else if ( escIndex != -1 && (*line)[i] == ';' ) { - TQString esc = line->mid( escIndex, i - escIndex + 1 ); - TQString c; - if ( esc == "<" ) - c = '<'; - else if ( esc == ">" ) - c = '>'; - else if ( esc == "&" ) - c = '&'; - line->replace( escIndex, i - escIndex + 1, c ); - len = line->length(); - i -= i-escIndex; - escIndex = -1; - continue; - } - - if ( state == 0 && tagOpen ) { - state = 1; - startIndex = i; - continue; - } - if ( state == 1 && tagClose ) { - state = 0; - endIndex = i; - if ( startIndex != -1 ) { - int l = (endIndex == -1) ? - line->length() - startIndex : endIndex - startIndex; - line->remove( startIndex, l+1 ); - len = line->length(); - i -= l+1; - } - continue; - } - } -} - -/*! \internal - - Inserts the text into \a line at index \a index. -*/ - -void TQTextEdit::optimInsert(const TQString& text, int line, int index) -{ - if (text.isEmpty() || d->maxLogLines == 0) - return; - if (line < 0) - line = 0; - if (line > d->od->numLines-1) - line = d->od->numLines-1; - if (index < 0) - index = 0; - if (index > (int) d->od->lines[line].length()) - index = d->od->lines[line].length(); - - TQStringList strl = TQStringList::split('\n', text, TRUE); - int numNewLines = (int)strl.count() - 1; - TQTextEditOptimPrivate::Tag *tag = 0; - TQMap<int,TQTextEditOptimPrivate::Tag *>::ConstIterator ii; - int x; - - if (numNewLines == 0) { - // Case 1. Fast single line case - just inject it! - TQString stripped = text; - qStripTags( &stripped ); - d->od->lines[LOGOFFSET(line)].insert(index, stripped); - // move the tag indices following the insertion pt. - if ((ii = d->od->tagIndex.find(LOGOFFSET(line))) != d->od->tagIndex.end()) { - tag = *ii; - while (tag && (LOGOFFSET(tag->line) == line && tag->index < index)) - tag = tag->next; - while (tag && (LOGOFFSET(tag->line) == line)) { - tag->index += stripped.length(); - tag = tag->next; - } - } - stripped = text; - optimParseTags(&stripped, line, index); - } else if (numNewLines > 0) { - // Case 2. We have at least 1 newline char - split at - // insertion pt. and make room for new lines - complex and slow! - TQString left = d->od->lines[LOGOFFSET(line)].left(index); - TQString right = d->od->lines[LOGOFFSET(line)].mid(index); - - // rearrange lines for insertion - for (x = d->od->numLines - 1; x > line; x--) - d->od->lines[x + numNewLines] = d->od->lines[x]; - d->od->numLines += numNewLines; - - // fix the tag index and the tag line/index numbers - this - // might take a while.. - for (x = line; x < d->od->numLines; x++) { - if ((ii = d->od->tagIndex.find(LOGOFFSET(line))) != d->od->tagIndex.end()) { - tag = ii.data(); - if (LOGOFFSET(tag->line) == line) - while (tag && (LOGOFFSET(tag->line) == line && tag->index < index)) - tag = tag->next; - } - } - - // relabel affected tags with new line numbers and new index - // positions - while (tag) { - if (LOGOFFSET(tag->line) == line) - tag->index -= index; - tag->line += numNewLines; - tag = tag->next; - } - - // generate a new tag index - d->od->tagIndex.clear(); - tag = d->od->tags; - while (tag) { - if (!((ii = d->od->tagIndex.find(LOGOFFSET(tag->line))) != d->od->tagIndex.end())) - d->od->tagIndex[LOGOFFSET(tag->line)] = tag; - tag = tag->next; - } - - // update the tag indices on the spliced line - needs to be done before new tags are added - TQString stripped = strl[strl.count() - 1]; - qStripTags(&stripped); - if ((ii = d->od->tagIndex.find(LOGOFFSET(line + numNewLines))) != d->od->tagIndex.end()) { - tag = *ii; - while (tag && (LOGOFFSET(tag->line) == line + numNewLines)) { - tag->index += stripped.length(); - tag = tag->next; - } - } - - // inject the new lines - TQStringList::Iterator it = strl.begin(); - x = line; - int idx; - for (; it != strl.end(); ++it) { - stripped = *it; - qStripTags(&stripped); - if (x == line) { - stripped = left + stripped; - idx = index; - } else { - idx = 0; - } - d->od->lines[LOGOFFSET(x)] = stripped; - optimParseTags(&*it, x++, idx); - } - d->od->lines[LOGOFFSET(x - 1)] += right; - } - // recalculate the pixel width of the longest injected line - - TQFontMetrics fm(TQScrollView::font()); - int lWidth = 0; - - for (x = line; x < line + numNewLines; x++) { - if (optimHasBoldMetrics(x)) { - TQFont fnt = TQScrollView::font(); - fnt.setBold(TRUE); - fm = TQFontMetrics(fnt); - } - lWidth = fm.width(d->od->lines[x]) + 4; - if (lWidth > d->od->maxLineWidth) - d->od->maxLineWidth = lWidth; - } - resizeContents(d->od->maxLineWidth + 4, d->od->numLines * fm.lineSpacing() + 1); - repaintContents(); - emit textChanged(); -} - - - -/*! \internal - - Returns the first open left-tag appearing before line \a line. - */ -TQTextEditOptimPrivate::Tag * TQTextEdit::optimPreviousLeftTag( int line ) -{ - TQTextEditOptimPrivate::Tag * ftag = 0; - TQMapConstIterator<int,TQTextEditOptimPrivate::Tag *> it; - if ( (it = d->od->tagIndex.find( LOGOFFSET(line) )) != d->od->tagIndex.end() ) - ftag = it.data(); - if ( !ftag ) { - // start searching for an open tag - ftag = d->od->tags; - while ( ftag ) { - if ( ftag->line > line || ftag->next == 0 ) { - if ( ftag->line > line ) - ftag = ftag->prev; - break; - } - ftag = ftag->next; - } - } else { - ftag = ftag->prev; - } - - if ( ftag ) { - if ( ftag && ftag->parent ) // use the open parent tag - ftag = ftag->parent; - else if ( ftag && ftag->leftTag ) // this is a right-tag with no parent - ftag = 0; - } - return ftag; -} - -/*! \internal - - Set the format for the string starting at index \a start and ending - at \a end according to \a tag. If \a tag is a Format tag, find the - first open color tag appearing before \a tag and use that tag to - color the string. -*/ -void TQTextEdit::optimSetTextFormat( TQTextDocument * td, TQTextCursor * cur, - TQTextFormat * f, int start, int end, - TQTextEditOptimPrivate::Tag * tag ) -{ - int formatFlags = TQTextFormat::Bold | TQTextFormat::Italic | - TQTextFormat::Underline; - cur->setIndex( start ); - td->setSelectionStart( 0, *cur ); - cur->setIndex( end ); - td->setSelectionEnd( 0, *cur ); - TQStyleSheetItem * ssItem = styleSheet()->item( tag->tag ); - if ( !ssItem || tag->type == TQTextEditOptimPrivate::Format ) { - f->setBold( tag->bold ); - f->setItalic( tag->italic ); - f->setUnderline( tag->underline ); - if ( tag->type == TQTextEditOptimPrivate::Format ) { - // check to see if there are any open color tags prior to - // this format tag - tag = tag->prev; - while ( tag && (tag->type == TQTextEditOptimPrivate::Format || - tag->leftTag) ) { - tag = tag->leftTag ? tag->parent : tag->prev; - } - } - if ( tag ) { - TQString col = tag->tag.simplifyWhiteSpace(); - if ( col.left( 10 ) == "font color" ) { - int i = col.find( '=', 10 ); - col = col.mid( i + 1 ).simplifyWhiteSpace(); - if ( col[0] == '\"' ) - col = col.mid( 1, col.length() - 2 ); - } - TQColor color = TQColor( col ); - if ( color.isValid() ) { - formatFlags |= TQTextFormat::Color; - f->setColor( color ); - } - } - } else { // use the stylesheet tag definition - if ( ssItem->color().isValid() ) { - formatFlags |= TQTextFormat::Color; - f->setColor( ssItem->color() ); - } - f->setBold( ssItem->fontWeight() == TQFont::Bold ); - f->setItalic( ssItem->fontItalic() ); - f->setUnderline( ssItem->fontUnderline() ); - } - td->setFormat( 0, f, formatFlags ); - td->removeSelection( 0 ); -} - -/*! \internal */ -void TQTextEdit::optimDrawContents( TQPainter * p, int clipx, int clipy, - int clipw, int cliph ) -{ - TQFontMetrics fm( TQScrollView::font() ); - int startLine = clipy / fm.lineSpacing(); - - // we always have to fetch at least two lines for drawing because the - // painter may be translated so that parts of two lines cover the area - // of a single line - int nLines = (cliph / fm.lineSpacing()) + 2; - int endLine = startLine + nLines; - - if ( startLine >= d->od->numLines ) - return; - if ( (startLine + nLines) > d->od->numLines ) - nLines = d->od->numLines - startLine; - - int i = 0; - TQString str; - for ( i = startLine; i < (startLine + nLines); i++ ) - str.append( d->od->lines[ LOGOFFSET(i) ] + "\n" ); - - TQTextDocument * td = new TQTextDocument( 0 ); - td->setDefaultFormat( TQScrollView::font(), TQColor() ); - td->setPlainText( str ); - td->setFormatter( new TQTextFormatterBreakWords ); // deleted by TQTextDoc - td->formatter()->setWrapEnabled( FALSE ); - td->setTabStops(doc->tabStopWidth()); - - // get the current text color from the current format - td->selectAll( TQTextDocument::Standard ); - TQTextFormat f; - f.setColor( colorGroup().text() ); - f.setFont( TQScrollView::font() ); - td->setFormat( TQTextDocument::Standard, &f, - TQTextFormat::Color | TQTextFormat::Font ); - td->removeSelection( TQTextDocument::Standard ); - - // add tag formatting - if ( d->od->tags ) { - int i = startLine; - TQMapConstIterator<int,TQTextEditOptimPrivate::Tag *> it; - TQTextEditOptimPrivate::Tag * tag = 0, * tmp = 0; - TQTextCursor cur( td ); - // Step 1 - find previous left-tag - tmp = optimPreviousLeftTag( i ); - for ( ; i < startLine + nLines; i++ ) { - if ( (it = d->od->tagIndex.find( LOGOFFSET(i) )) != d->od->tagIndex.end() ) - tag = it.data(); - // Step 2 - iterate over tags on the current line - int lastIndex = 0; - while ( tag && tag->line == i ) { - tmp = 0; - if ( tag->prev && !tag->prev->leftTag ) { - tmp = tag->prev; - } else if ( tag->prev && tag->prev->parent ) { - tmp = tag->prev->parent; - } - if ( (tag->index - lastIndex) > 0 && tmp ) { - optimSetTextFormat( td, &cur, &f, lastIndex, tag->index, tmp ); - } - lastIndex = tag->index; - tmp = tag; - tag = tag->next; - } - // Step 3 - color last part of the line - if necessary - if ( tmp && tmp->parent ) - tmp = tmp->parent; - if ( (cur.paragraph()->length()-1 - lastIndex) > 0 && tmp && !tmp->leftTag ) { - optimSetTextFormat( td, &cur, &f, lastIndex, - cur.paragraph()->length() - 1, tmp ); - } - cur.setParagraph( cur.paragraph()->next() ); - } - // useful debug info - // -// tag = d->od->tags; -// tqWarning("###"); -// while ( tag ) { -// tqWarning( "Tag: %p, parent: %09p, leftTag: %09p, Name: %-15s, ParentName: %s, %d%d%d", tag, -// tag->parent, tag->leftTag, tag->tag.latin1(), tag->parent ? tag->parent->tag.latin1():"<none>", -// tag->bold, tag->italic, tag->underline ); -// tag = tag->next; -// } - } - - // if there is a selection, make sure that the selection in the - // part we need to redraw is set correctly - if ( optimHasSelection() ) { - TQTextCursor c1( td ); - TQTextCursor c2( td ); - int selStart = d->od->selStart.line; - int idxStart = d->od->selStart.index; - int selEnd = d->od->selEnd.line; - int idxEnd = d->od->selEnd.index; - if ( selEnd < selStart ) { - tqSwap( &selStart, &selEnd ); - tqSwap( &idxStart, &idxEnd ); - } - if ( selEnd > d->od->numLines-1 ) { - selEnd = d->od->numLines-1; - } - if ( startLine <= selStart && endLine >= selEnd ) { - // case 1: area to paint covers entire selection - int paragS = selStart - startLine; - int paragE = paragS + (selEnd - selStart); - TQTextParagraph * parag = td->paragAt( paragS ); - if ( parag ) { - c1.setParagraph( parag ); - if ( td->text( paragS ).length() >= (uint) idxStart ) - c1.setIndex( idxStart ); - } - parag = td->paragAt( paragE ); - if ( parag ) { - c2.setParagraph( parag ); - if ( td->text( paragE ).length() >= (uint) idxEnd ) - c2.setIndex( idxEnd ); - } - } else if ( startLine > selStart && endLine < selEnd ) { - // case 2: area to paint is all part of the selection - td->selectAll( TQTextDocument::Standard ); - } else if ( startLine > selStart && endLine >= selEnd && - startLine <= selEnd ) { - // case 3: area to paint starts inside a selection, ends past it - c1.setParagraph( td->firstParagraph() ); - c1.setIndex( 0 ); - int paragE = selEnd - startLine; - TQTextParagraph * parag = td->paragAt( paragE ); - if ( parag ) { - c2.setParagraph( parag ); - if ( td->text( paragE ).length() >= (uint) idxEnd ) - c2.setIndex( idxEnd ); - } - } else if ( startLine <= selStart && endLine < selEnd && - endLine > selStart ) { - // case 4: area to paint starts before a selection, ends inside it - int paragS = selStart - startLine; - TQTextParagraph * parag = td->paragAt( paragS ); - if ( parag ) { - c1.setParagraph( parag ); - c1.setIndex( idxStart ); - } - c2.setParagraph( td->lastParagraph() ); - c2.setIndex( td->lastParagraph()->string()->toString().length() - 1 ); - - } - // previously selected? - if ( !td->hasSelection( TQTextDocument::Standard ) ) { - td->setSelectionStart( TQTextDocument::Standard, c1 ); - td->setSelectionEnd( TQTextDocument::Standard, c2 ); - } - } - td->doLayout( p, contentsWidth() ); - - // have to align the painter so that partly visible lines are - // drawn at the correct position within the area that needs to be - // painted - int offset = clipy % fm.lineSpacing() + 2; - TQRect r( clipx, 0, clipw, cliph + offset ); - p->translate( 0, clipy - offset ); - td->draw( p, r.x(), r.y(), r.width(), r.height(), colorGroup() ); - p->translate( 0, -(clipy - offset) ); - delete td; -} - -/*! \internal */ -void TQTextEdit::optimMousePressEvent( TQMouseEvent * e ) -{ - if ( e->button() != LeftButton ) - return; - - TQFontMetrics fm( TQScrollView::font() ); - mousePressed = TRUE; - mousePos = e->pos(); - d->od->selStart.line = e->y() / fm.lineSpacing(); - if ( d->od->selStart.line > d->od->numLines-1 ) { - d->od->selStart.line = d->od->numLines-1; - d->od->selStart.index = d->od->lines[ LOGOFFSET(d->od->numLines-1) ].length(); - } else { - TQString str = d->od->lines[ LOGOFFSET(d->od->selStart.line) ]; - d->od->selStart.index = optimCharIndex( str, mousePos.x() ); - } - d->od->selEnd.line = d->od->selStart.line; - d->od->selEnd.index = d->od->selStart.index; - oldMousePos = e->pos(); - repaintContents( FALSE ); -} - -/*! \internal */ -void TQTextEdit::optimMouseReleaseEvent( TQMouseEvent * e ) -{ - if ( e->button() != LeftButton ) - return; - - if ( scrollTimer->isActive() ) - scrollTimer->stop(); - if ( !inDoubleClick ) { - TQFontMetrics fm( TQScrollView::font() ); - d->od->selEnd.line = e->y() / fm.lineSpacing(); - if ( d->od->selEnd.line > d->od->numLines-1 ) { - d->od->selEnd.line = d->od->numLines-1; - } - TQString str = d->od->lines[ LOGOFFSET(d->od->selEnd.line) ]; - mousePos = e->pos(); - d->od->selEnd.index = optimCharIndex( str, mousePos.x() ); - if ( d->od->selEnd.line < d->od->selStart.line ) { - tqSwap( &d->od->selStart.line, &d->od->selEnd.line ); - tqSwap( &d->od->selStart.index, &d->od->selEnd.index ); - } else if ( d->od->selStart.line == d->od->selEnd.line && - d->od->selStart.index > d->od->selEnd.index ) { - tqSwap( &d->od->selStart.index, &d->od->selEnd.index ); - } - oldMousePos = e->pos(); - repaintContents( FALSE ); - } - if ( mousePressed ) { - mousePressed = FALSE; - copyToClipboard(); - } - - inDoubleClick = FALSE; - emit copyAvailable( optimHasSelection() ); - emit selectionChanged(); -} - -/*! \internal */ -void TQTextEdit::optimMouseMoveEvent( TQMouseEvent * e ) -{ - mousePos = e->pos(); - optimDoAutoScroll(); - oldMousePos = mousePos; -} - -/*! \internal */ -void TQTextEdit::optimDoAutoScroll() -{ - if ( !mousePressed ) - return; - - TQFontMetrics fm( TQScrollView::font() ); - TQPoint pos( mapFromGlobal( TQCursor::pos() ) ); - bool doScroll = FALSE; - int xx = contentsX() + pos.x(); - int yy = contentsY() + pos.y(); - - // find out how much we have to scroll in either dir. - if ( pos.x() < 0 || pos.x() > viewport()->width() || - pos.y() < 0 || pos.y() > viewport()->height() ) { - int my = yy; - if ( pos.x() < 0 ) - xx = contentsX() - fm.width( 'w'); - else if ( pos.x() > viewport()->width() ) - xx = contentsX() + viewport()->width() + fm.width('w'); - - if ( pos.y() < 0 ) { - my = contentsY() - 1; - yy = (my / fm.lineSpacing()) * fm.lineSpacing() + 1; - } else if ( pos.y() > viewport()->height() ) { - my = contentsY() + viewport()->height() + 1; - yy = (my / fm.lineSpacing() + 1) * fm.lineSpacing() - 1; - } - d->od->selEnd.line = my / fm.lineSpacing(); - mousePos.setX( xx ); - mousePos.setY( my ); - doScroll = TRUE; - } else { - d->od->selEnd.line = mousePos.y() / fm.lineSpacing(); - } - - if ( d->od->selEnd.line < 0 ) { - d->od->selEnd.line = 0; - } else if ( d->od->selEnd.line > d->od->numLines-1 ) { - d->od->selEnd.line = d->od->numLines-1; - } - - TQString str = d->od->lines[ LOGOFFSET(d->od->selEnd.line) ]; - d->od->selEnd.index = optimCharIndex( str, mousePos.x() ); - - // have to have a valid index before generating a paint event - if ( doScroll ) - ensureVisible( xx, yy, 1, 1 ); - - // if the text document is smaller than the height of the viewport - // - redraw the whole thing otherwise calculate the rect that - // needs drawing. - if ( d->od->numLines * fm.lineSpacing() < viewport()->height() ) { - repaintContents( contentsX(), contentsY(), width(), height(), FALSE ); - } else { - int h = TQABS(mousePos.y() - oldMousePos.y()) + fm.lineSpacing() * 2; - int y; - if ( oldMousePos.y() < mousePos.y() ) { - y = oldMousePos.y() - fm.lineSpacing(); - } else { - // expand paint area for a fully selected line - h += fm.lineSpacing(); - y = mousePos.y() - fm.lineSpacing()*2; - } - if ( y < 0 ) - y = 0; - repaintContents( contentsX(), y, width(), h, FALSE ); - } - - if ( (!scrollTimer->isActive() && pos.y() < 0) || pos.y() > height() ) - scrollTimer->start( 100, FALSE ); - else if ( scrollTimer->isActive() && pos.y() >= 0 && pos.y() <= height() ) - scrollTimer->stop(); -} - -/*! \internal - - Returns the index of the character in the string \a str that is - currently under the mouse pointer. -*/ -int TQTextEdit::optimCharIndex( const TQString &str, int mx ) const -{ - TQFontMetrics fm(TQScrollView::font()); - uint i = 0; - int dd, dist = 10000000; - int curpos = 0; - int strWidth; - mx = mx - 4; // ### get the real margin from somewhere - - if (!str.contains('\t') && mx > fm.width(str)) - return str.length(); - - while (i < str.length()) { - strWidth = qStrWidth(str.left(i), tabStopWidth(), fm); - dd = strWidth - mx; - if (TQABS(dd) <= dist) { - dist = TQABS(dd); - if (mx >= strWidth) - curpos = i; - } - ++i; - } - return curpos; -} - -/*! \internal */ -void TQTextEdit::optimSelectAll() -{ - d->od->selStart.line = d->od->selStart.index = 0; - d->od->selEnd.line = d->od->numLines - 1; - d->od->selEnd.index = d->od->lines[ LOGOFFSET(d->od->selEnd.line) ].length(); - - repaintContents( FALSE ); - emit copyAvailable( optimHasSelection() ); - emit selectionChanged(); -} - -/*! \internal */ -void TQTextEdit::optimRemoveSelection() -{ - d->od->selStart.line = d->od->selEnd.line = -1; - d->od->selStart.index = d->od->selEnd.index = -1; - repaintContents( FALSE ); -} - -/*! \internal */ -void TQTextEdit::optimSetSelection( int startLine, int startIdx, - int endLine, int endIdx ) -{ - d->od->selStart.line = startLine; - d->od->selEnd.line = endLine; - d->od->selStart.index = startIdx; - d->od->selEnd.index = endIdx; -} - -/*! \internal */ -bool TQTextEdit::optimHasSelection() const -{ - if ( d->od->selStart.line != d->od->selEnd.line || - d->od->selStart.index != d->od->selEnd.index ) - return TRUE; - return FALSE; -} - -/*! \internal */ -TQString TQTextEdit::optimSelectedText() const -{ - TQString str; - - if ( !optimHasSelection() ) - return str; - - // concatenate all strings - if ( d->od->selStart.line == d->od->selEnd.line ) { - str = d->od->lines[ LOGOFFSET(d->od->selEnd.line) ].mid( d->od->selStart.index, - d->od->selEnd.index - d->od->selStart.index ); - } else { - int i = d->od->selStart.line; - str = d->od->lines[ LOGOFFSET(i) ].right( d->od->lines[ LOGOFFSET(i) ].length() - - d->od->selStart.index ) + "\n"; - i++; - for ( ; i < d->od->selEnd.line; i++ ) { - if ( d->od->lines[ LOGOFFSET(i) ].isEmpty() ) // CR lines are empty - str += "\n"; - else - str += d->od->lines[ LOGOFFSET(i) ] + "\n"; - } - str += d->od->lines[ LOGOFFSET(d->od->selEnd.line) ].left( d->od->selEnd.index ); - } - return str; -} - -/*! \internal */ -bool TQTextEdit::optimFind( const TQString & expr, bool cs, bool /*wo*/, - bool fw, int * para, int * index ) -{ - bool found = FALSE; - int parag = para ? *para : d->od->search.line, - idx = index ? *index : d->od->search.index, i; - - if ( d->od->len == 0 ) - return FALSE; - - for ( i = parag; fw ? i < d->od->numLines : i >= 0; fw ? i++ : i-- ) { - idx = fw ? d->od->lines[ LOGOFFSET(i) ].find( expr, idx, cs ) : - d->od->lines[ LOGOFFSET(i) ].findRev( expr, idx, cs ); - if ( idx != -1 ) { - found = TRUE; - break; - } else if ( fw ) - idx = 0; - } - - if ( found ) { - if ( index ) - *index = idx; - if ( para ) - *para = i; - d->od->search.index = idx + 1; - d->od->search.line = i; - optimSetSelection( i, idx, i, idx + expr.length() ); - TQFontMetrics fm( TQScrollView::font() ); - int h = fm.lineSpacing(); - int x = fm.width( d->od->lines[ LOGOFFSET(i) ].left( idx + expr.length()) ) + 4; - ensureVisible( x, i * h + h / 2, 1, h / 2 + 2 ); - repaintContents(); // could possibly be optimized - } - return found; -} - -/*! \reimp */ -void TQTextEdit::polish() -{ - // this will ensure that the last line is visible if text have - // been added to the widget before it is shown - if ( d->optimMode ) - scrollToBottom(); - TQWidget::polish(); -} - -/*! - Sets the maximum number of lines a TQTextEdit can hold in \c - LogText mode to \a limit. If \a limit is -1 (the default), this - signifies an unlimited number of lines. - - \warning Never use formatting tags that span more than one line - when the maximum log lines is set. When lines are removed from the - top of the buffer it could result in an unbalanced tag pair, i.e. - the left formatting tag is removed before the right one. - */ -void TQTextEdit::setMaxLogLines( int limit ) -{ - d->maxLogLines = limit; - if ( d->maxLogLines < -1 ) - d->maxLogLines = -1; - if ( d->maxLogLines == -1 ) - d->logOffset = 0; -} - -/*! - Returns the maximum number of lines TQTextEdit can hold in \c - LogText mode. By default the number of lines is unlimited, which - is signified by a value of -1. - */ -int TQTextEdit::maxLogLines() -{ - return d->maxLogLines; -} - -/*! - Check if the number of lines in the buffer is limited, and uphold - that limit when appending new lines. - */ -void TQTextEdit::optimCheckLimit( const TQString& str ) -{ - if ( d->maxLogLines > -1 && d->maxLogLines <= d->od->numLines ) { - // NB! Removing the top line in the buffer will potentially - // destroy the structure holding the formatting tags - if line - // spanning tags are used. - TQTextEditOptimPrivate::Tag *t = d->od->tags, *tmp, *itr; - TQPtrList<TQTextEditOptimPrivate::Tag> lst; - while ( t ) { - t->line -= 1; - // unhook the ptr from the tag structure - if ( ((uint) LOGOFFSET(t->line) < (uint) d->logOffset && - (uint) LOGOFFSET(t->line) < (uint) LOGOFFSET(d->od->numLines) && - (uint) LOGOFFSET(d->od->numLines) > (uint) d->logOffset) ) - { - if ( t->prev ) - t->prev->next = t->next; - if ( t->next ) - t->next->prev = t->prev; - if ( d->od->tags == t ) - d->od->tags = t->next; - if ( d->od->lastTag == t ) { - if ( t->prev ) - d->od->lastTag = t->prev; - else - d->od->lastTag = d->od->tags; - } - tmp = t; - t = t->next; - lst.append( tmp ); - delete tmp; - } else { - t = t->next; - } - } - // Remove all references to the ptrs we just deleted - itr = d->od->tags; - while ( itr ){ - for ( tmp = lst.first(); tmp; tmp = lst.next() ) { - if ( itr->parent == tmp ) - itr->parent = 0; - if ( itr->leftTag == tmp ) - itr->leftTag = 0; - } - itr = itr->next; - } - // ...in the tag index as well - TQMapIterator<int, TQTextEditOptimPrivate::Tag *> idx; - if ( (idx = d->od->tagIndex.find( d->logOffset )) != d->od->tagIndex.end() ) - d->od->tagIndex.remove( idx ); - - TQMapIterator<int,TQString> it; - if ( (it = d->od->lines.find( d->logOffset )) != d->od->lines.end() ) { - d->od->len -= (*it).length(); - d->od->lines.remove( it ); - d->od->numLines--; - d->logOffset = LOGOFFSET(1); - } - } - d->od->len += str.length(); - d->od->lines[ LOGOFFSET(d->od->numLines++) ] = str; -} - -#endif // QT_TEXTEDIT_OPTIMIZATION - -/*! - \property TQTextEdit::autoFormatting - \brief the enabled set of auto formatting features - - The value can be any combination of the values in the \c - AutoFormatting enum. The default is \c AutoAll. Choose \c AutoNone - to disable all automatic formatting. - - Currently, the only automatic formatting feature provided is \c - AutoBulletList; future versions of TQt may offer more. -*/ - -void TQTextEdit::setAutoFormatting( uint features ) -{ - d->autoFormatting = features; -} - -uint TQTextEdit::autoFormatting() const -{ - return d->autoFormatting; -} - -/*! - Returns the TQSyntaxHighlighter set on this TQTextEdit. 0 is - returned if no syntax highlighter is set. - */ -TQSyntaxHighlighter * TQTextEdit::syntaxHighlighter() const -{ - if (document()->preProcessor()) - return ((TQSyntaxHighlighterInternal *) document()->preProcessor())->highlighter; - else - return 0; -} - -#endif //TQT_NO_TEXTEDIT diff --git a/src/widgets/qtextview.cpp b/src/widgets/qtextview.cpp deleted file mode 100644 index b672bee3d..000000000 --- a/src/widgets/qtextview.cpp +++ /dev/null @@ -1,103 +0,0 @@ -/**************************************************************************** -** -** Implementation of the TQTextView class -** -** Created : 990101 -** -** Copyright (C) 1992-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 "ntqtextview.h" - -#ifndef TQT_NO_TEXTVIEW - -/*! \class TQTextView - \brief The TQTextView class provides a rich-text viewer. - - \obsolete - - This class wraps a read-only \l TQTextEdit. - Use a \l TQTextEdit instead, and call setReadOnly(TRUE) - to disable editing. -*/ - -/*! \reimp */ - -TQTextView::TQTextView( const TQString& text, const TQString& context, - TQWidget *parent, const char *name ) - : TQTextEdit( text, context, parent, name ) -{ - setReadOnly( TRUE ); -} - -/*! \reimp */ - -TQTextView::TQTextView( TQWidget *parent, const char *name ) - : TQTextEdit( parent, name ) -{ - setReadOnly( TRUE ); -} - -/*! \reimp */ - -TQTextView::~TQTextView() -{ -} - -/*! - \property TQTextView::undoDepth - \brief the number of undoable steps -*/ - -/*! - \property TQTextView::overwriteMode - \brief whether new text overwrites or pushes aside existing text -*/ - -/*! - \property TQTextView::modified - \brief Whether the text view's contents have been modified. -*/ - -/*! - \property TQTextView::readOnly - \brief Whether the text view's contents are read only. -*/ - -/*! - \property TQTextView::undoRedoEnabled - \brief Whether undo and redo are enabled. -*/ - -#endif diff --git a/src/widgets/tqtextbrowser.cpp b/src/widgets/tqtextbrowser.cpp new file mode 100644 index 000000000..dfafb32c8 --- /dev/null +++ b/src/widgets/tqtextbrowser.cpp @@ -0,0 +1,555 @@ +/**************************************************************************** +** +** Implementation of the TQTextBrowser class +** +** Created : 990101 +** +** Copyright (C) 1992-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 "tqtextbrowser.h" +#ifndef TQT_NO_TEXTBROWSER +#include "../kernel/qrichtext_p.h" + +#include "ntqapplication.h" +#include "ntqlayout.h" +#include "ntqpainter.h" + +#include "tqvaluestack.h" +#include "stdio.h" +#include "ntqfile.h" +#include "tqtextstream.h" +#include "ntqlayout.h" +#include "ntqbitmap.h" +#include "ntqtimer.h" +#include "tqimage.h" +#include "ntqsimplerichtext.h" +#include "ntqdragobject.h" +#include "ntqurl.h" +#include "ntqcursor.h" + +/*! + \class TQTextBrowser tqtextbrowser.h + \brief The TQTextBrowser class provides a rich text browser with hypertext navigation. + + \ingroup advanced + \ingroup helpsystem + \ingroup text + \mainclass + + This class extends TQTextEdit (in read-only mode), adding some + navigation functionality so that users can follow links in + hypertext documents. The contents of TQTextEdit is set with + setText(), but TQTextBrowser has an additional function, + setSource(), which makes it possible to set the text to a named + document. The name is looked up in the text view's mime source + factory. If a document name ends with an anchor (for example, "\c + #anchor"), the text browser automatically scrolls to that position + (using scrollToAnchor()). When the user clicks on a hyperlink, the + browser will call setSource() itself, with the link's \c href + value as argument. You can track the current source by connetion + to the sourceChanged() signal. + + TQTextBrowser provides backward() and forward() slots which you can + use to implement Back and Forward buttons. The home() slot sets + the text to the very first document displayed. The linkClicked() + signal is emitted when the user clicks a link. + + By using TQTextEdit::setMimeSourceFactory() you can provide your + own subclass of TQMimeSourceFactory. This makes it possible to + access data from anywhere, for example from a network or from a + database. See TQMimeSourceFactory::data() for details. + + If you intend using the mime factory to read the data directly + from the file system, you may have to specify the encoding for the + file extension you are using. For example: + \code + mimeSourceFactory()->setExtensionType("qml", "text/utf8"); + \endcode + This is to ensure that the factory is able to resolve the document + names. + + TQTextBrowser interprets the tags it processes in accordance with + the default style sheet. Change the style sheet with + \l{setStyleSheet()}; see TQStyleSheet for details. + + If you want to provide your users with editable rich text use + TQTextEdit. If you want a text browser without hypertext navigation + use TQTextEdit, and use TQTextEdit::setReadOnly() to disable + editing. If you just need to display a small piece of rich text + use TQSimpleRichText or TQLabel. + + <img src=tqtextbrowser-m.png> <img src=tqtextbrowser-w.png> +*/ + +class TQTextBrowserData +{ +public: + TQTextBrowserData():textOrSourceChanged(FALSE) {} + + TQValueStack<TQString> stack; + TQValueStack<TQString> forwardStack; + TQString home; + TQString curmain; + TQString curmark; + + /*flag necessary to give the linkClicked() signal some meaningful + semantics when somebody connected to it calls setText() or + setSource() */ + bool textOrSourceChanged; +}; + + +/*! + Constructs an empty TQTextBrowser called \a name, with parent \a + parent. +*/ +TQTextBrowser::TQTextBrowser(TQWidget *parent, const char *name) + : TQTextEdit( parent, name ) +{ + setReadOnly( TRUE ); + d = new TQTextBrowserData; + + viewport()->setMouseTracking( TRUE ); +} + +/*! + \reimp +*/ +TQTextBrowser::~TQTextBrowser() +{ + delete d; +} + + +/*! + \property TQTextBrowser::source + \brief the name of the displayed document. + + This is a TQString::null if no document is displayed or if the + source is unknown. + + Setting this property uses the mimeSourceFactory() to lookup the + named document. It also checks for optional anchors and scrolls + the document accordingly. + + If the first tag in the document is \c{<qt type=detail>}, the + document is displayed as a popup rather than as new document in + the browser window itself. Otherwise, the document is displayed + normally in the text browser with the text set to the contents of + the named document with setText(). + + If you are using the filesystem access capabilities of the mime + source factory, you must ensure that the factory knows about the + encoding of specified files; otherwise no data will be available. + The default factory handles a couple of common file extensions + such as \c *.html and \c *.txt with reasonable defaults. See + TQMimeSourceFactory::data() for details. +*/ + +TQString TQTextBrowser::source() const +{ + if ( d->stack.isEmpty() ) + return TQString::null; + else + return d->stack.top(); +} + +/*! + \property TQTextBrowser::undoDepth + \brief This text browser's undo depth. +*/ + +/*! + \property TQTextBrowser::overwriteMode + \brief This text browser's overwrite mode. +*/ + +/*! + \property TQTextBrowser::modified + \brief Whether the contents have been modified. +*/ + +/*! + \property TQTextBrowser::readOnly + \brief Whether the contents are read only. +*/ + +/*! + \property TQTextBrowser::undoRedoEnabled + \brief Whether undo and redo are enabled. +*/ + + + +/*! + Reloads the current set source. +*/ + +void TQTextBrowser::reload() +{ + TQString s = d->curmain; + d->curmain = ""; + setSource( s ); +} + + +void TQTextBrowser::setSource(const TQString& name) +{ +#ifndef TQT_NO_CURSOR + if ( isVisible() ) + tqApp->setOverrideCursor( waitCursor ); +#endif + d->textOrSourceChanged = TRUE; + TQString source = name; + TQString mark; + int hash = name.find('#'); + if ( hash != -1) { + source = name.left( hash ); + mark = name.mid( hash+1 ); + } + + if ( source.left(5) == "file:" ) + source = source.mid(6); + + TQString url = mimeSourceFactory()->makeAbsolute( source, context() ); + TQString txt; + bool dosettext = FALSE; + + if ( !source.isEmpty() && url != d->curmain ) { + const TQMimeSource* m = + mimeSourceFactory()->data( source, context() ); + if ( !m ){ + tqWarning("TQTextBrowser: no mimesource for %s", source.latin1() ); + } + else { + if ( !TQTextDrag::decode( m, txt ) ) { + tqWarning("TQTextBrowser: cannot decode %s", source.latin1() ); + } + } + if ( isVisible() ) { + TQString firstTag = txt.left( txt.find( '>' ) + 1 ); + if ( firstTag.left( 3 ) == "<qt" && firstTag.contains( "type" ) && firstTag.contains( "detail" ) ) { + popupDetail( txt, TQCursor::pos() ); +#ifndef TQT_NO_CURSOR + tqApp->restoreOverrideCursor(); +#endif + return; + } + } + + d->curmain = url; + dosettext = TRUE; + } + + d->curmark = mark; + + if ( !mark.isEmpty() ) { + url += "#"; + url += mark; + } + if ( !d->home ) + d->home = url; + + if ( d->stack.isEmpty() || d->stack.top() != url) + d->stack.push( url ); + + int stackCount = (int)d->stack.count(); + if ( d->stack.top() == url ) + stackCount--; + emit backwardAvailable( stackCount > 0 ); + stackCount = (int)d->forwardStack.count(); + if ( d->forwardStack.isEmpty() || d->forwardStack.top() == url ) + stackCount--; + emit forwardAvailable( stackCount > 0 ); + + if ( dosettext ) + TQTextEdit::setText( txt, url ); + + if ( !mark.isEmpty() ) + scrollToAnchor( mark ); + else + setContentsPos( 0, 0 ); + +#ifndef TQT_NO_CURSOR + if ( isVisible() ) + tqApp->restoreOverrideCursor(); +#endif + + emit sourceChanged( url ); +} + +/*! + \fn void TQTextBrowser::backwardAvailable(bool available) + + This signal is emitted when the availability of backward() + changes. \a available is FALSE when the user is at home(); + otherwise it is TRUE. +*/ + +/*! + \fn void TQTextBrowser::forwardAvailable(bool available) + + This signal is emitted when the availability of forward() changes. + \a available is TRUE after the user navigates backward() and FALSE + when the user navigates or goes forward(). +*/ + +/*! + \fn void TQTextBrowser::sourceChanged( const TQString& src) + + This signal is emitted when the mime source has changed, \a src + being the new source. + + Source changes happen both programmatically when calling + setSource(), forward(), backword() or home() or when the user + clicks on links or presses the equivalent key sequences. +*/ + +/*! \fn void TQTextBrowser::highlighted (const TQString &link) + + This signal is emitted when the user has selected but not + activated a link in the document. \a link is the value of the \c + href i.e. the name of the target document. +*/ + +/*! + \fn void TQTextBrowser::linkClicked( const TQString& link) + + This signal is emitted when the user clicks a link. The \a link is + the value of the \c href i.e. the name of the target document. + + The \a link will be the absolute location of the document, based + on the value of the anchor's href tag and the current context of + the document. + + \sa anchorClicked(), context() +*/ + +/*! + \fn void TQTextBrowser::anchorClicked( const TQString& name, const TQString &link) + + This signal is emitted when the user clicks an anchor. The \a link is + the value of the \c href i.e. the name of the target document. The \a name + is the name of the anchor. + + \sa linkClicked() +*/ + +/*! + Changes the document displayed to the previous document in the + list of documents built by navigating links. Does nothing if there + is no previous document. + + \sa forward(), backwardAvailable() +*/ +void TQTextBrowser::backward() +{ + if ( d->stack.count() <= 1) + return; + d->forwardStack.push( d->stack.pop() ); + setSource( d->stack.pop() ); + emit forwardAvailable( TRUE ); +} + +/*! + Changes the document displayed to the next document in the list of + documents built by navigating links. Does nothing if there is no + next document. + + \sa backward(), forwardAvailable() +*/ +void TQTextBrowser::forward() +{ + if ( d->forwardStack.isEmpty() ) + return; + setSource( d->forwardStack.pop() ); + emit forwardAvailable( !d->forwardStack.isEmpty() ); +} + +/*! + Changes the document displayed to be the first document the + browser displayed. +*/ +void TQTextBrowser::home() +{ + if (!d->home.isNull() ) + setSource( d->home ); +} + +/*! + The event \a e is used to provide the following keyboard shortcuts: + \table + \header \i Keypress \i Action + \row \i Alt+Left Arrow \i \l backward() + \row \i Alt+Right Arrow \i \l forward() + \row \i Alt+Up Arrow \i \l home() + \endtable +*/ +void TQTextBrowser::keyPressEvent( TQKeyEvent * e ) +{ + if ( e->state() & AltButton ) { + switch (e->key()) { + case Key_Right: + forward(); + return; + case Key_Left: + backward(); + return; + case Key_Up: + home(); + return; + } + } + TQTextEdit::keyPressEvent(e); +} + +class TQTextDetailPopup : public TQWidget +{ +public: + TQTextDetailPopup() + : TQWidget ( 0, "automatic TQText detail widget", WType_Popup | WDestructiveClose ) + { + } + +protected: + + void mousePressEvent( TQMouseEvent*) + { + close(); + } +}; + + +void TQTextBrowser::popupDetail( const TQString& contents, const TQPoint& pos ) +{ + + const int shadowWidth = 6; // also used as '5' and '6' and even '8' below + const int vMargin = 8; + const int hMargin = 12; + + TQWidget* popup = new TQTextDetailPopup; + popup->setBackgroundMode( TQWidget::NoBackground ); + + TQSimpleRichText* doc = new TQSimpleRichText( contents, popup->font() ); + doc->adjustSize(); + TQRect r( 0, 0, doc->width(), doc->height() ); + + int w = r.width() + 2*hMargin; + int h = r.height() + 2*vMargin; + + popup->resize( w + shadowWidth, h + shadowWidth ); + + // okay, now to find a suitable location + //###### we need a global fancy popup positioning somewhere + popup->move(pos - popup->rect().center()); + if (popup->geometry().right() > TQApplication::desktop()->width()) + popup->move( TQApplication::desktop()->width() - popup->width(), + popup->y() ); + if (popup->geometry().bottom() > TQApplication::desktop()->height()) + popup->move( popup->x(), + TQApplication::desktop()->height() - popup->height() ); + if ( popup->x() < 0 ) + popup->move( 0, popup->y() ); + if ( popup->y() < 0 ) + popup->move( popup->x(), 0 ); + + + popup->show(); + + // now for super-clever shadow stuff. super-clever mostly in + // how many window system problems it skirts around. + + TQPainter p( popup ); + p.setPen( TQApplication::palette().active().foreground() ); + p.drawRect( 0, 0, w, h ); + p.setPen( TQApplication::palette().active().mid() ); + p.setBrush( TQColor( 255, 255, 240 ) ); + p.drawRect( 1, 1, w-2, h-2 ); + p.setPen( black ); + + doc->draw( &p, hMargin, vMargin, r, popup->colorGroup(), 0 ); + delete doc; + + p.drawPoint( w + 5, 6 ); + p.drawLine( w + 3, 6, + w + 5, 8 ); + p.drawLine( w + 1, 6, + w + 5, 10 ); + int i; + for( i=7; i < h; i += 2 ) + p.drawLine( w, i, + w + 5, i + 5 ); + for( i = w - i + h; i > 6; i -= 2 ) + p.drawLine( i, h, + i + 5, h + 5 ); + for( ; i > 0 ; i -= 2 ) + p.drawLine( 6, h + 6 - i, + i + 5, h + 5 ); +} + +/*! + \fn void TQTextBrowser::setText( const TQString &txt ) + + \overload + + Sets the text to \a txt. +*/ + +/*! + \reimp +*/ + +void TQTextBrowser::setText( const TQString &txt, const TQString &context ) +{ + d->textOrSourceChanged = TRUE; + d->curmark = ""; + d->curmain = ""; + TQTextEdit::setText( txt, context ); +} + +void TQTextBrowser::emitHighlighted( const TQString &s ) +{ + emit highlighted( s ); +} + +void TQTextBrowser::emitLinkClicked( const TQString &s ) +{ + d->textOrSourceChanged = FALSE; + emit linkClicked( s ); + if ( !d->textOrSourceChanged ) + setSource( s ); +} + +#endif // TQT_NO_TEXTBROWSER diff --git a/src/widgets/tqtextbrowser.h b/src/widgets/tqtextbrowser.h new file mode 100644 index 000000000..c68031ff1 --- /dev/null +++ b/src/widgets/tqtextbrowser.h @@ -0,0 +1,107 @@ +/**************************************************************************** +** +** Definition of the TQTextBrowser class +** +** Created : 990101 +** +** Copyright (C) 1992-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 TQTEXTBROWSER_H +#define TQTEXTBROWSER_H + +#ifndef QT_H +#include "tqptrlist.h" +#include "ntqpixmap.h" +#include "ntqcolor.h" +#include "tqtextedit.h" +#endif // QT_H + +#ifndef TQT_NO_TEXTBROWSER + +class TQTextBrowserData; + +class TQ_EXPORT TQTextBrowser : public TQTextEdit +{ + TQ_OBJECT + TQ_PROPERTY( TQString source READ source WRITE setSource ) + TQ_OVERRIDE( int undoDepth DESIGNABLE false SCRIPTABLE false ) + TQ_OVERRIDE( bool overwriteMode DESIGNABLE false SCRIPTABLE false ) + TQ_OVERRIDE( bool modified SCRIPTABLE false) + TQ_OVERRIDE( bool readOnly DESIGNABLE false SCRIPTABLE false ) + TQ_OVERRIDE( bool undoRedoEnabled DESIGNABLE false SCRIPTABLE false ) + +public: + TQTextBrowser( TQWidget* parent=0, const char* name=0 ); + ~TQTextBrowser(); + + TQString source() const; + +public slots: + virtual void setSource(const TQString& name); + virtual void backward(); + virtual void forward(); + virtual void home(); + virtual void reload(); + void setText( const TQString &txt ) { setText( txt, TQString::null ); } + virtual void setText( const TQString &txt, const TQString &context ); + +signals: + void backwardAvailable( bool ); + void forwardAvailable( bool ); + void sourceChanged( const TQString& ); + void highlighted( const TQString& ); + void linkClicked( const TQString& ); + void anchorClicked( const TQString&, const TQString& ); + +protected: + void keyPressEvent( TQKeyEvent * e); + +private: + void popupDetail( const TQString& contents, const TQPoint& pos ); + bool linksEnabled() const { return TRUE; } + void emitHighlighted( const TQString &s ); + void emitLinkClicked( const TQString &s ); + TQTextBrowserData *d; + +private: // Disabled copy constructor and operator= +#if defined(TQ_DISABLE_COPY) + TQTextBrowser( const TQTextBrowser & ); + TQTextBrowser& operator=( const TQTextBrowser & ); +#endif +}; + +#endif // TQT_NO_TEXTBROWSER + +#endif // TQTEXTBROWSER_H diff --git a/src/widgets/tqtextedit.cpp b/src/widgets/tqtextedit.cpp new file mode 100644 index 000000000..a4cc6cf11 --- /dev/null +++ b/src/widgets/tqtextedit.cpp @@ -0,0 +1,7474 @@ +/**************************************************************************** +** +** Implementation of the TQTextEdit class +** +** Created : 990101 +** +** Copyright (C) 1992-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 "tqtextedit.h" + +#ifndef TQT_NO_TEXTEDIT + +// Keep this position to avoid patch rejection +#ifndef TQT_NO_IM +#include "ntqinputcontext.h" +#endif + +#include "../kernel/qrichtext_p.h" +#include "ntqpainter.h" +#include "ntqpen.h" +#include "ntqbrush.h" +#include "ntqpixmap.h" +#include "ntqfont.h" +#include "ntqcolor.h" +#include "ntqstyle.h" +#include "ntqsize.h" +#include "ntqevent.h" +#include "ntqtimer.h" +#include "ntqapplication.h" +#include "ntqlistbox.h" +#include "ntqvbox.h" +#include "ntqapplication.h" +#include "ntqclipboard.h" +#include "ntqcolordialog.h" +#include "ntqfontdialog.h" +#include "ntqstylesheet.h" +#include "ntqdragobject.h" +#include "ntqurl.h" +#include "ntqcursor.h" +#include "ntqregexp.h" +#include "ntqpopupmenu.h" +#include "tqptrstack.h" +#include "ntqmetaobject.h" +#include "tqtextbrowser.h" +#include <private/qucom_p.h> +#include "private/qsyntaxhighlighter_p.h" +#include <ntqguardedptr.h> + +#ifndef TQT_NO_ACCEL +#include <ntqkeysequence.h> +#define ACCEL_KEY(k) "\t" + TQString(TQKeySequence( TQt::CTRL | TQt::Key_ ## k )) +#else +#define ACCEL_KEY(k) "\t" + TQString("Ctrl+" #k) +#endif + +#ifdef QT_TEXTEDIT_OPTIMIZATION +#define LOGOFFSET(i) d->logOffset + i +#endif + +struct TQUndoRedoInfoPrivate +{ + TQTextString text; +}; + +class TQTextEditPrivate +{ +public: + TQTextEditPrivate() + :preeditStart(-1),preeditLength(-1),ensureCursorVisibleInShowEvent(FALSE), + tabChangesFocus(FALSE), +#ifndef TQT_NO_CLIPBOARD + clipboard_mode( TQClipboard::Clipboard ), +#endif +#ifdef QT_TEXTEDIT_OPTIMIZATION + od(0), optimMode(FALSE), + maxLogLines(-1), + logOffset(0), +#endif + autoFormatting( (uint)TQTextEdit::AutoAll ) + { + for ( int i=0; i<7; i++ ) + id[i] = 0; + } + int id[ 7 ]; + int preeditStart; + int preeditLength; + bool composeMode() const { return ( preeditLength > 0 ); } + + uint ensureCursorVisibleInShowEvent : 1; + uint tabChangesFocus : 1; + TQString scrollToAnchor; // used to deferr scrollToAnchor() until the show event when we are resized + TQString pressedName; + TQString onName; +#ifndef TQT_NO_CLIPBOARD + TQClipboard::Mode clipboard_mode; +#endif + TQTimer *trippleClickTimer; + TQPoint trippleClickPoint; +#ifdef QT_TEXTEDIT_OPTIMIZATION + TQTextEditOptimPrivate * od; + bool optimMode : 1; + int maxLogLines; + int logOffset; +#endif + uint autoFormatting; +}; + +#ifndef TQT_NO_MIME +class TQRichTextDrag : public TQTextDrag +{ +public: + TQRichTextDrag( TQWidget *dragSource = 0, const char *name = 0 ); + + void setPlainText( const TQString &txt ) { setText( txt ); } + void setRichText( const TQString &txt ) { richTxt = txt; } + + virtual TQByteArray encodedData( const char *mime ) const; + virtual const char* format( int i ) const; + + static bool decode( TQMimeSource *e, TQString &str, const TQCString &mimetype, + const TQCString &subtype ); + static bool canDecode( TQMimeSource* e ); + +private: + TQString richTxt; + +}; + +TQRichTextDrag::TQRichTextDrag( TQWidget *dragSource, const char *name ) + : TQTextDrag( dragSource, name ) +{ +} + +TQByteArray TQRichTextDrag::encodedData( const char *mime ) const +{ + if ( qstrcmp( "application/x-qrichtext", mime ) == 0 ) { + return richTxt.utf8(); // #### perhaps we should use USC2 instead? + } else + return TQTextDrag::encodedData( mime ); +} + +bool TQRichTextDrag::decode( TQMimeSource *e, TQString &str, const TQCString &mimetype, + const TQCString &subtype ) +{ + if ( mimetype == "application/x-qrichtext" ) { + // do richtext decode + const char *mime; + int i; + for ( i = 0; ( mime = e->format( i ) ); ++i ) { + if ( qstrcmp( "application/x-qrichtext", mime ) != 0 ) + continue; + str = TQString::fromUtf8( e->encodedData( mime ) ); + return TRUE; + } + return FALSE; + } + + // do a regular text decode + TQCString subt = subtype; + return TQTextDrag::decode( e, str, subt ); +} + +bool TQRichTextDrag::canDecode( TQMimeSource* e ) +{ + if ( e->provides( "application/x-qrichtext" ) ) + return TRUE; + return TQTextDrag::canDecode( e ); +} + +const char* TQRichTextDrag::format( int i ) const +{ + if ( TQTextDrag::format( i ) ) + return TQTextDrag::format( i ); + if ( TQTextDrag::format( i-1 ) ) + return "application/x-qrichtext"; + return 0; +} + +#endif + +static bool block_set_alignment = FALSE; + +/*! + \class TQTextEdit tqtextedit.h + \brief The TQTextEdit widget provides a powerful single-page rich text editor. + + \ingroup basic + \ingroup text + \mainclass + + \tableofcontents + + \section1 Introduction and Concepts + + TQTextEdit is an advanced WYSIWYG viewer/editor supporting rich + text formatting using HTML-style tags. It is optimized to handle + large documents and to respond quickly to user input. + + TQTextEdit has four modes of operation: + \table + \header \i Mode \i Command \i Notes + \row \i Plain Text Editor \i setTextFormat(PlainText) + \i Set text with setText(); text() returns plain text. Text + attributes (e.g. colors) can be set, but plain text is always + returned. + \row \i Rich Text Editor \i setTextFormat(RichText) + \i Set text with setText(); text() returns rich text. Rich + text editing is fairly limited. You can't set margins or + insert images for example (although you can read and + correctly display files that have margins set and that + include images). This mode is mostly useful for editing small + amounts of rich text. <sup>1.</sup> + \row \i Text Viewer \i setReadOnly(TRUE) + \i Set text with setText() or append() (which has no undo + history so is faster and uses less memory); text() returns + plain or rich text depending on the textFormat(). This mode + can correctly display a large subset of HTML tags. + \row \i Log Viewer \i setTextFormat(LogText) + \i Append text using append(). The widget is set to be read + only and rich text support is disabled although a few HTML + tags (for color, bold, italic and underline) may be used. + (See \link #logtextmode LogText mode\endlink for details.) + \endtable + + <sup>1.</sup><small>A more complete API that supports setting + margins, images, etc., is planned for a later TQt release.</small> + + TQTextEdit can be used as a syntax highlighting editor when used in + conjunction with TQSyntaxHighlighter. + + We recommend that you always call setTextFormat() to set the mode + you want to use. If you use \c AutoText then setText() and + append() will try to determine whether the text they are given is + plain text or rich text. If you use \c RichText then setText() and + append() will assume that the text they are given is rich text. + insert() simply inserts the text it is given. + + TQTextEdit works on paragraphs and characters. A paragraph is a + formatted string which is word-wrapped to fit into the width of + the widget. By default when reading plain text, one newline + signify a paragraph. A document consists of zero or more + paragraphs, indexed from 0. Characters are indexed on a + per-paragraph basis, also indexed from 0. The words in the + paragraph are aligned in accordance with the paragraph's + alignment(). Paragraphs are separated by hard line breaks. Each + character within a paragraph has its own attributes, for example, + font and color. + + The text edit documentation uses the following concepts: + \list + \i \e{current format} -- + this is the format at the current cursor position, \e and it + is the format of the selected text if any. + \i \e{current paragraph} -- the paragraph which contains the + cursor. + \endlist + + TQTextEdit can display images (using TQMimeSourceFactory), lists and + tables. If the text is too large to view within the text edit's + viewport, scrollbars will appear. The text edit can load both + plain text and HTML files (a subset of HTML 3.2 and 4). The + rendering style and the set of valid tags are defined by a + styleSheet(). Custom tags can be created and placed in a custom + style sheet. Change the style sheet with \l{setStyleSheet()}; see + TQStyleSheet for details. The images identified by image tags are + displayed if they can be interpreted using the text edit's + \l{TQMimeSourceFactory}; see setMimeSourceFactory(). + + If you want a text browser with more navigation use TQTextBrowser. + If you just need to display a small piece of rich text use TQLabel + or TQSimpleRichText. + + If you create a new TQTextEdit, and want to allow the user to edit + rich text, call setTextFormat(TQt::RichText) to ensure that the + text is treated as rich text. (Rich text uses HTML tags to set + text formatting attributes. See TQStyleSheet for information on the + HTML tags that are supported.). If you don't call setTextFormat() + explicitly the text edit will guess from the text itself whether + it is rich text or plain text. This means that if the text looks + like HTML or XML it will probably be interpreted as rich text, so + you should call setTextFormat(TQt::PlainText) to preserve such + text. + + Note that we do not intend to add a full-featured web browser + widget to TQt (because that would easily double TQt's size and only + a few applications would benefit from it). The rich + text support in TQt is designed to provide a fast, portable and + efficient way to add reasonable online help facilities to + applications, and to provide a basis for rich text editors. + + \section1 Using TQTextEdit as a Display Widget + + TQTextEdit can display a large HTML subset, including tables and + images. + + The text is set or replaced using setText() which deletes any + existing text and replaces it with the text passed in the + setText() call. If you call setText() with legacy HTML (with + setTextFormat(RichText) in force), and then call text(), the text + that is returned may have different markup, but will render the + same. Text can be inserted with insert(), paste(), pasteSubType() + and append(). Text that is appended does not go into the undo + history; this makes append() faster and consumes less memory. Text + can also be cut(). The entire text is deleted with clear() and the + selected text is deleted with removeSelectedText(). Selected + (marked) text can also be deleted with del() (which will delete + the character to the right of the cursor if no text is selected). + + Loading and saving text is achieved using setText() and text(), + for example: + \code + TQFile file( fileName ); // Read the text from a file + if ( file.open( IO_ReadOnly ) ) { + TQTextStream stream( &file ); + textEdit->setText( stream.read() ); + } + + TQFile file( fileName ); // Write the text to a file + if ( file.open( IO_WriteOnly ) ) { + TQTextStream stream( &file ); + stream << textEdit->text(); + textEdit->setModified( FALSE ); + } + \endcode + + By default the text edit wraps words at whitespace to fit within + the text edit widget. The setWordWrap() function is used to + specify the kind of word wrap you want, or \c NoWrap if you don't + want any wrapping. Call setWordWrap() to set a fixed pixel width + \c FixedPixelWidth, or character column (e.g. 80 column) \c + FixedColumnWidth with the pixels or columns specified with + setWrapColumnOrWidth(). If you use word wrap to the widget's width + \c WidgetWidth, you can specify whether to break on whitespace or + anywhere with setWrapPolicy(). + + The background color is set differently than other widgets, using + setPaper(). You specify a brush style which could be a plain color + or a complex pixmap. + + Hypertext links are automatically underlined; this can be changed + with setLinkUnderline(). The tab stop width is set with + setTabStopWidth(). + + The zoomIn() and zoomOut() functions can be used to resize the + text by increasing (decreasing for zoomOut()) the point size used. + Images are not affected by the zoom functions. + + The lines() function returns the number of lines in the text and + paragraphs() returns the number of paragraphs. The number of lines + within a particular paragraph is returned by linesOfParagraph(). + The length of the entire text in characters is returned by + length(). + + You can scroll to an anchor in the text, e.g. + \c{<a name="anchor">} with scrollToAnchor(). The find() function + can be used to find and select a given string within the text. + + A read-only TQTextEdit provides the same functionality as the + (obsolete) TQTextView. (TQTextView is still supplied for + compatibility with old code.) + + \section2 Read-only key bindings + + When TQTextEdit is used read-only the key-bindings are limited to + navigation, and text may only be selected with the mouse: + \table + \header \i Keypresses \i Action + \row \i UpArrow \i Move one line up + \row \i DownArrow \i Move one line down + \row \i LeftArrow \i Move one character left + \row \i RightArrow \i Move one character right + \row \i PageUp \i Move one (viewport) page up + \row \i PageDown \i Move one (viewport) page down + \row \i Home \i Move to the beginning of the text + \row \i End \i Move to the end of the text + \row \i Shift+Wheel + \i Scroll the page horizontally (the Wheel is the mouse wheel) + \row \i Ctrl+Wheel \i Zoom the text + \endtable + + The text edit may be able to provide some meta-information. For + example, the documentTitle() function will return the text from + within HTML \c{<title>} tags. + + The text displayed in a text edit has a \e context. The context is + a path which the text edit's TQMimeSourceFactory uses to resolve + the locations of files and images. It is passed to the + mimeSourceFactory() when quering data. (See TQTextEdit() and + \l{context()}.) + + \target logtextmode + \section2 Using TQTextEdit in LogText Mode + + Setting the text format to \c LogText puts the widget in a special + mode which is optimized for very large texts. Editing, word wrap, + and rich text support are disabled in this mode (the widget is + explicitly made read-only). This allows the text to be stored in a + different, more memory efficient manner. However, a certain degree + of text formatting is supported through the use of formatting tags. + A tag is delimited by \c < and \c {>}. The characters \c {<}, \c > + and \c & are escaped by using \c {<}, \c {>} and \c {&}. + A tag pair consists of a left and a right tag (or open/close tags). + Left-tags mark the starting point for formatting, while right-tags + mark the ending point. A right-tag always start with a \c / before + the tag keyword. For example \c <b> and \c </b> are a tag pair. + Tags can be nested, but they have to be closed in the same order as + they are opened. For example, \c <b><u></u></b> is valid, while \c + <b><u></b></u> will output an error message. + + By using tags it is possible to change the color, bold, italic and + underline settings for a piece of text. A color can be specified + by using the HTML font tag \c {<font color=colorname>}. The color + name can be one of the color names from the X11 color database, or + a RGB hex value (e.g \c {#00ff00}). Example of valid color tags: + \c {<font color=red>}, \c {<font color="light blue">}, \c {<font + color="#223344">}. Bold, italic and underline settings can be + specified by the tags \c {<b>}, \c <i> and \c {<u>}. Note that a + tag does not necessarily have to be closed. A valid example: + \code + This is <font color=red>red</font> while <b>this</b> is <font color=blue>blue</font>. + <font color=green><font color=yellow>Yellow,</font> and <u>green</u>. + \endcode + + Stylesheets can also be used in LogText mode. To create and use a + custom tag, you could do the following: + \code + TQTextEdit * log = new TQTextEdit( this ); + log->setTextFormat( TQt::LogText ); + TQStyleSheetItem * item = new TQStyleSheetItem( log->styleSheet(), "mytag" ); + item->setColor( "red" ); + item->setFontWeight( TQFont::Bold ); + item->setFontUnderline( TRUE ); + log->append( "This is a <mytag>custom tag</mytag>!" ); + \endcode + Note that only the color, bold, underline and italic attributes of + a TQStyleSheetItem is used in LogText mode. + + Note that you can use setMaxLogLines() to limit the number of + lines the widget can hold in LogText mode. + + There are a few things that you need to be aware of when the + widget is in this mode: + \list + \i Functions that deal with rich text formatting and cursor + movement will not work or return anything valid. + \i Lines are equivalent to paragraphs. + \endlist + + \section1 Using TQTextEdit as an Editor + + All the information about using TQTextEdit as a display widget also + applies here. + + The current format's attributes are set with setItalic(), + setBold(), setUnderline(), setFamily() (font family), + setPointSize(), setColor() and setCurrentFont(). The current + paragraph's alignment is set with setAlignment(). + + Use setSelection() to select text. The setSelectionAttributes() + function is used to indicate how selected text should be + displayed. Use hasSelectedText() to find out if any text is + selected. The currently selected text's position is available + using getSelection() and the selected text itself is returned by + selectedText(). The selection can be copied to the clipboard with + copy(), or cut to the clipboard with cut(). It can be deleted with + removeSelectedText(). The entire text can be selected (or + unselected) using selectAll(). TQTextEdit supports multiple + selections. Most of the selection functions operate on the default + selection, selection 0. If the user presses a non-selecting key, + e.g. a cursor key without also holding down Shift, all selections + are cleared. + + Set and get the position of the cursor with setCursorPosition() + and getCursorPosition() respectively. When the cursor is moved, + the signals currentFontChanged(), currentColorChanged() and + currentAlignmentChanged() are emitted to reflect the font, color + and alignment at the new cursor position. + + If the text changes, the textChanged() signal is emitted, and if + the user inserts a new line by pressing Return or Enter, + returnPressed() is emitted. The isModified() function will return + TRUE if the text has been modified. + + TQTextEdit provides command-based undo and redo. To set the depth + of the command history use setUndoDepth() which defaults to 100 + steps. To undo or redo the last operation call undo() or redo(). + The signals undoAvailable() and redoAvailable() indicate whether + the undo and redo operations can be executed. + + The indent() function is used to reindent a paragraph. It is + useful for code editors, for example in \link designer-manual.book + TQt Designer\endlink's code editor \e{Ctrl+I} invokes the indent() + function. + + \section2 Editing key bindings + + The list of key-bindings which are implemented for editing: + \table + \header \i Keypresses \i Action + \row \i Backspace \i Delete the character to the left of the cursor + \row \i Delete \i Delete the character to the right of the cursor + \row \i Ctrl+A \i Move the cursor to the beginning of the line + \row \i Ctrl+B \i Move the cursor one character left + \row \i Ctrl+C \i Copy the marked text to the clipboard (also + Ctrl+Insert under Windows) + \row \i Ctrl+D \i Delete the character to the right of the cursor + \row \i Ctrl+E \i Move the cursor to the end of the line + \row \i Ctrl+F \i Move the cursor one character right + \row \i Ctrl+H \i Delete the character to the left of the cursor + \row \i Ctrl+K \i Delete to end of line + \row \i Ctrl+N \i Move the cursor one line down + \row \i Ctrl+P \i Move the cursor one line up + \row \i Ctrl+V \i Paste the clipboard text into line edit + (also Shift+Insert under Windows) + \row \i Ctrl+X \i Cut the marked text, copy to clipboard + (also Shift+Delete under Windows) + \row \i Ctrl+Z \i Undo the last operation + \row \i Ctrl+Y \i Redo the last operation + \row \i LeftArrow \i Move the cursor one character left + \row \i Ctrl+LeftArrow \i Move the cursor one word left + \row \i RightArrow \i Move the cursor one character right + \row \i Ctrl+RightArrow \i Move the cursor one word right + \row \i UpArrow \i Move the cursor one line up + \row \i Ctrl+UpArrow \i Move the cursor one word up + \row \i DownArrow \i Move the cursor one line down + \row \i Ctrl+Down Arrow \i Move the cursor one word down + \row \i PageUp \i Move the cursor one page up + \row \i PageDown \i Move the cursor one page down + \row \i Home \i Move the cursor to the beginning of the line + \row \i Ctrl+Home \i Move the cursor to the beginning of the text + \row \i End \i Move the cursor to the end of the line + \row \i Ctrl+End \i Move the cursor to the end of the text + \row \i Shift+Wheel \i Scroll the page horizontally + (the Wheel is the mouse wheel) + \row \i Ctrl+Wheel \i Zoom the text + \endtable + + To select (mark) text hold down the Shift key whilst pressing one + of the movement keystrokes, for example, \e{Shift+Right Arrow} + will select the character to the right, and \e{Shift+Ctrl+Right + Arrow} will select the word to the right, etc. + + By default the text edit widget operates in insert mode so all + text that the user enters is inserted into the text edit and any + text to the right of the cursor is moved out of the way. The mode + can be changed to overwrite, where new text overwrites any text to + the right of the cursor, using setOverwriteMode(). +*/ + +/*! + \enum TQTextEdit::AutoFormatting + + \value AutoNone Do not perform any automatic formatting + \value AutoBulletList Only automatically format bulletted lists + \value AutoAll Apply all available autoformatting +*/ + + +/*! + \enum TQTextEdit::KeyboardAction + + This enum is used by doKeyboardAction() to specify which action + should be executed: + + \value ActionBackspace Delete the character to the left of the + cursor. + + \value ActionDelete Delete the character to the right of the + cursor. + + \value ActionReturn Split the paragraph at the cursor position. + + \value ActionKill If the cursor is not at the end of the + paragraph, delete the text from the cursor position until the end + of the paragraph. If the cursor is at the end of the paragraph, + delete the hard line break at the end of the paragraph: this will + cause this paragraph to be joined with the following paragraph. + + \value ActionWordBackspace Delete the word to the left of the + cursor position. + + \value ActionWordDelete Delete the word to the right of the + cursor position + +*/ + +/*! + \enum TQTextEdit::VerticalAlignment + + This enum is used to set the vertical alignment of the text. + + \value AlignNormal Normal alignment + \value AlignSuperScript Superscript + \value AlignSubScript Subscript +*/ + +/*! + \enum TQTextEdit::TextInsertionFlags + + \internal + + \value RedoIndentation + \value CheckNewLines + \value RemoveSelected +*/ + + +/*! + \fn void TQTextEdit::copyAvailable(bool yes) + + This signal is emitted when text is selected or de-selected in the + text edit. + + When text is selected this signal will be emitted with \a yes set + to TRUE. If no text has been selected or if the selected text is + de-selected this signal is emitted with \a yes set to FALSE. + + If \a yes is TRUE then copy() can be used to copy the selection to + the clipboard. If \a yes is FALSE then copy() does nothing. + + \sa selectionChanged() +*/ + + +/*! + \fn void TQTextEdit::textChanged() + + This signal is emitted whenever the text in the text edit changes. + + \sa setText() append() +*/ + +/*! + \fn void TQTextEdit::selectionChanged() + + This signal is emitted whenever the selection changes. + + \sa setSelection() copyAvailable() +*/ + +/*! \fn TQTextDocument *TQTextEdit::document() const + + \internal + + This function returns the TQTextDocument which is used by the text + edit. +*/ + +/*! \fn void TQTextEdit::setDocument( TQTextDocument *doc ) + + \internal + + This function sets the TQTextDocument which should be used by the text + edit to \a doc. This can be used, for example, if you want to + display a document using multiple views. You would create a + TQTextDocument and set it to the text edits which should display it. + You would need to connect to the textChanged() and + selectionChanged() signals of all the text edits and update them all + accordingly (preferably with a slight delay for efficiency reasons). +*/ + +/*! + \enum TQTextEdit::CursorAction + + This enum is used by moveCursor() to specify in which direction + the cursor should be moved: + + \value MoveBackward Moves the cursor one character backward + + \value MoveWordBackward Moves the cursor one word backward + + \value MoveForward Moves the cursor one character forward + + \value MoveWordForward Moves the cursor one word forward + + \value MoveUp Moves the cursor up one line + + \value MoveDown Moves the cursor down one line + + \value MoveLineStart Moves the cursor to the beginning of the line + + \value MoveLineEnd Moves the cursor to the end of the line + + \value MoveHome Moves the cursor to the beginning of the document + + \value MoveEnd Moves the cursor to the end of the document + + \value MovePgUp Moves the cursor one viewport page up + + \value MovePgDown Moves the cursor one viewport page down +*/ + +/*! + \enum TQt::AnchorAttribute + + An anchor has one or more of the following attributes: + + \value AnchorName the name attribute of the anchor. This attribute is + used when scrolling to an anchor in the document. + + \value AnchorHref the href attribute of the anchor. This attribute is + used when a link is clicked to determine what content to load. +*/ + +/*! + \property TQTextEdit::overwriteMode + \brief the text edit's overwrite mode + + If FALSE (the default) characters entered by the user are inserted + with any characters to the right being moved out of the way. If + TRUE, the editor is in overwrite mode, i.e. characters entered by + the user overwrite any characters to the right of the cursor + position. +*/ + +/*! + \fn void TQTextEdit::setCurrentFont( const TQFont &f ) + + Sets the font of the current format to \a f. + + If the widget is in \c LogText mode this function will do + nothing. Use setFont() instead. + + \sa currentFont() setPointSize() setFamily() +*/ + +/*! + \property TQTextEdit::undoDepth + \brief the depth of the undo history + + The maximum number of steps in the undo/redo history. The default + is 100. + + \sa undo() redo() +*/ + +/*! + \fn void TQTextEdit::undoAvailable( bool yes ) + + This signal is emitted when the availability of undo changes. If + \a yes is TRUE, then undo() will work until undoAvailable( FALSE ) + is next emitted. + + \sa undo() undoDepth() +*/ + +/*! + \fn void TQTextEdit::modificationChanged( bool m ) + + This signal is emitted when the modification status of the + document has changed. If \a m is TRUE, the document was modified, + otherwise the modification state has been reset to unmodified. + + \sa modified +*/ + +/*! + \fn void TQTextEdit::redoAvailable( bool yes ) + + This signal is emitted when the availability of redo changes. If + \a yes is TRUE, then redo() will work until redoAvailable( FALSE ) + is next emitted. + + \sa redo() undoDepth() +*/ + +/*! + \fn void TQTextEdit::currentFontChanged( const TQFont &f ) + + This signal is emitted if the font of the current format has + changed. + + The new font is \a f. + + \sa setCurrentFont() +*/ + +/*! + \fn void TQTextEdit::currentColorChanged( const TQColor &c ) + + This signal is emitted if the color of the current format has + changed. + + The new color is \a c. + + \sa setColor() +*/ + +/*! + \fn void TQTextEdit::currentVerticalAlignmentChanged( VerticalAlignment a ) + + This signal is emitted if the vertical alignment of the current + format has changed. + + The new vertical alignment is \a a. + + \sa setVerticalAlignment() +*/ + +/*! + \fn void TQTextEdit::currentAlignmentChanged( int a ) + + This signal is emitted if the alignment of the current paragraph + has changed. + + The new alignment is \a a. + + \sa setAlignment() +*/ + +/*! + \fn void TQTextEdit::cursorPositionChanged( TQTextCursor *c ) + + \internal +*/ + +/*! + \fn void TQTextEdit::cursorPositionChanged( int para, int pos ) + + This signal is emitted if the position of the cursor has changed. + \a para contains the paragraph index and \a pos contains the + character position within the paragraph. + + \sa setCursorPosition() +*/ + +/*! + \fn void TQTextEdit::clicked( int para, int pos ) + + This signal is emitted when the mouse is clicked on the paragraph + \a para at character position \a pos. + + \sa doubleClicked() +*/ + +/*! \fn void TQTextEdit::doubleClicked( int para, int pos ) + + This signal is emitted when the mouse is double-clicked on the + paragraph \a para at character position \a pos. + + \sa clicked() +*/ + + +/*! + \fn void TQTextEdit::returnPressed() + + This signal is emitted if the user pressed the Return or the Enter + key. +*/ + +/*! + \fn TQTextCursor *TQTextEdit::textCursor() const + + Returns the text edit's text cursor. + + \warning TQTextCursor is not in the public API, but in special + circumstances you might wish to use it. +*/ + +/*! + Constructs an empty TQTextEdit called \a name, with parent \a + parent. +*/ + +TQTextEdit::TQTextEdit( TQWidget *parent, const char *name ) + : TQScrollView( parent, name, WStaticContents | WNoAutoErase ), + doc( new TQTextDocument( 0 ) ), undoRedoInfo( doc ) +{ + init(); +} + +/*! + Constructs a TQTextEdit called \a name, with parent \a parent. The + text edit will display the text \a text using context \a context. + + The \a context is a path which the text edit's TQMimeSourceFactory + uses to resolve the locations of files and images. It is passed to + the mimeSourceFactory() when quering data. + + For example if the text contains an image tag, + \c{<img src="image.png">}, and the context is "path/to/look/in", the + TQMimeSourceFactory will try to load the image from + "path/to/look/in/image.png". If the tag was + \c{<img src="/image.png">}, the context will not be used (because + TQMimeSourceFactory recognizes that we have used an absolute path) + and will try to load "/image.png". The context is applied in exactly + the same way to \e hrefs, for example, + \c{<a href="target.html">Target</a>}, would resolve to + "path/to/look/in/target.html". +*/ + +TQTextEdit::TQTextEdit( const TQString& text, const TQString& context, + TQWidget *parent, const char *name) + : TQScrollView( parent, name, WStaticContents | WNoAutoErase ), + doc( new TQTextDocument( 0 ) ), undoRedoInfo( doc ) +{ + init(); + setText( text, context ); +} + +/*! + \reimp +*/ + +TQTextEdit::~TQTextEdit() +{ + delete undoRedoInfo.d; + undoRedoInfo.d = 0; + delete cursor; + delete doc; +#ifdef QT_TEXTEDIT_OPTIMIZATION + if ( d->optimMode ) + delete d->od; +#endif + delete d; +} + +void TQTextEdit::init() +{ + d = new TQTextEditPrivate; + doc->formatCollection()->setPaintDevice( this ); + undoEnabled = TRUE; + readOnly = TRUE; + setReadOnly( FALSE ); + setFrameStyle( LineEditPanel | Sunken ); + connect( doc, TQ_SIGNAL( minimumWidthChanged(int) ), + this, TQ_SLOT( documentWidthChanged(int) ) ); + + mousePressed = FALSE; + inDoubleClick = FALSE; + modified = FALSE; + onLink = TQString::null; + d->onName = TQString::null; + overWrite = FALSE; + wrapMode = WidgetWidth; + wrapWidth = -1; + wPolicy = AtWhiteSpace; + mightStartDrag = FALSE; + inDnD = FALSE; + doc->setFormatter( new TQTextFormatterBreakWords ); + doc->formatCollection()->defaultFormat()->setFont( TQScrollView::font() ); + doc->formatCollection()->defaultFormat()->setColor( colorGroup().color( TQColorGroup::Text ) ); + currentFormat = doc->formatCollection()->defaultFormat(); + currentAlignment = TQt::AlignAuto; + + setBackgroundMode( PaletteBase ); + viewport()->setBackgroundMode( PaletteBase ); + viewport()->setAcceptDrops( TRUE ); + resizeContents( 0, doc->lastParagraph() ? + ( doc->lastParagraph()->paragId() + 1 ) * doc->formatCollection()->defaultFormat()->height() : 0 ); + + setKeyCompression( TRUE ); + viewport()->setMouseTracking( TRUE ); +#ifndef TQT_NO_CURSOR + viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); +#endif + cursor = new TQTextCursor( doc ); + + formatTimer = new TQTimer( this ); + connect( formatTimer, TQ_SIGNAL( timeout() ), + this, TQ_SLOT( formatMore() ) ); + lastFormatted = doc->firstParagraph(); + + scrollTimer = new TQTimer( this ); + connect( scrollTimer, TQ_SIGNAL( timeout() ), + this, TQ_SLOT( autoScrollTimerDone() ) ); + + interval = 0; + changeIntervalTimer = new TQTimer( this ); + connect( changeIntervalTimer, TQ_SIGNAL( timeout() ), + this, TQ_SLOT( doChangeInterval() ) ); + + cursorVisible = TRUE; + blinkTimer = new TQTimer( this ); + connect( blinkTimer, TQ_SIGNAL( timeout() ), + this, TQ_SLOT( blinkCursor() ) ); + +#ifndef TQT_NO_DRAGANDDROP + dragStartTimer = new TQTimer( this ); + connect( dragStartTimer, TQ_SIGNAL( timeout() ), + this, TQ_SLOT( startDrag() ) ); +#endif + + d->trippleClickTimer = new TQTimer( this ); + + formatMore(); + + blinkCursorVisible = FALSE; + + viewport()->setFocusProxy( this ); + viewport()->setFocusPolicy( WheelFocus ); + setInputMethodEnabled( TRUE ); + viewport()->installEventFilter( this ); + connect( this, TQ_SIGNAL(horizontalSliderReleased()), this, TQ_SLOT(sliderReleased()) ); + connect( this, TQ_SIGNAL(verticalSliderReleased()), this, TQ_SLOT(sliderReleased()) ); + installEventFilter( this ); +} + +void TQTextEdit::paintDocument( bool drawAll, TQPainter *p, int cx, int cy, int cw, int ch ) +{ +#ifdef QT_TEXTEDIT_OPTIMIZATION + Q_ASSERT( !d->optimMode ); + if ( d->optimMode ) + return; +#endif + + bool drawCur = hasFocus() || viewport()->hasFocus(); + if (( hasSelectedText() && !style().styleHint( TQStyle::SH_BlinkCursorWhenTextSelected ) ) || + isReadOnly() || !cursorVisible || doc->hasSelection( TQTextDocument::IMSelectionText )) + drawCur = FALSE; + TQColorGroup g = colorGroup(); + const TQColorGroup::ColorRole backRole = TQPalette::backgroundRoleFromMode(backgroundMode()); + if ( doc->paper() ) + g.setBrush( backRole, *doc->paper() ); + + if ( contentsY() < doc->y() ) { + p->fillRect( contentsX(), contentsY(), visibleWidth(), doc->y(), + g.brush( backRole ) ); + } + if ( drawAll && doc->width() - contentsX() < cx + cw ) { + p->fillRect( doc->width() - contentsX(), cy, cx + cw - doc->width() + contentsX(), ch, + g.brush( backRole ) ); + } + + p->setBrushOrigin( -contentsX(), -contentsY() ); + + lastFormatted = doc->draw( p, cx, cy, cw, ch, g, !drawAll, drawCur, cursor ); + + if ( lastFormatted == doc->lastParagraph() ) + resizeContents( contentsWidth(), doc->height() ); + + if ( contentsHeight() < visibleHeight() && ( !doc->lastParagraph() || doc->lastParagraph()->isValid() ) && drawAll ) + p->fillRect( 0, contentsHeight(), visibleWidth(), + visibleHeight() - contentsHeight(), g.brush( backRole ) ); +} + +/*! + \reimp +*/ + +void TQTextEdit::drawContents( TQPainter *p, int cx, int cy, int cw, int ch ) +{ +#ifdef QT_TEXTEDIT_OPTIMIZATION + if ( d->optimMode ) { + optimDrawContents( p, cx, cy, cw, ch ); + return; + } +#endif + paintDocument( TRUE, p, cx, cy, cw, ch ); + int v; + p->setPen( foregroundColor() ); + if ( document()->isPageBreakEnabled() && ( v = document()->flow()->pageSize() ) > 0 ) { + int l = int(cy / v) * v; + while ( l < cy + ch ) { + p->drawLine( cx, l, cx + cw - 1, l ); + l += v; + } + } + + // This invocation is required to follow dragging of active window + // by the showed candidate window. + updateMicroFocusHint(); +} + +/*! + \reimp +*/ + +void TQTextEdit::drawContents( TQPainter *p ) +{ + if ( horizontalScrollBar()->isVisible() && + verticalScrollBar()->isVisible() ) { + const TQRect verticalRect = verticalScrollBar()->geometry(); + const TQRect horizontalRect = horizontalScrollBar()->geometry(); + + TQRect cornerRect; + cornerRect.setTop( verticalRect.bottom() ); + cornerRect.setBottom( horizontalRect.bottom() ); + cornerRect.setLeft( verticalRect.left() ); + cornerRect.setRight( verticalRect.right() ); + + p->fillRect( cornerRect, colorGroup().background() ); + } +} + +/*! + \reimp +*/ + +bool TQTextEdit::event( TQEvent *e ) +{ + if ( e->type() == TQEvent::AccelOverride && !isReadOnly() ) { + TQKeyEvent* ke = (TQKeyEvent*) e; + switch((int)(ke->state())) { + case NoButton: + case Keypad: + case ShiftButton: + if ( ke->key() < Key_Escape ) { + ke->accept(); + } else { + switch ( ke->key() ) { + case Key_Return: + case Key_Enter: + case Key_Delete: + case Key_Home: + case Key_End: + case Key_Backspace: + case Key_Left: + case Key_Right: + ke->accept(); + default: + break; + } + } + break; + + case ControlButton: + case ControlButton|ShiftButton: + case ControlButton|Keypad: + case ControlButton|ShiftButton|Keypad: + switch ( ke->key() ) { + case Key_Tab: + case Key_Backtab: + ke->ignore(); + break; +// Those are too frequently used for application functionality +/* case Key_A: + case Key_B: + case Key_D: + case Key_E: + case Key_F: + case Key_H: + case Key_I: + case Key_K: + case Key_N: + case Key_P: + case Key_T: +*/ + case Key_C: + case Key_V: + case Key_X: + case Key_Y: + case Key_Z: + case Key_Left: + case Key_Right: + case Key_Up: + case Key_Down: + case Key_Home: + case Key_End: +#if defined (TQ_WS_WIN) + case Key_Insert: + case Key_Delete: +#endif + ke->accept(); + default: + break; + } + break; + + default: + switch ( ke->key() ) { +#if defined (TQ_WS_WIN) + case Key_Insert: + ke->accept(); +#endif + default: + break; + } + break; + } + } + + if ( e->type() == TQEvent::Show ) { + if ( +#ifdef QT_TEXTEDIT_OPTIMIZATION + !d->optimMode && +#endif + d->ensureCursorVisibleInShowEvent ) { + ensureCursorVisible(); + d->ensureCursorVisibleInShowEvent = FALSE; + } + if ( !d->scrollToAnchor.isEmpty() ) { + scrollToAnchor( d->scrollToAnchor ); + d->scrollToAnchor = TQString::null; + } + } + return TQWidget::event( e ); +} + +/*! + Processes the key event, \a e. By default key events are used to + provide keyboard navigation and text editing. +*/ + +void TQTextEdit::keyPressEvent( TQKeyEvent *e ) +{ + changeIntervalTimer->stop(); + interval = 10; + bool unknownKey = FALSE; + if ( isReadOnly() ) { + if ( !handleReadOnlyKeyEvent( e ) ) + TQScrollView::keyPressEvent( e ); + changeIntervalTimer->start( 100, TRUE ); + return; + } + + + bool selChanged = FALSE; + for ( int i = 1; i < doc->numSelections(); ++i ) // start with 1 as we don't want to remove the Standard-Selection + selChanged = doc->removeSelection( i ) || selChanged; + + if ( selChanged ) { + cursor->paragraph()->document()->nextDoubleBuffered = TRUE; + repaintChanged(); + } + + bool clearUndoRedoInfo = TRUE; + + + switch ( e->key() ) { + case Key_Left: + case Key_Right: { + // a bit hacky, but can't change this without introducing new enum values for move and keeping the + // correct semantics and movement for BiDi and non BiDi text. + CursorAction a; + if ( cursor->paragraph()->string()->isRightToLeft() == (e->key() == Key_Right) ) + a = e->state() & ControlButton ? MoveWordBackward : MoveBackward; + else + a = e->state() & ControlButton ? MoveWordForward : MoveForward; + moveCursor( a, e->state() & ShiftButton ); + break; + } + case Key_Up: + moveCursor( e->state() & ControlButton ? MovePgUp : MoveUp, e->state() & ShiftButton ); + break; + case Key_Down: + moveCursor( e->state() & ControlButton ? MovePgDown : MoveDown, e->state() & ShiftButton ); + break; + case Key_Home: + moveCursor( e->state() & ControlButton ? MoveHome : MoveLineStart, e->state() & ShiftButton ); + break; + case Key_End: + moveCursor( e->state() & ControlButton ? MoveEnd : MoveLineEnd, e->state() & ShiftButton ); + break; + case Key_Prior: + moveCursor( MovePgUp, e->state() & ShiftButton ); + break; + case Key_Next: + moveCursor( MovePgDown, e->state() & ShiftButton ); + break; + case Key_Return: case Key_Enter: + if ( doc->hasSelection( TQTextDocument::Standard, FALSE ) ) + removeSelectedText(); + if ( textFormat() == TQt::RichText && ( e->state() & ControlButton ) ) { + // Ctrl-Enter inserts a line break in rich text mode + insert( TQString( TQChar( 0x2028) ), TRUE, FALSE ); + } else { +#ifndef TQT_NO_CURSOR + viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); +#endif + clearUndoRedoInfo = FALSE; + doKeyboardAction( ActionReturn ); + emit returnPressed(); + } + break; + case Key_Delete: +#if defined (TQ_WS_WIN) + if ( e->state() & ShiftButton ) { + cut(); + break; + } else +#endif + if ( doc->hasSelection( TQTextDocument::Standard, TRUE ) ) { + removeSelectedText(); + break; + } + doKeyboardAction( e->state() & ControlButton ? ActionWordDelete + : ActionDelete ); + clearUndoRedoInfo = FALSE; + + break; + case Key_Insert: + if ( e->state() & ShiftButton ) + paste(); +#if defined (TQ_WS_WIN) + else if ( e->state() & ControlButton ) + copy(); +#endif + else + setOverwriteMode( !isOverwriteMode() ); + break; + case Key_Backspace: +#if defined (TQ_WS_WIN) + if ( e->state() & AltButton ) { + if (e->state() & ControlButton ) { + break; + } else if ( e->state() & ShiftButton ) { + redo(); + break; + } else { + undo(); + break; + } + } else +#endif + if ( doc->hasSelection( TQTextDocument::Standard, TRUE ) ) { + removeSelectedText(); + break; + } + + doKeyboardAction( e->state() & ControlButton ? ActionWordBackspace + : ActionBackspace ); + clearUndoRedoInfo = FALSE; + break; + case Key_F16: // Copy key on Sun keyboards + copy(); + break; + case Key_F18: // Paste key on Sun keyboards + paste(); + break; + case Key_F20: // Cut key on Sun keyboards + cut(); + break; + case Key_Direction_L: + if ( doc->textFormat() == TQt::PlainText ) { + // change the whole doc + TQTextParagraph *p = doc->firstParagraph(); + while ( p ) { + p->setDirection( TQChar::DirL ); + p->setAlignment( TQt::AlignLeft ); + p->invalidate( 0 ); + p = p->next(); + } + } else { + if ( !cursor->paragraph() || cursor->paragraph()->direction() == TQChar::DirL ) + return; + cursor->paragraph()->setDirection( TQChar::DirL ); + if ( cursor->paragraph()->length() <= 1&& + ( (cursor->paragraph()->alignment() & (TQt::AlignLeft | TQt::AlignRight) ) != 0 ) ) + setAlignment( TQt::AlignLeft ); + } + repaintChanged(); + break; + case Key_Direction_R: + if ( doc->textFormat() == TQt::PlainText ) { + // change the whole doc + TQTextParagraph *p = doc->firstParagraph(); + while ( p ) { + p->setDirection( TQChar::DirR ); + p->setAlignment( TQt::AlignRight ); + p->invalidate( 0 ); + p = p->next(); + } + } else { + if ( !cursor->paragraph() || cursor->paragraph()->direction() == TQChar::DirR ) + return; + cursor->paragraph()->setDirection( TQChar::DirR ); + if ( cursor->paragraph()->length() <= 1&& + ( (cursor->paragraph()->alignment() & (TQt::AlignLeft | TQt::AlignRight) ) != 0 ) ) + setAlignment( TQt::AlignRight ); + } + repaintChanged(); + break; + default: { + if ( e->text().length() && + ( ( !( e->state() & ControlButton ) && +#ifndef Q_OS_MACX + !( e->state() & AltButton ) && +#endif + !( e->state() & MetaButton ) ) || + ( ( (e->state()&ControlButton) | AltButton ) == (ControlButton|AltButton) ) ) && + ( !e->ascii() || e->ascii() >= 32 || e->text() == "\t" ) ) { + clearUndoRedoInfo = FALSE; + if ( e->key() == Key_Tab ) { + if ( d->tabChangesFocus ) { + e->ignore(); + break; + } + if ( textFormat() == TQt::RichText && cursor->index() == 0 + && ( cursor->paragraph()->isListItem() || cursor->paragraph()->listDepth() ) ) { + clearUndoRedo(); + undoRedoInfo.type = UndoRedoInfo::Style; + undoRedoInfo.id = cursor->paragraph()->paragId(); + undoRedoInfo.eid = undoRedoInfo.id; + undoRedoInfo.styleInformation = TQTextStyleCommand::readStyleInformation( doc, undoRedoInfo.id, undoRedoInfo.eid ); + cursor->paragraph()->setListDepth( cursor->paragraph()->listDepth() +1 ); + clearUndoRedo(); + drawCursor( FALSE ); + repaintChanged(); + drawCursor( TRUE ); + break; + } + } else if ( e->key() == Key_BackTab ) { + if ( d->tabChangesFocus ) { + e->ignore(); + break; + } + } + + if ( ( autoFormatting() & AutoBulletList ) && + textFormat() == TQt::RichText && cursor->index() == 0 + && !cursor->paragraph()->isListItem() + && ( e->text()[0] == '-' || e->text()[0] == '*' ) ) { + clearUndoRedo(); + undoRedoInfo.type = UndoRedoInfo::Style; + undoRedoInfo.id = cursor->paragraph()->paragId(); + undoRedoInfo.eid = undoRedoInfo.id; + undoRedoInfo.styleInformation = TQTextStyleCommand::readStyleInformation( doc, undoRedoInfo.id, undoRedoInfo.eid ); + setParagType( TQStyleSheetItem::DisplayListItem, TQStyleSheetItem::ListDisc ); + clearUndoRedo(); + drawCursor( FALSE ); + repaintChanged(); + drawCursor( TRUE ); + break; + } + if (overWrite && !cursor->atParagEnd() && !doc->hasSelection(TQTextDocument::Standard)) { + doKeyboardAction(ActionDelete); + clearUndoRedoInfo = FALSE; + } + TQString t = e->text(); +#ifdef TQ_WS_X11 + extern bool tqt_hebrew_keyboard_hack; + if ( tqt_hebrew_keyboard_hack ) { + // the X11 keyboard layout is broken and does not reverse + // braces correctly. This is a hack to get halfway correct + // behaviour + TQTextParagraph *p = cursor->paragraph(); + if ( p && p->string() && p->string()->isRightToLeft() ) { + TQChar *c = (TQChar *)t.unicode(); + int l = t.length(); + while( l-- ) { + if ( c->mirrored() ) + *c = c->mirroredChar(); + c++; + } + } + } +#endif + insert( t, TRUE, FALSE ); + break; + } else if ( e->state() & ControlButton ) { + switch ( e->key() ) { + case Key_C: case Key_F16: // Copy key on Sun keyboards + copy(); + break; + case Key_V: + paste(); + break; + case Key_X: + cut(); + break; + case Key_I: case Key_T: case Key_Tab: + if ( !d->tabChangesFocus ) + indent(); + break; + case Key_A: +#if defined(TQ_WS_X11) + moveCursor( MoveLineStart, e->state() & ShiftButton ); +#else + selectAll( TRUE ); +#endif + break; + case Key_B: + moveCursor( MoveBackward, e->state() & ShiftButton ); + break; + case Key_F: + moveCursor( MoveForward, e->state() & ShiftButton ); + break; + case Key_D: + if ( doc->hasSelection( TQTextDocument::Standard ) ) { + removeSelectedText(); + break; + } + doKeyboardAction( ActionDelete ); + clearUndoRedoInfo = FALSE; + break; + case Key_H: + if ( doc->hasSelection( TQTextDocument::Standard ) ) { + removeSelectedText(); + break; + } + if ( !cursor->paragraph()->prev() && + cursor->atParagStart() ) + break; + + doKeyboardAction( ActionBackspace ); + clearUndoRedoInfo = FALSE; + break; + case Key_E: + moveCursor( MoveLineEnd, e->state() & ShiftButton ); + break; + case Key_N: + moveCursor( MoveDown, e->state() & ShiftButton ); + break; + case Key_P: + moveCursor( MoveUp, e->state() & ShiftButton ); + break; + case Key_Z: + if(e->state() & ShiftButton) + redo(); + else + undo(); + break; + case Key_Y: + redo(); + break; + case Key_K: + doKeyboardAction( ActionKill ); + break; +#if defined(TQ_WS_WIN) + case Key_Insert: + copy(); + break; + case Key_Delete: + del(); + break; +#endif + default: + unknownKey = FALSE; + break; + } + } else { + unknownKey = TRUE; + } + } + } + + emit cursorPositionChanged( cursor ); + emit cursorPositionChanged( cursor->paragraph()->paragId(), cursor->index() ); + if ( clearUndoRedoInfo ) + clearUndoRedo(); + changeIntervalTimer->start( 100, TRUE ); + if ( unknownKey ) + e->ignore(); +} + +/*! + This function is not intended as polymorphic usage. Just a shared code + fragment that calls TQWidget::sendMouseEventToInputContext() easily for this + class. + */ +bool TQTextEdit::sendMouseEventToInputContext( TQMouseEvent *e ) +{ +#ifndef TQT_NO_IM + if ( d->composeMode() ) { + TQTextCursor c( doc ); + if ( c.place( e->pos(), doc->firstParagraph(), FALSE, FALSE, FALSE ) ) { + int mousePos = c.index() - d->preeditStart; + if ( cursor->globalY() == c.globalY() && + mousePos >= 0 && mousePos < d->preeditLength ) { + TQWidget::sendMouseEventToInputContext( mousePos, e->type(), + e->button(), e->state() ); + } + } else if ( e->type() != TQEvent::MouseMove ) { + // send button events on out of preedit + TQWidget::sendMouseEventToInputContext( -1, e->type(), + e->button(), e->state() ); + } + return TRUE; + } +#endif + return FALSE; +} + + +/*! + \reimp +*/ +void TQTextEdit::imStartEvent( TQIMEvent *e ) +{ + if ( isReadOnly() ) { + e->ignore(); + return; + } + + if ( hasSelectedText() ) + removeSelectedText(); + d->preeditStart = cursor->index(); + clearUndoRedo(); + undoRedoInfo.type = UndoRedoInfo::IME; +} + +/*! + \reimp +*/ +void TQTextEdit::imComposeEvent( TQIMEvent *e ) +{ + if ( isReadOnly() ) { + e->ignore(); + return; + } + + doc->removeSelection( TQTextDocument::IMCompositionText ); + doc->removeSelection( TQTextDocument::IMSelectionText ); + + if ( d->composeMode() && cursor->paragraph() ) + cursor->paragraph()->remove( d->preeditStart, d->preeditLength ); + cursor->setIndex( d->preeditStart ); + d->preeditLength = e->text().length(); + + int sellen = e->selectionLength(); + uint insertionFlags = CheckNewLines | RemoveSelected | AsIMCompositionText; + if ( sellen > 0 ) { + insertionFlags |= WithIMSelection; + } + insert( e->text(), insertionFlags ); + // insert can trigger an imEnd event as it emits a textChanged signal, so better + // be careful + if(d->preeditStart != -1) { + cursor->setIndex( d->preeditStart + d->preeditLength ); + TQTextCursor c = *cursor; + cursor->setIndex( d->preeditStart ); + doc->setSelectionStart( TQTextDocument::IMCompositionText, *cursor ); + doc->setSelectionEnd( TQTextDocument::IMCompositionText, c ); + + cursor->setIndex( d->preeditStart + e->cursorPos() ); + + if ( sellen > 0 ) { + cursor->setIndex( d->preeditStart + e->cursorPos() + sellen ); + c = *cursor; + cursor->setIndex( d->preeditStart + e->cursorPos() ); + doc->setSelectionStart( TQTextDocument::IMSelectionText, *cursor ); + doc->setSelectionEnd( TQTextDocument::IMSelectionText, c ); +#if 0 + // Disabled for Asian input method that shows candidate + // window. This behavior is same as TQt/E 2.3.7 which supports + // Asian input methods. Asian input methods need start point + // of IM selection text to place candidate window as adjacent + // to the selection text. + cursor->setIndex( d->preeditStart + d->preeditLength ); +#endif + } + } + + updateMicroFocusHint(); + repaintChanged(); +} + +/*! + \reimp +*/ +void TQTextEdit::imEndEvent( TQIMEvent *e ) +{ + if ( isReadOnly() ) { + e->ignore(); + return; + } + + doc->removeSelection( TQTextDocument::IMCompositionText ); + doc->removeSelection( TQTextDocument::IMSelectionText ); + + if (undoRedoInfo.type == UndoRedoInfo::IME) + undoRedoInfo.type = UndoRedoInfo::Invalid; + + if ( d->composeMode() && cursor->paragraph() ) + cursor->paragraph()->remove( d->preeditStart, d->preeditLength ); + if ( d->preeditStart >= 0 ) { + cursor->setIndex( d->preeditStart ); + //TODO: TQt 4 we should use the new virtual insert function + insert( e->text(), FALSE ); + } + d->preeditStart = d->preeditLength = -1; + + repaintChanged(); +} + + +static bool tqtextedit_ignore_readonly = FALSE; + +/*! + Executes keyboard action \a action. This is normally called by a + key event handler. +*/ + +void TQTextEdit::doKeyboardAction( KeyboardAction action ) +{ + if ( isReadOnly() && !tqtextedit_ignore_readonly ) + return; + + if ( cursor->nestedDepth() != 0 ) // #### for 3.0, disable editing of tables as this is not advanced enough + return; + + lastFormatted = cursor->paragraph(); + drawCursor( FALSE ); + bool doUpdateCurrentFormat = TRUE; + + switch ( action ) { + case ActionWordDelete: + case ActionDelete: + if ( action == ActionDelete && !cursor->atParagEnd() ) { + if ( undoEnabled ) { + checkUndoRedoInfo( UndoRedoInfo::Delete ); + if ( !undoRedoInfo.valid() ) { + undoRedoInfo.id = cursor->paragraph()->paragId(); + undoRedoInfo.index = cursor->index(); + undoRedoInfo.d->text = TQString::null; + } + int idx = cursor->index(); + do { + undoRedoInfo.d->text.insert( undoRedoInfo.d->text.length(), cursor->paragraph()->at( idx++ ), TRUE ); + } while ( !cursor->paragraph()->string()->validCursorPosition( idx ) ); + } + cursor->remove(); + } else { + clearUndoRedo(); + doc->setSelectionStart( TQTextDocument::Temp, *cursor ); + if ( action == ActionWordDelete && !cursor->atParagEnd() ) { + cursor->gotoNextWord(); + } else { + cursor->gotoNextLetter(); + } + doc->setSelectionEnd( TQTextDocument::Temp, *cursor ); + removeSelectedText( TQTextDocument::Temp ); + } + break; + case ActionWordBackspace: + case ActionBackspace: + if ( textFormat() == TQt::RichText + && (cursor->paragraph()->isListItem() + || cursor->paragraph()->listDepth() ) + && cursor->index() == 0 ) { + if ( undoEnabled ) { + clearUndoRedo(); + undoRedoInfo.type = UndoRedoInfo::Style; + undoRedoInfo.id = cursor->paragraph()->paragId(); + undoRedoInfo.eid = undoRedoInfo.id; + undoRedoInfo.styleInformation = TQTextStyleCommand::readStyleInformation( doc, undoRedoInfo.id, undoRedoInfo.eid ); + } + int ldepth = cursor->paragraph()->listDepth(); + if ( cursor->paragraph()->isListItem() && ldepth == 1 ) { + cursor->paragraph()->setListItem( FALSE ); + } else if ( TQMAX( ldepth, 1 ) == 1 ) { + cursor->paragraph()->setListItem( FALSE ); + cursor->paragraph()->setListDepth( 0 ); + } else { + cursor->paragraph()->setListDepth( ldepth - 1 ); + } + clearUndoRedo(); + lastFormatted = cursor->paragraph(); + repaintChanged(); + drawCursor( TRUE ); + return; + } + + if ( action == ActionBackspace && !cursor->atParagStart() ) { + if ( undoEnabled ) { + checkUndoRedoInfo( UndoRedoInfo::Delete ); + if ( !undoRedoInfo.valid() ) { + undoRedoInfo.id = cursor->paragraph()->paragId(); + undoRedoInfo.index = cursor->index(); + undoRedoInfo.d->text = TQString::null; + } + undoRedoInfo.d->text.insert( 0, cursor->paragraph()->at( cursor->index()-1 ), TRUE ); + undoRedoInfo.index = cursor->index()-1; + } + cursor->removePreviousChar(); + lastFormatted = cursor->paragraph(); + } else if ( cursor->paragraph()->prev() + || (action == ActionWordBackspace + && !cursor->atParagStart()) ) { + clearUndoRedo(); + doc->setSelectionStart( TQTextDocument::Temp, *cursor ); + if ( action == ActionWordBackspace && !cursor->atParagStart() ) { + cursor->gotoPreviousWord(); + } else { + cursor->gotoPreviousLetter(); + } + doc->setSelectionEnd( TQTextDocument::Temp, *cursor ); + removeSelectedText( TQTextDocument::Temp ); + } + break; + case ActionReturn: + if ( undoEnabled ) { + checkUndoRedoInfo( UndoRedoInfo::Return ); + if ( !undoRedoInfo.valid() ) { + undoRedoInfo.id = cursor->paragraph()->paragId(); + undoRedoInfo.index = cursor->index(); + undoRedoInfo.d->text = TQString::null; + } + undoRedoInfo.d->text += "\n"; + } + cursor->splitAndInsertEmptyParagraph(); + if ( cursor->paragraph()->prev() ) { + lastFormatted = cursor->paragraph()->prev(); + lastFormatted->invalidate( 0 ); + } + doUpdateCurrentFormat = FALSE; + break; + case ActionKill: + clearUndoRedo(); + doc->setSelectionStart( TQTextDocument::Temp, *cursor ); + if ( cursor->atParagEnd() ) + cursor->gotoNextLetter(); + else + cursor->setIndex( cursor->paragraph()->length() - 1 ); + doc->setSelectionEnd( TQTextDocument::Temp, *cursor ); + removeSelectedText( TQTextDocument::Temp ); + break; + } + + formatMore(); + repaintChanged(); + ensureCursorVisible(); + drawCursor( TRUE ); + updateMicroFocusHint(); + if ( doUpdateCurrentFormat ) + updateCurrentFormat(); + setModified(); + emit textChanged(); +} + +void TQTextEdit::readFormats( TQTextCursor &c1, TQTextCursor &c2, TQTextString &text, bool fillStyles ) +{ +#ifndef TQT_NO_DATASTREAM + TQDataStream styleStream( undoRedoInfo.styleInformation, IO_WriteOnly ); +#endif + c2.restoreState(); + c1.restoreState(); + int lastIndex = text.length(); + if ( c1.paragraph() == c2.paragraph() ) { + for ( int i = c1.index(); i < c2.index(); ++i ) + text.insert( lastIndex + i - c1.index(), c1.paragraph()->at( i ), TRUE ); +#ifndef TQT_NO_DATASTREAM + if ( fillStyles ) { + styleStream << (int) 1; + c1.paragraph()->writeStyleInformation( styleStream ); + } +#endif + } else { + int i; + for ( i = c1.index(); i < c1.paragraph()->length()-1; ++i ) + text.insert( lastIndex++, c1.paragraph()->at( i ), TRUE ); + int num = 2; // start and end, being different + text += "\n"; lastIndex++; + + if (c1.paragraph()->next() != c2.paragraph()) { + num += text.appendParagraphs(c1.paragraph()->next(), c2.paragraph()); + lastIndex = text.length(); + } + + for ( i = 0; i < c2.index(); ++i ) + text.insert( i + lastIndex, c2.paragraph()->at( i ), TRUE ); +#ifndef TQT_NO_DATASTREAM + if ( fillStyles ) { + styleStream << num; + for ( TQTextParagraph *p = c1.paragraph(); --num >= 0; p = p->next() ) + p->writeStyleInformation( styleStream ); + } +#endif + } +} + +/*! + Removes the selection \a selNum (by default 0). This does not + remove the selected text. + + \sa removeSelectedText() +*/ + +void TQTextEdit::removeSelection( int selNum ) +{ + doc->removeSelection( selNum ); + repaintChanged(); +} + +/*! + Deletes the text of selection \a selNum (by default, the default + selection, 0). If there is no selected text nothing happens. + + \sa selectedText removeSelection() +*/ + +void TQTextEdit::removeSelectedText( int selNum ) +{ + if(selNum != 0) + resetInputContext(); + + TQTextCursor c1 = doc->selectionStartCursor( selNum ); + c1.restoreState(); + TQTextCursor c2 = doc->selectionEndCursor( selNum ); + c2.restoreState(); + + // ### no support for editing tables yet, plus security for broken selections + if ( c1.nestedDepth() || c2.nestedDepth() ) + return; + + for ( int i = 0; i < (int)doc->numSelections(); ++i ) { + if ( i == selNum ) + continue; + doc->removeSelection( i ); + } + + drawCursor( FALSE ); + if ( undoEnabled ) { + checkUndoRedoInfo( UndoRedoInfo::RemoveSelected ); + if ( !undoRedoInfo.valid() ) { + doc->selectionStart( selNum, undoRedoInfo.id, undoRedoInfo.index ); + undoRedoInfo.d->text = TQString::null; + } + readFormats( c1, c2, undoRedoInfo.d->text, TRUE ); + } + + doc->removeSelectedText( selNum, cursor ); + if ( cursor->isValid() ) { + lastFormatted = 0; // make sync a noop + ensureCursorVisible(); + lastFormatted = cursor->paragraph(); + formatMore(); + repaintContents( FALSE ); + ensureCursorVisible(); + drawCursor( TRUE ); + clearUndoRedo(); +#if defined(TQ_WS_WIN) + // there seems to be a problem with repainting or erasing the area + // of the scrollview which is not the contents on windows + if ( contentsHeight() < visibleHeight() ) + viewport()->repaint( 0, contentsHeight(), visibleWidth(), visibleHeight() - contentsHeight(), TRUE ); +#endif +#ifndef TQT_NO_CURSOR + viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); +#endif + updateMicroFocusHint(); + } else { + delete cursor; + cursor = new TQTextCursor( doc ); + drawCursor( TRUE ); + repaintContents( TRUE ); + } + setModified(); + emit textChanged(); + emit selectionChanged(); + emit copyAvailable( doc->hasSelection( TQTextDocument::Standard ) ); +} + +/*! + Moves the text cursor according to \a action. This is normally + used by some key event handler. \a select specifies whether the + text between the current cursor position and the new position + should be selected. +*/ + +void TQTextEdit::moveCursor( CursorAction action, bool select ) +{ +#ifdef QT_TEXTEDIT_OPTIMIZATION + if ( d->optimMode ) + return; +#endif +#ifdef TQ_WS_MACX + TQTextCursor c1 = *cursor; + TQTextCursor c2; +#endif + drawCursor( FALSE ); + if ( select ) { + if ( !doc->hasSelection( TQTextDocument::Standard ) ) + doc->setSelectionStart( TQTextDocument::Standard, *cursor ); + moveCursor( action ); +#ifdef TQ_WS_MACX + c2 = *cursor; + if (c1 == c2) + if (action == MoveDown || action == MovePgDown) + moveCursor( MoveEnd ); + else if (action == MoveUp || action == MovePgUp) + moveCursor( MoveHome ); +#endif + if ( doc->setSelectionEnd( TQTextDocument::Standard, *cursor ) ) { + cursor->paragraph()->document()->nextDoubleBuffered = TRUE; + repaintChanged(); + } else { + drawCursor( TRUE ); + } + ensureCursorVisible(); + emit selectionChanged(); + emit copyAvailable( doc->hasSelection( TQTextDocument::Standard ) ); + } else { +#ifdef TQ_WS_MACX + TQTextCursor cStart = doc->selectionStartCursor( TQTextDocument::Standard ); + TQTextCursor cEnd = doc->selectionEndCursor( TQTextDocument::Standard ); + bool redraw = doc->removeSelection( TQTextDocument::Standard ); + if (redraw && action == MoveDown) + *cursor = cEnd; + else if (redraw && action == MoveUp) + *cursor = cStart; + if (redraw && action == MoveForward) + *cursor = cEnd; + else if (redraw && action == MoveBackward) + *cursor = cStart; + else + moveCursor( action ); + c2 = *cursor; + if (c1 == c2) + if (action == MoveDown) + moveCursor( MoveEnd ); + else if (action == MoveUp) + moveCursor( MoveHome ); +#else + bool redraw = doc->removeSelection( TQTextDocument::Standard ); + moveCursor( action ); +#endif + if ( !redraw ) { + ensureCursorVisible(); + drawCursor( TRUE ); + } else { + cursor->paragraph()->document()->nextDoubleBuffered = TRUE; + repaintChanged(); + ensureCursorVisible(); + drawCursor( TRUE ); +#ifndef TQT_NO_CURSOR + viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); +#endif + } + if ( redraw ) { + emit copyAvailable( doc->hasSelection( TQTextDocument::Standard ) ); + emit selectionChanged(); + } + } + + drawCursor( TRUE ); + updateCurrentFormat(); + updateMicroFocusHint(); +} + +/*! + \overload +*/ + +void TQTextEdit::moveCursor( CursorAction action ) +{ + resetInputContext(); + switch ( action ) { + case MoveBackward: + cursor->gotoPreviousLetter(); + break; + case MoveWordBackward: + cursor->gotoPreviousWord(); + break; + case MoveForward: + cursor->gotoNextLetter(); + break; + case MoveWordForward: + cursor->gotoNextWord(); + break; + case MoveUp: + cursor->gotoUp(); + break; + case MovePgUp: + cursor->gotoPageUp( visibleHeight() ); + break; + case MoveDown: + cursor->gotoDown(); + break; + case MovePgDown: + cursor->gotoPageDown( visibleHeight() ); + break; + case MoveLineStart: + cursor->gotoLineStart(); + break; + case MoveHome: + cursor->gotoHome(); + break; + case MoveLineEnd: + cursor->gotoLineEnd(); + break; + case MoveEnd: + ensureFormatted( doc->lastParagraph() ); + cursor->gotoEnd(); + break; + } + updateMicroFocusHint(); + updateCurrentFormat(); +} + +/*! + \reimp +*/ + +void TQTextEdit::resizeEvent( TQResizeEvent *e ) +{ + TQScrollView::resizeEvent( e ); + if ( doc->visibleWidth() == 0 ) + doResize(); +} + +/*! + \reimp +*/ + +void TQTextEdit::viewportResizeEvent( TQResizeEvent *e ) +{ + TQScrollView::viewportResizeEvent( e ); + if ( e->oldSize().width() != e->size().width() ) { + bool stayAtBottom = e->oldSize().height() != e->size().height() && + contentsY() > 0 && contentsY() >= doc->height() - e->oldSize().height(); + doResize(); + if ( stayAtBottom ) + scrollToBottom(); + } +} + +/*! + Ensures that the cursor is visible by scrolling the text edit if + necessary. + + \sa setCursorPosition() +*/ + +void TQTextEdit::ensureCursorVisible() +{ + // Not visible or the user is draging the window, so don't position to caret yet + if ( !isUpdatesEnabled() || !isVisible() || isHorizontalSliderPressed() || isVerticalSliderPressed() ) { + d->ensureCursorVisibleInShowEvent = TRUE; + return; + } + sync(); + TQTextStringChar *chr = cursor->paragraph()->at( cursor->index() ); + int h = cursor->paragraph()->lineHeightOfChar( cursor->index() ); + int x = cursor->paragraph()->rect().x() + chr->x + cursor->offsetX(); + int y = 0; int dummy; + cursor->paragraph()->lineHeightOfChar( cursor->index(), &dummy, &y ); + y += cursor->paragraph()->rect().y() + cursor->offsetY(); + int w = 1; + ensureVisible( x, y + h / 2, w, h / 2 + 2 ); +} + +/*! + \internal +*/ +void TQTextEdit::sliderReleased() +{ + if ( d->ensureCursorVisibleInShowEvent && isVisible() ) { + d->ensureCursorVisibleInShowEvent = FALSE; + ensureCursorVisible(); + } +} + +/*! + \internal +*/ +void TQTextEdit::drawCursor( bool visible ) +{ + if ( !isUpdatesEnabled() || + !viewport()->isUpdatesEnabled() || + !cursor->paragraph() || + !cursor->paragraph()->isValid() || + ( !style().styleHint( TQStyle::SH_BlinkCursorWhenTextSelected ) && + ( d->optimMode ? optimHasSelection() : doc->hasSelection( TQTextDocument::Standard, TRUE ))) || + ( visible && !hasFocus() && !viewport()->hasFocus() && !inDnD ) || + doc->hasSelection( TQTextDocument::IMSelectionText ) || + isReadOnly() ) + return; + + // Asian users regard selection text as cursor on candidate + // selection phase of input method, so ordinary cursor should be + // invisible if IM selection text exists. + if ( doc->hasSelection( TQTextDocument::IMSelectionText ) ) { + visible = FALSE; + } + + TQPainter p( viewport() ); + TQRect r( cursor->topParagraph()->rect() ); + cursor->paragraph()->setChanged( TRUE ); + p.translate( -contentsX() + cursor->totalOffsetX(), -contentsY() + cursor->totalOffsetY() ); + TQPixmap *pix = 0; + TQColorGroup cg( colorGroup() ); + const TQColorGroup::ColorRole backRole = TQPalette::backgroundRoleFromMode(backgroundMode()); + if ( cursor->paragraph()->background() ) + cg.setBrush( backRole, *cursor->paragraph()->background() ); + else if ( doc->paper() ) + cg.setBrush( backRole, *doc->paper() ); + p.setBrushOrigin( -contentsX(), -contentsY() ); + cursor->paragraph()->document()->nextDoubleBuffered = TRUE; + if ( !cursor->nestedDepth() ) { + int h = cursor->paragraph()->lineHeightOfChar( cursor->index() ); + int dist = 5; + if ( ( cursor->paragraph()->alignment() & TQt::AlignJustify ) == TQt::AlignJustify ) + dist = 50; + int x = r.x() - cursor->totalOffsetX() + cursor->x() - dist; + x = TQMAX( x, 0 ); + p.setClipRect( TQRect( x - contentsX(), + r.y() - cursor->totalOffsetY() + cursor->y() - contentsY(), 2 * dist, h ) ); + doc->drawParagraph( &p, cursor->paragraph(), x, + r.y() - cursor->totalOffsetY() + cursor->y(), 2 * dist, h, pix, cg, visible, cursor ); + } else { + doc->drawParagraph( &p, cursor->paragraph(), r.x() - cursor->totalOffsetX(), + r.y() - cursor->totalOffsetY(), r.width(), r.height(), + pix, cg, visible, cursor ); + } + cursorVisible = visible; +} + +enum { + IdUndo = 0, + IdRedo = 1, + IdCut = 2, + IdCopy = 3, + IdPaste = 4, + IdClear = 5, + IdSelectAll = 6 +}; + +/*! + \reimp +*/ +#ifndef TQT_NO_WHEELEVENT +void TQTextEdit::contentsWheelEvent( TQWheelEvent *e ) +{ + if ( isReadOnly() ) { + if ( e->state() & ControlButton ) { + if ( e->delta() > 0 ) + zoomOut(); + else if ( e->delta() < 0 ) + zoomIn(); + return; + } + } + TQScrollView::contentsWheelEvent( e ); +} +#endif + +/*! + \reimp +*/ + +void TQTextEdit::contentsMousePressEvent( TQMouseEvent *e ) +{ +#ifdef QT_TEXTEDIT_OPTIMIZATION + if ( d->optimMode ) { + optimMousePressEvent( e ); + return; + } +#endif + + if ( sendMouseEventToInputContext( e ) ) + return; + + if ( d->trippleClickTimer->isActive() && + ( e->globalPos() - d->trippleClickPoint ).manhattanLength() < + TQApplication::startDragDistance() ) { + TQTextCursor c1 = *cursor; + TQTextCursor c2 = *cursor; + c1.gotoLineStart(); + c2.gotoLineEnd(); + doc->setSelectionStart( TQTextDocument::Standard, c1 ); + doc->setSelectionEnd( TQTextDocument::Standard, c2 ); + *cursor = c2; + repaintChanged(); + mousePressed = TRUE; + return; + } + + clearUndoRedo(); + TQTextCursor oldCursor = *cursor; + TQTextCursor c = *cursor; + mousePos = e->pos(); + mightStartDrag = FALSE; + pressedLink = TQString::null; + d->pressedName = TQString::null; + + if ( e->button() == LeftButton ) { + mousePressed = TRUE; + drawCursor( FALSE ); + placeCursor( e->pos() ); + ensureCursorVisible(); + + if ( isReadOnly() && linksEnabled() ) { + TQTextCursor c = *cursor; + placeCursor( e->pos(), &c, TRUE ); + if ( c.paragraph() && c.paragraph()->at( c.index() ) && + c.paragraph()->at( c.index() )->isAnchor() ) { + pressedLink = c.paragraph()->at( c.index() )->anchorHref(); + d->pressedName = c.paragraph()->at( c.index() )->anchorName(); + } + } + +#ifndef TQT_NO_DRAGANDDROP + if ( doc->inSelection( TQTextDocument::Standard, e->pos() ) ) { + mightStartDrag = TRUE; + drawCursor( TRUE ); + dragStartTimer->start( TQApplication::startDragTime(), TRUE ); + dragStartPos = e->pos(); + return; + } +#endif + + bool redraw = FALSE; + if ( doc->hasSelection( TQTextDocument::Standard ) ) { + if ( !( e->state() & ShiftButton ) ) { + redraw = doc->removeSelection( TQTextDocument::Standard ); + doc->setSelectionStart( TQTextDocument::Standard, *cursor ); + } else { + redraw = doc->setSelectionEnd( TQTextDocument::Standard, *cursor ) || redraw; + } + } else { + if ( isReadOnly() || !( e->state() & ShiftButton ) ) { + doc->setSelectionStart( TQTextDocument::Standard, *cursor ); + } else { + doc->setSelectionStart( TQTextDocument::Standard, c ); + redraw = doc->setSelectionEnd( TQTextDocument::Standard, *cursor ) || redraw; + } + } + + for ( int i = 1; i < doc->numSelections(); ++i ) // start with 1 as we don't want to remove the Standard-Selection + redraw = doc->removeSelection( i ) || redraw; + + if ( !redraw ) { + drawCursor( TRUE ); + } else { + repaintChanged(); +#ifndef TQT_NO_CURSOR + viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); +#endif + } + } else if ( e->button() == MidButton ) { + bool redraw = doc->removeSelection( TQTextDocument::Standard ); + if ( !redraw ) { + drawCursor( TRUE ); + } else { + repaintChanged(); +#ifndef TQT_NO_CURSOR + viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); +#endif + } + } + + if ( *cursor != oldCursor ) + updateCurrentFormat(); +} + +/*! + \reimp +*/ + +void TQTextEdit::contentsMouseMoveEvent( TQMouseEvent *e ) +{ +#ifdef QT_TEXTEDIT_OPTIMIZATION + if ( d->optimMode ) { + optimMouseMoveEvent( e ); + return; + } +#endif + if ( sendMouseEventToInputContext( e ) ) { + // don't return from here to avoid cursor vanishing + } else if ( mousePressed ) { +#ifndef TQT_NO_DRAGANDDROP + if ( mightStartDrag ) { + dragStartTimer->stop(); + if ( ( e->pos() - dragStartPos ).manhattanLength() > TQApplication::startDragDistance() ) { + TQGuardedPtr<TQTextEdit> guard( this ); + startDrag(); + if (guard.isNull()) // we got deleted during the dnd + return; + } +#ifndef TQT_NO_CURSOR + if ( !isReadOnly() ) + viewport()->setCursor( ibeamCursor ); +#endif + return; + } +#endif + mousePos = e->pos(); + handleMouseMove( mousePos ); + oldMousePos = mousePos; + } + +#ifndef TQT_NO_CURSOR + if ( !isReadOnly() && !mousePressed ) { + if ( doc->hasSelection( TQTextDocument::Standard ) && doc->inSelection( TQTextDocument::Standard, e->pos() ) ) + viewport()->setCursor( arrowCursor ); + else + viewport()->setCursor( ibeamCursor ); + } +#endif + updateCursor( e->pos() ); +} + +void TQTextEdit::copyToClipboard() +{ +#ifndef TQT_NO_CLIPBOARD + if (TQApplication::clipboard()->supportsSelection()) { + d->clipboard_mode = TQClipboard::Selection; + + // don't listen to selection changes + disconnect( TQApplication::clipboard(), TQ_SIGNAL(selectionChanged()), this, 0); + copy(); + // listen to selection changes + connect( TQApplication::clipboard(), TQ_SIGNAL(selectionChanged()), + this, TQ_SLOT(clipboardChanged()) ); + + d->clipboard_mode = TQClipboard::Clipboard; + } +#endif +} + +/*! + \reimp +*/ + +void TQTextEdit::contentsMouseReleaseEvent( TQMouseEvent * e ) +{ + if ( !inDoubleClick && !d->composeMode() ) { // could be the release of a dblclick + int para = 0; + int index = charAt( e->pos(), ¶ ); + emit clicked( para, index ); + } +#ifdef QT_TEXTEDIT_OPTIMIZATION + if ( d->optimMode ) { + optimMouseReleaseEvent( e ); + return; + } +#endif + if ( sendMouseEventToInputContext( e ) ) + return; + TQTextCursor oldCursor = *cursor; + if ( scrollTimer->isActive() ) + scrollTimer->stop(); +#ifndef TQT_NO_DRAGANDDROP + if ( dragStartTimer->isActive() ) + dragStartTimer->stop(); + if ( mightStartDrag ) { + selectAll( FALSE ); + mousePressed = FALSE; + } +#endif + bool mouseWasPressed = mousePressed; + if ( mousePressed ) { + mousePressed = FALSE; + copyToClipboard(); + } +#ifndef TQT_NO_CLIPBOARD + else if ( e->button() == MidButton && !isReadOnly() ) { + // only do middle-click pasting on systems that have selections (ie. X11) + if (TQApplication::clipboard()->supportsSelection()) { + drawCursor( FALSE ); + placeCursor( e->pos() ); + ensureCursorVisible(); + doc->setSelectionStart( TQTextDocument::Standard, oldCursor ); + bool redraw = FALSE; + if ( doc->hasSelection( TQTextDocument::Standard ) ) { + redraw = doc->removeSelection( TQTextDocument::Standard ); + doc->setSelectionStart( TQTextDocument::Standard, *cursor ); + } else { + doc->setSelectionStart( TQTextDocument::Standard, *cursor ); + } + // start with 1 as we don't want to remove the Standard-Selection + for ( int i = 1; i < doc->numSelections(); ++i ) + redraw = doc->removeSelection( i ) || redraw; + if ( !redraw ) { + drawCursor( TRUE ); + } else { + repaintChanged(); +#ifndef TQT_NO_CURSOR + viewport()->setCursor( ibeamCursor ); +#endif + } + d->clipboard_mode = TQClipboard::Selection; + paste(); + d->clipboard_mode = TQClipboard::Clipboard; + } + } +#endif + emit cursorPositionChanged( cursor ); + emit cursorPositionChanged( cursor->paragraph()->paragId(), cursor->index() ); + if ( oldCursor != *cursor ) + updateCurrentFormat(); + inDoubleClick = FALSE; + +#ifndef TQT_NO_NETWORKPROTOCOL + if ( ( (!onLink.isEmpty() && onLink == pressedLink) + || (!d->onName.isEmpty() && d->onName == d->pressedName)) + && linksEnabled() && mouseWasPressed ) { + if (!onLink.isEmpty()) { + TQUrl u( doc->context(), onLink, TRUE ); + emitLinkClicked( u.toString( FALSE, FALSE ) ); + } + if (::tqt_cast<TQTextBrowser*>(this)) { // change for 4.0 + TQConnectionList *clist = receivers( + "anchorClicked(const TQString&,const TQString&)"); + if (!signalsBlocked() && clist) { + TQUObject o[3]; + static_QUType_TQString.set(o+1, d->onName); + static_QUType_TQString.set(o+2, onLink); + activate_signal( clist, o); + } + } + + // emitting linkClicked() may result in that the cursor winds + // up hovering over a different valid link - check this and + // set the appropriate cursor shape + updateCursor( e->pos() ); + } +#endif + drawCursor( TRUE ); + if ( !doc->hasSelection( TQTextDocument::Standard, TRUE ) ) + doc->removeSelection( TQTextDocument::Standard ); + + emit copyAvailable( doc->hasSelection( TQTextDocument::Standard ) ); + emit selectionChanged(); +} + +/*! + \reimp +*/ + +void TQTextEdit::contentsMouseDoubleClickEvent( TQMouseEvent * e ) +{ + if ( e->button() != TQt::LeftButton && !d->composeMode() ) { + e->ignore(); + return; + } + int para = 0; + int index = charAt( e->pos(), ¶ ); +#ifdef QT_TEXTEDIT_OPTIMIZATION + if ( d->optimMode ) { + TQString str = d->od->lines[ LOGOFFSET(para) ]; + int startIdx = index, endIdx = index, i; + if ( !str[ index ].isSpace() ) { + i = startIdx; + // find start of word + while ( i >= 0 && !str[ i ].isSpace() ) { + startIdx = i--; + } + i = endIdx; + // find end of word.. + while ( (uint) i < str.length() && !str[ i ].isSpace() ) { + endIdx = ++i; + } + // ..and start of next + while ( (uint) i < str.length() && str[ i ].isSpace() ) { + endIdx = ++i; + } + optimSetSelection( para, startIdx, para, endIdx ); + repaintContents( FALSE ); + } + } else +#endif + { + if ( sendMouseEventToInputContext( e ) ) + return; + + TQTextCursor c1 = *cursor; + TQTextCursor c2 = *cursor; +#if defined(Q_OS_MAC) + TQTextParagraph *para = cursor->paragraph(); + if ( cursor->isValid() ) { + if ( para->at( cursor->index() )->c.isLetterOrNumber() ) { + while ( c1.index() > 0 && + c1.paragraph()->at( c1.index()-1 )->c.isLetterOrNumber() ) + c1.gotoPreviousLetter(); + while ( c2.paragraph()->at( c2.index() )->c.isLetterOrNumber() && + !c2.atParagEnd() ) + c2.gotoNextLetter(); + } else if ( para->at( cursor->index() )->c.isSpace() ) { + while ( c1.index() > 0 && + c1.paragraph()->at( c1.index()-1 )->c.isSpace() ) + c1.gotoPreviousLetter(); + while ( c2.paragraph()->at( c2.index() )->c.isSpace() && + !c2.atParagEnd() ) + c2.gotoNextLetter(); + } else if ( !c2.atParagEnd() ) { + c2.gotoNextLetter(); + } + } +#else + if ( cursor->index() > 0 && !cursor->paragraph()->at( cursor->index()-1 )->c.isSpace() ) + c1.gotoPreviousWord(); + if ( !cursor->paragraph()->at( cursor->index() )->c.isSpace() && !cursor->atParagEnd() ) + c2.gotoNextWord(); +#endif + doc->setSelectionStart( TQTextDocument::Standard, c1 ); + doc->setSelectionEnd( TQTextDocument::Standard, c2 ); + + *cursor = c2; + + repaintChanged(); + + d->trippleClickTimer->start( tqApp->doubleClickInterval(), TRUE ); + d->trippleClickPoint = e->globalPos(); + } + inDoubleClick = TRUE; + mousePressed = TRUE; + emit doubleClicked( para, index ); +} + +#ifndef TQT_NO_DRAGANDDROP + +/*! + \reimp +*/ + +void TQTextEdit::contentsDragEnterEvent( TQDragEnterEvent *e ) +{ + if ( isReadOnly() || !TQTextDrag::canDecode( e ) ) { + e->ignore(); + return; + } + e->acceptAction(); + inDnD = TRUE; +} + +/*! + \reimp +*/ + +void TQTextEdit::contentsDragMoveEvent( TQDragMoveEvent *e ) +{ + if ( isReadOnly() || !TQTextDrag::canDecode( e ) ) { + e->ignore(); + return; + } + drawCursor( FALSE ); + placeCursor( e->pos(), cursor ); + drawCursor( TRUE ); + e->acceptAction(); +} + +/*! + \reimp +*/ + +void TQTextEdit::contentsDragLeaveEvent( TQDragLeaveEvent * ) +{ + drawCursor( FALSE ); + inDnD = FALSE; +} + +/*! + \reimp +*/ + +void TQTextEdit::contentsDropEvent( TQDropEvent *e ) +{ + if ( isReadOnly() ) + return; + inDnD = FALSE; + e->acceptAction(); + bool intern = FALSE; + if ( TQRichTextDrag::canDecode( e ) ) { + bool hasSel = doc->hasSelection( TQTextDocument::Standard ); + bool internalDrag = e->source() == this || e->source() == viewport(); + int dropId, dropIndex; + TQTextCursor insertCursor = *cursor; + dropId = cursor->paragraph()->paragId(); + dropIndex = cursor->index(); + if ( hasSel && internalDrag ) { + TQTextCursor c1, c2; + int selStartId, selStartIndex; + int selEndId, selEndIndex; + c1 = doc->selectionStartCursor( TQTextDocument::Standard ); + c1.restoreState(); + c2 = doc->selectionEndCursor( TQTextDocument::Standard ); + c2.restoreState(); + selStartId = c1.paragraph()->paragId(); + selStartIndex = c1.index(); + selEndId = c2.paragraph()->paragId(); + selEndIndex = c2.index(); + if ( ( ( dropId > selStartId ) || + ( dropId == selStartId && dropIndex > selStartIndex ) ) && + ( ( dropId < selEndId ) || + ( dropId == selEndId && dropIndex <= selEndIndex ) ) ) + insertCursor = c1; + if ( dropId == selEndId && dropIndex > selEndIndex ) { + insertCursor = c1; + if ( selStartId == selEndId ) { + insertCursor.setIndex( dropIndex - + ( selEndIndex - selStartIndex ) ); + } else { + insertCursor.setIndex( dropIndex - selEndIndex + + selStartIndex ); + } + } + } + + if ( internalDrag && e->action() == TQDropEvent::Move ) { + removeSelectedText(); + intern = TRUE; + doc->removeSelection( TQTextDocument::Standard ); + } else { + doc->removeSelection( TQTextDocument::Standard ); +#ifndef TQT_NO_CURSOR + viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); +#endif + } + drawCursor( FALSE ); + cursor->setParagraph( insertCursor.paragraph() ); + cursor->setIndex( insertCursor.index() ); + drawCursor( TRUE ); + if ( !cursor->nestedDepth() ) { + TQString subType = "plain"; + if ( textFormat() != PlainText ) { + if ( e->provides( "application/x-qrichtext" ) ) + subType = "x-qrichtext"; + } +#ifndef TQT_NO_CLIPBOARD + pasteSubType( subType.latin1(), e ); +#endif + // emit appropriate signals. + emit selectionChanged(); + emit cursorPositionChanged( cursor ); + emit cursorPositionChanged( cursor->paragraph()->paragId(), cursor->index() ); + } else { + if ( intern ) + undo(); + e->ignore(); + } + } +} + +#endif + +/*! + \reimp +*/ +void TQTextEdit::contentsContextMenuEvent( TQContextMenuEvent *e ) +{ + e->accept(); +#ifndef TQT_NO_IM + if ( d->composeMode() ) + return; +#endif + + clearUndoRedo(); + mousePressed = FALSE; + +#ifndef TQT_NO_POPUPMENU + TQGuardedPtr<TQTextEdit> that = this; + TQGuardedPtr<TQPopupMenu> popup = createPopupMenu( e->pos() ); + if ( !popup ) + popup = createPopupMenu(); + if ( !popup ) + return; + + int r = popup->exec( e->globalPos() ); + delete popup; + if (!that) + return; + + if ( r == d->id[ IdClear ] ) + clear(); + else if ( r == d->id[ IdSelectAll ] ) { + selectAll(); +#ifndef TQT_NO_CLIPBOARD + // if the clipboard support selections, put the newly selected text into + // the clipboard + if (TQApplication::clipboard()->supportsSelection()) { + d->clipboard_mode = TQClipboard::Selection; + + // don't listen to selection changes + disconnect( TQApplication::clipboard(), TQ_SIGNAL(selectionChanged()), this, 0); + copy(); + // listen to selection changes + connect( TQApplication::clipboard(), TQ_SIGNAL(selectionChanged()), + this, TQ_SLOT(clipboardChanged()) ); + + d->clipboard_mode = TQClipboard::Clipboard; + } +#endif + } else if ( r == d->id[ IdUndo ] ) + undo(); + else if ( r == d->id[ IdRedo ] ) + redo(); +#ifndef TQT_NO_CLIPBOARD + else if ( r == d->id[ IdCut ] ) + cut(); + else if ( r == d->id[ IdCopy ] ) + copy(); + else if ( r == d->id[ IdPaste ] ) + paste(); +#endif +#endif +} + + +void TQTextEdit::autoScrollTimerDone() +{ + if ( mousePressed ) + handleMouseMove( viewportToContents( viewport()->mapFromGlobal( TQCursor::pos() ) ) ); +} + +void TQTextEdit::handleMouseMove( const TQPoint& pos ) +{ + if ( !mousePressed ) + return; + + if ( (!scrollTimer->isActive() && pos.y() < contentsY()) || pos.y() > contentsY() + visibleHeight() ) + scrollTimer->start( 100, FALSE ); + else if ( scrollTimer->isActive() && pos.y() >= contentsY() && pos.y() <= contentsY() + visibleHeight() ) + scrollTimer->stop(); + + drawCursor( FALSE ); + TQTextCursor oldCursor = *cursor; + + placeCursor( pos ); + + if ( inDoubleClick ) { + TQTextCursor cl = *cursor; + cl.gotoPreviousWord(); + TQTextCursor cr = *cursor; + cr.gotoNextWord(); + + int diff = TQABS( oldCursor.paragraph()->at( oldCursor.index() )->x - mousePos.x() ); + int ldiff = TQABS( cl.paragraph()->at( cl.index() )->x - mousePos.x() ); + int rdiff = TQABS( cr.paragraph()->at( cr.index() )->x - mousePos.x() ); + + + if ( cursor->paragraph()->lineStartOfChar( cursor->index() ) != + oldCursor.paragraph()->lineStartOfChar( oldCursor.index() ) ) + diff = 0xFFFFFF; + + if ( rdiff < diff && rdiff < ldiff ) + *cursor = cr; + else if ( ldiff < diff && ldiff < rdiff ) + *cursor = cl; + else + *cursor = oldCursor; + + } + ensureCursorVisible(); + + bool redraw = FALSE; + if ( doc->hasSelection( TQTextDocument::Standard ) ) { + redraw = doc->setSelectionEnd( TQTextDocument::Standard, *cursor ) || redraw; + } + + if ( !redraw ) { + drawCursor( TRUE ); + } else { + repaintChanged(); + drawCursor( TRUE ); + } + + if ( currentFormat && currentFormat->key() != cursor->paragraph()->at( cursor->index() )->format()->key() ) { + currentFormat->removeRef(); + currentFormat = doc->formatCollection()->format( cursor->paragraph()->at( cursor->index() )->format() ); + if ( currentFormat->isMisspelled() ) { + currentFormat->removeRef(); + currentFormat = doc->formatCollection()->format( currentFormat->font(), currentFormat->color() ); + } + emit currentFontChanged( currentFormat->font() ); + emit currentColorChanged( currentFormat->color() ); + emit currentVerticalAlignmentChanged( (VerticalAlignment)currentFormat->vAlign() ); + } + + if ( currentAlignment != cursor->paragraph()->alignment() ) { + currentAlignment = cursor->paragraph()->alignment(); + block_set_alignment = TRUE; + emit currentAlignmentChanged( currentAlignment ); + block_set_alignment = FALSE; + } +} + +/*! \internal */ + +void TQTextEdit::placeCursor( const TQPoint &pos, TQTextCursor *c, bool link ) +{ +#ifdef QT_TEXTEDIT_OPTIMIZATION + if ( d->optimMode ) + return; +#endif + if ( !c ) + c = cursor; + + resetInputContext(); + c->restoreState(); + TQTextParagraph *s = doc->firstParagraph(); + c->place( pos, s, link ); + updateMicroFocusHint(); +} + + +void TQTextEdit::updateMicroFocusHint() +{ + TQTextCursor c( *cursor ); +#if 0 + // Disabled for Asian input method that shows candidate + // window. This behavior is same as TQt/E 2.3.7 which supports + // Asian input methods. Asian input methods need start point of IM + // selection text to place candidate window as adjacent to the + // selection text. + if ( d->preeditStart != -1 ) { + c.setIndex( d->preeditStart ); + if(doc->hasSelection(TQTextDocument::IMSelectionText)) { + int para, index; + doc->selectionStart(TQTextDocument::IMSelectionText, para, index); + c.setIndex(index); + } + } +#endif + + if ( hasFocus() || viewport()->hasFocus() ) { + int h = c.paragraph()->lineHeightOfChar( cursor->index() ); + if ( !readOnly ) { + TQFont f = c.paragraph()->at( c.index() )->format()->font(); + setMicroFocusHint( c.x() - contentsX() + frameWidth(), + c.y() + cursor->paragraph()->rect().y() - contentsY() + frameWidth(), 0, h, TRUE, &f ); + } + } +} + + + +void TQTextEdit::formatMore() +{ + if ( !lastFormatted ) + return; + + int bottom = contentsHeight(); + int lastTop = -1; + int lastBottom = -1; + int to = 20; + bool firstVisible = FALSE; + TQRect cr( contentsX(), contentsY(), visibleWidth(), visibleHeight() ); + for ( int i = 0; lastFormatted && + ( i < to || ( firstVisible && lastTop < contentsY()+height() ) ); + i++ ) { + lastFormatted->format(); + lastTop = lastFormatted->rect().top(); + lastBottom = lastFormatted->rect().bottom(); + if ( i == 0 ) + firstVisible = lastBottom < cr.bottom(); + bottom = TQMAX( bottom, lastBottom ); + lastFormatted = lastFormatted->next(); + } + + if ( bottom > contentsHeight() ) { + resizeContents( contentsWidth(), TQMAX( doc->height(), bottom ) ); + } else if ( !lastFormatted && lastBottom < contentsHeight() ) { + resizeContents( contentsWidth(), TQMAX( doc->height(), lastBottom ) ); + if ( contentsHeight() < visibleHeight() ) + updateContents( 0, contentsHeight(), visibleWidth(), + visibleHeight() - contentsHeight() ); + } + + if ( lastFormatted ) + formatTimer->start( interval, TRUE ); + else + interval = TQMAX( 0, interval ); +} + +void TQTextEdit::doResize() +{ +#ifdef QT_TEXTEDIT_OPTIMIZATION + if ( !d->optimMode ) +#endif + { + if ( wrapMode == FixedPixelWidth ) + return; + doc->setMinimumWidth( -1 ); + resizeContents( 0, 0 ); + doc->setWidth( visibleWidth() ); + doc->invalidate(); + lastFormatted = doc->firstParagraph(); + interval = 0; + formatMore(); + } + repaintContents( FALSE ); +} + +/*! \internal */ + +void TQTextEdit::doChangeInterval() +{ + interval = 0; +} + +/*! + \reimp +*/ + +bool TQTextEdit::eventFilter( TQObject *o, TQEvent *e ) +{ +#ifdef QT_TEXTEDIT_OPTIMIZATION + if ( !d->optimMode && (o == this || o == viewport()) ) { +#else + if ( o == this || o == viewport() ) { +#endif + if ( e->type() == TQEvent::FocusIn ) { + if ( TQApplication::cursorFlashTime() > 0 ) + blinkTimer->start( TQApplication::cursorFlashTime() / 2 ); + drawCursor( TRUE ); + updateMicroFocusHint(); + } else if ( e->type() == TQEvent::FocusOut ) { + blinkTimer->stop(); + drawCursor( FALSE ); + } + } + + if ( o == this && e->type() == TQEvent::PaletteChange ) { + TQColor old( viewport()->colorGroup().color( TQColorGroup::Text ) ); + if ( old != colorGroup().color( TQColorGroup::Text ) ) { + TQColor c( colorGroup().color( TQColorGroup::Text ) ); + doc->setMinimumWidth( -1 ); + doc->setDefaultFormat( doc->formatCollection()->defaultFormat()->font(), c ); + lastFormatted = doc->firstParagraph(); + formatMore(); + repaintChanged(); + } + } + + return TQScrollView::eventFilter( o, e ); +} + +/*! + \obsolete + */ +void TQTextEdit::insert( const TQString &text, bool indent, + bool checkNewLine, bool removeSelected ) +{ + uint f = 0; + if ( indent ) + f |= RedoIndentation; + if ( checkNewLine ) + f |= CheckNewLines; + if ( removeSelected ) + f |= RemoveSelected; + insert( text, f ); +} + +/*! + Inserts \a text at the current cursor position. + + The \a insertionFlags define how the text is inserted. If \c + RedoIndentation is set, the paragraph is re-indented. If \c + CheckNewLines is set, newline characters in \a text result in hard + line breaks (i.e. new paragraphs). If \c checkNewLine is not set, + the behaviour of the editor is undefined if the \a text contains + newlines. (It is not possible to change TQTextEdit's newline handling + behavior, but you can use TQString::replace() to preprocess text + before inserting it.) If \c RemoveSelected is set, any selected + text (in selection 0) is removed before the text is inserted. + + The default flags are \c CheckNewLines | \c RemoveSelected. + + If the widget is in \c LogText mode this function will do nothing. + + \sa paste() pasteSubType() +*/ + + +void TQTextEdit::insert( const TQString &text, uint insertionFlags ) +{ +#ifdef QT_TEXTEDIT_OPTIMIZATION + if ( d->optimMode ) + return; +#endif + + if ( cursor->nestedDepth() != 0 ) // #### for 3.0, disable editing of tables as this is not advanced enough + return; + + bool indent = insertionFlags & RedoIndentation; + bool checkNewLine = insertionFlags & CheckNewLines; + bool removeSelected = insertionFlags & RemoveSelected; + bool imComposition = insertionFlags & AsIMCompositionText; + bool imSelection = insertionFlags & WithIMSelection; + TQString txt( text ); + drawCursor( FALSE ); + if ( !isReadOnly() && doc->hasSelection( TQTextDocument::Standard ) && removeSelected ) + removeSelectedText(); + TQTextCursor c2 = *cursor; + int oldLen = 0; + + if ( undoEnabled && !isReadOnly() && undoRedoInfo.type != UndoRedoInfo::IME ) { + checkUndoRedoInfo( UndoRedoInfo::Insert ); + + if (undoRedoInfo.valid() && undoRedoInfo.index + undoRedoInfo.d->text.length() != cursor->index()) { + clearUndoRedo(); + undoRedoInfo.type = UndoRedoInfo::Insert; + } + + if ( !undoRedoInfo.valid() ) { + undoRedoInfo.id = cursor->paragraph()->paragId(); + undoRedoInfo.index = cursor->index(); + undoRedoInfo.d->text = TQString::null; + } + oldLen = undoRedoInfo.d->text.length(); + } + + lastFormatted = checkNewLine && cursor->paragraph()->prev() ? + cursor->paragraph()->prev() : cursor->paragraph(); + TQTextCursor oldCursor = *cursor; + cursor->insert( txt, checkNewLine ); + if ( doc->useFormatCollection() && !doc->preProcessor() ) { + doc->setSelectionStart( TQTextDocument::Temp, oldCursor ); + doc->setSelectionEnd( TQTextDocument::Temp, *cursor ); + doc->setFormat( TQTextDocument::Temp, currentFormat, TQTextFormat::Format ); + doc->removeSelection( TQTextDocument::Temp ); + } + + if ( indent && ( txt == "{" || txt == "}" || txt == ":" || txt == "#" ) ) + cursor->indent(); + formatMore(); + repaintChanged(); + ensureCursorVisible(); + // Asian users regard selection text as cursor on candidate + // selection phase of input method, so ordinary cursor should be + // invisible if IM selection text exists. + drawCursor( !imSelection ); + + if ( undoEnabled && !isReadOnly() && undoRedoInfo.type != UndoRedoInfo::IME ) { + undoRedoInfo.d->text += txt; + if ( !doc->preProcessor() ) { + for ( int i = 0; i < (int)txt.length(); ++i ) { + if ( txt[ i ] != '\n' && c2.paragraph()->at( c2.index() )->format() ) { + c2.paragraph()->at( c2.index() )->format()->addRef(); + undoRedoInfo.d->text. + setFormat( oldLen + i, + c2.paragraph()->at( c2.index() )->format(), TRUE ); + } + c2.gotoNextLetter(); + } + } + } + + if ( !removeSelected ) { + doc->setSelectionStart( TQTextDocument::Standard, oldCursor ); + doc->setSelectionEnd( TQTextDocument::Standard, *cursor ); + repaintChanged(); + } + // updateMicroFocusHint() should not be invoked here when this + // function is invoked from imComposeEvent() because cursor + // postion is incorrect yet. imComposeEvent() invokes + // updateMicroFocusHint() later. + if ( !imComposition ) { + updateMicroFocusHint(); + } + setModified(); + emit textChanged(); +} + +/*! + Inserts \a text in the paragraph \a para at position \a index. +*/ + +void TQTextEdit::insertAt( const TQString &text, int para, int index ) +{ +#ifdef QT_TEXTEDIT_OPTIMIZATION + if ( d->optimMode ) { + optimInsert( text, para, index ); + return; + } +#endif + resetInputContext(); + TQTextParagraph *p = doc->paragAt( para ); + if ( !p ) + return; + removeSelection( TQTextDocument::Standard ); + TQTextCursor tmp = *cursor; + cursor->setParagraph( p ); + cursor->setIndex( index ); + insert( text, FALSE, TRUE, FALSE ); + *cursor = tmp; + removeSelection( TQTextDocument::Standard ); +} + +/*! + Inserts \a text as a new paragraph at position \a para. If \a para + is -1, the text is appended. Use append() if the append operation + is performance critical. +*/ + +void TQTextEdit::insertParagraph( const TQString &text, int para ) +{ +#ifdef QT_TEXTEDIT_OPTIMIZATION + if ( d->optimMode ) { + optimInsert( text + "\n", para, 0 ); + return; + } +#endif + resetInputContext(); + for ( int i = 0; i < (int)doc->numSelections(); ++i ) + doc->removeSelection( i ); + + TQTextParagraph *p = doc->paragAt( para ); + + bool append = !p; + if ( !p ) + p = doc->lastParagraph(); + + TQTextCursor old = *cursor; + drawCursor( FALSE ); + + cursor->setParagraph( p ); + cursor->setIndex( 0 ); + clearUndoRedo(); + tqtextedit_ignore_readonly = TRUE; + if ( append && cursor->paragraph()->length() > 1 ) { + cursor->setIndex( cursor->paragraph()->length() - 1 ); + doKeyboardAction( ActionReturn ); + } + insert( text, FALSE, TRUE, TRUE ); + doKeyboardAction( ActionReturn ); + tqtextedit_ignore_readonly = FALSE; + + drawCursor( FALSE ); + *cursor = old; + drawCursor( TRUE ); + + repaintChanged(); +} + +/*! + Removes the paragraph \a para. +*/ + +void TQTextEdit::removeParagraph( int para ) +{ +#ifdef QT_TEXTEDIT_OPTIMIZATION + if ( d->optimMode ) + return; +#endif + resetInputContext(); + TQTextParagraph *p = doc->paragAt( para ); + if ( !p ) + return; + + for ( int i = 0; i < doc->numSelections(); ++i ) + doc->removeSelection( i ); + + TQTextCursor start( doc ); + TQTextCursor end( doc ); + start.setParagraph( p ); + start.setIndex( 0 ); + end.setParagraph( p ); + end.setIndex( p->length() - 1 ); + + if ( !(p == doc->firstParagraph() && p == doc->lastParagraph()) ) { + if ( p->next() ) { + end.setParagraph( p->next() ); + end.setIndex( 0 ); + } else if ( p->prev() ) { + start.setParagraph( p->prev() ); + start.setIndex( p->prev()->length() - 1 ); + } + } + + doc->setSelectionStart( TQTextDocument::Temp, start ); + doc->setSelectionEnd( TQTextDocument::Temp, end ); + removeSelectedText( TQTextDocument::Temp ); +} + +/*! + Undoes the last operation. + + If there is no operation to undo, i.e. there is no undo step in + the undo/redo history, nothing happens. + + \sa undoAvailable() redo() undoDepth() +*/ + +void TQTextEdit::undo() +{ + clearUndoRedo(); + if ( isReadOnly() || !doc->commands()->isUndoAvailable() || !undoEnabled ) + return; + + resetInputContext(); + for ( int i = 0; i < (int)doc->numSelections(); ++i ) + doc->removeSelection( i ); + +#ifndef TQT_NO_CURSOR + viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); +#endif + + clearUndoRedo(); + drawCursor( FALSE ); + TQTextCursor *c = doc->undo( cursor ); + if ( !c ) { + drawCursor( TRUE ); + return; + } + lastFormatted = 0; + repaintChanged(); + ensureCursorVisible(); + drawCursor( TRUE ); + updateMicroFocusHint(); + setModified(); + // ### If we get back to a completely blank textedit, it + // is possible that cursor is invalid and further actions + // might not fix the problem, so reset the cursor here. + // This is copied from removeSeletedText(), it might be + // okay to just call that. + if ( !cursor->isValid() ) { + delete cursor; + cursor = new TQTextCursor( doc ); + drawCursor( TRUE ); + repaintContents( TRUE ); + } + emit undoAvailable( isUndoAvailable() ); + emit redoAvailable( isRedoAvailable() ); + emit textChanged(); +} + +/*! + Redoes the last operation. + + If there is no operation to redo, i.e. there is no redo step in + the undo/redo history, nothing happens. + + \sa redoAvailable() undo() undoDepth() +*/ + +void TQTextEdit::redo() +{ + if ( isReadOnly() || !doc->commands()->isRedoAvailable() || !undoEnabled ) + return; + + resetInputContext(); + for ( int i = 0; i < (int)doc->numSelections(); ++i ) + doc->removeSelection( i ); + +#ifndef TQT_NO_CURSOR + viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); +#endif + + clearUndoRedo(); + drawCursor( FALSE ); + TQTextCursor *c = doc->redo( cursor ); + if ( !c ) { + drawCursor( TRUE ); + return; + } + lastFormatted = 0; + ensureCursorVisible(); + repaintChanged(); + ensureCursorVisible(); + drawCursor( TRUE ); + updateMicroFocusHint(); + setModified(); + emit undoAvailable( isUndoAvailable() ); + emit redoAvailable( isRedoAvailable() ); + emit textChanged(); +} + +/*! + Pastes the text from the clipboard into the text edit at the + current cursor position. Only plain text is pasted. + + If there is no text in the clipboard nothing happens. + + \sa pasteSubType() cut() TQTextEdit::copy() +*/ + +void TQTextEdit::paste() +{ +#ifndef TQT_NO_MIMECLIPBOARD + if ( isReadOnly() ) + return; + TQString subType = "plain"; + if ( textFormat() != PlainText ) { + TQMimeSource *m = TQApplication::clipboard()->data( d->clipboard_mode ); + if ( !m ) + return; + if ( m->provides( "application/x-qrichtext" ) ) + subType = "x-qrichtext"; + } + + pasteSubType( subType.latin1() ); + updateMicroFocusHint(); +#endif +} + +void TQTextEdit::checkUndoRedoInfo( UndoRedoInfo::Type t ) +{ + if ( undoRedoInfo.valid() && t != undoRedoInfo.type ) { + clearUndoRedo(); + } + undoRedoInfo.type = t; +} + +/*! + Repaints any paragraphs that have changed. + + Although used extensively internally you shouldn't need to call + this yourself. +*/ + +void TQTextEdit::repaintChanged() +{ + if ( !isUpdatesEnabled() || !viewport()->isUpdatesEnabled() ) + return; + + TQPainter p( viewport() ); +#ifdef QT_TEXTEDIT_OPTIMIZATION + if ( d->optimMode ) { + optimDrawContents( &p, contentsX(), contentsY(), visibleWidth(), visibleHeight() ); + return; + } +#endif + p.translate( -contentsX(), -contentsY() ); + paintDocument( FALSE, &p, contentsX(), contentsY(), visibleWidth(), visibleHeight() ); +} + +#ifndef TQT_NO_MIME +TQTextDrag *TQTextEdit::dragObject( TQWidget *parent ) const +{ + if ( !doc->hasSelection( TQTextDocument::Standard ) || + doc->selectedText( TQTextDocument::Standard ).isEmpty() ) + return 0; + if ( textFormat() != RichText ) + return new TQTextDrag( doc->selectedText( TQTextDocument::Standard ), parent ); + TQRichTextDrag *drag = new TQRichTextDrag( parent ); + drag->setPlainText( doc->selectedText( TQTextDocument::Standard ) ); + drag->setRichText( doc->selectedText( TQTextDocument::Standard, TRUE ) ); + return drag; +} +#endif + +/*! + Copies the selected text (from selection 0) to the clipboard and + deletes it from the text edit. + + If there is no selected text (in selection 0) nothing happens. + + \sa TQTextEdit::copy() paste() pasteSubType() +*/ + +void TQTextEdit::cut() +{ + if ( isReadOnly() ) + return; + resetInputContext(); + normalCopy(); + removeSelectedText(); + updateMicroFocusHint(); +} + +void TQTextEdit::normalCopy() +{ +#ifndef TQT_NO_MIME + TQTextDrag *drag = dragObject(); + if ( !drag ) + return; +#ifndef TQT_NO_MIMECLIPBOARD + TQApplication::clipboard()->setData( drag, d->clipboard_mode ); +#endif // TQT_NO_MIMECLIPBOARD +#endif // TQT_NO_MIME +} + +/*! + Copies any selected text (from selection 0) to the clipboard. + + \sa hasSelectedText() copyAvailable() +*/ + +void TQTextEdit::copy() +{ +#ifndef TQT_NO_CLIPBOARD +# ifdef QT_TEXTEDIT_OPTIMIZATION + if ( d->optimMode && optimHasSelection() ) + TQApplication::clipboard()->setText( optimSelectedText(), d->clipboard_mode ); + else + normalCopy(); +# else + normalCopy(); +# endif +#endif +} + +/*! + \internal + + Re-indents the current paragraph. +*/ + +void TQTextEdit::indent() +{ + if ( isReadOnly() ) + return; + + drawCursor( FALSE ); + if ( !doc->hasSelection( TQTextDocument::Standard ) ) + cursor->indent(); + else + doc->indentSelection( TQTextDocument::Standard ); + repaintChanged(); + drawCursor( TRUE ); + setModified(); + emit textChanged(); +} + +/*! + Reimplemented to allow tabbing through links. If \a n is TRUE the + tab moves the focus to the next child; if \a n is FALSE the tab + moves the focus to the previous child. Returns TRUE if the focus + was moved; otherwise returns FALSE. + */ + +bool TQTextEdit::focusNextPrevChild( bool n ) +{ + if ( !isReadOnly() || !linksEnabled() ) + return FALSE; + bool b = doc->focusNextPrevChild( n ); + repaintChanged(); + if ( b ) { + TQTextParagraph *p = doc->focusIndicator.parag; + int start = doc->focusIndicator.start; + int len = doc->focusIndicator.len; + + int y = p->rect().y(); + while ( p + && len == 0 + && p->at( start )->isCustom() + && p->at( start )->customItem()->isNested() ) { + + TQTextTable *t = (TQTextTable*)p->at( start )->customItem(); + TQPtrList<TQTextTableCell> cells = t->tableCells(); + TQTextTableCell *c; + for ( c = cells.first(); c; c = cells.next() ) { + TQTextDocument *cellDoc = c->richText(); + if ( cellDoc->hasFocusParagraph() ) { + y += c->geometry().y() + c->verticalAlignmentOffset(); + + p = cellDoc->focusIndicator.parag; + start = cellDoc->focusIndicator.start; + len = cellDoc->focusIndicator.len; + if ( p ) + y += p->rect().y(); + + break; + } + } + } + setContentsPos( contentsX(), TQMIN( y, contentsHeight() - visibleHeight() ) ); + } + return b; +} + +/*! + \internal + + This functions sets the current format to \a f. Only the fields of \a + f which are specified by the \a flags are used. +*/ + +void TQTextEdit::setFormat( TQTextFormat *f, int flags ) +{ + if ( doc->hasSelection( TQTextDocument::Standard ) ) { + drawCursor( FALSE ); + TQTextCursor c1 = doc->selectionStartCursor( TQTextDocument::Standard ); + c1.restoreState(); + TQTextCursor c2 = doc->selectionEndCursor( TQTextDocument::Standard ); + c2.restoreState(); + if ( undoEnabled ) { + clearUndoRedo(); + undoRedoInfo.type = UndoRedoInfo::Format; + undoRedoInfo.id = c1.paragraph()->paragId(); + undoRedoInfo.index = c1.index(); + undoRedoInfo.eid = c2.paragraph()->paragId(); + undoRedoInfo.eindex = c2.index(); + readFormats( c1, c2, undoRedoInfo.d->text ); + undoRedoInfo.format = f; + undoRedoInfo.flags = flags; + clearUndoRedo(); + } + doc->setFormat( TQTextDocument::Standard, f, flags ); + repaintChanged(); + formatMore(); + drawCursor( TRUE ); + setModified(); + emit textChanged(); + } + if ( currentFormat && currentFormat->key() != f->key() ) { + currentFormat->removeRef(); + currentFormat = doc->formatCollection()->format( f ); + if ( currentFormat->isMisspelled() ) { + currentFormat->removeRef(); + currentFormat = doc->formatCollection()->format( currentFormat->font(), + currentFormat->color() ); + } + emit currentFontChanged( currentFormat->font() ); + emit currentColorChanged( currentFormat->color() ); + emit currentVerticalAlignmentChanged( (VerticalAlignment)currentFormat->vAlign() ); + if ( cursor->index() == cursor->paragraph()->length() - 1 ) { + currentFormat->addRef(); + cursor->paragraph()->string()->setFormat( cursor->index(), currentFormat, TRUE ); + if ( cursor->paragraph()->length() == 1 ) { + cursor->paragraph()->invalidate( 0 ); + cursor->paragraph()->format(); + repaintChanged(); + } + } + } +} + +/*! + \reimp +*/ + +void TQTextEdit::setPalette( const TQPalette &p ) +{ + TQScrollView::setPalette( p ); + if ( textFormat() == PlainText ) { + TQTextFormat *f = doc->formatCollection()->defaultFormat(); + f->setColor( colorGroup().text() ); + updateContents(); + } +} + +/*! \internal + \warning In TQt 3.1 we will provide a cleaer API for the + functionality which is provided by this function and in TQt 4.0 this + function will go away. + + Sets the paragraph style of the current paragraph + to \a dm. If \a dm is TQStyleSheetItem::DisplayListItem, the + type of the list item is set to \a listStyle. + + \sa setAlignment() +*/ + +void TQTextEdit::setParagType( TQStyleSheetItem::DisplayMode dm, + TQStyleSheetItem::ListStyle listStyle ) +{ + if ( isReadOnly() ) + return; + + drawCursor( FALSE ); + TQTextParagraph *start = cursor->paragraph(); + TQTextParagraph *end = start; + if ( doc->hasSelection( TQTextDocument::Standard ) ) { + start = doc->selectionStartCursor( TQTextDocument::Standard ).topParagraph(); + end = doc->selectionEndCursor( TQTextDocument::Standard ).topParagraph(); + if ( end->paragId() < start->paragId() ) + return; // do not trust our selections + } + + clearUndoRedo(); + undoRedoInfo.type = UndoRedoInfo::Style; + undoRedoInfo.id = start->paragId(); + undoRedoInfo.eid = end->paragId(); + undoRedoInfo.styleInformation = TQTextStyleCommand::readStyleInformation( doc, undoRedoInfo.id, undoRedoInfo.eid ); + + while ( start != end->next() ) { + start->setListStyle( listStyle ); + if ( dm == TQStyleSheetItem::DisplayListItem ) { + start->setListItem( TRUE ); + if( start->listDepth() == 0 ) + start->setListDepth( 1 ); + } else if ( start->isListItem() ) { + start->setListItem( FALSE ); + start->setListDepth( TQMAX( start->listDepth()-1, 0 ) ); + } + start = start->next(); + } + + clearUndoRedo(); + repaintChanged(); + formatMore(); + drawCursor( TRUE ); + setModified(); + emit textChanged(); +} + +/*! + Sets the alignment of the current paragraph to \a a. Valid + alignments are \c TQt::AlignLeft, \c TQt::AlignRight, + \c TQt::AlignJustify and \c TQt::AlignCenter (which centers + horizontally). +*/ + +void TQTextEdit::setAlignment( int a ) +{ + if ( isReadOnly() || block_set_alignment ) + return; + + drawCursor( FALSE ); + TQTextParagraph *start = cursor->paragraph(); + TQTextParagraph *end = start; + if ( doc->hasSelection( TQTextDocument::Standard ) ) { + start = doc->selectionStartCursor( TQTextDocument::Standard ).topParagraph(); + end = doc->selectionEndCursor( TQTextDocument::Standard ).topParagraph(); + if ( end->paragId() < start->paragId() ) + return; // do not trust our selections + } + + clearUndoRedo(); + undoRedoInfo.type = UndoRedoInfo::Style; + undoRedoInfo.id = start->paragId(); + undoRedoInfo.eid = end->paragId(); + undoRedoInfo.styleInformation = TQTextStyleCommand::readStyleInformation( doc, undoRedoInfo.id, undoRedoInfo.eid ); + + while ( start != end->next() ) { + start->setAlignment( a ); + start = start->next(); + } + + clearUndoRedo(); + repaintChanged(); + formatMore(); + drawCursor( TRUE ); + if ( currentAlignment != a ) { + currentAlignment = a; + emit currentAlignmentChanged( currentAlignment ); + } + setModified(); + emit textChanged(); +} + +void TQTextEdit::updateCurrentFormat() +{ + int i = cursor->index(); + if ( i > 0 ) + --i; + if ( doc->useFormatCollection() && + ( !currentFormat || currentFormat->key() != cursor->paragraph()->at( i )->format()->key() ) ) { + if ( currentFormat ) + currentFormat->removeRef(); + currentFormat = doc->formatCollection()->format( cursor->paragraph()->at( i )->format() ); + if ( currentFormat->isMisspelled() ) { + currentFormat->removeRef(); + currentFormat = doc->formatCollection()->format( currentFormat->font(), currentFormat->color() ); + } + emit currentFontChanged( currentFormat->font() ); + emit currentColorChanged( currentFormat->color() ); + emit currentVerticalAlignmentChanged( (VerticalAlignment)currentFormat->vAlign() ); + } + + if ( currentAlignment != cursor->paragraph()->alignment() ) { + currentAlignment = cursor->paragraph()->alignment(); + block_set_alignment = TRUE; + emit currentAlignmentChanged( currentAlignment ); + block_set_alignment = FALSE; + } +} + +/*! + If \a b is TRUE sets the current format to italic; otherwise sets + the current format to non-italic. + + \sa italic() +*/ + +void TQTextEdit::setItalic( bool b ) +{ + TQTextFormat f( *currentFormat ); + f.setItalic( b ); + TQTextFormat *f2 = doc->formatCollection()->format( &f ); + setFormat(f2, TQTextFormat::Italic ); +} + +/*! + If \a b is TRUE sets the current format to bold; otherwise sets + the current format to non-bold. + + \sa bold() +*/ + +void TQTextEdit::setBold( bool b ) +{ + TQTextFormat f( *currentFormat ); + f.setBold( b ); + TQTextFormat *f2 = doc->formatCollection()->format( &f ); + setFormat( f2, TQTextFormat::Bold ); +} + +/*! + If \a b is TRUE sets the current format to underline; otherwise + sets the current format to non-underline. + + \sa underline() +*/ + +void TQTextEdit::setUnderline( bool b ) +{ + TQTextFormat f( *currentFormat ); + f.setUnderline( b ); + TQTextFormat *f2 = doc->formatCollection()->format( &f ); + setFormat( f2, TQTextFormat::Underline ); +} + +/*! + Sets the font family of the current format to \a fontFamily. + + \sa family() setCurrentFont() +*/ + +void TQTextEdit::setFamily( const TQString &fontFamily ) +{ + TQTextFormat f( *currentFormat ); + f.setFamily( fontFamily ); + TQTextFormat *f2 = doc->formatCollection()->format( &f ); + setFormat( f2, TQTextFormat::Family ); +} + +/*! + Sets the point size of the current format to \a s. + + Note that if \a s is zero or negative, the behaviour of this + function is not defined. + + \sa pointSize() setCurrentFont() setFamily() +*/ + +void TQTextEdit::setPointSize( int s ) +{ + TQTextFormat f( *currentFormat ); + f.setPointSize( s ); + TQTextFormat *f2 = doc->formatCollection()->format( &f ); + setFormat( f2, TQTextFormat::Size ); +} + +/*! + Sets the color of the current format, i.e. of the text, to \a c. + + \sa color() setPaper() +*/ + +void TQTextEdit::setColor( const TQColor &c ) +{ + TQTextFormat f( *currentFormat ); + f.setColor( c ); + TQTextFormat *f2 = doc->formatCollection()->format( &f ); + setFormat( f2, TQTextFormat::Color ); +} + +/*! + Sets the vertical alignment of the current format, i.e. of the + text, to \a a. + + \sa color() setPaper() +*/ + +void TQTextEdit::setVerticalAlignment( VerticalAlignment a ) +{ + TQTextFormat f( *currentFormat ); + f.setVAlign( (TQTextFormat::VerticalAlignment)a ); + TQTextFormat *f2 = doc->formatCollection()->format( &f ); + setFormat( f2, TQTextFormat::VAlign ); +} + +void TQTextEdit::setFontInternal( const TQFont &f_ ) +{ + TQTextFormat f( *currentFormat ); + f.setFont( f_ ); + TQTextFormat *f2 = doc->formatCollection()->format( &f ); + setFormat( f2, TQTextFormat::Font ); +} + + +TQString TQTextEdit::text() const +{ +#ifdef QT_TEXTEDIT_OPTIMIZATION + if ( d->optimMode ) + return optimText(); +#endif + + TQTextParagraph *p = doc->firstParagraph(); + if ( !p || (!p->next() && p->length() <= 1) ) + return TQString::fromLatin1(""); + + if ( isReadOnly() ) + return doc->originalText(); + return doc->text(); +} + +/*! + \overload + + Returns the text of paragraph \a para. + + If textFormat() is \c RichText the text will contain HTML + formatting tags. +*/ + +TQString TQTextEdit::text( int para ) const +{ +#ifdef QT_TEXTEDIT_OPTIMIZATION + if ( d->optimMode && (d->od->numLines >= para) ) { + TQString paraStr = d->od->lines[ LOGOFFSET(para) ]; + if ( paraStr.isEmpty() ) + paraStr = "\n"; + return paraStr; + } else +#endif + return doc->text( para ); +} + +/*! + \overload + + Changes the text of the text edit to the string \a text and the + context to \a context. Any previous text is removed. + + \a text may be interpreted either as plain text or as rich text, + depending on the textFormat(). The default setting is \c AutoText, + i.e. the text edit auto-detects the format from \a text. + + For rich text the rendering style and available tags are defined + by a styleSheet(); see TQStyleSheet for details. + + The optional \a context is a path which the text edit's + TQMimeSourceFactory uses to resolve the locations of files and + images. (See \l{TQTextEdit::TQTextEdit()}.) It is passed to the text + edit's TQMimeSourceFactory when quering data. + + Note that the undo/redo history is cleared by this function. + + \sa text(), setTextFormat() +*/ + +void TQTextEdit::setText( const TQString &text, const TQString &context ) +{ +#ifdef QT_TEXTEDIT_OPTIMIZATION + if ( d->optimMode ) { + optimSetText( text ); + return; + } +#endif + resetInputContext(); + if ( !isModified() && isReadOnly() && + this->context() == context && this->text() == text ) + return; + + emit undoAvailable( FALSE ); + emit redoAvailable( FALSE ); + undoRedoInfo.clear(); + doc->commands()->clear(); + + lastFormatted = 0; + int oldCursorPos = cursor->index(); + int oldCursorPar = cursor->paragraph()->paragId(); + cursor->restoreState(); + delete cursor; + doc->setText( text, context ); + + if ( wrapMode == FixedPixelWidth ) { + resizeContents( wrapWidth, 0 ); + doc->setWidth( wrapWidth ); + doc->setMinimumWidth( wrapWidth ); + } else { + doc->setMinimumWidth( -1 ); + resizeContents( 0, 0 ); + } + + lastFormatted = doc->firstParagraph(); + cursor = new TQTextCursor( doc ); + updateContents(); + + if ( isModified() ) + setModified( FALSE ); + emit textChanged(); + if ( cursor->index() != oldCursorPos || cursor->paragraph()->paragId() != oldCursorPar ) { + emit cursorPositionChanged( cursor ); + emit cursorPositionChanged( cursor->paragraph()->paragId(), cursor->index() ); + } + formatMore(); + updateCurrentFormat(); + d->scrollToAnchor = TQString::null; +} + +/*! + \property TQTextEdit::text + \brief the text edit's text + + There is no default text. + + On setting, any previous text is deleted. + + The text may be interpreted either as plain text or as rich text, + depending on the textFormat(). The default setting is \c AutoText, + i.e. the text edit auto-detects the format of the text. + + For richtext, calling text() on an editable TQTextEdit will cause + the text to be regenerated from the textedit. This may mean that + the TQString returned may not be exactly the same as the one that + was set. + + \sa textFormat +*/ + + +/*! + \property TQTextEdit::readOnly + \brief whether the text edit is read-only + + In a read-only text edit the user can only navigate through the + text and select text; modifying the text is not possible. + + This property's default is FALSE. +*/ + +/*! + Finds the next occurrence of the string, \a expr. Returns TRUE if + \a expr was found; otherwise returns FALSE. + + If \a para and \a index are both 0 the search begins from the + current cursor position. If \a para and \a index are both not 0, + the search begins from the \a *index character position in the + \a *para paragraph. + + If \a cs is TRUE the search is case sensitive, otherwise it is + case insensitive. If \a wo is TRUE the search looks for whole word + matches only; otherwise it searches for any matching text. If \a + forward is TRUE (the default) the search works forward from the + starting position to the end of the text, otherwise it works + backwards to the beginning of the text. + + If \a expr is found the function returns TRUE. If \a index and \a + para are not 0, the number of the paragraph in which the first + character of the match was found is put into \a *para, and the + index position of that character within the paragraph is put into + \a *index. + + If \a expr is not found the function returns FALSE. If \a index + and \a para are not 0 and \a expr is not found, \a *index + and \a *para are undefined. + + Please note that this function will make the next occurrence of + the string (if found) the current selection, and will thus + modify the cursor position. + + Using the \a para and \a index parameters will not work correctly + in case the document contains tables. +*/ + +bool TQTextEdit::find( const TQString &expr, bool cs, bool wo, bool forward, + int *para, int *index ) +{ +#ifdef QT_TEXTEDIT_OPTIMIZATION + if ( d->optimMode ) + return optimFind( expr, cs, wo, forward, para, index ); +#endif + drawCursor( FALSE ); +#ifndef TQT_NO_CURSOR + viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); +#endif + TQTextCursor findcur = *cursor; + if ( para && index ) { + if ( doc->paragAt( *para ) ) + findcur.gotoPosition( doc->paragAt(*para), *index ); + else + findcur.gotoEnd(); + } else if ( doc->hasSelection( TQTextDocument::Standard ) ){ + // maks sure we do not find the same selection again + if ( forward ) + findcur.gotoNextLetter(); + else + findcur.gotoPreviousLetter(); + } else if (!forward && findcur.index() == 0 && findcur.paragraph() == findcur.topParagraph()) { + findcur.gotoEnd(); + } + removeSelection( TQTextDocument::Standard ); + bool found = doc->find( findcur, expr, cs, wo, forward ); + if ( found ) { + if ( para ) + *para = findcur.paragraph()->paragId(); + if ( index ) + *index = findcur.index(); + *cursor = findcur; + repaintChanged(); + ensureCursorVisible(); + } + drawCursor( TRUE ); + if (found) { + emit cursorPositionChanged( cursor ); + emit cursorPositionChanged( cursor->paragraph()->paragId(), cursor->index() ); + } + return found; +} + +void TQTextEdit::blinkCursor() +{ + if ( !cursorVisible ) + return; + bool cv = cursorVisible; + blinkCursorVisible = !blinkCursorVisible; + drawCursor( blinkCursorVisible ); + cursorVisible = cv; +} + +/*! + Sets the cursor to position \a index in paragraph \a para. + + \sa getCursorPosition() +*/ + +void TQTextEdit::setCursorPosition( int para, int index ) +{ + TQTextParagraph *p = doc->paragAt( para ); + if ( !p ) + return; + + resetInputContext(); + if ( index > p->length() - 1 ) + index = p->length() - 1; + + drawCursor( FALSE ); + cursor->setParagraph( p ); + cursor->setIndex( index ); + ensureCursorVisible(); + drawCursor( TRUE ); + updateCurrentFormat(); + emit cursorPositionChanged( cursor ); + emit cursorPositionChanged( cursor->paragraph()->paragId(), cursor->index() ); +} + +/*! + This function sets the \a *para and \a *index parameters to the + current cursor position. \a para and \a index must not be 0. + + \sa setCursorPosition() +*/ + +void TQTextEdit::getCursorPosition( int *para, int *index ) const +{ + if ( !para || !index ) + return; + *para = cursor->paragraph()->paragId(); + *index = cursor->index(); +} + +/*! + Sets a selection which starts at position \a indexFrom in + paragraph \a paraFrom and ends at position \a indexTo in paragraph + \a paraTo. + + Any existing selections which have a different id (\a selNum) are + left alone, but if an existing selection has the same id as \a + selNum it is removed and replaced by this selection. + + Uses the selection settings of selection \a selNum. If \a selNum + is 0, this is the default selection. + + The cursor is moved to the end of the selection if \a selNum is 0, + otherwise the cursor position remains unchanged. + + \sa getSelection() selectedText +*/ + +void TQTextEdit::setSelection( int paraFrom, int indexFrom, + int paraTo, int indexTo, int selNum ) +{ +#ifdef QT_TEXTEDIT_OPTIMIZATION + if (d->optimMode) { + optimSetSelection(paraFrom, indexFrom, paraTo, indexTo); + repaintContents(FALSE); + return; + } +#endif + resetInputContext(); + if ( doc->hasSelection( selNum ) ) { + doc->removeSelection( selNum ); + repaintChanged(); + } + if ( selNum > doc->numSelections() - 1 ) + doc->addSelection( selNum ); + TQTextParagraph *p1 = doc->paragAt( paraFrom ); + if ( !p1 ) + return; + TQTextParagraph *p2 = doc->paragAt( paraTo ); + if ( !p2 ) + return; + + if ( indexFrom > p1->length() - 1 ) + indexFrom = p1->length() - 1; + if ( indexTo > p2->length() - 1 ) + indexTo = p2->length() - 1; + + drawCursor( FALSE ); + TQTextCursor c = *cursor; + TQTextCursor oldCursor = *cursor; + c.setParagraph( p1 ); + c.setIndex( indexFrom ); + cursor->setParagraph( p2 ); + cursor->setIndex( indexTo ); + doc->setSelectionStart( selNum, c ); + doc->setSelectionEnd( selNum, *cursor ); + repaintChanged(); + ensureCursorVisible(); + if ( selNum != TQTextDocument::Standard ) + *cursor = oldCursor; + drawCursor( TRUE ); +} + +/*! + If there is a selection, \a *paraFrom is set to the number of the + paragraph in which the selection begins and \a *paraTo is set to + the number of the paragraph in which the selection ends. (They + could be the same.) \a *indexFrom is set to the index at which the + selection begins within \a *paraFrom, and \a *indexTo is set to + the index at which the selection ends within \a *paraTo. + + If there is no selection, \a *paraFrom, \a *indexFrom, \a *paraTo + and \a *indexTo are all set to -1. + + If \a paraFrom, \a indexFrom, \a paraTo or \a indexTo is 0 this + function does nothing. + + The \a selNum is the number of the selection (multiple selections + are supported). It defaults to 0 (the default selection). + + \sa setSelection() selectedText +*/ + +void TQTextEdit::getSelection( int *paraFrom, int *indexFrom, + int *paraTo, int *indexTo, int selNum ) const +{ + if ( !paraFrom || !paraTo || !indexFrom || !indexTo ) + return; +#ifdef QT_TEXTEDIT_OPTIMIZATION + if (d->optimMode) { + *paraFrom = d->od->selStart.line; + *paraTo = d->od->selEnd.line; + *indexFrom = d->od->selStart.index; + *indexTo = d->od->selEnd.index; + return; + } +#endif + if ( !doc->hasSelection( selNum ) ) { + *paraFrom = -1; + *indexFrom = -1; + *paraTo = -1; + *indexTo = -1; + return; + } + + doc->selectionStart( selNum, *paraFrom, *indexFrom ); + doc->selectionEnd( selNum, *paraTo, *indexTo ); +} + +/*! + \property TQTextEdit::textFormat + \brief the text format: rich text, plain text, log text or auto text. + + The text format is one of the following: + \list + \i PlainText - all characters, except newlines, are displayed + verbatim, including spaces. Whenever a newline appears in the text + the text edit inserts a hard line break and begins a new + paragraph. + \i RichText - rich text rendering. The available styles are + defined in the default stylesheet TQStyleSheet::defaultSheet(). + \i LogText - optimized mode for very large texts. Supports a very + limited set of formatting tags (color, bold, underline and italic + settings). + \i AutoText - this is the default. The text edit autodetects which + rendering style is best, \c PlainText or \c RichText. This is done + by using the TQStyleSheet::mightBeRichText() function. + \endlist +*/ + +void TQTextEdit::setTextFormat( TextFormat format ) +{ + doc->setTextFormat( format ); +#ifdef QT_TEXTEDIT_OPTIMIZATION + checkOptimMode(); +#endif +} + +TQt::TextFormat TQTextEdit::textFormat() const +{ + return doc->textFormat(); +} + +/*! + Returns the number of paragraphs in the text; an empty textedit is always + considered to have one paragraph, so 1 is returned in this case. +*/ + +int TQTextEdit::paragraphs() const +{ +#ifdef QT_TEXTEDIT_OPTIMIZATION + if ( d->optimMode ) { + return d->od->numLines; + } +#endif + return doc->lastParagraph()->paragId() + 1; +} + +/*! + Returns the number of lines in paragraph \a para, or -1 if there + is no paragraph with index \a para. +*/ + +int TQTextEdit::linesOfParagraph( int para ) const +{ +#ifdef QT_TEXTEDIT_OPTIMIZATION + if ( d->optimMode ) { + if ( d->od->numLines >= para ) + return 1; + else + return -1; + } +#endif + TQTextParagraph *p = doc->paragAt( para ); + if ( !p ) + return -1; + return p->lines(); +} + +/*! + Returns the length of the paragraph \a para (i.e. the number of + characters), or -1 if there is no paragraph with index \a para. + + This function ignores newlines. +*/ + +int TQTextEdit::paragraphLength( int para ) const +{ +#ifdef QT_TEXTEDIT_OPTIMIZATION + if ( d->optimMode ) { + if ( d->od->numLines >= para ) { + if ( d->od->lines[ LOGOFFSET(para) ].isEmpty() ) // CR + return 1; + else + return d->od->lines[ LOGOFFSET(para) ].length(); + } + return -1; + } +#endif + TQTextParagraph *p = doc->paragAt( para ); + if ( !p ) + return -1; + return p->length() - 1; +} + +/*! + Returns the number of lines in the text edit; this could be 0. + + \warning This function may be slow. Lines change all the time + during word wrapping, so this function has to iterate over all the + paragraphs and get the number of lines from each one individually. +*/ + +int TQTextEdit::lines() const +{ +#ifdef QT_TEXTEDIT_OPTIMIZATION + if ( d->optimMode ) { + return d->od->numLines; + } +#endif + TQTextParagraph *p = doc->firstParagraph(); + int l = 0; + while ( p ) { + l += p->lines(); + p = p->next(); + } + + return l; +} + +/*! + Returns the line number of the line in paragraph \a para in which + the character at position \a index appears. The \a index position is + relative to the beginning of the paragraph. If there is no such + paragraph or no such character at the \a index position (e.g. the + index is out of range) -1 is returned. +*/ + +int TQTextEdit::lineOfChar( int para, int index ) +{ + TQTextParagraph *p = doc->paragAt( para ); + if ( !p ) + return -1; + + int idx, line; + TQTextStringChar *c = p->lineStartOfChar( index, &idx, &line ); + if ( !c ) + return -1; + + return line; +} + +void TQTextEdit::setModified( bool m ) +{ + bool oldModified = modified; + modified = m; + if ( modified && doc->oTextValid ) + doc->invalidateOriginalText(); + if ( oldModified != modified ) + emit modificationChanged( modified ); +} + +/*! + \property TQTextEdit::modified + \brief whether the document has been modified by the user +*/ + +bool TQTextEdit::isModified() const +{ + return modified; +} + +void TQTextEdit::setModified() +{ + if ( !isModified() ) + setModified( TRUE ); +} + +/*! + Returns TRUE if the current format is italic; otherwise returns FALSE. + + \sa setItalic() +*/ + +bool TQTextEdit::italic() const +{ + return currentFormat->font().italic(); +} + +/*! + Returns TRUE if the current format is bold; otherwise returns FALSE. + + \sa setBold() +*/ + +bool TQTextEdit::bold() const +{ + return currentFormat->font().bold(); +} + +/*! + Returns TRUE if the current format is underlined; otherwise returns + FALSE. + + \sa setUnderline() +*/ + +bool TQTextEdit::underline() const +{ + return currentFormat->font().underline(); +} + +/*! + Returns the font family of the current format. + + \sa setFamily() setCurrentFont() setPointSize() +*/ + +TQString TQTextEdit::family() const +{ + return currentFormat->font().family(); +} + +/*! + Returns the point size of the font of the current format. + + \sa setFamily() setCurrentFont() setPointSize() +*/ + +int TQTextEdit::pointSize() const +{ + return currentFormat->font().pointSize(); +} + +/*! + Returns the color of the current format. + + \sa setColor() setPaper() +*/ + +TQColor TQTextEdit::color() const +{ + return currentFormat->color(); +} + +/*! + \obsolete + + Returns TQScrollView::font() + + \warning In previous versions this function returned the font of + the current format. This lead to confusion. Please use + currentFont() instead. +*/ + +TQFont TQTextEdit::font() const +{ + return TQScrollView::font(); +} + +/*! + Returns the font of the current format. + + \sa setCurrentFont() setFamily() setPointSize() +*/ + +TQFont TQTextEdit::currentFont() const +{ + return currentFormat->font(); +} + + +/*! + Returns the alignment of the current paragraph. + + \sa setAlignment() +*/ + +int TQTextEdit::alignment() const +{ + return currentAlignment; +} + +void TQTextEdit::startDrag() +{ +#ifndef TQT_NO_DRAGANDDROP + mousePressed = FALSE; + inDoubleClick = FALSE; + TQDragObject *drag = dragObject( viewport() ); + if ( !drag ) + return; + if ( isReadOnly() ) { + drag->dragCopy(); + } else { + if ( drag->drag() && TQDragObject::target() != this && TQDragObject::target() != viewport() ) + removeSelectedText(); + } +#endif +} + +/*! + If \a select is TRUE (the default), all the text is selected as + selection 0. If \a select is FALSE any selected text is + unselected, i.e. the default selection (selection 0) is cleared. + + \sa selectedText +*/ + +void TQTextEdit::selectAll( bool select ) +{ +#ifdef QT_TEXTEDIT_OPTIMIZATION + if ( d->optimMode ) { + if ( select ) + optimSelectAll(); + else + optimRemoveSelection(); + return; + } +#endif + if ( !select ) + doc->removeSelection( TQTextDocument::Standard ); + else + doc->selectAll( TQTextDocument::Standard ); + repaintChanged(); + emit copyAvailable( doc->hasSelection( TQTextDocument::Standard ) ); + emit selectionChanged(); +#ifndef TQT_NO_CURSOR + viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); +#endif +} + +void TQTextEdit::UndoRedoInfo::clear() +{ + if ( valid() ) { + if ( type == Insert || type == Return ) + doc->addCommand( new TQTextInsertCommand( doc, id, index, d->text.rawData(), styleInformation ) ); + else if ( type == Format ) + doc->addCommand( new TQTextFormatCommand( doc, id, index, eid, eindex, d->text.rawData(), format, flags ) ); + else if ( type == Style ) + doc->addCommand( new TQTextStyleCommand( doc, id, eid, styleInformation ) ); + else if ( type != Invalid ) { + doc->addCommand( new TQTextDeleteCommand( doc, id, index, d->text.rawData(), styleInformation ) ); + } + } + type = Invalid; + d->text = TQString::null; + id = -1; + index = -1; + styleInformation = TQByteArray(); +} + + +/*! + If there is some selected text (in selection 0) it is deleted. If + there is no selected text (in selection 0) the character to the + right of the text cursor is deleted. + + \sa removeSelectedText() cut() +*/ + +void TQTextEdit::del() +{ + if ( doc->hasSelection( TQTextDocument::Standard ) ) { + removeSelectedText(); + return; + } + + doKeyboardAction( ActionDelete ); +} + + +TQTextEdit::UndoRedoInfo::UndoRedoInfo( TQTextDocument *dc ) + : type( Invalid ), doc( dc ) +{ + d = new TQUndoRedoInfoPrivate; + d->text = TQString::null; + id = -1; + index = -1; +} + +TQTextEdit::UndoRedoInfo::~UndoRedoInfo() +{ + delete d; +} + +bool TQTextEdit::UndoRedoInfo::valid() const +{ + return id >= 0 && type != Invalid; +} + +/*! + \internal + + Resets the current format to the default format. +*/ + +void TQTextEdit::resetFormat() +{ + setAlignment( TQt::AlignAuto ); + setParagType( TQStyleSheetItem::DisplayBlock, TQStyleSheetItem::ListDisc ); + setFormat( doc->formatCollection()->defaultFormat(), TQTextFormat::Format ); +} + +/*! + Returns the TQStyleSheet which is being used by this text edit. + + \sa setStyleSheet() +*/ + +TQStyleSheet* TQTextEdit::styleSheet() const +{ + return doc->styleSheet(); +} + +/*! + Sets the stylesheet to use with this text edit to \a styleSheet. + Changes will only take effect for new text added with setText() or + append(). + + \sa styleSheet() +*/ + +void TQTextEdit::setStyleSheet( TQStyleSheet* styleSheet ) +{ + doc->setStyleSheet( styleSheet ); +} + +/*! + \property TQTextEdit::paper + \brief the background (paper) brush. + + The brush that is currently used to draw the background of the + text edit. The initial setting is an empty brush. +*/ + +void TQTextEdit::setPaper( const TQBrush& pap ) +{ + doc->setPaper( new TQBrush( pap ) ); + + if ( pap.pixmap() ) { + viewport()->setBackgroundPixmap( *pap.pixmap() ); + } else { + setPaletteBackgroundColor( pap.color() ); + viewport()->setPaletteBackgroundColor( pap.color() ); + } + +#ifdef QT_TEXTEDIT_OPTIMIZATION + // force a repaint of the entire viewport - using updateContents() + // would clip the coords to the content size + if (d->optimMode) + repaintContents(contentsX(), contentsY(), viewport()->width(), viewport()->height()); + else +#endif + updateContents(); +} + +TQBrush TQTextEdit::paper() const +{ + if ( doc->paper() ) + return *doc->paper(); + return TQBrush( colorGroup().base() ); +} + +/*! + \property TQTextEdit::linkUnderline + \brief whether hypertext links will be underlined + + If TRUE (the default) hypertext links will be displayed + underlined. If FALSE links will not be displayed underlined. +*/ + +void TQTextEdit::setLinkUnderline( bool b ) +{ + if ( doc->underlineLinks() == b ) + return; + doc->setUnderlineLinks( b ); + repaintChanged(); +} + +bool TQTextEdit::linkUnderline() const +{ + return doc->underlineLinks(); +} + +/*! + Sets the text edit's mimesource factory to \a factory. See + TQMimeSourceFactory for further details. + + \sa mimeSourceFactory() + */ + +#ifndef TQT_NO_MIME +void TQTextEdit::setMimeSourceFactory( TQMimeSourceFactory* factory ) +{ + doc->setMimeSourceFactory( factory ); +} + +/*! + Returns the TQMimeSourceFactory which is being used by this text + edit. + + \sa setMimeSourceFactory() +*/ + +TQMimeSourceFactory* TQTextEdit::mimeSourceFactory() const +{ + return doc->mimeSourceFactory(); +} +#endif + +/*! + Returns how many pixels high the text edit needs to be to display + all the text if the text edit is \a w pixels wide. +*/ + +int TQTextEdit::heightForWidth( int w ) const +{ + int oldw = doc->width(); + doc->doLayout( 0, w ); + int h = doc->height(); + doc->setWidth( oldw ); + doc->invalidate(); + ( (TQTextEdit*)this )->formatMore(); + return h; +} + +/*! + Appends a new paragraph with \a text to the end of the text edit. Note that + the undo/redo history is cleared by this function, and no undo + history is kept for appends which makes them faster than + insert()s. If you want to append text which is added to the + undo/redo history as well, use insertParagraph(). +*/ + +void TQTextEdit::append( const TQString &text ) +{ +#ifdef QT_TEXTEDIT_OPTIMIZATION + if ( d->optimMode ) { + optimAppend( text ); + return; + } +#endif + // flush and clear the undo/redo stack if necessary + undoRedoInfo.clear(); + doc->commands()->clear(); + + doc->removeSelection( TQTextDocument::Standard ); + TextFormat f = doc->textFormat(); + if ( f == AutoText ) { + if ( TQStyleSheet::mightBeRichText( text ) ) + f = RichText; + else + f = PlainText; + } + + drawCursor( FALSE ); + TQTextCursor oldc( *cursor ); + ensureFormatted( doc->lastParagraph() ); + bool atBottom = contentsY() >= contentsHeight() - visibleHeight(); + cursor->gotoEnd(); + if ( cursor->index() > 0 ) + cursor->splitAndInsertEmptyParagraph(); + TQTextCursor oldCursor2 = *cursor; + + if ( f == TQt::PlainText ) { + cursor->insert( text, TRUE ); + if ( doc->useFormatCollection() && !doc->preProcessor() && + currentFormat != cursor->paragraph()->at( cursor->index() )->format() ) { + doc->setSelectionStart( TQTextDocument::Temp, oldCursor2 ); + doc->setSelectionEnd( TQTextDocument::Temp, *cursor ); + doc->setFormat( TQTextDocument::Temp, currentFormat, TQTextFormat::Format ); + doc->removeSelection( TQTextDocument::Temp ); + } + } else { + cursor->paragraph()->setListItem( FALSE ); + cursor->paragraph()->setListDepth( 0 ); + if ( cursor->paragraph()->prev() ) + cursor->paragraph()->prev()->invalidate(0); // vertical margins might have to change + doc->setRichTextInternal( text ); + } + formatMore(); + repaintChanged(); + if ( atBottom ) + scrollToBottom(); + *cursor = oldc; + if ( !isReadOnly() ) + cursorVisible = TRUE; + setModified(); + emit textChanged(); +} + +/*! + \property TQTextEdit::hasSelectedText + \brief whether some text is selected in selection 0 +*/ + +bool TQTextEdit::hasSelectedText() const +{ +#ifdef QT_TEXTEDIT_OPTIMIZATION + if ( d->optimMode ) + return optimHasSelection(); + else +#endif + return doc->hasSelection( TQTextDocument::Standard ); +} + +/*! + \property TQTextEdit::selectedText + \brief The selected text (from selection 0) or an empty string if + there is no currently selected text (in selection 0). + + The text is always returned as \c PlainText if the textFormat() is + \c PlainText or \c AutoText, otherwise it is returned as HTML. + + \sa hasSelectedText +*/ + +TQString TQTextEdit::selectedText() const +{ +#ifdef QT_TEXTEDIT_OPTIMIZATION + if ( d->optimMode ) + return optimSelectedText(); + else +#endif + return doc->selectedText( TQTextDocument::Standard, textFormat() == RichText ); +} + +bool TQTextEdit::handleReadOnlyKeyEvent( TQKeyEvent *e ) +{ + switch( e->key() ) { + case Key_Down: + setContentsPos( contentsX(), contentsY() + 10 ); + break; + case Key_Up: + setContentsPos( contentsX(), contentsY() - 10 ); + break; + case Key_Left: + setContentsPos( contentsX() - 10, contentsY() ); + break; + case Key_Right: + setContentsPos( contentsX() + 10, contentsY() ); + break; + case Key_PageUp: + setContentsPos( contentsX(), contentsY() - visibleHeight() ); + break; + case Key_PageDown: + setContentsPos( contentsX(), contentsY() + visibleHeight() ); + break; + case Key_Home: + setContentsPos( contentsX(), 0 ); + break; + case Key_End: + setContentsPos( contentsX(), contentsHeight() - visibleHeight() ); + break; + case Key_F16: // Copy key on Sun keyboards + copy(); + break; +#ifndef TQT_NO_NETWORKPROTOCOL + case Key_Return: + case Key_Enter: + case Key_Space: { + if (!doc->focusIndicator.href.isEmpty() + || !doc->focusIndicator.name.isEmpty()) { + if (!doc->focusIndicator.href.isEmpty()) { + TQUrl u( doc->context(), doc->focusIndicator.href, TRUE ); + emitLinkClicked( u.toString( FALSE, FALSE ) ); + } + if (!doc->focusIndicator.name.isEmpty()) { + if (::tqt_cast<TQTextBrowser*>(this)) { // change for 4.0 + TQConnectionList *clist = receivers( + "anchorClicked(const TQString&,const TQString&)"); + if (!signalsBlocked() && clist) { + TQUObject o[3]; + static_QUType_TQString.set(o+1, + doc->focusIndicator.name); + static_QUType_TQString.set(o+2, + doc->focusIndicator.href); + activate_signal( clist, o); + } + } + } +#ifndef TQT_NO_CURSOR + viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); +#endif + } + } break; +#endif + default: + if ( e->state() & ControlButton ) { + switch ( e->key() ) { + case Key_C: case Key_F16: // Copy key on Sun keyboards + copy(); + break; +#ifdef TQ_WS_WIN + case Key_Insert: + copy(); + break; + case Key_A: + selectAll(); + break; +#endif + } + + } + return FALSE; + } + return TRUE; +} + +/*! + Returns the context of the text edit. The context is a path which + the text edit's TQMimeSourceFactory uses to resolve the locations + of files and images. + + \sa text +*/ + +TQString TQTextEdit::context() const +{ + return doc->context(); +} + +/*! + \property TQTextEdit::documentTitle + \brief the title of the document parsed from the text. + + For \c PlainText the title will be an empty string. For \c + RichText the title will be the text between the \c{<title>} tags, + if present, otherwise an empty string. +*/ + +TQString TQTextEdit::documentTitle() const +{ + return doc->attributes()[ "title" ]; +} + +void TQTextEdit::makeParagVisible( TQTextParagraph *p ) +{ + setContentsPos( contentsX(), TQMIN( p->rect().y(), contentsHeight() - visibleHeight() ) ); +} + +/*! + Scrolls the text edit to make the text at the anchor called \a + name visible, if it can be found in the document. If the anchor + isn't found no scrolling will occur. An anchor is defined using + the HTML anchor tag, e.g. \c{<a name="target">}. +*/ + +void TQTextEdit::scrollToAnchor( const TQString& name ) +{ + if ( !isVisible() ) { + d->scrollToAnchor = name; + return; + } + if ( name.isEmpty() ) + return; + sync(); + TQTextCursor cursor( doc ); + TQTextParagraph* last = doc->lastParagraph(); + for (;;) { + TQTextStringChar* c = cursor.paragraph()->at( cursor.index() ); + if( c->isAnchor() ) { + TQString a = c->anchorName(); + if ( a == name || + (a.contains( '#' ) && TQStringList::split( '#', a ).contains( name ) ) ) { + setContentsPos( contentsX(), TQMIN( cursor.paragraph()->rect().top() + cursor.totalOffsetY(), contentsHeight() - visibleHeight() ) ); + break; + } + } + if ( cursor.paragraph() == last && cursor.atParagEnd() ) + break; + cursor.gotoNextLetter(); + } +} + +/*! + \overload + + If there is an anchor at position \a pos (in contents + coordinates), its \c href is returned, otherwise TQString::null is + returned. +*/ + +TQString TQTextEdit::anchorAt( const TQPoint& pos ) +{ + return anchorAt(pos, AnchorHref); +} + +/*! + If there is an anchor at position \a pos (in contents + coordinates), the text for attribute \a attr is returned, + otherwise TQString::null is returned. +*/ + +TQString TQTextEdit::anchorAt( const TQPoint& pos, AnchorAttribute attr ) +{ + TQTextCursor c( doc ); + placeCursor( pos, &c ); + switch(attr) { + case AnchorName: + return c.paragraph()->at( c.index() )->anchorName(); + case AnchorHref: + return c.paragraph()->at( c.index() )->anchorHref(); + } + // incase the compiler is really dumb about determining if a function + // returns something :) + return TQString::null; +} + +void TQTextEdit::documentWidthChanged( int w ) +{ + resizeContents( TQMAX( visibleWidth(), w), contentsHeight() ); +} + +/*! \internal + + This function does nothing +*/ + +void TQTextEdit::updateStyles() +{ +} + +void TQTextEdit::setDocument( TQTextDocument *dc ) +{ + if ( dc == 0 ) { + tqWarning( "Q3TextEdit::setDocument() called with null Q3TextDocument pointer" ); + return; + } + if ( dc == doc ) + return; + resetInputContext(); + doc = dc; + delete cursor; + cursor = new TQTextCursor( doc ); + clearUndoRedo(); + undoRedoInfo.doc = doc; + lastFormatted = 0; +} + +#ifndef TQT_NO_CLIPBOARD + +/*! + Pastes the text with format \a subtype from the clipboard into the + text edit at the current cursor position. The \a subtype can be + "plain" or "html". + + If there is no text with format \a subtype in the clipboard + nothing happens. + + \sa paste() cut() TQTextEdit::copy() +*/ + +void TQTextEdit::pasteSubType( const TQCString &subtype ) +{ +#ifndef TQT_NO_MIMECLIPBOARD + TQMimeSource *m = TQApplication::clipboard()->data( d->clipboard_mode ); + pasteSubType( subtype, m ); +#endif +} + +/*! \internal */ + +void TQTextEdit::pasteSubType( const TQCString& subtype, TQMimeSource *m ) +{ +#ifndef TQT_NO_MIME + TQCString st = subtype; + if ( subtype != "x-qrichtext" ) + st.prepend( "text/" ); + else + st.prepend( "application/" ); + if ( !m ) + return; + if ( doc->hasSelection( TQTextDocument::Standard ) ) + removeSelectedText(); + if ( !TQRichTextDrag::canDecode( m ) ) + return; + TQString t; + if ( !TQRichTextDrag::decode( m, t, st.data(), subtype ) ) + return; + if ( st == "application/x-qrichtext" ) { + int start; + if ( (start = t.find( "<!--StartFragment-->" )) != -1 ) { + start += 20; + int end = t.find( "<!--EndFragment-->" ); + TQTextCursor oldC = *cursor; + + // during the setRichTextInternal() call the cursors + // paragraph might get joined with the provious one, so + // the cursors one would get deleted and oldC.paragraph() + // would be a dnagling pointer. To avoid that try to go + // one letter back and later go one forward again. + oldC.gotoPreviousLetter(); + bool couldGoBack = oldC != *cursor; + // first para might get deleted, so remember to reset it + bool wasAtFirst = oldC.paragraph() == doc->firstParagraph(); + + if ( start < end ) + t = t.mid( start, end - start ); + else + t = t.mid( start ); + lastFormatted = cursor->paragraph(); + if ( lastFormatted->prev() ) + lastFormatted = lastFormatted->prev(); + doc->setRichTextInternal( t, cursor ); + + // the first para might have been deleted in + // setRichTextInternal(). To be sure, reset it if + // necessary. + if ( wasAtFirst ) { + int index = oldC.index(); + oldC.setParagraph( doc->firstParagraph() ); + oldC.setIndex( index ); + } + + // if we went back one letter before (see last comment), + // go one forward to point to the right position + if ( couldGoBack ) + oldC.gotoNextLetter(); + + if ( undoEnabled && !isReadOnly() ) { + doc->setSelectionStart( TQTextDocument::Temp, oldC ); + doc->setSelectionEnd( TQTextDocument::Temp, *cursor ); + + checkUndoRedoInfo( UndoRedoInfo::Insert ); + if ( !undoRedoInfo.valid() ) { + undoRedoInfo.id = oldC.paragraph()->paragId(); + undoRedoInfo.index = oldC.index(); + undoRedoInfo.d->text = TQString::null; + } + int oldLen = undoRedoInfo.d->text.length(); + if ( !doc->preProcessor() ) { + TQString txt = doc->selectedText( TQTextDocument::Temp ); + undoRedoInfo.d->text += txt; + for ( int i = 0; i < (int)txt.length(); ++i ) { + if ( txt[ i ] != '\n' && oldC.paragraph()->at( oldC.index() )->format() ) { + oldC.paragraph()->at( oldC.index() )->format()->addRef(); + undoRedoInfo.d->text. + setFormat( oldLen + i, oldC.paragraph()->at( oldC.index() )->format(), TRUE ); + } + oldC.gotoNextLetter(); + } + } + undoRedoInfo.clear(); + removeSelection( TQTextDocument::Temp ); + } + + formatMore(); + setModified(); + emit textChanged(); + repaintChanged(); + ensureCursorVisible(); + return; + } + } else { +#if defined(Q_OS_WIN32) + // Need to convert CRLF to LF + t.replace( "\r\n", "\n" ); +#elif defined(Q_OS_MAC) + //need to convert CR to LF + t.replace( '\r', '\n' ); +#endif + TQChar *uc = (TQChar *)t.unicode(); + for ( int i=0; (uint) i<t.length(); i++ ) { + if ( uc[ i ] < ' ' && uc[ i ] != '\n' && uc[ i ] != '\t' ) + uc[ i ] = ' '; + } + if ( !t.isEmpty() ) + insert( t, FALSE, TRUE ); + } +#endif //TQT_NO_MIME +} + +#ifndef TQT_NO_MIMECLIPBOARD +/*! + Prompts the user to choose a type from a list of text types + available, then copies text from the clipboard (if there is any) + into the text edit at the current text cursor position. Any + selected text (in selection 0) is first deleted. +*/ +void TQTextEdit::pasteSpecial( const TQPoint& pt ) +{ + TQCString st = pickSpecial( TQApplication::clipboard()->data( d->clipboard_mode ), + TRUE, pt ); + if ( !st.isEmpty() ) + pasteSubType( st ); +} +#endif +#ifndef TQT_NO_MIME +TQCString TQTextEdit::pickSpecial( TQMimeSource* ms, bool always_ask, const TQPoint& pt ) +{ + if ( ms ) { +#ifndef TQT_NO_POPUPMENU + TQPopupMenu popup( this, "qt_pickspecial_menu" ); + TQString fmt; + int n = 0; + TQDict<void> done; + for (int i = 0; !( fmt = ms->format( i ) ).isNull(); i++) { + int semi = fmt.find( ";" ); + if ( semi >= 0 ) + fmt = fmt.left( semi ); + if ( fmt.left( 5 ) == "text/" ) { + fmt = fmt.mid( 5 ); + if ( !done.find( fmt ) ) { + done.insert( fmt,(void*)1 ); + popup.insertItem( fmt, i ); + n++; + } + } + } + if ( n ) { + int i = n ==1 && !always_ask ? popup.idAt( 0 ) : popup.exec( pt ); + if ( i >= 0 ) + return popup.text(i).latin1(); + } +#else + TQString fmt; + for (int i = 0; !( fmt = ms->format( i ) ).isNull(); i++) { + int semi = fmt.find( ";" ); + if ( semi >= 0 ) + fmt = fmt.left( semi ); + if ( fmt.left( 5 ) == "text/" ) { + fmt = fmt.mid( 5 ); + return fmt.latin1(); + } + } +#endif + } + return TQCString(); +} +#endif // TQT_NO_MIME +#endif // TQT_NO_CLIPBOARD + +/*! + \enum TQTextEdit::WordWrap + + This enum defines the TQTextEdit's word wrap modes. + + \value NoWrap Do not wrap the text. + + \value WidgetWidth Wrap the text at the current width of the + widget (this is the default). Wrapping is at whitespace by + default; this can be changed with setWrapPolicy(). + + \value FixedPixelWidth Wrap the text at a fixed number of pixels + from the widget's left side. The number of pixels is set with + wrapColumnOrWidth(). + + \value FixedColumnWidth Wrap the text at a fixed number of + character columns from the widget's left side. The number of + characters is set with wrapColumnOrWidth(). This is useful if you + need formatted text that can also be displayed gracefully on + devices with monospaced fonts, for example a standard VT100 + terminal, where you might set wrapColumnOrWidth() to 80. + + \sa setWordWrap() wordWrap() +*/ + +/*! + \property TQTextEdit::wordWrap + \brief the word wrap mode + + The default mode is \c WidgetWidth which causes words to be + wrapped at the right edge of the text edit. Wrapping occurs at + whitespace, keeping whole words intact. If you want wrapping to + occur within words use setWrapPolicy(). If you set a wrap mode of + \c FixedPixelWidth or \c FixedColumnWidth you should also call + setWrapColumnOrWidth() with the width you want. + + \sa WordWrap, wrapColumnOrWidth, wrapPolicy, +*/ + +void TQTextEdit::setWordWrap( WordWrap mode ) +{ + if ( wrapMode == mode ) + return; + wrapMode = mode; + switch ( mode ) { + case NoWrap: + document()->formatter()->setWrapEnabled( FALSE ); + document()->formatter()->setWrapAtColumn( -1 ); + doc->setWidth( visibleWidth() ); + doc->setMinimumWidth( -1 ); + doc->invalidate(); + updateContents(); + lastFormatted = doc->firstParagraph(); + interval = 0; + formatMore(); + break; + case WidgetWidth: + document()->formatter()->setWrapEnabled( TRUE ); + document()->formatter()->setWrapAtColumn( -1 ); + doResize(); + break; + case FixedPixelWidth: + document()->formatter()->setWrapEnabled( TRUE ); + document()->formatter()->setWrapAtColumn( -1 ); + if ( wrapWidth < 0 ) + wrapWidth = 200; + setWrapColumnOrWidth( wrapWidth ); + break; + case FixedColumnWidth: + if ( wrapWidth < 0 ) + wrapWidth = 80; + document()->formatter()->setWrapEnabled( TRUE ); + document()->formatter()->setWrapAtColumn( wrapWidth ); + setWrapColumnOrWidth( wrapWidth ); + break; + } +#ifdef QT_TEXTEDIT_OPTIMIZATION + checkOptimMode(); +#endif +} + +TQTextEdit::WordWrap TQTextEdit::wordWrap() const +{ + return wrapMode; +} + +/*! + \property TQTextEdit::wrapColumnOrWidth + \brief the position (in pixels or columns depending on the wrap mode) where text will be wrapped + + If the wrap mode is \c FixedPixelWidth, the value is the number of + pixels from the left edge of the text edit at which text should be + wrapped. If the wrap mode is \c FixedColumnWidth, the value is the + column number (in character columns) from the left edge of the + text edit at which text should be wrapped. + + \sa wordWrap +*/ +void TQTextEdit::setWrapColumnOrWidth( int value ) +{ + wrapWidth = value; + if ( wrapMode == FixedColumnWidth ) { + document()->formatter()->setWrapAtColumn( wrapWidth ); + resizeContents( 0, 0 ); + doc->setWidth( visibleWidth() ); + doc->setMinimumWidth( -1 ); + } else if (wrapMode == FixedPixelWidth ) { + document()->formatter()->setWrapAtColumn( -1 ); + resizeContents( wrapWidth, 0 ); + doc->setWidth( wrapWidth ); + doc->setMinimumWidth( wrapWidth ); + } else { + return; + } + doc->invalidate(); + updateContents(); + lastFormatted = doc->firstParagraph(); + interval = 0; + formatMore(); +} + +int TQTextEdit::wrapColumnOrWidth() const +{ + if ( wrapMode == WidgetWidth ) + return visibleWidth(); + return wrapWidth; +} + + +/*! + \enum TQTextEdit::WrapPolicy + + This enum defines where text can be wrapped in word wrap mode. + + \value AtWhiteSpace Don't use this deprecated value (it is a + synonym for \c AtWordBoundary which you should use instead). + \value Anywhere Break anywhere, including within words. + \value AtWordBoundary Break lines at word boundaries, e.g. spaces or + newlines + \value AtWordOrDocumentBoundary Break lines at whitespace, e.g. + spaces or newlines if possible. Break it anywhere otherwise. + + \sa setWrapPolicy() +*/ + +/*! + \property TQTextEdit::wrapPolicy + \brief the word wrap policy, at whitespace or anywhere + + Defines where text can be wrapped when word wrap mode is not \c + NoWrap. The choices are \c AtWordBoundary (the default), \c + Anywhere and \c AtWordOrDocumentBoundary + + \sa wordWrap +*/ + +void TQTextEdit::setWrapPolicy( WrapPolicy policy ) +{ + if ( wPolicy == policy ) + return; + wPolicy = policy; + TQTextFormatter *formatter; + if ( policy == AtWordBoundary || policy == AtWordOrDocumentBoundary ) { + formatter = new TQTextFormatterBreakWords; + formatter->setAllowBreakInWords( policy == AtWordOrDocumentBoundary ); + } else { + formatter = new TQTextFormatterBreakInWords; + } + formatter->setWrapAtColumn( document()->formatter()->wrapAtColumn() ); + formatter->setWrapEnabled( document()->formatter()->isWrapEnabled( 0 ) ); + document()->setFormatter( formatter ); + doc->invalidate(); + updateContents(); + lastFormatted = doc->firstParagraph(); + interval = 0; + formatMore(); +} + +TQTextEdit::WrapPolicy TQTextEdit::wrapPolicy() const +{ + return wPolicy; +} + +/*! + Deletes all the text in the text edit. + + \sa cut() removeSelectedText() setText() +*/ + +void TQTextEdit::clear() +{ +#ifdef QT_TEXTEDIT_OPTIMIZATION + if ( d->optimMode ) { + optimSetText(""); + } else +#endif + { + // make clear undoable + doc->selectAll( TQTextDocument::Temp ); + removeSelectedText( TQTextDocument::Temp ); + setContentsPos( 0, 0 ); + if ( cursor->isValid() ) + cursor->restoreState(); + doc->clear( TRUE ); + delete cursor; + cursor = new TQTextCursor( doc ); + lastFormatted = 0; + } + updateContents(); + + emit cursorPositionChanged( cursor ); + emit cursorPositionChanged( cursor->paragraph()->paragId(), cursor->index() ); +} + +int TQTextEdit::undoDepth() const +{ + return document()->undoDepth(); +} + +/*! + \property TQTextEdit::length + \brief the number of characters in the text +*/ + +int TQTextEdit::length() const +{ +#ifdef QT_TEXTEDIT_OPTIMIZATION + if ( d->optimMode ) + return d->od->len; + else +#endif + return document()->length(); +} + +/*! + \property TQTextEdit::tabStopWidth + \brief the tab stop width in pixels +*/ + +int TQTextEdit::tabStopWidth() const +{ + return document()->tabStopWidth(); +} + +void TQTextEdit::setUndoDepth( int d ) +{ + document()->setUndoDepth( d ); +} + +void TQTextEdit::setTabStopWidth( int ts ) +{ + document()->setTabStops( ts ); + doc->invalidate(); + lastFormatted = doc->firstParagraph(); + interval = 0; + formatMore(); + updateContents(); +} + +/*! + \reimp +*/ + +TQSize TQTextEdit::sizeHint() const +{ + // cf. TQScrollView::sizeHint() + constPolish(); + int f = 2 * frameWidth(); + int h = fontMetrics().height(); + TQSize sz( f, f ); + return sz.expandedTo( TQSize(12 * h, 8 * h) ); +} + +void TQTextEdit::clearUndoRedo() +{ + if ( !undoEnabled ) + return; + undoRedoInfo.clear(); + emit undoAvailable( doc->commands()->isUndoAvailable() ); + emit redoAvailable( doc->commands()->isRedoAvailable() ); +} + +/*! \internal + \warning In TQt 3.1 we will provide a cleaer API for the + functionality which is provided by this function and in TQt 4.0 this + function will go away. + + This function gets the format of the character at position \a + index in paragraph \a para. Sets \a font to the character's font, \a + color to the character's color and \a verticalAlignment to the + character's vertical alignment. + + Returns FALSE if \a para or \a index is out of range otherwise + returns TRUE. +*/ + +bool TQTextEdit::getFormat( int para, int index, TQFont *font, TQColor *color, VerticalAlignment *verticalAlignment ) +{ + if ( !font || !color ) + return FALSE; + TQTextParagraph *p = doc->paragAt( para ); + if ( !p ) + return FALSE; + if ( index < 0 || index >= p->length() ) + return FALSE; + *font = p->at( index )->format()->font(); + *color = p->at( index )->format()->color(); + *verticalAlignment = (VerticalAlignment)p->at( index )->format()->vAlign(); + return TRUE; +} + +/*! \internal + \warning In TQt 3.1 we will provide a cleaer API for the + functionality which is provided by this function and in TQt 4.0 this + function will go away. + + This function gets the format of the paragraph \a para. Sets \a + font to the paragraphs's font, \a color to the paragraph's color, \a + verticalAlignment to the paragraph's vertical alignment, \a + alignment to the paragraph's alignment, \a displayMode to the + paragraph's display mode, \a listStyle to the paragraph's list style + (if the display mode is TQStyleSheetItem::DisplayListItem) and \a + listDepth to the depth of the list (if the display mode is + TQStyleSheetItem::DisplayListItem). + + Returns FALSE if \a para is out of range otherwise returns TRUE. +*/ + +bool TQTextEdit::getParagraphFormat( int para, TQFont *font, TQColor *color, + VerticalAlignment *verticalAlignment, int *alignment, + TQStyleSheetItem::DisplayMode *displayMode, + TQStyleSheetItem::ListStyle *listStyle, + int *listDepth ) +{ + if ( !font || !color || !alignment || !displayMode || !listStyle ) + return FALSE; + TQTextParagraph *p = doc->paragAt( para ); + if ( !p ) + return FALSE; + *font = p->at(0)->format()->font(); + *color = p->at(0)->format()->color(); + *verticalAlignment = (VerticalAlignment)p->at(0)->format()->vAlign(); + *alignment = p->alignment(); + *displayMode = p->isListItem() ? TQStyleSheetItem::DisplayListItem : TQStyleSheetItem::DisplayBlock; + *listStyle = p->listStyle(); + *listDepth = p->listDepth(); + return TRUE; +} + + + +/*! + This function is called to create a right mouse button popup menu + at the document position \a pos. If you want to create a custom + popup menu, reimplement this function and return the created popup + menu. Ownership of the popup menu is transferred to the caller. + + \warning The TQPopupMenu ID values 0-7 are reserved, and they map to the + standard operations. When inserting items into your custom popup menu, be + sure to specify ID values larger than 7. +*/ + +TQPopupMenu *TQTextEdit::createPopupMenu( const TQPoint& pos ) +{ + Q_UNUSED( pos ) +#ifndef TQT_NO_POPUPMENU + TQPopupMenu *popup = new TQPopupMenu( this, "qt_edit_menu" ); + if ( !isReadOnly() ) { + d->id[ IdUndo ] = popup->insertItem( tr( "&Undo" ) + ACCEL_KEY( Z ) ); + d->id[ IdRedo ] = popup->insertItem( tr( "&Redo" ) + ACCEL_KEY( Y ) ); + popup->insertSeparator(); + } +#ifndef TQT_NO_CLIPBOARD + if ( !isReadOnly() ) + d->id[ IdCut ] = popup->insertItem( tr( "Cu&t" ) + ACCEL_KEY( X ) ); + d->id[ IdCopy ] = popup->insertItem( tr( "&Copy" ) + ACCEL_KEY( C ) ); + if ( !isReadOnly() ) + d->id[ IdPaste ] = popup->insertItem( tr( "&Paste" ) + ACCEL_KEY( V ) ); +#endif + if ( !isReadOnly() ) { + d->id[ IdClear ] = popup->insertItem( tr( "Clear" ) ); + popup->insertSeparator(); + } +#if defined(TQ_WS_X11) + d->id[ IdSelectAll ] = popup->insertItem( tr( "Select All" ) ); +#else + d->id[ IdSelectAll ] = popup->insertItem( tr( "Select All" ) + ACCEL_KEY( A ) ); +#endif + +#ifndef TQT_NO_IM + TQInputContext *qic = getInputContext(); + if ( qic ) + qic->addMenusTo( popup ); +#endif + + popup->setItemEnabled( d->id[ IdUndo ], !isReadOnly() && doc->commands()->isUndoAvailable() ); + popup->setItemEnabled( d->id[ IdRedo ], !isReadOnly() && doc->commands()->isRedoAvailable() ); +#ifndef TQT_NO_CLIPBOARD + popup->setItemEnabled( d->id[ IdCut ], !isReadOnly() && doc->hasSelection( TQTextDocument::Standard, TRUE ) ); +#ifdef QT_TEXTEDIT_OPTIMIZATION + popup->setItemEnabled( d->id[ IdCopy ], d->optimMode ? optimHasSelection() : doc->hasSelection( TQTextDocument::Standard, TRUE ) ); +#else + popup->setItemEnabled( d->id[ IdCopy ], doc->hasSelection( TQTextDocument::Standard, TRUE ) ); +#endif + popup->setItemEnabled( d->id[ IdPaste ], !isReadOnly() && !TQApplication::clipboard()->text( d->clipboard_mode ).isEmpty() ); +#endif + const bool isEmptyDocument = (length() == 0); + popup->setItemEnabled( d->id[ IdClear ], !isReadOnly() && !isEmptyDocument ); + popup->setItemEnabled( d->id[ IdSelectAll ], !isEmptyDocument ); + return popup; +#else + return 0; +#endif +} + +/*! \overload + \obsolete + This function is called to create a right mouse button popup menu. + If you want to create a custom popup menu, reimplement this function + and return the created popup menu. Ownership of the popup menu is + transferred to the caller. + + This function is only called if createPopupMenu( const TQPoint & ) + returns 0. +*/ + +TQPopupMenu *TQTextEdit::createPopupMenu() +{ + return 0; +} + +/*! + \reimp +*/ + +void TQTextEdit::setFont( const TQFont &f ) +{ +#ifdef QT_TEXTEDIT_OPTIMIZATION + if ( d->optimMode ) { + TQScrollView::setFont( f ); + doc->setDefaultFormat( f, doc->formatCollection()->defaultFormat()->color() ); + // recalculate the max string width + TQFontMetrics fm(f); + int i, sw; + d->od->maxLineWidth = 0; + for ( i = 0; i < d->od->numLines; i++ ) { + sw = fm.width(d->od->lines[LOGOFFSET(i)]); + if (d->od->maxLineWidth < sw) + d->od->maxLineWidth = sw; + } + resizeContents(d->od->maxLineWidth + 4, d->od->numLines * fm.lineSpacing() + 1); + return; + } +#endif + TQScrollView::setFont( f ); + doc->setMinimumWidth( -1 ); + doc->setDefaultFormat( f, doc->formatCollection()->defaultFormat()->color() ); + lastFormatted = doc->firstParagraph(); + formatMore(); + repaintChanged(); +} + +/*! + \fn TQTextEdit::zoomIn() + + \overload + + Zooms in on the text by making the base font size one point + larger and recalculating all font sizes to be the new size. This + does not change the size of any images. + + \sa zoomOut() +*/ + +/*! + \fn TQTextEdit::zoomOut() + + \overload + + Zooms out on the text by making the base font size one point + smaller and recalculating all font sizes to be the new size. This + does not change the size of any images. + + \sa zoomIn() +*/ + + +/*! + Zooms in on the text by making the base font size \a range + points larger and recalculating all font sizes to be the new size. + This does not change the size of any images. + + \sa zoomOut() +*/ + +void TQTextEdit::zoomIn( int range ) +{ + TQFont f( TQScrollView::font() ); + TQFontInfo fi(f); + if (fi.pointSize() <= 0) { + f.setPixelSize( fi.pixelSize() + range ); + } else { + f.setPointSize( fi.pointSize() + range ); + } + setFont( f ); +} + +/*! + Zooms out on the text by making the base font size \a range points + smaller and recalculating all font sizes to be the new size. This + does not change the size of any images. + + \sa zoomIn() +*/ + +void TQTextEdit::zoomOut( int range ) +{ + TQFont f( TQScrollView::font() ); + TQFontInfo fi(f); + if (fi.pointSize() <= 0) { + f.setPixelSize( TQMAX( 1, fi.pixelSize() - range ) ); + } else { + f.setPointSize( TQMAX( 1, fi.pointSize() - range ) ); + } + setFont( f ); +} + +/*! + Zooms the text by making the base font size \a size points and + recalculating all font sizes to be the new size. This does not + change the size of any images. +*/ + +void TQTextEdit::zoomTo( int size ) +{ + TQFont f( TQScrollView::font() ); + f.setPointSize( size ); + setFont( f ); +} + +/*! + TQTextEdit is optimized for large amounts text. One of its + optimizations is to format only the visible text, formatting the rest + on demand, e.g. as the user scrolls, so you don't usually need to + call this function. + + In some situations you may want to force the whole text + to be formatted. For example, if after calling setText(), you wanted + to know the height of the document (using contentsHeight()), you + would call this function first. +*/ + +void TQTextEdit::sync() +{ +#ifdef QT_TEXTEDIT_OPTIMIZATION + if ( d->optimMode ) { + TQFontMetrics fm( TQScrollView::font() ); + resizeContents( d->od->maxLineWidth + 4, d->od->numLines * fm.lineSpacing() + 1 ); + } else +#endif + { + while ( lastFormatted ) { + lastFormatted->format(); + lastFormatted = lastFormatted->next(); + } + resizeContents( contentsWidth(), doc->height() ); + } + updateScrollBars(); +} + +/*! + \reimp +*/ + +void TQTextEdit::setEnabled( bool b ) +{ + TQScrollView::setEnabled( b ); + if ( textFormat() == PlainText ) { + TQTextFormat *f = doc->formatCollection()->defaultFormat(); + f->setColor( colorGroup().text() ); + updateContents(); + } +} + +/*! + Sets the background color of selection number \a selNum to \a back + and specifies whether the text of this selection should be + inverted with \a invertText. + + This only works for \a selNum > 0. The default selection (\a + selNum == 0) gets its attributes from the text edit's + colorGroup(). +*/ + +void TQTextEdit::setSelectionAttributes( int selNum, const TQColor &back, bool invertText ) +{ + if ( selNum < 1 ) + return; + if ( selNum > doc->numSelections() ) + doc->addSelection( selNum ); + doc->setSelectionColor( selNum, back ); + doc->setInvertSelectionText( selNum, invertText ); +} + +/*! + \reimp +*/ +void TQTextEdit::windowActivationChange( bool oldActive ) +{ + if ( oldActive && scrollTimer ) + scrollTimer->stop(); + if ( palette().active() != palette().inactive() ) + updateContents(); + TQScrollView::windowActivationChange( oldActive ); +} + +void TQTextEdit::setReadOnly( bool b ) +{ + if ( (bool) readOnly == b ) + return; + readOnly = b; +#ifndef TQT_NO_CURSOR + if ( readOnly ) + viewport()->setCursor( arrowCursor ); + else + viewport()->setCursor( ibeamCursor ); + setInputMethodEnabled( !readOnly ); +#endif +#ifdef QT_TEXTEDIT_OPTIMIZATION + checkOptimMode(); +#endif +} + +/*! + Scrolls to the bottom of the document and does formatting if + required. +*/ + +void TQTextEdit::scrollToBottom() +{ + sync(); + setContentsPos( contentsX(), contentsHeight() - visibleHeight() ); +} + +/*! + Returns the rectangle of the paragraph \a para in contents + coordinates, or an invalid rectangle if \a para is out of range. +*/ + +TQRect TQTextEdit::paragraphRect( int para ) const +{ + TQTextEdit *that = (TQTextEdit *)this; + that->sync(); + TQTextParagraph *p = doc->paragAt( para ); + if ( !p ) + return TQRect( -1, -1, -1, -1 ); + return p->rect(); +} + +/*! + Returns the paragraph which is at position \a pos (in contents + coordinates). +*/ + +int TQTextEdit::paragraphAt( const TQPoint &pos ) const +{ +#ifdef QT_TEXTEDIT_OPTIMIZATION + if ( d->optimMode ) { + TQFontMetrics fm( TQScrollView::font() ); + int parag = pos.y() / fm.lineSpacing(); + if ( parag <= d->od->numLines ) + return parag; + else + return 0; + } +#endif + TQTextCursor c( doc ); + c.place( pos, doc->firstParagraph() ); + if ( c.paragraph() ) + return c.paragraph()->paragId(); + return -1; // should never happen.. +} + +/*! + Returns the index of the character (relative to its paragraph) at + position \a pos (in contents coordinates). If \a para is not 0, + \a *para is set to the character's paragraph. +*/ + +int TQTextEdit::charAt( const TQPoint &pos, int *para ) const +{ +#ifdef QT_TEXTEDIT_OPTIMIZATION + if ( d->optimMode ) { + int par = paragraphAt( pos ); + if ( para ) + *para = par; + return optimCharIndex( d->od->lines[ LOGOFFSET(par) ], pos.x() ); + } +#endif + TQTextCursor c( doc ); + c.place( pos, doc->firstParagraph() ); + if ( c.paragraph() ) { + if ( para ) + *para = c.paragraph()->paragId(); + return c.index(); + } + return -1; // should never happen.. +} + +/*! + Sets the background color of the paragraph \a para to \a bg. +*/ + +void TQTextEdit::setParagraphBackgroundColor( int para, const TQColor &bg ) +{ + TQTextParagraph *p = doc->paragAt( para ); + if ( !p ) + return; + p->setBackgroundColor( bg ); + repaintChanged(); +} + +/*! + Clears the background color of the paragraph \a para, so that the + default color is used again. +*/ + +void TQTextEdit::clearParagraphBackground( int para ) +{ + TQTextParagraph *p = doc->paragAt( para ); + if ( !p ) + return; + p->clearBackgroundColor(); + repaintChanged(); +} + +/*! + Returns the background color of the paragraph \a para or an + invalid color if \a para is out of range or the paragraph has no + background set +*/ + +TQColor TQTextEdit::paragraphBackgroundColor( int para ) const +{ + TQTextParagraph *p = doc->paragAt( para ); + if ( !p ) + return TQColor(); + TQColor *c = p->backgroundColor(); + if ( c ) + return *c; + return TQColor(); +} + +/*! + \property TQTextEdit::undoRedoEnabled + \brief whether undo/redo is enabled + + When changing this property, the undo/redo history is cleared. + + The default is TRUE. +*/ + +void TQTextEdit::setUndoRedoEnabled( bool b ) +{ + undoRedoInfo.clear(); + doc->commands()->clear(); + + undoEnabled = b; +} + +bool TQTextEdit::isUndoRedoEnabled() const +{ + return undoEnabled; +} + +/*! + Returns TRUE if undo is available; otherwise returns FALSE. +*/ + +bool TQTextEdit::isUndoAvailable() const +{ + return undoEnabled && (doc->commands()->isUndoAvailable() || undoRedoInfo.valid()); +} + +/*! + Returns TRUE if redo is available; otherwise returns FALSE. +*/ + +bool TQTextEdit::isRedoAvailable() const +{ + return undoEnabled && doc->commands()->isRedoAvailable(); +} + +void TQTextEdit::ensureFormatted( TQTextParagraph *p ) +{ + while ( !p->isValid() ) { + if ( !lastFormatted ) + return; + formatMore(); + } +} + +/*! \internal */ +void TQTextEdit::updateCursor( const TQPoint & pos ) +{ + if ( isReadOnly() && linksEnabled() ) { + TQTextCursor c = *cursor; + placeCursor( pos, &c, TRUE ); + +#ifndef TQT_NO_NETWORKPROTOCOL + bool insideParagRect = TRUE; + if (c.paragraph() == doc->lastParagraph() + && c.paragraph()->rect().y() + c.paragraph()->rect().height() < pos.y()) + insideParagRect = FALSE; + if (insideParagRect && c.paragraph() && c.paragraph()->at( c.index() ) && + c.paragraph()->at( c.index() )->isAnchor()) { + if (!c.paragraph()->at( c.index() )->anchorHref().isEmpty() + && c.index() < c.paragraph()->length() - 1 ) + onLink = c.paragraph()->at( c.index() )->anchorHref(); + else + onLink = TQString::null; + + if (!c.paragraph()->at( c.index() )->anchorName().isEmpty() + && c.index() < c.paragraph()->length() - 1 ) + d->onName = c.paragraph()->at( c.index() )->anchorName(); + else + d->onName = TQString::null; + + if (!c.paragraph()->at( c.index() )->anchorHref().isEmpty() ) { +#ifndef TQT_NO_CURSOR + viewport()->setCursor( onLink.isEmpty() ? arrowCursor : pointingHandCursor ); +#endif + TQUrl u( doc->context(), onLink, TRUE ); + emitHighlighted( u.toString( FALSE, FALSE ) ); + } + } else { +#ifndef TQT_NO_CURSOR + viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); +#endif + onLink = TQString::null; + emitHighlighted( TQString::null ); + } +#endif + } +} + +/*! + Places the cursor \a c at the character which is closest to position + \a pos (in contents coordinates). If \a c is 0, the default text + cursor is used. + + \sa setCursorPosition() +*/ +void TQTextEdit::placeCursor( const TQPoint &pos, TQTextCursor *c ) +{ + placeCursor( pos, c, FALSE ); +} + +/*! \internal */ +void TQTextEdit::clipboardChanged() +{ +#ifndef TQT_NO_CLIPBOARD + // don't listen to selection changes + disconnect( TQApplication::clipboard(), TQ_SIGNAL(selectionChanged()), this, 0); +#endif + selectAll(FALSE); +} + +/*! \property TQTextEdit::tabChangesFocus + \brief whether TAB changes focus or is accepted as input + + In some occasions text edits should not allow the user to input + tabulators or change indentation using the TAB key, as this breaks + the focus chain. The default is FALSE. + +*/ + +void TQTextEdit::setTabChangesFocus( bool b ) +{ + d->tabChangesFocus = b; +} + +bool TQTextEdit::tabChangesFocus() const +{ + return d->tabChangesFocus; +} + +#ifdef QT_TEXTEDIT_OPTIMIZATION +/* Implementation of optimized LogText mode follows */ + +static void tqSwap( int * a, int * b ) +{ + if ( !a || !b ) + return; + int tmp = *a; + *a = *b; + *b = tmp; +} + +/*! \internal */ +bool TQTextEdit::checkOptimMode() +{ + bool oldMode = d->optimMode; + if ( textFormat() == LogText ) { + setReadOnly( TRUE ); + d->optimMode = TRUE; + } else { + d->optimMode = FALSE; + } + + // when changing mode - try to keep selections and text + if ( oldMode != d->optimMode ) { + if ( d->optimMode ) { + d->od = new TQTextEditOptimPrivate; + connect( scrollTimer, TQ_SIGNAL( timeout() ), this, TQ_SLOT( optimDoAutoScroll() ) ); + disconnect( doc, TQ_SIGNAL( minimumWidthChanged(int) ), this, TQ_SLOT( documentWidthChanged(int) ) ); + disconnect( scrollTimer, TQ_SIGNAL( timeout() ), this, TQ_SLOT( autoScrollTimerDone() ) ); + disconnect( formatTimer, TQ_SIGNAL( timeout() ), this, TQ_SLOT( formatMore() ) ); + optimSetText( doc->originalText() ); + doc->clear(TRUE); + delete cursor; + cursor = new TQTextCursor( doc ); + } else { + disconnect( scrollTimer, TQ_SIGNAL( timeout() ), this, TQ_SLOT( optimDoAutoScroll() ) ); + connect( doc, TQ_SIGNAL( minimumWidthChanged(int) ), this, TQ_SLOT( documentWidthChanged(int) ) ); + connect( scrollTimer, TQ_SIGNAL( timeout() ), this, TQ_SLOT( autoScrollTimerDone() ) ); + connect( formatTimer, TQ_SIGNAL( timeout() ), this, TQ_SLOT( formatMore() ) ); + setText( optimText() ); + delete d->od; + d->od = 0; + } + } + return d->optimMode; +} + +/*! \internal */ +TQString TQTextEdit::optimText() const +{ + TQString str, tmp; + + if ( d->od->len == 0 ) + return str; + + // concatenate all strings + int i; + int offset; + TQMapConstIterator<int,TQTextEditOptimPrivate::Tag *> it; + TQTextEditOptimPrivate::Tag * ftag = 0; + for ( i = 0; i < d->od->numLines; i++ ) { + if ( d->od->lines[ LOGOFFSET(i) ].isEmpty() ) { // CR lines are empty + str += "\n"; + } else { + tmp = d->od->lines[ LOGOFFSET(i) ] + "\n"; + // inject the tags for this line + if ( (it = d->od->tagIndex.find( LOGOFFSET(i) )) != d->od->tagIndex.end() ) + ftag = it.data(); + offset = 0; + while ( ftag && ftag->line == i ) { + tmp.insert( ftag->index + offset, "<" + ftag->tag + ">" ); + offset += ftag->tag.length() + 2; // 2 -> the '<' and '>' chars + ftag = ftag->next; + } + str += tmp; + } + } + return str; +} + +/*! \internal */ +void TQTextEdit::optimSetText( const TQString &str ) +{ + optimRemoveSelection(); +// this is just too slow - but may have to go in due to compatibility reasons +// if ( str == optimText() ) +// return; + d->od->numLines = 0; + d->od->lines.clear(); + d->od->maxLineWidth = 0; + d->od->len = 0; + d->od->clearTags(); + TQFontMetrics fm( TQScrollView::font() ); + if ( !(str.isEmpty() || str.isNull() || d->maxLogLines == 0) ) { + TQStringList strl = TQStringList::split( '\n', str, TRUE ); + int lWidth = 0; + for ( TQStringList::Iterator it = strl.begin(); it != strl.end(); ++it ) { + optimParseTags( &*it ); + optimCheckLimit( *it ); + lWidth = fm.width( *it ); + if ( lWidth > d->od->maxLineWidth ) + d->od->maxLineWidth = lWidth; + } + } + resizeContents( d->od->maxLineWidth + 4, d->od->numLines * fm.lineSpacing() + 1 ); + repaintContents(); + emit textChanged(); +} + +/*! \internal + + Append \a tag to the tag list. +*/ +TQTextEditOptimPrivate::Tag * TQTextEdit::optimAppendTag( int index, const TQString & tag ) +{ + TQTextEditOptimPrivate::Tag * t = new TQTextEditOptimPrivate::Tag, * tmp; + + if ( d->od->tags == 0 ) + d->od->tags = t; + t->bold = t->italic = t->underline = FALSE; + t->line = d->od->numLines; + t->index = index; + t->tag = tag; + t->leftTag = 0; + t->parent = 0; + t->prev = d->od->lastTag; + if ( d->od->lastTag ) + d->od->lastTag->next = t; + t->next = 0; + d->od->lastTag = t; + tmp = d->od->tagIndex[ LOGOFFSET(t->line) ]; + if ( !tmp || (tmp && tmp->index > t->index) ) { + d->od->tagIndex.replace( LOGOFFSET(t->line), t ); + } + return t; +} + + /*! \internal + + Insert \a tag in the tag - according to line and index numbers +*/ + +TQTextEditOptimPrivate::Tag *TQTextEdit::optimInsertTag(int line, int index, const TQString &tag) +{ + TQTextEditOptimPrivate::Tag *t = new TQTextEditOptimPrivate::Tag, *tmp; + + if (d->od->tags == 0) + d->od->tags = t; + t->bold = t->italic = t->underline = FALSE; + t->line = line; + t->index = index; + t->tag = tag; + t->leftTag = 0; + t->parent = 0; + t->next = 0; + t->prev = 0; + + // find insertion pt. in tag struct. + TQMap<int,TQTextEditOptimPrivate::Tag *>::ConstIterator it; + if ((it = d->od->tagIndex.find(LOGOFFSET(line))) != d->od->tagIndex.end()) { + tmp = *it; + if (tmp->index >= index) { // the exisiting tag may be placed AFTER the one we want to insert + tmp = tmp->prev; + } else { + while (tmp && tmp->next && tmp->next->line == line && tmp->next->index <= index) + tmp = tmp->next; + } + } else { + tmp = d->od->tags; + while (tmp && tmp->next && tmp->next->line < line) + tmp = tmp->next; + if (tmp == d->od->tags) + tmp = 0; + } + + t->prev = tmp; + t->next = tmp ? tmp->next : 0; + if (t->next) + t->next->prev = t; + if (tmp) + tmp->next = t; + + tmp = d->od->tagIndex[LOGOFFSET(t->line)]; + if (!tmp || (tmp && tmp->index >= t->index)) { + d->od->tagIndex.replace(LOGOFFSET(t->line), t); + } + return t; +} + + +/*! \internal + + Find tags in \a line, remove them from \a line and put them in a + structure. + + A tag is delimited by '<' and '>'. The characters '<', '>' and '&' + are escaped by using '<', '>' and '&'. Left-tags marks + the starting point for formatting, while right-tags mark the ending + point. A right-tag is the same as a left-tag, but with a '/' + appearing before the tag keyword. E.g a valid left-tag: <b>, and + a valid right-tag: </b>. Tags can be nested, but they have to be + closed in the same order as they are opened. E.g: + <font color=red><font color=blue>blue</font>red</font> - is valid, while: + <font color=red><b>bold red</font> just bold</b> - is invalid since the font tag is + closed before the bold tag. Note that a tag does not have to be + closed: '<font color=blue>Lots of text - and then some..' is perfectly valid for + setting all text appearing after the tag to blue. A tag can be used + to change the color of a piece of text, or set one of the following + formatting attributes: bold, italic and underline. These attributes + are set using the <b>, <i> and <u> tags. Example of valid tags: + <font color=red>, </font>, <b>, <u>, <i>, </i>. + Example of valid text: + This is some <font color=red>red text</font>, while this is some <font color=green>green + text</font>. <font color=blue><font color=yellow>This is yellow</font>, while this is + blue.</font> + + Note that only the color attribute of the HTML font tag is supported. + + Limitations: + 1. A tag cannot span several lines. + 2. Very limited error checking - mismatching left/right-tags is the + only thing that is detected. + +*/ +void TQTextEdit::optimParseTags( TQString * line, int lineNo, int indexOffset ) +{ + int len = line->length(); + int i, startIndex = -1, endIndex = -1, escIndex = -1; + int state = 0; // 0 = outside tag, 1 = inside tag + bool tagOpen, tagClose; + int bold = 0, italic = 0, underline = 0; + TQString tagStr; + TQPtrStack<TQTextEditOptimPrivate::Tag> tagStack; + + for ( i = 0; i < len; i++ ) { + tagOpen = (*line)[i] == '<'; + tagClose = (*line)[i] == '>'; + + // handle '<' and '>' and '&' + if ( (*line)[i] == '&' ) { + escIndex = i; + continue; + } else if ( escIndex != -1 && (*line)[i] == ';' ) { + TQString esc = line->mid( escIndex, i - escIndex + 1 ); + TQString c; + if ( esc == "<" ) + c = '<'; + else if ( esc == ">" ) + c = '>'; + else if ( esc == "&" ) + c = '&'; + line->replace( escIndex, i - escIndex + 1, c ); + len = line->length(); + i -= i-escIndex; + escIndex = -1; + continue; + } + + if ( state == 0 && tagOpen ) { + state = 1; + startIndex = i; + continue; + } + if ( state == 1 && tagClose ) { + state = 0; + endIndex = i; + if ( !tagStr.isEmpty() ) { + TQTextEditOptimPrivate::Tag * tag, * cur, * tmp; + bool format = TRUE; + + if ( tagStr == "b" ) + bold++; + else if ( tagStr == "/b" ) + bold--; + else if ( tagStr == "i" ) + italic++; + else if ( tagStr == "/i" ) + italic--; + else if ( tagStr == "u" ) + underline++; + else if ( tagStr == "/u" ) + underline--; + else + format = FALSE; + if ( lineNo > -1 ) + tag = optimInsertTag( lineNo, startIndex + indexOffset, tagStr ); + else + tag = optimAppendTag( startIndex, tagStr ); + // everything that is not a b, u or i tag is considered + // to be a color tag. + tag->type = format ? TQTextEditOptimPrivate::Format + : TQTextEditOptimPrivate::Color; + if ( tagStr[0] == '/' ) { + // this is a right-tag - search for the left-tag + // and possible parent tag + cur = tag->prev; + if ( !cur ) { +#ifdef QT_CHECK_RANGE + tqWarning( "TQTextEdit::optimParseTags: no left-tag for '<%s>' in line %d.", tag->tag.ascii(), tag->line + 1 ); +#endif + return; // something is wrong - give up + } + while ( cur ) { + if ( cur->leftTag ) { // push right-tags encountered + tagStack.push( cur ); + } else { + tmp = tagStack.pop(); + if ( !tmp ) { + if ( (("/" + cur->tag) == tag->tag) || + (tag->tag == "/font" && cur->tag.left(4) == "font") ) { + // set up the left and parent of this tag + tag->leftTag = cur; + tmp = cur->prev; + if ( tmp && tmp->parent ) { + tag->parent = tmp->parent; + } else if ( tmp && !tmp->leftTag ) { + tag->parent = tmp; + } + break; + } else if ( !cur->leftTag ) { +#ifdef QT_CHECK_RANGE + tqWarning( "TQTextEdit::optimParseTags: mismatching %s-tag for '<%s>' in line %d.", cur->tag[0] == '/' ? "left" : "right", cur->tag.ascii(), cur->line + 1 ); +#endif + return; // something is amiss - give up + } + } + } + cur = cur->prev; + } + } else { + tag->bold = bold > 0; + tag->italic = italic > 0; + tag->underline = underline > 0; + tmp = tag->prev; + while ( tmp && tmp->leftTag ) { + tmp = tmp->leftTag->parent; + } + if ( tmp ) { + tag->bold |= tmp->bold; + tag->italic |= tmp->italic; + tag->underline |= tmp->underline; + } + } + } + if ( startIndex != -1 ) { + int l = (endIndex == -1) ? + line->length() - startIndex : endIndex - startIndex; + line->remove( startIndex, l+1 ); + len = line->length(); + i -= l+1; + } + tagStr = ""; + continue; + } + + if ( state == 1 ) { + tagStr += (*line)[i]; + } + } +} + +// calculate the width of a string in pixels inc. tabs +static int qStrWidth(const TQString& str, int tabWidth, const TQFontMetrics& fm) +{ + int tabs = str.contains('\t'); + + if (!tabs) + return fm.width(str); + + int newIdx = 0; + int lastIdx = 0; + int strWidth = 0; + int tn; + for (tn = 1; tn <= tabs; ++tn) { + newIdx = str.find('\t', newIdx); + strWidth += fm.width(str.mid(lastIdx, newIdx - lastIdx)); + if (strWidth >= tn * tabWidth) { + int u = tn; + while (strWidth >= u * tabWidth) + ++u; + strWidth = u * tabWidth; + } else { + strWidth = tn * tabWidth; + } + lastIdx = ++newIdx; + } + if ((int)str.length() > newIdx) + strWidth += fm.width(str.mid(newIdx)); + return strWidth; +} + +bool TQTextEdit::optimHasBoldMetrics(int line) +{ + TQTextEditOptimPrivate::Tag *t; + TQMapConstIterator<int,TQTextEditOptimPrivate::Tag *> it; + if ((it = d->od->tagIndex.find(line)) != d->od->tagIndex.end()) { + t = *it; + while (t && t->line == line) { + if (t->bold) + return TRUE; + t = t->next; + } + } else if ((t = optimPreviousLeftTag(line)) && t->bold) { + return TRUE; + } + return FALSE; +} + +/*! \internal + + Append \a str to the current text buffer. Parses each line to find + formatting tags. +*/ +void TQTextEdit::optimAppend( const TQString &str ) +{ + if ( str.isEmpty() || str.isNull() || d->maxLogLines == 0 ) + return; + + TQStringList strl = TQStringList::split( '\n', str, TRUE ); + TQStringList::Iterator it = strl.begin(); + + TQFontMetrics fm(TQScrollView::font()); + int lWidth = 0; + + for ( ; it != strl.end(); ++it ) { + optimParseTags( &*it ); + optimCheckLimit( *it ); + if (optimHasBoldMetrics(d->od->numLines-1)) { + TQFont fnt = TQScrollView::font(); + fnt.setBold(TRUE); + fm = TQFontMetrics(fnt); + } + lWidth = qStrWidth(*it, tabStopWidth(), fm) + 4; + if ( lWidth > d->od->maxLineWidth ) + d->od->maxLineWidth = lWidth; + } + bool scrollToEnd = contentsY() >= contentsHeight() - visibleHeight(); + resizeContents( d->od->maxLineWidth + 4, d->od->numLines * fm.lineSpacing() + 1 ); + if ( scrollToEnd ) { + updateScrollBars(); + ensureVisible( contentsX(), contentsHeight(), 0, 0 ); + } + // when a max log size is set, the text may not be redrawn because + // the size of the viewport may not have changed + if ( d->maxLogLines > -1 ) + viewport()->update(); + emit textChanged(); +} + + +static void qStripTags(TQString *line) +{ + int len = line->length(); + int i, startIndex = -1, endIndex = -1, escIndex = -1; + int state = 0; // 0 = outside tag, 1 = inside tag + bool tagOpen, tagClose; + + for ( i = 0; i < len; i++ ) { + tagOpen = (*line)[i] == '<'; + tagClose = (*line)[i] == '>'; + + // handle '<' and '>' and '&' + if ( (*line)[i] == '&' ) { + escIndex = i; + continue; + } else if ( escIndex != -1 && (*line)[i] == ';' ) { + TQString esc = line->mid( escIndex, i - escIndex + 1 ); + TQString c; + if ( esc == "<" ) + c = '<'; + else if ( esc == ">" ) + c = '>'; + else if ( esc == "&" ) + c = '&'; + line->replace( escIndex, i - escIndex + 1, c ); + len = line->length(); + i -= i-escIndex; + escIndex = -1; + continue; + } + + if ( state == 0 && tagOpen ) { + state = 1; + startIndex = i; + continue; + } + if ( state == 1 && tagClose ) { + state = 0; + endIndex = i; + if ( startIndex != -1 ) { + int l = (endIndex == -1) ? + line->length() - startIndex : endIndex - startIndex; + line->remove( startIndex, l+1 ); + len = line->length(); + i -= l+1; + } + continue; + } + } +} + +/*! \internal + + Inserts the text into \a line at index \a index. +*/ + +void TQTextEdit::optimInsert(const TQString& text, int line, int index) +{ + if (text.isEmpty() || d->maxLogLines == 0) + return; + if (line < 0) + line = 0; + if (line > d->od->numLines-1) + line = d->od->numLines-1; + if (index < 0) + index = 0; + if (index > (int) d->od->lines[line].length()) + index = d->od->lines[line].length(); + + TQStringList strl = TQStringList::split('\n', text, TRUE); + int numNewLines = (int)strl.count() - 1; + TQTextEditOptimPrivate::Tag *tag = 0; + TQMap<int,TQTextEditOptimPrivate::Tag *>::ConstIterator ii; + int x; + + if (numNewLines == 0) { + // Case 1. Fast single line case - just inject it! + TQString stripped = text; + qStripTags( &stripped ); + d->od->lines[LOGOFFSET(line)].insert(index, stripped); + // move the tag indices following the insertion pt. + if ((ii = d->od->tagIndex.find(LOGOFFSET(line))) != d->od->tagIndex.end()) { + tag = *ii; + while (tag && (LOGOFFSET(tag->line) == line && tag->index < index)) + tag = tag->next; + while (tag && (LOGOFFSET(tag->line) == line)) { + tag->index += stripped.length(); + tag = tag->next; + } + } + stripped = text; + optimParseTags(&stripped, line, index); + } else if (numNewLines > 0) { + // Case 2. We have at least 1 newline char - split at + // insertion pt. and make room for new lines - complex and slow! + TQString left = d->od->lines[LOGOFFSET(line)].left(index); + TQString right = d->od->lines[LOGOFFSET(line)].mid(index); + + // rearrange lines for insertion + for (x = d->od->numLines - 1; x > line; x--) + d->od->lines[x + numNewLines] = d->od->lines[x]; + d->od->numLines += numNewLines; + + // fix the tag index and the tag line/index numbers - this + // might take a while.. + for (x = line; x < d->od->numLines; x++) { + if ((ii = d->od->tagIndex.find(LOGOFFSET(line))) != d->od->tagIndex.end()) { + tag = ii.data(); + if (LOGOFFSET(tag->line) == line) + while (tag && (LOGOFFSET(tag->line) == line && tag->index < index)) + tag = tag->next; + } + } + + // relabel affected tags with new line numbers and new index + // positions + while (tag) { + if (LOGOFFSET(tag->line) == line) + tag->index -= index; + tag->line += numNewLines; + tag = tag->next; + } + + // generate a new tag index + d->od->tagIndex.clear(); + tag = d->od->tags; + while (tag) { + if (!((ii = d->od->tagIndex.find(LOGOFFSET(tag->line))) != d->od->tagIndex.end())) + d->od->tagIndex[LOGOFFSET(tag->line)] = tag; + tag = tag->next; + } + + // update the tag indices on the spliced line - needs to be done before new tags are added + TQString stripped = strl[strl.count() - 1]; + qStripTags(&stripped); + if ((ii = d->od->tagIndex.find(LOGOFFSET(line + numNewLines))) != d->od->tagIndex.end()) { + tag = *ii; + while (tag && (LOGOFFSET(tag->line) == line + numNewLines)) { + tag->index += stripped.length(); + tag = tag->next; + } + } + + // inject the new lines + TQStringList::Iterator it = strl.begin(); + x = line; + int idx; + for (; it != strl.end(); ++it) { + stripped = *it; + qStripTags(&stripped); + if (x == line) { + stripped = left + stripped; + idx = index; + } else { + idx = 0; + } + d->od->lines[LOGOFFSET(x)] = stripped; + optimParseTags(&*it, x++, idx); + } + d->od->lines[LOGOFFSET(x - 1)] += right; + } + // recalculate the pixel width of the longest injected line - + TQFontMetrics fm(TQScrollView::font()); + int lWidth = 0; + + for (x = line; x < line + numNewLines; x++) { + if (optimHasBoldMetrics(x)) { + TQFont fnt = TQScrollView::font(); + fnt.setBold(TRUE); + fm = TQFontMetrics(fnt); + } + lWidth = fm.width(d->od->lines[x]) + 4; + if (lWidth > d->od->maxLineWidth) + d->od->maxLineWidth = lWidth; + } + resizeContents(d->od->maxLineWidth + 4, d->od->numLines * fm.lineSpacing() + 1); + repaintContents(); + emit textChanged(); +} + + + +/*! \internal + + Returns the first open left-tag appearing before line \a line. + */ +TQTextEditOptimPrivate::Tag * TQTextEdit::optimPreviousLeftTag( int line ) +{ + TQTextEditOptimPrivate::Tag * ftag = 0; + TQMapConstIterator<int,TQTextEditOptimPrivate::Tag *> it; + if ( (it = d->od->tagIndex.find( LOGOFFSET(line) )) != d->od->tagIndex.end() ) + ftag = it.data(); + if ( !ftag ) { + // start searching for an open tag + ftag = d->od->tags; + while ( ftag ) { + if ( ftag->line > line || ftag->next == 0 ) { + if ( ftag->line > line ) + ftag = ftag->prev; + break; + } + ftag = ftag->next; + } + } else { + ftag = ftag->prev; + } + + if ( ftag ) { + if ( ftag && ftag->parent ) // use the open parent tag + ftag = ftag->parent; + else if ( ftag && ftag->leftTag ) // this is a right-tag with no parent + ftag = 0; + } + return ftag; +} + +/*! \internal + + Set the format for the string starting at index \a start and ending + at \a end according to \a tag. If \a tag is a Format tag, find the + first open color tag appearing before \a tag and use that tag to + color the string. +*/ +void TQTextEdit::optimSetTextFormat( TQTextDocument * td, TQTextCursor * cur, + TQTextFormat * f, int start, int end, + TQTextEditOptimPrivate::Tag * tag ) +{ + int formatFlags = TQTextFormat::Bold | TQTextFormat::Italic | + TQTextFormat::Underline; + cur->setIndex( start ); + td->setSelectionStart( 0, *cur ); + cur->setIndex( end ); + td->setSelectionEnd( 0, *cur ); + TQStyleSheetItem * ssItem = styleSheet()->item( tag->tag ); + if ( !ssItem || tag->type == TQTextEditOptimPrivate::Format ) { + f->setBold( tag->bold ); + f->setItalic( tag->italic ); + f->setUnderline( tag->underline ); + if ( tag->type == TQTextEditOptimPrivate::Format ) { + // check to see if there are any open color tags prior to + // this format tag + tag = tag->prev; + while ( tag && (tag->type == TQTextEditOptimPrivate::Format || + tag->leftTag) ) { + tag = tag->leftTag ? tag->parent : tag->prev; + } + } + if ( tag ) { + TQString col = tag->tag.simplifyWhiteSpace(); + if ( col.left( 10 ) == "font color" ) { + int i = col.find( '=', 10 ); + col = col.mid( i + 1 ).simplifyWhiteSpace(); + if ( col[0] == '\"' ) + col = col.mid( 1, col.length() - 2 ); + } + TQColor color = TQColor( col ); + if ( color.isValid() ) { + formatFlags |= TQTextFormat::Color; + f->setColor( color ); + } + } + } else { // use the stylesheet tag definition + if ( ssItem->color().isValid() ) { + formatFlags |= TQTextFormat::Color; + f->setColor( ssItem->color() ); + } + f->setBold( ssItem->fontWeight() == TQFont::Bold ); + f->setItalic( ssItem->fontItalic() ); + f->setUnderline( ssItem->fontUnderline() ); + } + td->setFormat( 0, f, formatFlags ); + td->removeSelection( 0 ); +} + +/*! \internal */ +void TQTextEdit::optimDrawContents( TQPainter * p, int clipx, int clipy, + int clipw, int cliph ) +{ + TQFontMetrics fm( TQScrollView::font() ); + int startLine = clipy / fm.lineSpacing(); + + // we always have to fetch at least two lines for drawing because the + // painter may be translated so that parts of two lines cover the area + // of a single line + int nLines = (cliph / fm.lineSpacing()) + 2; + int endLine = startLine + nLines; + + if ( startLine >= d->od->numLines ) + return; + if ( (startLine + nLines) > d->od->numLines ) + nLines = d->od->numLines - startLine; + + int i = 0; + TQString str; + for ( i = startLine; i < (startLine + nLines); i++ ) + str.append( d->od->lines[ LOGOFFSET(i) ] + "\n" ); + + TQTextDocument * td = new TQTextDocument( 0 ); + td->setDefaultFormat( TQScrollView::font(), TQColor() ); + td->setPlainText( str ); + td->setFormatter( new TQTextFormatterBreakWords ); // deleted by TQTextDoc + td->formatter()->setWrapEnabled( FALSE ); + td->setTabStops(doc->tabStopWidth()); + + // get the current text color from the current format + td->selectAll( TQTextDocument::Standard ); + TQTextFormat f; + f.setColor( colorGroup().text() ); + f.setFont( TQScrollView::font() ); + td->setFormat( TQTextDocument::Standard, &f, + TQTextFormat::Color | TQTextFormat::Font ); + td->removeSelection( TQTextDocument::Standard ); + + // add tag formatting + if ( d->od->tags ) { + int i = startLine; + TQMapConstIterator<int,TQTextEditOptimPrivate::Tag *> it; + TQTextEditOptimPrivate::Tag * tag = 0, * tmp = 0; + TQTextCursor cur( td ); + // Step 1 - find previous left-tag + tmp = optimPreviousLeftTag( i ); + for ( ; i < startLine + nLines; i++ ) { + if ( (it = d->od->tagIndex.find( LOGOFFSET(i) )) != d->od->tagIndex.end() ) + tag = it.data(); + // Step 2 - iterate over tags on the current line + int lastIndex = 0; + while ( tag && tag->line == i ) { + tmp = 0; + if ( tag->prev && !tag->prev->leftTag ) { + tmp = tag->prev; + } else if ( tag->prev && tag->prev->parent ) { + tmp = tag->prev->parent; + } + if ( (tag->index - lastIndex) > 0 && tmp ) { + optimSetTextFormat( td, &cur, &f, lastIndex, tag->index, tmp ); + } + lastIndex = tag->index; + tmp = tag; + tag = tag->next; + } + // Step 3 - color last part of the line - if necessary + if ( tmp && tmp->parent ) + tmp = tmp->parent; + if ( (cur.paragraph()->length()-1 - lastIndex) > 0 && tmp && !tmp->leftTag ) { + optimSetTextFormat( td, &cur, &f, lastIndex, + cur.paragraph()->length() - 1, tmp ); + } + cur.setParagraph( cur.paragraph()->next() ); + } + // useful debug info + // +// tag = d->od->tags; +// tqWarning("###"); +// while ( tag ) { +// tqWarning( "Tag: %p, parent: %09p, leftTag: %09p, Name: %-15s, ParentName: %s, %d%d%d", tag, +// tag->parent, tag->leftTag, tag->tag.latin1(), tag->parent ? tag->parent->tag.latin1():"<none>", +// tag->bold, tag->italic, tag->underline ); +// tag = tag->next; +// } + } + + // if there is a selection, make sure that the selection in the + // part we need to redraw is set correctly + if ( optimHasSelection() ) { + TQTextCursor c1( td ); + TQTextCursor c2( td ); + int selStart = d->od->selStart.line; + int idxStart = d->od->selStart.index; + int selEnd = d->od->selEnd.line; + int idxEnd = d->od->selEnd.index; + if ( selEnd < selStart ) { + tqSwap( &selStart, &selEnd ); + tqSwap( &idxStart, &idxEnd ); + } + if ( selEnd > d->od->numLines-1 ) { + selEnd = d->od->numLines-1; + } + if ( startLine <= selStart && endLine >= selEnd ) { + // case 1: area to paint covers entire selection + int paragS = selStart - startLine; + int paragE = paragS + (selEnd - selStart); + TQTextParagraph * parag = td->paragAt( paragS ); + if ( parag ) { + c1.setParagraph( parag ); + if ( td->text( paragS ).length() >= (uint) idxStart ) + c1.setIndex( idxStart ); + } + parag = td->paragAt( paragE ); + if ( parag ) { + c2.setParagraph( parag ); + if ( td->text( paragE ).length() >= (uint) idxEnd ) + c2.setIndex( idxEnd ); + } + } else if ( startLine > selStart && endLine < selEnd ) { + // case 2: area to paint is all part of the selection + td->selectAll( TQTextDocument::Standard ); + } else if ( startLine > selStart && endLine >= selEnd && + startLine <= selEnd ) { + // case 3: area to paint starts inside a selection, ends past it + c1.setParagraph( td->firstParagraph() ); + c1.setIndex( 0 ); + int paragE = selEnd - startLine; + TQTextParagraph * parag = td->paragAt( paragE ); + if ( parag ) { + c2.setParagraph( parag ); + if ( td->text( paragE ).length() >= (uint) idxEnd ) + c2.setIndex( idxEnd ); + } + } else if ( startLine <= selStart && endLine < selEnd && + endLine > selStart ) { + // case 4: area to paint starts before a selection, ends inside it + int paragS = selStart - startLine; + TQTextParagraph * parag = td->paragAt( paragS ); + if ( parag ) { + c1.setParagraph( parag ); + c1.setIndex( idxStart ); + } + c2.setParagraph( td->lastParagraph() ); + c2.setIndex( td->lastParagraph()->string()->toString().length() - 1 ); + + } + // previously selected? + if ( !td->hasSelection( TQTextDocument::Standard ) ) { + td->setSelectionStart( TQTextDocument::Standard, c1 ); + td->setSelectionEnd( TQTextDocument::Standard, c2 ); + } + } + td->doLayout( p, contentsWidth() ); + + // have to align the painter so that partly visible lines are + // drawn at the correct position within the area that needs to be + // painted + int offset = clipy % fm.lineSpacing() + 2; + TQRect r( clipx, 0, clipw, cliph + offset ); + p->translate( 0, clipy - offset ); + td->draw( p, r.x(), r.y(), r.width(), r.height(), colorGroup() ); + p->translate( 0, -(clipy - offset) ); + delete td; +} + +/*! \internal */ +void TQTextEdit::optimMousePressEvent( TQMouseEvent * e ) +{ + if ( e->button() != LeftButton ) + return; + + TQFontMetrics fm( TQScrollView::font() ); + mousePressed = TRUE; + mousePos = e->pos(); + d->od->selStart.line = e->y() / fm.lineSpacing(); + if ( d->od->selStart.line > d->od->numLines-1 ) { + d->od->selStart.line = d->od->numLines-1; + d->od->selStart.index = d->od->lines[ LOGOFFSET(d->od->numLines-1) ].length(); + } else { + TQString str = d->od->lines[ LOGOFFSET(d->od->selStart.line) ]; + d->od->selStart.index = optimCharIndex( str, mousePos.x() ); + } + d->od->selEnd.line = d->od->selStart.line; + d->od->selEnd.index = d->od->selStart.index; + oldMousePos = e->pos(); + repaintContents( FALSE ); +} + +/*! \internal */ +void TQTextEdit::optimMouseReleaseEvent( TQMouseEvent * e ) +{ + if ( e->button() != LeftButton ) + return; + + if ( scrollTimer->isActive() ) + scrollTimer->stop(); + if ( !inDoubleClick ) { + TQFontMetrics fm( TQScrollView::font() ); + d->od->selEnd.line = e->y() / fm.lineSpacing(); + if ( d->od->selEnd.line > d->od->numLines-1 ) { + d->od->selEnd.line = d->od->numLines-1; + } + TQString str = d->od->lines[ LOGOFFSET(d->od->selEnd.line) ]; + mousePos = e->pos(); + d->od->selEnd.index = optimCharIndex( str, mousePos.x() ); + if ( d->od->selEnd.line < d->od->selStart.line ) { + tqSwap( &d->od->selStart.line, &d->od->selEnd.line ); + tqSwap( &d->od->selStart.index, &d->od->selEnd.index ); + } else if ( d->od->selStart.line == d->od->selEnd.line && + d->od->selStart.index > d->od->selEnd.index ) { + tqSwap( &d->od->selStart.index, &d->od->selEnd.index ); + } + oldMousePos = e->pos(); + repaintContents( FALSE ); + } + if ( mousePressed ) { + mousePressed = FALSE; + copyToClipboard(); + } + + inDoubleClick = FALSE; + emit copyAvailable( optimHasSelection() ); + emit selectionChanged(); +} + +/*! \internal */ +void TQTextEdit::optimMouseMoveEvent( TQMouseEvent * e ) +{ + mousePos = e->pos(); + optimDoAutoScroll(); + oldMousePos = mousePos; +} + +/*! \internal */ +void TQTextEdit::optimDoAutoScroll() +{ + if ( !mousePressed ) + return; + + TQFontMetrics fm( TQScrollView::font() ); + TQPoint pos( mapFromGlobal( TQCursor::pos() ) ); + bool doScroll = FALSE; + int xx = contentsX() + pos.x(); + int yy = contentsY() + pos.y(); + + // find out how much we have to scroll in either dir. + if ( pos.x() < 0 || pos.x() > viewport()->width() || + pos.y() < 0 || pos.y() > viewport()->height() ) { + int my = yy; + if ( pos.x() < 0 ) + xx = contentsX() - fm.width( 'w'); + else if ( pos.x() > viewport()->width() ) + xx = contentsX() + viewport()->width() + fm.width('w'); + + if ( pos.y() < 0 ) { + my = contentsY() - 1; + yy = (my / fm.lineSpacing()) * fm.lineSpacing() + 1; + } else if ( pos.y() > viewport()->height() ) { + my = contentsY() + viewport()->height() + 1; + yy = (my / fm.lineSpacing() + 1) * fm.lineSpacing() - 1; + } + d->od->selEnd.line = my / fm.lineSpacing(); + mousePos.setX( xx ); + mousePos.setY( my ); + doScroll = TRUE; + } else { + d->od->selEnd.line = mousePos.y() / fm.lineSpacing(); + } + + if ( d->od->selEnd.line < 0 ) { + d->od->selEnd.line = 0; + } else if ( d->od->selEnd.line > d->od->numLines-1 ) { + d->od->selEnd.line = d->od->numLines-1; + } + + TQString str = d->od->lines[ LOGOFFSET(d->od->selEnd.line) ]; + d->od->selEnd.index = optimCharIndex( str, mousePos.x() ); + + // have to have a valid index before generating a paint event + if ( doScroll ) + ensureVisible( xx, yy, 1, 1 ); + + // if the text document is smaller than the height of the viewport + // - redraw the whole thing otherwise calculate the rect that + // needs drawing. + if ( d->od->numLines * fm.lineSpacing() < viewport()->height() ) { + repaintContents( contentsX(), contentsY(), width(), height(), FALSE ); + } else { + int h = TQABS(mousePos.y() - oldMousePos.y()) + fm.lineSpacing() * 2; + int y; + if ( oldMousePos.y() < mousePos.y() ) { + y = oldMousePos.y() - fm.lineSpacing(); + } else { + // expand paint area for a fully selected line + h += fm.lineSpacing(); + y = mousePos.y() - fm.lineSpacing()*2; + } + if ( y < 0 ) + y = 0; + repaintContents( contentsX(), y, width(), h, FALSE ); + } + + if ( (!scrollTimer->isActive() && pos.y() < 0) || pos.y() > height() ) + scrollTimer->start( 100, FALSE ); + else if ( scrollTimer->isActive() && pos.y() >= 0 && pos.y() <= height() ) + scrollTimer->stop(); +} + +/*! \internal + + Returns the index of the character in the string \a str that is + currently under the mouse pointer. +*/ +int TQTextEdit::optimCharIndex( const TQString &str, int mx ) const +{ + TQFontMetrics fm(TQScrollView::font()); + uint i = 0; + int dd, dist = 10000000; + int curpos = 0; + int strWidth; + mx = mx - 4; // ### get the real margin from somewhere + + if (!str.contains('\t') && mx > fm.width(str)) + return str.length(); + + while (i < str.length()) { + strWidth = qStrWidth(str.left(i), tabStopWidth(), fm); + dd = strWidth - mx; + if (TQABS(dd) <= dist) { + dist = TQABS(dd); + if (mx >= strWidth) + curpos = i; + } + ++i; + } + return curpos; +} + +/*! \internal */ +void TQTextEdit::optimSelectAll() +{ + d->od->selStart.line = d->od->selStart.index = 0; + d->od->selEnd.line = d->od->numLines - 1; + d->od->selEnd.index = d->od->lines[ LOGOFFSET(d->od->selEnd.line) ].length(); + + repaintContents( FALSE ); + emit copyAvailable( optimHasSelection() ); + emit selectionChanged(); +} + +/*! \internal */ +void TQTextEdit::optimRemoveSelection() +{ + d->od->selStart.line = d->od->selEnd.line = -1; + d->od->selStart.index = d->od->selEnd.index = -1; + repaintContents( FALSE ); +} + +/*! \internal */ +void TQTextEdit::optimSetSelection( int startLine, int startIdx, + int endLine, int endIdx ) +{ + d->od->selStart.line = startLine; + d->od->selEnd.line = endLine; + d->od->selStart.index = startIdx; + d->od->selEnd.index = endIdx; +} + +/*! \internal */ +bool TQTextEdit::optimHasSelection() const +{ + if ( d->od->selStart.line != d->od->selEnd.line || + d->od->selStart.index != d->od->selEnd.index ) + return TRUE; + return FALSE; +} + +/*! \internal */ +TQString TQTextEdit::optimSelectedText() const +{ + TQString str; + + if ( !optimHasSelection() ) + return str; + + // concatenate all strings + if ( d->od->selStart.line == d->od->selEnd.line ) { + str = d->od->lines[ LOGOFFSET(d->od->selEnd.line) ].mid( d->od->selStart.index, + d->od->selEnd.index - d->od->selStart.index ); + } else { + int i = d->od->selStart.line; + str = d->od->lines[ LOGOFFSET(i) ].right( d->od->lines[ LOGOFFSET(i) ].length() - + d->od->selStart.index ) + "\n"; + i++; + for ( ; i < d->od->selEnd.line; i++ ) { + if ( d->od->lines[ LOGOFFSET(i) ].isEmpty() ) // CR lines are empty + str += "\n"; + else + str += d->od->lines[ LOGOFFSET(i) ] + "\n"; + } + str += d->od->lines[ LOGOFFSET(d->od->selEnd.line) ].left( d->od->selEnd.index ); + } + return str; +} + +/*! \internal */ +bool TQTextEdit::optimFind( const TQString & expr, bool cs, bool /*wo*/, + bool fw, int * para, int * index ) +{ + bool found = FALSE; + int parag = para ? *para : d->od->search.line, + idx = index ? *index : d->od->search.index, i; + + if ( d->od->len == 0 ) + return FALSE; + + for ( i = parag; fw ? i < d->od->numLines : i >= 0; fw ? i++ : i-- ) { + idx = fw ? d->od->lines[ LOGOFFSET(i) ].find( expr, idx, cs ) : + d->od->lines[ LOGOFFSET(i) ].findRev( expr, idx, cs ); + if ( idx != -1 ) { + found = TRUE; + break; + } else if ( fw ) + idx = 0; + } + + if ( found ) { + if ( index ) + *index = idx; + if ( para ) + *para = i; + d->od->search.index = idx + 1; + d->od->search.line = i; + optimSetSelection( i, idx, i, idx + expr.length() ); + TQFontMetrics fm( TQScrollView::font() ); + int h = fm.lineSpacing(); + int x = fm.width( d->od->lines[ LOGOFFSET(i) ].left( idx + expr.length()) ) + 4; + ensureVisible( x, i * h + h / 2, 1, h / 2 + 2 ); + repaintContents(); // could possibly be optimized + } + return found; +} + +/*! \reimp */ +void TQTextEdit::polish() +{ + // this will ensure that the last line is visible if text have + // been added to the widget before it is shown + if ( d->optimMode ) + scrollToBottom(); + TQWidget::polish(); +} + +/*! + Sets the maximum number of lines a TQTextEdit can hold in \c + LogText mode to \a limit. If \a limit is -1 (the default), this + signifies an unlimited number of lines. + + \warning Never use formatting tags that span more than one line + when the maximum log lines is set. When lines are removed from the + top of the buffer it could result in an unbalanced tag pair, i.e. + the left formatting tag is removed before the right one. + */ +void TQTextEdit::setMaxLogLines( int limit ) +{ + d->maxLogLines = limit; + if ( d->maxLogLines < -1 ) + d->maxLogLines = -1; + if ( d->maxLogLines == -1 ) + d->logOffset = 0; +} + +/*! + Returns the maximum number of lines TQTextEdit can hold in \c + LogText mode. By default the number of lines is unlimited, which + is signified by a value of -1. + */ +int TQTextEdit::maxLogLines() +{ + return d->maxLogLines; +} + +/*! + Check if the number of lines in the buffer is limited, and uphold + that limit when appending new lines. + */ +void TQTextEdit::optimCheckLimit( const TQString& str ) +{ + if ( d->maxLogLines > -1 && d->maxLogLines <= d->od->numLines ) { + // NB! Removing the top line in the buffer will potentially + // destroy the structure holding the formatting tags - if line + // spanning tags are used. + TQTextEditOptimPrivate::Tag *t = d->od->tags, *tmp, *itr; + TQPtrList<TQTextEditOptimPrivate::Tag> lst; + while ( t ) { + t->line -= 1; + // unhook the ptr from the tag structure + if ( ((uint) LOGOFFSET(t->line) < (uint) d->logOffset && + (uint) LOGOFFSET(t->line) < (uint) LOGOFFSET(d->od->numLines) && + (uint) LOGOFFSET(d->od->numLines) > (uint) d->logOffset) ) + { + if ( t->prev ) + t->prev->next = t->next; + if ( t->next ) + t->next->prev = t->prev; + if ( d->od->tags == t ) + d->od->tags = t->next; + if ( d->od->lastTag == t ) { + if ( t->prev ) + d->od->lastTag = t->prev; + else + d->od->lastTag = d->od->tags; + } + tmp = t; + t = t->next; + lst.append( tmp ); + delete tmp; + } else { + t = t->next; + } + } + // Remove all references to the ptrs we just deleted + itr = d->od->tags; + while ( itr ){ + for ( tmp = lst.first(); tmp; tmp = lst.next() ) { + if ( itr->parent == tmp ) + itr->parent = 0; + if ( itr->leftTag == tmp ) + itr->leftTag = 0; + } + itr = itr->next; + } + // ...in the tag index as well + TQMapIterator<int, TQTextEditOptimPrivate::Tag *> idx; + if ( (idx = d->od->tagIndex.find( d->logOffset )) != d->od->tagIndex.end() ) + d->od->tagIndex.remove( idx ); + + TQMapIterator<int,TQString> it; + if ( (it = d->od->lines.find( d->logOffset )) != d->od->lines.end() ) { + d->od->len -= (*it).length(); + d->od->lines.remove( it ); + d->od->numLines--; + d->logOffset = LOGOFFSET(1); + } + } + d->od->len += str.length(); + d->od->lines[ LOGOFFSET(d->od->numLines++) ] = str; +} + +#endif // QT_TEXTEDIT_OPTIMIZATION + +/*! + \property TQTextEdit::autoFormatting + \brief the enabled set of auto formatting features + + The value can be any combination of the values in the \c + AutoFormatting enum. The default is \c AutoAll. Choose \c AutoNone + to disable all automatic formatting. + + Currently, the only automatic formatting feature provided is \c + AutoBulletList; future versions of TQt may offer more. +*/ + +void TQTextEdit::setAutoFormatting( uint features ) +{ + d->autoFormatting = features; +} + +uint TQTextEdit::autoFormatting() const +{ + return d->autoFormatting; +} + +/*! + Returns the TQSyntaxHighlighter set on this TQTextEdit. 0 is + returned if no syntax highlighter is set. + */ +TQSyntaxHighlighter * TQTextEdit::syntaxHighlighter() const +{ + if (document()->preProcessor()) + return ((TQSyntaxHighlighterInternal *) document()->preProcessor())->highlighter; + else + return 0; +} + +#endif //TQT_NO_TEXTEDIT diff --git a/src/widgets/tqtextedit.h b/src/widgets/tqtextedit.h new file mode 100644 index 000000000..40906dbfc --- /dev/null +++ b/src/widgets/tqtextedit.h @@ -0,0 +1,613 @@ +/**************************************************************************** +** +** Definition of the TQTextEdit class +** +** Created : 990101 +** +** Copyright (C) 1992-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 TQTEXTEDIT_H +#define TQTEXTEDIT_H + +#ifndef QT_H +#include "ntqscrollview.h" +#include "ntqstylesheet.h" +#include "tqptrvector.h" +#include "tqvaluelist.h" +#include "tqptrlist.h" +#endif // QT_H + +#ifndef TQT_NO_TEXTEDIT +// uncomment below to enable optimization mode - also uncomment the +// optimDoAutoScroll() private slot since moc ignores #ifdefs.. +#define QT_TEXTEDIT_OPTIMIZATION + +class TQPainter; +class TQTextDocument; +class TQTextCursor; +class TQKeyEvent; +class TQResizeEvent; +class TQMouseEvent; +class TQTimer; +class TQTextString; +class TQTextCommand; +class TQTextParagraph; +class TQTextFormat; +class TQFont; +class TQColor; +class TQTextEdit; +class TQTextBrowser; +class TQTextString; +struct TQUndoRedoInfoPrivate; +class TQPopupMenu; +class TQTextEditPrivate; +class TQSyntaxHighlighter; + +#ifdef QT_TEXTEDIT_OPTIMIZATION +class TQTextEditOptimPrivate +{ +public: + // Note: no left-tag has any value for leftTag or parent, and + // no right-tag has any formatting flags set. + enum TagType { Color = 0, Format = 1 }; + struct Tag { + TagType type:2; + bool bold:1; + bool italic:1; + bool underline:1; + int line; + int index; + Tag * leftTag; // ptr to left-tag in a left-right tag pair + Tag * parent; // ptr to parent left-tag in a nested tag + Tag * prev; + Tag * next; + TQString tag; + }; + TQTextEditOptimPrivate() + { + len = numLines = maxLineWidth = 0; + selStart.line = selStart.index = -1; + selEnd.line = selEnd.index = -1; + search.line = search.index = 0; + tags = lastTag = 0; + } + void clearTags() + { + Tag * itr = tags; + while ( tags ) { + itr = tags; + tags = tags->next; + delete itr; + } + tags = lastTag = 0; + tagIndex.clear(); + } + ~TQTextEditOptimPrivate() + { + clearTags(); + } + int len; + int numLines; + int maxLineWidth; + struct Selection { + int line; + int index; + }; + Selection selStart, selEnd, search; + Tag * tags, * lastTag; + TQMap<int, TQString> lines; + TQMap<int, Tag *> tagIndex; +}; +#endif + +class TQ_EXPORT TQTextEdit : public TQScrollView +{ + friend class TQTextBrowser; + friend class TQSyntaxHighlighter; + + TQ_OBJECT + TQ_ENUMS( WordWrap WrapPolicy ) + TQ_SETS( AutoFormatting ) + TQ_PROPERTY( TextFormat textFormat READ textFormat WRITE setTextFormat ) + TQ_PROPERTY( TQString text READ text WRITE setText ) + TQ_PROPERTY( TQBrush paper READ paper WRITE setPaper ) + TQ_PROPERTY( bool linkUnderline READ linkUnderline WRITE setLinkUnderline ) + TQ_PROPERTY( TQString documentTitle READ documentTitle ) + TQ_PROPERTY( int length READ length ) + TQ_PROPERTY( WordWrap wordWrap READ wordWrap WRITE setWordWrap ) + TQ_PROPERTY( int wrapColumnOrWidth READ wrapColumnOrWidth WRITE setWrapColumnOrWidth ) + TQ_PROPERTY( WrapPolicy wrapPolicy READ wrapPolicy WRITE setWrapPolicy ) + TQ_PROPERTY( bool hasSelectedText READ hasSelectedText ) + TQ_PROPERTY( TQString selectedText READ selectedText ) + TQ_PROPERTY( int undoDepth READ undoDepth WRITE setUndoDepth ) + TQ_PROPERTY( bool overwriteMode READ isOverwriteMode WRITE setOverwriteMode ) + TQ_PROPERTY( bool modified READ isModified WRITE setModified DESIGNABLE false ) + TQ_PROPERTY( bool readOnly READ isReadOnly WRITE setReadOnly ) + TQ_PROPERTY( bool undoRedoEnabled READ isUndoRedoEnabled WRITE setUndoRedoEnabled ) + TQ_PROPERTY( int tabStopWidth READ tabStopWidth WRITE setTabStopWidth ) + TQ_PROPERTY( bool tabChangesFocus READ tabChangesFocus WRITE setTabChangesFocus ) + TQ_PROPERTY( AutoFormatting autoFormatting READ autoFormatting WRITE setAutoFormatting ) + +public: + enum WordWrap { + NoWrap, + WidgetWidth, + FixedPixelWidth, + FixedColumnWidth + }; + + enum WrapPolicy { + AtWordBoundary, + AtWhiteSpace = AtWordBoundary, // AtWhiteSpace is deprecated + Anywhere, + AtWordOrDocumentBoundary + }; + + enum AutoFormatting { + AutoNone = 0, + AutoBulletList = 0x00000001, + AutoAll = 0xffffffff + }; + + enum KeyboardAction { + ActionBackspace, + ActionDelete, + ActionReturn, + ActionKill, + ActionWordBackspace, + ActionWordDelete + }; + + enum CursorAction { + MoveBackward, + MoveForward, + MoveWordBackward, + MoveWordForward, + MoveUp, + MoveDown, + MoveLineStart, + MoveLineEnd, + MoveHome, + MoveEnd, + MovePgUp, + MovePgDown + }; + + enum VerticalAlignment { + AlignNormal, + AlignSuperScript, + AlignSubScript + }; + + enum TextInsertionFlags { + RedoIndentation = 0x0001, + CheckNewLines = 0x0002, + RemoveSelected = 0x0004, + AsIMCompositionText = 0x0008, // internal use + WithIMSelection = 0x0010 // internal use + }; + + TQTextEdit( const TQString& text, const TQString& context = TQString::null, + TQWidget* parent=0, const char* name=0); + TQTextEdit( TQWidget* parent=0, const char* name=0 ); + virtual ~TQTextEdit(); + void setPalette( const TQPalette & ); + + TQString text() const; + TQString text( int para ) const; + TextFormat textFormat() const; + TQString context() const; + TQString documentTitle() const; + + void getSelection( int *paraFrom, int *indexFrom, + int *paraTo, int *indexTo, int selNum = 0 ) const; + virtual bool find( const TQString &expr, bool cs, bool wo, bool forward = TRUE, + int *para = 0, int *index = 0 ); + + int paragraphs() const; + int lines() const; + int linesOfParagraph( int para ) const; + int lineOfChar( int para, int chr ); + int length() const; + TQRect paragraphRect( int para ) const; + int paragraphAt( const TQPoint &pos ) const; + int charAt( const TQPoint &pos, int *para ) const; + int paragraphLength( int para ) const; + + TQStyleSheet* styleSheet() const; +#ifndef TQT_NO_MIME + TQMimeSourceFactory* mimeSourceFactory() const; +#endif + TQBrush paper() const; + bool linkUnderline() const; + + int heightForWidth( int w ) const; + + bool hasSelectedText() const; + TQString selectedText() const; + bool isUndoAvailable() const; + bool isRedoAvailable() const; + + WordWrap wordWrap() const; + int wrapColumnOrWidth() const; + WrapPolicy wrapPolicy() const; + + int tabStopWidth() const; + + TQString anchorAt( const TQPoint& pos ); + TQString anchorAt( const TQPoint& pos, AnchorAttribute a ); + + TQSize sizeHint() const; + + bool isReadOnly() const { return readOnly; } + + void getCursorPosition( int *parag, int *index ) const; + + bool isModified() const; + bool italic() const; + bool bold() const; + bool underline() const; + TQString family() const; + int pointSize() const; + TQColor color() const; + TQFont font() const; + TQFont currentFont() const; + int alignment() const; + int undoDepth() const; + + // do not use, will go away + virtual bool getFormat( int para, int index, TQFont *font, TQColor *color, VerticalAlignment *verticalAlignment ); + // do not use, will go away + virtual bool getParagraphFormat( int para, TQFont *font, TQColor *color, + VerticalAlignment *verticalAlignment, int *alignment, + TQStyleSheetItem::DisplayMode *displayMode, + TQStyleSheetItem::ListStyle *listStyle, + int *listDepth ); + + + bool isOverwriteMode() const { return overWrite; } + TQColor paragraphBackgroundColor( int para ) const; + + bool isUndoRedoEnabled() const; + bool eventFilter( TQObject *o, TQEvent *e ); + bool tabChangesFocus() const; + + void setAutoFormatting( uint features ); + uint autoFormatting() const; + TQSyntaxHighlighter *syntaxHighlighter() const; + +public slots: + void setEnabled( bool ); +#ifndef TQT_NO_MIME + virtual void setMimeSourceFactory( TQMimeSourceFactory* factory ); +#endif + virtual void setStyleSheet( TQStyleSheet* styleSheet ); + virtual void scrollToAnchor( const TQString& name ); + virtual void setPaper( const TQBrush& pap ); + virtual void setLinkUnderline( bool ); + + virtual void setWordWrap( WordWrap mode ); + virtual void setWrapColumnOrWidth( int ); + virtual void setWrapPolicy( WrapPolicy policy ); + + virtual void copy(); + virtual void append( const TQString& text ); + + void setText( const TQString &txt ) { setText( txt, TQString::null ); } + virtual void setText( const TQString &txt, const TQString &context ); + virtual void setTextFormat( TextFormat f ); + + virtual void selectAll( bool select = TRUE ); + virtual void setTabStopWidth( int ts ); + virtual void zoomIn( int range ); + virtual void zoomIn() { zoomIn( 1 ); } + virtual void zoomOut( int range ); + virtual void zoomOut() { zoomOut( 1 ); } + virtual void zoomTo( int size ); + + virtual void sync(); + virtual void setReadOnly( bool b ); + + virtual void undo(); + virtual void redo(); + virtual void cut(); + virtual void paste(); +#ifndef TQT_NO_CLIPBOARD + virtual void pasteSubType( const TQCString &subtype ); +#endif + virtual void clear(); + virtual void del(); + virtual void indent(); + virtual void setItalic( bool b ); + virtual void setBold( bool b ); + virtual void setUnderline( bool b ); + virtual void setFamily( const TQString &f ); + virtual void setPointSize( int s ); + virtual void setColor( const TQColor &c ); + virtual void setFont( const TQFont &f ); + virtual void setVerticalAlignment( VerticalAlignment a ); + virtual void setAlignment( int a ); + + // do not use, will go away + virtual void setParagType( TQStyleSheetItem::DisplayMode dm, TQStyleSheetItem::ListStyle listStyle ); + + virtual void setCursorPosition( int parag, int index ); + virtual void setSelection( int parag_from, int index_from, int parag_to, int index_to, int selNum = 0 ); + virtual void setSelectionAttributes( int selNum, const TQColor &back, bool invertText ); + virtual void setModified( bool m ); + virtual void resetFormat(); + virtual void setUndoDepth( int d ); + virtual void setFormat( TQTextFormat *f, int flags ); + virtual void ensureCursorVisible(); + virtual void placeCursor( const TQPoint &pos, TQTextCursor *c = 0 ); + virtual void moveCursor( CursorAction action, bool select ); + virtual void doKeyboardAction( KeyboardAction action ); + virtual void removeSelectedText( int selNum = 0 ); + virtual void removeSelection( int selNum = 0 ); + virtual void setCurrentFont( const TQFont &f ); + virtual void setOverwriteMode( bool b ) { overWrite = b; } + + virtual void scrollToBottom(); + + void insert( const TQString &text, uint insertionFlags = CheckNewLines | RemoveSelected ); // ## virtual in 4.0 + + // obsolete + virtual void insert( const TQString &text, bool, bool = TRUE, bool = TRUE ); + + virtual void insertAt( const TQString &text, int para, int index ); + virtual void removeParagraph( int para ); + virtual void insertParagraph( const TQString &text, int para ); + + virtual void setParagraphBackgroundColor( int para, const TQColor &bg ); + virtual void clearParagraphBackground( int para ); + + virtual void setUndoRedoEnabled( bool b ); + void setTabChangesFocus( bool b ); // ### make virtual in 4.0 + +#ifdef QT_TEXTEDIT_OPTIMIZATION + void polish(); + void setMaxLogLines( int numLines ); + int maxLogLines(); +#endif + +signals: + void textChanged(); + void selectionChanged(); + void copyAvailable( bool ); + void undoAvailable( bool yes ); + void redoAvailable( bool yes ); + void currentFontChanged( const TQFont &f ); + void currentColorChanged( const TQColor &c ); + void currentAlignmentChanged( int a ); + void currentVerticalAlignmentChanged( VerticalAlignment a ); + void cursorPositionChanged( TQTextCursor *c ); + void cursorPositionChanged( int para, int pos ); + void returnPressed(); + void modificationChanged( bool m ); + void clicked( int parag, int index ); + void doubleClicked( int parag, int index ); + +protected: + void repaintChanged(); + void updateStyles(); + void drawContents( TQPainter *p, int cx, int cy, int cw, int ch ); + bool event( TQEvent *e ); + void keyPressEvent( TQKeyEvent *e ); + void resizeEvent( TQResizeEvent *e ); + void viewportResizeEvent( TQResizeEvent* ); + void contentsMousePressEvent( TQMouseEvent *e ); + void contentsMouseMoveEvent( TQMouseEvent *e ); + void contentsMouseReleaseEvent( TQMouseEvent *e ); + void contentsMouseDoubleClickEvent( TQMouseEvent *e ); +#ifndef TQT_NO_WHEELEVENT + void contentsWheelEvent( TQWheelEvent *e ); +#endif + void imStartEvent( TQIMEvent * ); + void imComposeEvent( TQIMEvent * ); + void imEndEvent( TQIMEvent * ); +#ifndef TQT_NO_DRAGANDDROP + void contentsDragEnterEvent( TQDragEnterEvent *e ); + void contentsDragMoveEvent( TQDragMoveEvent *e ); + void contentsDragLeaveEvent( TQDragLeaveEvent *e ); + void contentsDropEvent( TQDropEvent *e ); +#endif + void contentsContextMenuEvent( TQContextMenuEvent *e ); + bool sendMouseEventToInputContext( TQMouseEvent *e ); + bool focusNextPrevChild( bool next ); + TQTextDocument *document() const; + TQTextCursor *textCursor() const; + void setDocument( TQTextDocument *doc ); + virtual TQPopupMenu *createPopupMenu( const TQPoint& pos ); + virtual TQPopupMenu *createPopupMenu(); + void drawCursor( bool visible ); + + void windowActivationChange( bool ); + +protected slots: + virtual void doChangeInterval(); + void sliderReleased(); // ### make virtual in 4.0 + +private slots: + void formatMore(); + void doResize(); + void autoScrollTimerDone(); + void blinkCursor(); + void setModified(); + void startDrag(); + void documentWidthChanged( int w ); + void clipboardChanged(); + +private: + struct TQ_EXPORT UndoRedoInfo { + enum Type { Invalid, Insert, Delete, Backspace, Return, RemoveSelected, Format, Style, IME }; + + UndoRedoInfo( TQTextDocument *dc ); + ~UndoRedoInfo(); + void clear(); + bool valid() const; + + TQUndoRedoInfoPrivate *d; + int id; + int index; + int eid; + int eindex; + TQTextFormat *format; + int flags; + Type type; + TQTextDocument *doc; + TQByteArray styleInformation; + }; + +private: + void updateCursor( const TQPoint & pos ); + void handleMouseMove( const TQPoint& pos ); + void drawContents( TQPainter * ); + virtual bool linksEnabled() const { return FALSE; } + void init(); + void checkUndoRedoInfo( UndoRedoInfo::Type t ); + void updateCurrentFormat(); + bool handleReadOnlyKeyEvent( TQKeyEvent *e ); + void makeParagVisible( TQTextParagraph *p ); + void normalCopy(); + void copyToClipboard(); +#ifndef TQT_NO_MIME + TQCString pickSpecial(TQMimeSource* ms, bool always_ask, const TQPoint&); + TQTextDrag *dragObject( TQWidget *parent = 0 ) const; +#endif +#ifndef TQT_NO_MIMECLIPBOARD + void pasteSpecial(const TQPoint&); +#endif + void setFontInternal( const TQFont &f ); + + virtual void emitHighlighted( const TQString & ) {} + virtual void emitLinkClicked( const TQString & ) {} + + void readFormats( TQTextCursor &c1, TQTextCursor &c2, TQTextString &text, bool fillStyles = FALSE ); + void clearUndoRedo(); + void paintDocument( bool drawAll, TQPainter *p, int cx = -1, int cy = -1, int cw = -1, int ch = -1 ); + void moveCursor( CursorAction action ); + void ensureFormatted( TQTextParagraph *p ); + void placeCursor( const TQPoint &pos, TQTextCursor *c, bool link ); + void updateMicroFocusHint(); + +#ifdef QT_TEXTEDIT_OPTIMIZATION + bool checkOptimMode(); + TQString optimText() const; + void optimSetText( const TQString &str ); + void optimAppend( const TQString &str ); + void optimInsert( const TQString &str, int line, int index ); + void optimDrawContents( TQPainter * p, int cx, int cy, int cw, int ch ); + void optimMousePressEvent( TQMouseEvent * e ); + void optimMouseReleaseEvent( TQMouseEvent * e ); + void optimMouseMoveEvent( TQMouseEvent * e ); + int optimCharIndex( const TQString &str, int mx ) const; + void optimSelectAll(); + void optimRemoveSelection(); + void optimSetSelection( int startLine, int startIdx, int endLine, + int endIdx ); + bool optimHasSelection() const; + TQString optimSelectedText() const; + bool optimFind( const TQString & str, bool, bool, bool, int *, int * ); + void optimParseTags( TQString * str, int lineNo = -1, int indexOffset = 0 ); + TQTextEditOptimPrivate::Tag * optimPreviousLeftTag( int line ); + void optimSetTextFormat( TQTextDocument *, TQTextCursor *, TQTextFormat * f, + int, int, TQTextEditOptimPrivate::Tag * t ); + TQTextEditOptimPrivate::Tag * optimAppendTag( int index, const TQString & tag ); + TQTextEditOptimPrivate::Tag * optimInsertTag( int line, int index, const TQString & tag ); + void optimCheckLimit( const TQString& str ); + bool optimHasBoldMetrics( int line ); + +private slots: + void optimDoAutoScroll(); +#endif // QT_TEXTEDIT_OPTIMIZATION + +private: +#ifndef TQT_NO_CLIPBOARD + void pasteSubType( const TQCString &subtype, TQMimeSource *m ); +#endif + +private: + TQTextDocument *doc; + TQTextCursor *cursor; + TQTimer *formatTimer, *scrollTimer, *changeIntervalTimer, *blinkTimer, *dragStartTimer; + TQTextParagraph *lastFormatted; + int interval; + UndoRedoInfo undoRedoInfo; + TQTextFormat *currentFormat; + int currentAlignment; + TQPoint oldMousePos, mousePos; + TQPoint dragStartPos; + TQString onLink; + WordWrap wrapMode; + WrapPolicy wPolicy; + int wrapWidth; + TQString pressedLink; + TQTextEditPrivate *d; + bool inDoubleClick : 1; + bool mousePressed : 1; + bool cursorVisible : 1; + bool blinkCursorVisible : 1; + bool noop: 1; //< Removed; keep as padding for binary compat or reuse if needed + bool modified : 1; + bool mightStartDrag : 1; + bool inDnD : 1; + bool readOnly : 1; + bool undoEnabled : 1; + bool overWrite : 1; + +private: // Disabled copy constructor and operator= +#if defined(TQ_DISABLE_COPY) + TQTextEdit( const TQTextEdit & ); + TQTextEdit &operator=( const TQTextEdit & ); +#endif +}; + +inline TQTextDocument *TQTextEdit::document() const +{ + return doc; +} + +inline TQTextCursor *TQTextEdit::textCursor() const +{ + return cursor; +} + +inline void TQTextEdit::setCurrentFont( const TQFont &f ) +{ + TQTextEdit::setFontInternal( f ); +} + +#endif //TQT_NO_TEXTEDIT +#endif //TQTEXTVIEW_H diff --git a/src/widgets/tqtextview.cpp b/src/widgets/tqtextview.cpp new file mode 100644 index 000000000..a475d7b4a --- /dev/null +++ b/src/widgets/tqtextview.cpp @@ -0,0 +1,103 @@ +/**************************************************************************** +** +** Implementation of the TQTextView class +** +** Created : 990101 +** +** Copyright (C) 1992-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 "tqtextview.h" + +#ifndef TQT_NO_TEXTVIEW + +/*! \class TQTextView + \brief The TQTextView class provides a rich-text viewer. + + \obsolete + + This class wraps a read-only \l TQTextEdit. + Use a \l TQTextEdit instead, and call setReadOnly(TRUE) + to disable editing. +*/ + +/*! \reimp */ + +TQTextView::TQTextView( const TQString& text, const TQString& context, + TQWidget *parent, const char *name ) + : TQTextEdit( text, context, parent, name ) +{ + setReadOnly( TRUE ); +} + +/*! \reimp */ + +TQTextView::TQTextView( TQWidget *parent, const char *name ) + : TQTextEdit( parent, name ) +{ + setReadOnly( TRUE ); +} + +/*! \reimp */ + +TQTextView::~TQTextView() +{ +} + +/*! + \property TQTextView::undoDepth + \brief the number of undoable steps +*/ + +/*! + \property TQTextView::overwriteMode + \brief whether new text overwrites or pushes aside existing text +*/ + +/*! + \property TQTextView::modified + \brief Whether the text view's contents have been modified. +*/ + +/*! + \property TQTextView::readOnly + \brief Whether the text view's contents are read only. +*/ + +/*! + \property TQTextView::undoRedoEnabled + \brief Whether undo and redo are enabled. +*/ + +#endif diff --git a/src/widgets/tqtextview.h b/src/widgets/tqtextview.h new file mode 100644 index 000000000..8970d10c8 --- /dev/null +++ b/src/widgets/tqtextview.h @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Definition of the TQTextView class +** +** Created : 990101 +** +** Copyright (C) 1992-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 TQTEXTVIEW_H +#define TQTEXTVIEW_H + +#ifndef QT_H +#include "tqtextedit.h" +#endif // QT_H + +#ifndef TQT_NO_TEXTVIEW + +class TQ_EXPORT TQTextView : public TQTextEdit +{ + TQ_OBJECT + TQ_OVERRIDE( int undoDepth DESIGNABLE false SCRIPTABLE false ) + TQ_OVERRIDE( bool overwriteMode DESIGNABLE false SCRIPTABLE false ) + TQ_OVERRIDE( bool modified SCRIPTABLE false) + TQ_OVERRIDE( bool readOnly DESIGNABLE false SCRIPTABLE false ) + TQ_OVERRIDE( bool undoRedoEnabled DESIGNABLE false SCRIPTABLE false ) + +public: + TQTextView( const TQString& text, const TQString& context = TQString::null, + TQWidget* parent=0, const char* name=0); + TQTextView( TQWidget* parent=0, const char* name=0 ); + + virtual ~TQTextView(); + +private: +#if defined(TQ_DISABLE_COPY) // Disabled copy constructor and operator= + TQTextView( const TQTextView & ); + TQTextView &operator=( const TQTextView & ); +#endif +}; + +#endif //TQT_NO_TEXTVIEW +#endif //TQTEXTVIEW_H diff --git a/src/xml/qsvgdevice.cpp b/src/xml/qsvgdevice.cpp index d2895838f..852cc7424 100644 --- a/src/xml/qsvgdevice.cpp +++ b/src/xml/qsvgdevice.cpp @@ -46,7 +46,7 @@ #include "tqmap.h" #include "ntqregexp.h" #include "tqvaluelist.h" -#include "ntqtextstream.h" +#include "tqtextstream.h" #include "tqimage.h" #include "ntqpixmap.h" diff --git a/src/xml/tqdom.cpp b/src/xml/tqdom.cpp index 4feaf47a6..c233afa76 100644 --- a/src/xml/tqdom.cpp +++ b/src/xml/tqdom.cpp @@ -45,8 +45,8 @@ #include "tqxml.h" #include "tqptrlist.h" #include "ntqdict.h" -#include "ntqtextstream.h" -#include "ntqtextcodec.h" +#include "tqtextstream.h" +#include "tqtextcodec.h" #include "ntqiodevice.h" #include "ntqregexp.h" #include "ntqbuffer.h" diff --git a/src/xml/tqxml.cpp b/src/xml/tqxml.cpp index 4a2b8615d..f9fa14b77 100644 --- a/src/xml/tqxml.cpp +++ b/src/xml/tqxml.cpp @@ -39,7 +39,7 @@ **********************************************************************/ #include "tqxml.h" -#include "ntqtextcodec.h" +#include "tqtextcodec.h" #include "ntqbuffer.h" #include "ntqregexp.h" #include "tqptrstack.h" diff --git a/src/xml/tqxml.h b/src/xml/tqxml.h index fb685a21e..d55004993 100644 --- a/src/xml/tqxml.h +++ b/src/xml/tqxml.h @@ -42,7 +42,7 @@ #define TQXML_H #ifndef QT_H -#include "ntqtextstream.h" +#include "tqtextstream.h" #include "ntqfile.h" #include "tqstring.h" #include "tqstringlist.h" -- cgit v1.2.3