summaryrefslogtreecommitdiffstats
path: root/tqtinterface/qt4/src/kernel/tqinternal.cpp
diff options
context:
space:
mode:
authorTimothy Pearson <kb9vqf@pearsoncomputing.net>2011-07-10 15:17:53 -0500
committerTimothy Pearson <kb9vqf@pearsoncomputing.net>2011-07-10 15:17:53 -0500
commitdda8474928bd7276e1fad8fb7a601e7c83ff2bc2 (patch)
tree7f83910598b33b12730035f086df20b5a53ab99c /tqtinterface/qt4/src/kernel/tqinternal.cpp
parent6260b6178868c03aab1644bf93b0ef043654bdb0 (diff)
downloadexperimental-dda8474928bd7276e1fad8fb7a601e7c83ff2bc2.tar.gz
experimental-dda8474928bd7276e1fad8fb7a601e7c83ff2bc2.zip
Added TQt4 HEAD
Diffstat (limited to 'tqtinterface/qt4/src/kernel/tqinternal.cpp')
-rw-r--r--tqtinterface/qt4/src/kernel/tqinternal.cpp785
1 files changed, 785 insertions, 0 deletions
diff --git a/tqtinterface/qt4/src/kernel/tqinternal.cpp b/tqtinterface/qt4/src/kernel/tqinternal.cpp
new file mode 100644
index 0000000..7ad13f1
--- /dev/null
+++ b/tqtinterface/qt4/src/kernel/tqinternal.cpp
@@ -0,0 +1,785 @@
+/****************************************************************************
+**
+** Implementation of some internal classes
+**
+** Created : 010427
+**
+** Copyright (C) 2010 Timothy Pearson and (C) 1992-2008 Trolltech ASA.
+**
+** This file is part of the kernel module of the TQt GUI Toolkit.
+**
+** This file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free
+** Software Foundation and appearing in the files LICENSE.GPL2
+** and LICENSE.GPL3 included in the packaging of this file.
+** Alternatively you may (at your option) use any later version
+** of the GNU General Public License if such license has been
+** publicly approved by Trolltech ASA (or its successors, if any)
+** and the KDE Free TQt Foundation.
+**
+** Please review the following information to ensure GNU General
+** Public Licensing requirements will be met:
+** http://trolltech.com/products/qt/licenses/licensing/opensource/.
+** If you are unsure which license is appropriate for your use, please
+** review the following information:
+** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
+** or contact the sales department at sales@trolltech.com.
+**
+** This file may be used under the terms of the Q Public License as
+** defined by Trolltech ASA and appearing in the file LICENSE.TQPL
+** included in the packaging of this file. Licensees holding valid TQt
+** Commercial licenses may use this file in accordance with the TQt
+** Commercial License Agreement provided with the Software.
+**
+** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
+** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted
+** herein.
+**
+**********************************************************************/
+
+#include "private/tqinternal_p.h"
+#include "tqwidget.h"
+#include "tqpixmap.h"
+#include "tqpainter.h"
+#include "tqcleanuphandler.h"
+
+static TQPixmap* qdb_shared_pixmap = 0;
+static TQPixmap *qdb_force_pixmap = 0;
+static TQSharedDoubleBuffer* qdb_owner = 0;
+
+TQCleanupHandler<TQPixmap> qdb_pixmap_cleanup;
+
+#ifdef TQ_WS_MACX
+bool TQSharedDoubleBuffer::dblbufr = FALSE;
+#else
+bool TQSharedDoubleBuffer::dblbufr = TRUE;
+#endif
+
+
+/*
+ hardLimitWidth/Height: if >= 0, the maximum number of pixels that
+ get double buffered.
+
+ sharedLimitWidth/Height: if >= 0, the maximum number of pixels the
+ shared double buffer can keep.
+
+ For x with sharedLimitSize < x <= hardLimitSize, temporary buffers
+ are constructed.
+ */
+static const int hardLimitWidth = -1;
+static const int hardLimitHeight = -1;
+// #if defined( TQ_WS_TQWS ) || defined( TQ_WS_MAC9 )
+// // Small in TQt/Embedded / Mac9 - 5K on 32bpp
+// static const int sharedLimitWidth = 64;
+// static const int sharedLimitHeight = 20;
+// #else
+// 240K on 32bpp
+static const int sharedLimitWidth = 640;
+static const int sharedLimitHeight = 100;
+// #endif
+
+// *******************************************************************
+// TQSharedDoubleBufferCleaner declaration and implementation
+// *******************************************************************
+
+/* \internal
+ This class is responsible for cleaning up the pixmaps created by the
+ TQSharedDoubleBuffer class. When TQSharedDoubleBuffer creates a
+ pixmap larger than the shared limits, this class deletes it after a
+ specified amount of time.
+
+ When the large pixmap is created/used, you must call start(). If the
+ large pixmap is ever deleted, you must call stop(). The start()
+ method always restarts the timer, so if the large pixmap is
+ constantly in use, the timer will never fire, and the pixmap will
+ not be constantly created and destroyed.
+*/
+
+static const int shared_double_buffer_cleanup_timeout = 30000; // 30 seconds
+
+// declaration
+
+class TQSharedDoubleBufferCleaner : public TQObject
+{
+public:
+ TQSharedDoubleBufferCleaner( void );
+
+ void start( void );
+ void stop( void );
+
+ void doCleanup( void );
+
+ bool event( TQEvent *e );
+
+private:
+ int timer_id;
+};
+
+// implementation
+
+/* \internal
+ Creates a TQSharedDoubleBufferCleaner object. The timer is not
+ started when creating the object.
+*/
+TQSharedDoubleBufferCleaner::TQSharedDoubleBufferCleaner( void )
+ : TQObject( 0, "internal shared double buffer cleanup object" ),
+ timer_id( -1 )
+{
+}
+
+/* \internal
+ Starts the cleanup timer. Any previously running timer is stopped.
+*/
+void TQSharedDoubleBufferCleaner::start( void )
+{
+ stop();
+ timer_id = startTimer( shared_double_buffer_cleanup_timeout );
+}
+
+/* \internal
+ Stops the cleanup timer, if it is running.
+*/
+void TQSharedDoubleBufferCleaner::stop( void )
+{
+ if ( timer_id != -1 )
+ killTimer( timer_id );
+ timer_id = -1;
+}
+
+/* \internal
+ */
+void TQSharedDoubleBufferCleaner::doCleanup( void )
+{
+ qdb_pixmap_cleanup.remove( &qdb_force_pixmap );
+ delete qdb_force_pixmap;
+ qdb_force_pixmap = 0;
+}
+
+/* \internal
+ Event handler reimplementation. Calls doCleanup() when the timer
+ fires.
+*/
+bool TQSharedDoubleBufferCleaner::event( TQEvent *e )
+{
+ if ( e->type() != TQEvent::Timer )
+ return FALSE;
+
+ TQTimerEvent *event = (TQTimerEvent *) e;
+ if ( event->timerId() == timer_id ) {
+ doCleanup();
+ stop();
+ }
+#ifdef TQT_CHECK_STATE
+ else {
+ qWarning( "TQSharedDoubleBufferCleaner::event: invalid timer event received." );
+ return FALSE;
+ }
+#endif // TQT_CHECK_STATE
+
+ return TRUE;
+}
+
+// static instance
+static TQSharedDoubleBufferCleaner *static_cleaner = 0;
+TQSingleCleanupHandler<TQSharedDoubleBufferCleaner> cleanup_static_cleaner;
+
+inline static TQSharedDoubleBufferCleaner *staticCleaner()
+{
+ if ( ! static_cleaner ) {
+ static_cleaner = new TQSharedDoubleBufferCleaner();
+ cleanup_static_cleaner.set( &static_cleaner );
+ }
+ return static_cleaner;
+}
+
+
+// *******************************************************************
+// TQSharedDoubleBuffer implementation
+// *******************************************************************
+
+/* \internal
+ \enum DoubleBufferFlags
+
+ \value InitBG initialize the background of the double buffer.
+
+ \value Force disable shared buffer size limits.
+
+ \value Default InitBG and Force are used by default.
+*/
+
+/* \internal
+ \enum DoubleBufferState
+
+ \value Active indicates that the buffer may be used.
+
+ \value BufferActive indicates that painting with painter() will be
+ double buffered.
+
+ \value ExternalPainter indicates that painter() will return a
+ painter that was not created by TQSharedDoubleBuffer.
+*/
+
+/* \internal
+ \class TQSharedDoubleBuffer
+
+ This class provides a single, reusable double buffer. This class
+ is used internally by TQt widgets that need double buffering, which
+ prevents each individual widget form creating a double buffering
+ pixmap.
+
+ Using a single pixmap double buffer and sharing it across all
+ widgets is nicer on window system resources.
+*/
+
+/* \internal
+ Creates a TQSharedDoubleBuffer with flags \f.
+
+ \sa DoubleBufferFlags
+*/
+TQSharedDoubleBuffer::TQSharedDoubleBuffer( DBFlags f )
+ : wid( 0 ), rx( 0 ), ry( 0 ), rw( 0 ), rh( 0 ), flags( f ), state( 0 ),
+ p( 0 ), external_p( 0 ), pix( 0 )
+{
+}
+
+/* \internal
+ Creates a TQSharedDoubleBuffer with flags \f. The \a widget, \a x,
+ \a y, \a w and \a h arguments are passed to begin().
+
+ \sa DoubleBufferFlags begin()
+*/
+TQSharedDoubleBuffer::TQSharedDoubleBuffer( TQWidget* widget,
+ int x, int y, int w, int h,
+ DBFlags f )
+ : wid( 0 ), rx( 0 ), ry( 0 ), rw( 0 ), rh( 0 ), flags( f ), state( 0 ),
+ p( 0 ), external_p( 0 ), pix( 0 )
+{
+ begin( widget, x, y, w, h );
+}
+
+/* \internal
+ Creates a TQSharedDoubleBuffer with flags \f. The \a painter, \a x,
+ \a y, \a w and \a h arguments are passed to begin().
+
+ \sa DoubleBufferFlags begin()
+*/
+TQSharedDoubleBuffer::TQSharedDoubleBuffer( TQPainter* painter,
+ int x, int y, int w, int h,
+ DBFlags f)
+ : wid( 0 ), rx( 0 ), ry( 0 ), rw( 0 ), rh( 0 ), flags( f ), state( 0 ),
+ p( 0 ), external_p( 0 ), pix( 0 )
+{
+ begin( painter, x, y, w, h );
+}
+
+/* \internal
+ Creates a TQSharedDoubleBuffer with flags \f. The \a widget and
+ \a r arguments are passed to begin().
+
+ \sa DoubleBufferFlags begin()
+*/
+TQSharedDoubleBuffer::TQSharedDoubleBuffer( TQWidget *widget, const TQRect &r, DBFlags f )
+ : wid( 0 ), rx( 0 ), ry( 0 ), rw( 0 ), rh( 0 ), flags( f ), state( 0 ),
+ p( 0 ), external_p( 0 ), pix( 0 )
+{
+ begin( widget, r );
+}
+
+/* \internal
+ Creates a TQSharedDoubleBuffer with flags \f. The \a painter and
+ \a r arguments are passed to begin().
+
+ \sa DoubleBufferFlags begin()
+*/
+TQSharedDoubleBuffer::TQSharedDoubleBuffer( TQPainter *painter, const TQRect &r, DBFlags f )
+ : wid( 0 ), rx( 0 ), ry( 0 ), rw( 0 ), rh( 0 ), flags( f ), state( 0 ),
+ p( 0 ), external_p( 0 ), pix( 0 )
+{
+ begin( painter, r );
+}
+
+/* \internal
+ Destructs the TQSharedDoubleBuffer and calls end() if the buffer is
+ active.
+
+ \sa isActive() end()
+*/
+TQSharedDoubleBuffer::~TQSharedDoubleBuffer()
+{
+ if ( isActive() )
+ end();
+}
+
+/* \internal
+ Starts double buffered painting in the area specified by \a x,
+ \a y, \a w and \a h on \a painter. Painting should be done using the
+ TQPainter returned by TQSharedDoubleBuffer::painter().
+
+ The double buffered area will be updated when calling end().
+
+ \sa painter() isActive() end()
+*/
+bool TQSharedDoubleBuffer::begin( TQPainter* painter, int x, int y, int w, int h )
+{
+ if ( isActive() ) {
+#if defined(TQT_CHECK_STATE)
+ qWarning( "TQSharedDoubleBuffer::begin: Buffer is already active."
+ "\n\tYou must end() the buffer before a second begin()" );
+#endif // TQT_CHECK_STATE
+ return FALSE;
+ }
+
+ external_p = painter;
+
+ if ( painter->tqdevice()->devType() == TQInternal::Widget )
+// return begin( (TQWidget *) painter->tqdevice(), x, y, w, h ); // This was very lazy code on Trolltech's part! Nothing like a bad reinterpret cast, completely ignoring the different base object addresses, to ruin your week...
+ return begin( static_cast<TQWidget*>(static_cast<QWidget*>(static_cast<QPaintDevice*>(painter->tqdevice()))), x, y, w, h );
+
+ state = Active;
+
+ rx = x;
+ ry = y;
+ rw = w;
+ rh = h;
+
+ if ( ( pix = getPixmap() ) ) {
+#ifdef TQ_WS_X11
+ if ( painter->tqdevice()->x11Screen() != pix->x11Screen() )
+ pix->x11SetScreen( painter->tqdevice()->x11Screen() );
+ TQPixmap::x11SetDefaultScreen( pix->x11Screen() );
+#endif // TQ_WS_X11
+
+ state |= BufferActive;
+ p = new TQPainter( pix );
+ if ( p->isActive() ) {
+ p->setPen( external_p->pen() );
+ p->setBackgroundColor( external_p->backgroundColor() );
+ p->setFont( external_p->font() );
+ }
+ } else {
+ state |= ExternalPainter;
+ p = external_p;
+ }
+
+ return TRUE;
+}
+
+/* \internal
+
+
+ Starts double buffered painting in the area specified by \a x,
+ \a y, \a w and \a h on \a widget. Painting should be done using the
+ TQPainter returned by TQSharedDoubleBuffer::painter().
+
+ The double buffered area will be updated when calling end().
+
+ \sa painter() isActive() end()
+*/
+bool TQSharedDoubleBuffer::begin( TQWidget* widget, int x, int y, int w, int h )
+{
+ if ( isActive() ) {
+#if defined(TQT_CHECK_STATE)
+ qWarning( "TQSharedDoubleBuffer::begin: Buffer is already active."
+ "\n\tYou must end() the buffer before a second begin()" );
+#endif // TQT_CHECK_STATE
+ return FALSE;
+ }
+
+ state = Active;
+
+ wid = widget;
+ rx = x;
+ ry = y;
+ rw = w <= 0 ? wid->width() : w;
+ rh = h <= 0 ? wid->height() : h;
+
+ if ( ( pix = getPixmap() ) ) {
+#ifdef TQ_WS_X11
+ if ( wid->x11Screen() != pix->x11Screen() )
+ pix->x11SetScreen( wid->x11Screen() );
+ TQPixmap::x11SetDefaultScreen( pix->x11Screen() );
+#endif // TQ_WS_X11
+
+ state |= BufferActive;
+ if ( flags & InitBG ) {
+ pix->fill( wid, rx, ry );
+ }
+ p = new TQPainter( static_cast<QPaintDevice*>(pix), wid );
+ // newly created painters should be translated to the origin
+ // of the widget, so that paint methods can draw onto the double
+ // buffered painter in widget coordinates.
+ p->setBrushOrigin( -rx, -ry );
+ p->translate( -rx, -ry );
+ } else {
+ if ( external_p ) {
+ state |= ExternalPainter;
+ p = external_p;
+ } else {
+ p = new TQPainter( wid );
+ }
+
+ if ( flags & InitBG ) {
+ wid->erase( rx, ry, rw, rh );
+ }
+ }
+ return TRUE;
+}
+
+/* \internal
+ Ends double buffered painting. The contents of the shared double
+ buffer pixmap are drawn onto the destination by calling flush(),
+ and ownership of the shared double buffer pixmap is released.
+
+ \sa begin() flush()
+*/
+bool TQSharedDoubleBuffer::end()
+{
+ if ( ! isActive() ) {
+#if defined(TQT_CHECK_STATE)
+ qWarning( "TQSharedDoubleBuffer::end: Buffer is not active."
+ "\n\tYou must call begin() before calling end()." );
+#endif // TQT_CHECK_STATE
+ return FALSE;
+ }
+
+ if ( ! ( state & ExternalPainter ) ) {
+ p->end();
+ delete p;
+ }
+
+ flush();
+
+ if ( pix ) {
+ releasePixmap();
+ }
+
+ wid = 0;
+ rx = ry = rw = rh = 0;
+ // do not reset flags!
+ state = 0;
+
+ p = external_p = 0;
+ pix = 0;
+
+ return TRUE;
+}
+
+/* \internal
+ Paints the contents of the shared double buffer pixmap onto the
+ destination. The destination is determined from the arguments
+ based to begin().
+
+ Note: You should not need to call this function, since it is called
+ from end().
+
+ \sa begin() end()
+*/
+void TQSharedDoubleBuffer::flush()
+{
+ if ( ! isActive() || ! ( state & BufferActive ) )
+ return;
+
+ if ( external_p )
+ external_p->drawPixmap( rx, ry, *pix, 0, 0, rw, rh );
+ else if ( wid && wid->isVisible() )
+ bitBlt( wid, rx, ry, pix, 0, 0, rw, rh );
+}
+
+/* \internal
+ Aquire ownership of the shared double buffer pixmap, subject to the
+ following conditions:
+
+ \list 1
+ \i double buffering is enabled globally.
+ \i the shared double buffer pixmap is not in use.
+ \i the size specified in begin() is valid, and within limits.
+ \endlist
+
+ If all of these conditions are met, then this TQSharedDoubleBuffer
+ object becomes the owner of the shared double buffer pixmap. The
+ shared double buffer pixmap is resize if necessary, and this
+ function returns a pointer to the pixmap. Ownership must later be
+ relinquished by calling releasePixmap().
+
+ If none of the above conditions are met, this function returns
+ zero.
+
+ \sa releasePixmap()
+*/
+TQPixmap *TQSharedDoubleBuffer::getPixmap()
+{
+ if ( isDisabled() ) {
+ // double buffering disabled globally
+ return 0;
+ }
+
+ if ( qdb_owner ) {
+ // shared pixmap already in use
+ return 0;
+ }
+
+ if ( rw <= 0 || rh <= 0 ||
+ ( hardLimitWidth > 0 && rw >= hardLimitWidth ) ||
+ ( hardLimitHeight > 0 && rh >= hardLimitHeight ) ) {
+ // invalid size, or hard limit reached
+ return 0;
+ }
+
+ if ( rw >= sharedLimitWidth || rh >= sharedLimitHeight ) {
+ if ( flags & Force ) {
+#ifdef USE_QT4
+ printf("[WARNING] Working around mysterious TQSharedDoubleBuffer [tqinternal.cpp] resize problem\n\r");
+ rw = 4000; // 32MB seems reasonable enough, but the usage is likely to be wider than it is tall (think of multiple wide monitors)
+ rh = 2000;
+#else // USE_QT4
+ rw = TQMIN(rw, 8000);
+ rh = TQMIN(rh, 8000);
+#endif // USE_QT4
+ // need to create a big pixmap and start the cleaner
+ if ( ! qdb_force_pixmap ) {
+ qdb_force_pixmap = new TQPixmap( rw, rh );
+ qdb_pixmap_cleanup.add( &qdb_force_pixmap );
+ } else if ( qdb_force_pixmap->width () < rw ||
+ qdb_force_pixmap->height() < rh ) {
+// qdb_force_pixmap->resize( rw, rh );
+ qdb_force_pixmap->resize( TQMAX(rw,qdb_force_pixmap->width()), TQMAX(rh,qdb_force_pixmap->height()) );
+ }
+ qdb_owner = this;
+ staticCleaner()->start();
+ return qdb_force_pixmap;
+ }
+
+ // size is outside shared limit
+ return 0;
+ }
+
+ if ( ! qdb_shared_pixmap ) {
+#ifdef USE_QT4
+ printf("[WARNING] Working around mysterious TQSharedDoubleBuffer [tqinternal.cpp] resize problem\n\r");
+ qdb_shared_pixmap = new TQPixmap( sharedLimitWidth, sharedLimitHeight );
+#else // USE_QT4
+ qdb_shared_pixmap = new TQPixmap( rw, rh );
+#endif // USE_QT4
+ qdb_pixmap_cleanup.add( &qdb_shared_pixmap );
+ } else if ( qdb_shared_pixmap->width() < rw ||
+ qdb_shared_pixmap->height() < rh ) {
+// qdb_shared_pixmap->resize( rw, rh );
+ qdb_shared_pixmap->resize( TQMAX(rw,qdb_shared_pixmap->width()), TQMAX(rh,qdb_shared_pixmap->height()) );
+ }
+ qdb_owner = this;
+ return qdb_shared_pixmap;
+}
+
+/* \internal
+ Releases ownership of the shared double buffer pixmap.
+
+ \sa getPixmap()
+*/
+void TQSharedDoubleBuffer::releasePixmap()
+{
+ if ( qdb_owner != this ) {
+ // sanity check
+
+#ifdef TQT_CHECK_STATE
+ qWarning( "TQSharedDoubleBuffer::releasePixmap: internal error."
+ "\n\t%p does not own shared pixmap, %p does.",
+ (void*)this, (void*)qdb_owner );
+#endif // TQT_CHECK_STATE
+
+ return;
+ }
+
+ qdb_owner = 0;
+}
+
+/* \internal
+ \fn bool TQSharedDoubleBuffer::isDisabled()
+
+ Returns TRUE if double buffering is disabled globally, FALSE otherwise.
+*/
+
+/* \internal
+ \fn void TQSharedDoubleBuffer::setDisabled( bool off )
+
+ Disables global double buffering \a off is TRUE, otherwise global
+ double buffering is enabled.
+*/
+
+/* \internal
+ Deletes the shared double buffer pixmap. You should not need to
+ call this function, since it is called from the TQApplication
+ destructor.
+*/
+void TQSharedDoubleBuffer::cleanup()
+{
+ qdb_pixmap_cleanup.remove( &qdb_shared_pixmap );
+ qdb_pixmap_cleanup.remove( &qdb_force_pixmap );
+ delete qdb_shared_pixmap;
+ delete qdb_force_pixmap;
+ qdb_shared_pixmap = 0;
+ qdb_force_pixmap = 0;
+ qdb_owner = 0;
+}
+
+/* \internal
+ \fn bool TQSharedDoubleBuffer::begin( TQWidget *widget, const TQRect &r )
+ \overload
+*/
+
+/* \internal
+ \fn bool TQSharedDoubleBuffer::begin( TQPainter *painter, const TQRect &r )
+ \overload
+*/
+
+/* \internal
+ \fn TQPainter *TQSharedDoubleBuffer::painter() const
+
+ Returns the active painter on the double buffered area,
+ or zero if double buffered painting is not active.
+*/
+
+/* \internal
+ \fn bool TQSharedDoubleBuffer::isActive() const
+
+ Returns TRUE if double buffered painting is active, FALSE otherwise.
+*/
+
+/* \internal
+ \fn bool TQSharedDoubleBuffer::isBuffered() const
+
+ Returns TRUE if painting is double buffered, FALSE otherwise.
+*/
+
+
+// *******************************************************************
+// TQMembuf declaration and implementation
+// *******************************************************************
+
+/* \internal
+ This class implements an efficient buffering of data that is often used by
+ asynchronous IO classes like TQSocket, TQHttp and TQProcess.
+*/
+
+TQMembuf::TQMembuf() : _size(0), _index(0)
+{
+ buf = new TQPtrList<TQByteArray>;
+ buf->setAutoDelete( TRUE );
+}
+
+TQMembuf::~TQMembuf()
+{
+ delete buf;
+}
+
+/*! \internal
+ This function consumes \a nbytes bytes of data from the
+ buffer and copies it into \a sink. If \a sink is a 0 pointer
+ the data goes into the nirvana.
+*/
+bool TQMembuf::consumeBytes( TQ_ULONG nbytes, char *sink )
+{
+ if ( nbytes <= 0 || nbytes > _size )
+ return FALSE;
+ _size -= nbytes;
+ for ( ;; ) {
+ TQByteArray *a = buf->first();
+ if ( _index + nbytes >= a->size() ) {
+ // Here we skip the whole byte array and get the next later
+ int len = a->size() - _index;
+ if ( sink ) {
+ memcpy( sink, a->data()+_index, len );
+ sink += len;
+ }
+ nbytes -= len;
+ buf->remove();
+ _index = 0;
+ if ( nbytes == 0 )
+ break;
+ } else {
+ // Here we skip only a part of the first byte array
+ if ( sink )
+ memcpy( sink, a->data()+_index, nbytes );
+ _index += nbytes;
+ break;
+ }
+ }
+ return TRUE;
+}
+
+/*! \internal
+ Scans for any occurrence of '\n' in the buffer. If \a store
+ is not 0 the text up to the first '\n' (or terminating 0) is
+ written to \a store, and a terminating 0 is appended to \a store
+ if necessary. Returns TRUE if a '\n' was found; otherwise returns
+ FALSE.
+*/
+bool TQMembuf::scanNewline( TQByteArray *store )
+{
+ if ( _size == 0 )
+ return FALSE;
+ int i = 0; // index into 'store'
+ TQByteArray *a = 0;
+ char *p;
+ int n;
+ for ( ;; ) {
+ if ( !a ) {
+ a = buf->first();
+ if ( !a || a->size() == 0 )
+ return FALSE;
+ p = a->data() + _index;
+ n = a->size() - _index;
+ } else {
+ a = buf->next();
+ if ( !a || a->size() == 0 )
+ return FALSE;
+ p = a->data();
+ n = a->size();
+ }
+ if ( store ) {
+ while ( n-- > 0 ) {
+ *(store->data()+i) = *p;
+ if ( ++i == (int)store->size() )
+ store->resize( store->size() < 256
+ ? 1024 : store->size()*4 );
+ switch ( *p ) {
+ case '\0':
+ store->resize( i );
+ return FALSE;
+ case '\n':
+ *(store->data()+i) = '\0';
+ store->resize( i );
+ return TRUE;
+ }
+ p++;
+ }
+ } else {
+ while ( n-- > 0 ) {
+ switch ( *p++ ) {
+ case '\0':
+ return FALSE;
+ case '\n':
+ return TRUE;
+ }
+ }
+ }
+ }
+}
+
+int TQMembuf::ungetch( int ch )
+{
+ if ( buf->isEmpty() || _index==0 ) {
+ // we need a new TQByteArray
+ TQByteArray *ba = new TQByteArray( 1 );
+ buf->insert( 0, ba );
+ _size++;
+ ba->tqat( 0 ) = ch;
+ } else {
+ // we can reuse a place in the buffer
+ TQByteArray *ba = buf->first();
+ _index--;
+ _size++;
+ ba->tqat( _index ) = ch;
+ }
+ return ch;
+}