~ubuntu-branches/debian/lenny/italc/lenny

« back to all changes in this revision

Viewing changes to lib/src/ivs_connection.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Patrick Winnertz
  • Date: 2008-06-17 13:46:54 UTC
  • mfrom: (1.2.1 upstream) (4.1.1 gutsy)
  • Revision ID: james.westby@ubuntu.com-20080617134654-cl0gi4u524cv1ici
Tags: 1:1.0.9~rc3-1
* Package new upstream version
  - upstream ported the code to qt4.4 (Closes: #481974)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * ivs_connection.cpp - class ivsConnection, an implementation of the 
 
3
 *                      RFB-protocol with iTALC-extensions for Qt
 
4
 *
 
5
 * Copyright (c) 2004-2008 Tobias Doerffel <tobydox/at/users/dot/sf/dot/net>
 
6
 *
 
7
 * This file is part of iTALC - http://italc.sourceforge.net
 
8
 *
 
9
 * This program is free software; you can redistribute it and/or
 
10
 * modify it under the terms of the GNU General Public
 
11
 * License as published by the Free Software Foundation; either
 
12
 * version 2 of the License, or (at your option) any later version.
 
13
 *
 
14
 * This program is distributed in the hope that it will be useful,
 
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
17
 * General Public License for more details.
 
18
 *
 
19
 * You should have received a copy of the GNU General Public
 
20
 * License along with this program (see COPYING); if not, write to the
 
21
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 
22
 * Boston, MA 02111-1307, USA.
 
23
 *
 
24
 */
 
25
 
 
26
 
 
27
#ifdef HAVE_CONFIG_H
 
28
#include <config.h>
 
29
#endif
 
30
 
 
31
#include <cstring>
 
32
 
 
33
 
 
34
#include <QtCore/QCoreApplication>
 
35
#include <QtCore/QDateTime>
 
36
#include <QtGui/QImage>
 
37
#include <QtGui/QPainter>
 
38
 
 
39
 
 
40
#include "ivs_connection.h"
 
41
#include "qt_user_events.h"
 
42
#include "local_system.h"
 
43
#include "messagebox.h"
 
44
 
 
45
#include "minilzo.h"
 
46
 
 
47
 
 
48
static const rfbPixelFormat __localDisplayFormat =
 
49
{
 
50
        32,             // bit per pixel
 
51
        32,             // depth
 
52
#ifdef WORDS_BIGENDIAN
 
53
        1,              // big endian
 
54
#else
 
55
        0,              // big endian
 
56
#endif
 
57
        1,              // true color
 
58
        255,            // red max
 
59
        255,            // green max
 
60
        255,            // blue max
 
61
        16,             // red shift
 
62
        8,              // green shift
 
63
        0,              // blue shift,
 
64
        0, 0            // only for padding
 
65
} ;
 
66
 
 
67
 
 
68
 
 
69
 
 
70
// =============================================================================
 
71
// implementation of IVS-connection
 
72
// =============================================================================
 
73
 
 
74
 
 
75
// normal ctor
 
76
ivsConnection::ivsConnection( const QString & _host, quality _q,
 
77
                                                        bool _use_auth_file,
 
78
                                                        QObject * _parent ) :
 
79
        isdConnection( ( _host.contains( ':' ) ? _host : _host + ":5900" ),
 
80
                                                                _parent ),
 
81
        m_isDemoServer( FALSE ),
 
82
        m_useAuthFile( _use_auth_file ),
 
83
        m_quality( _q ),
 
84
        m_imageLock(),
 
85
        m_screen(),
 
86
        m_scaledScreen(),
 
87
        m_scaledScreenNeedsUpdate( FALSE ),
 
88
        m_scaledSize(),
 
89
        m_softwareCursor( FALSE ),
 
90
        m_cursorPos( 0, 0 ),
 
91
        m_cursorShape(),
 
92
        m_rawBufferSize( -1 ),
 
93
        m_rawBuffer( NULL ),
 
94
        m_decompStreamInited( FALSE )
 
95
{
 
96
#ifdef HAVE_LIBZ
 
97
        m_zlibStreamActive[0] = m_zlibStreamActive[1] = m_zlibStreamActive[2] =
 
98
                                                m_zlibStreamActive[3] = FALSE;
 
99
#endif
 
100
}
 
101
 
 
102
 
 
103
 
 
104
 
 
105
ivsConnection::~ivsConnection()
 
106
{
 
107
        delete[] m_rawBuffer;
 
108
}
 
109
 
 
110
 
 
111
 
 
112
 
 
113
ivsConnection::states ivsConnection::protocolInitialization( void )
 
114
{
 
115
        rfbProtocolVersionMsg protocol_version;
 
116
 
 
117
        if( !readFromServer( protocol_version, sz_rfbProtocolVersionMsg ) )
 
118
        {
 
119
                return( state_ref() = ConnectionFailed );
 
120
        }
 
121
 
 
122
        protocol_version[sz_rfbProtocolVersionMsg] = 0;
 
123
 
 
124
        int major, minor;
 
125
        if( sscanf( protocol_version, rfbProtocolVersionFormat, &major,
 
126
                                                        &minor ) != 2 )
 
127
        {
 
128
                // not a standard VNC server - check whether it is an iTALC-
 
129
                // demo-server
 
130
                if( sscanf( protocol_version, idsProtocolVersionFormat, &major,
 
131
                                                        &minor ) != 2 )
 
132
                {
 
133
                        qCritical( "not a server I can deal with" );
 
134
                        return( state_ref() = InvalidServer );
 
135
                }
 
136
                m_isDemoServer = TRUE;
 
137
        }
 
138
 
 
139
        if( !writeToServer( protocol_version, sz_rfbProtocolVersionMsg ) )
 
140
        {
 
141
                return( state_ref() = ConnectionFailed );
 
142
        }
 
143
 
 
144
        if( authAgainstServer( m_quality >= QualityDemoLow ?
 
145
                                m_useAuthFile ?
 
146
                                        ItalcAuthChallengeViaAuthFile
 
147
                                        :
 
148
                                        ItalcAuthAppInternalChallenge
 
149
                                :
 
150
                                ItalcAuthNone
 
151
                                                ) != Connecting )
 
152
        {
 
153
                return( state() );
 
154
        }
 
155
 
 
156
 
 
157
        const rfbClientInitMsg ci = { 1 };
 
158
 
 
159
        if( !writeToServer( (const char *) &ci, sizeof( ci ) ) )
 
160
        {
 
161
                return( state_ref() = ConnectionFailed );
 
162
        }
 
163
 
 
164
        if( !readFromServer( (char *)&m_si, sizeof( m_si ) ) )
 
165
        {
 
166
                return( state_ref() = ConnectionFailed );
 
167
        }
 
168
 
 
169
        m_si.framebufferWidth = swap16IfLE( m_si.framebufferWidth );
 
170
        m_si.framebufferHeight = swap16IfLE( m_si.framebufferHeight );
 
171
        m_si.format.redMax = swap16IfLE( m_si.format.redMax );
 
172
        m_si.format.greenMax = swap16IfLE( m_si.format.greenMax );
 
173
        m_si.format.blueMax = swap16IfLE( m_si.format.blueMax );
 
174
        m_si.nameLength = swap32IfLE( m_si.nameLength );
 
175
 
 
176
        char * desktop_name = new char[m_si.nameLength+1];
 
177
 
 
178
        if( !readFromServer( desktop_name, m_si.nameLength ) )
 
179
        {
 
180
                return( state_ref() = ConnectionFailed );
 
181
        }
 
182
 
 
183
        //desktop_name[m_si.nameLength] = 0;
 
184
        delete[] desktop_name;
 
185
 
 
186
 
 
187
        rfbSetPixelFormatMsg spf;
 
188
 
 
189
        spf.type = rfbSetPixelFormat;
 
190
        spf.format = __localDisplayFormat;
 
191
        spf.format.redMax = swap16IfLE( spf.format.redMax );
 
192
        spf.format.greenMax = swap16IfLE( spf.format.greenMax );
 
193
        spf.format.blueMax = swap16IfLE( spf.format.blueMax );
 
194
 
 
195
        if( !writeToServer( (const char *) &spf, sizeof( spf ) ) )
 
196
        {
 
197
                return( state_ref() = ConnectionFailed );
 
198
        }
 
199
 
 
200
 
 
201
        char buf[sizeof( rfbSetPixelFormatMsg ) + MAX_ENCODINGS *
 
202
                                                        sizeof( Q_UINT32 )];
 
203
        rfbSetEncodingsMsg * se = (rfbSetEncodingsMsg *) buf;
 
204
        se->type = rfbSetEncodings;
 
205
        se->nEncodings = 0;
 
206
 
 
207
        Q_UINT32 * encs = (Q_UINT32 *)( &buf[sizeof(rfbSetEncodingsMsg)] );
 
208
 
 
209
        if( m_quality >= QualityDemoLow )
 
210
        {
 
211
                encs[se->nEncodings++] = swap32IfLE( rfbEncodingRaw );
 
212
        }
 
213
        else
 
214
        {
 
215
#ifdef HAVE_LIBZ
 
216
#ifdef HAVE_LIBJPEG
 
217
                encs[se->nEncodings++] = swap32IfLE( rfbEncodingTight );
 
218
#endif
 
219
                encs[se->nEncodings++] = swap32IfLE( rfbEncodingZlib );
 
220
#endif
 
221
                encs[se->nEncodings++] = swap32IfLE( rfbEncodingCoRRE );
 
222
                encs[se->nEncodings++] = swap32IfLE( rfbEncodingCopyRect );
 
223
                encs[se->nEncodings++] = swap32IfLE( rfbEncodingRaw );
 
224
                encs[se->nEncodings++] = swap32IfLE( rfbEncodingRichCursor );
 
225
                //encs[se->nEncodings++] = swap32IfLE( rfbEncodingXCursor );
 
226
                encs[se->nEncodings++] = swap32IfLE( rfbEncodingPointerPos );
 
227
                //encs[se->nEncodings++] = swap32IfLE( rfbEncodingRRE );
 
228
#ifdef HAVE_LIBZ
 
229
#ifdef HAVE_LIBJPEG
 
230
                switch( m_quality )
 
231
                {
 
232
                        case QualityLow:
 
233
                                encs[se->nEncodings++] = swap32IfLE(
 
234
                                                rfbEncodingQualityLevel4 );
 
235
                                break;
 
236
                        case QualityMedium:
 
237
                                encs[se->nEncodings++] = swap32IfLE(
 
238
                                                rfbEncodingQualityLevel9 );
 
239
                                break;
 
240
                        case QualityHigh:
 
241
                                // no JPEG
 
242
                                break;
 
243
                        default:
 
244
                                break;
 
245
                }
 
246
#endif
 
247
                encs[se->nEncodings++] = swap32IfLE(
 
248
                                                rfbEncodingCompressLevel4 );
 
249
#endif
 
250
        }
 
251
 
 
252
        //encs[se->nEncodings++] = swap32IfLE( rfbEncodingLastRect );
 
253
        encs[se->nEncodings++] = swap32IfLE( rfbEncodingItalc );
 
254
        encs[se->nEncodings++] = swap32IfLE( rfbEncodingItalcCursor );
 
255
 
 
256
 
 
257
        unsigned int len = sizeof( rfbSetEncodingsMsg ) +
 
258
                                        se->nEncodings * sizeof( Q_UINT32 );
 
259
 
 
260
        se->nEncodings = swap16IfLE( se->nEncodings );
 
261
 
 
262
        if( !writeToServer( buf, len ) )
 
263
        {
 
264
                return( state_ref() = ConnectionFailed );
 
265
        }
 
266
 
 
267
        state_ref() = Connected;
 
268
 
 
269
        m_screen = QImage( m_si.framebufferWidth, m_si.framebufferHeight,
 
270
                                                        QImage::Format_RGB32 );
 
271
        m_screen.fill( Qt::black );
 
272
 
 
273
        sendFramebufferUpdateRequest();
 
274
        sendGetUserInformationRequest();
 
275
        return( state() );
 
276
}
 
277
 
 
278
 
 
279
 
 
280
 
 
281
void ivsConnection::close( void )
 
282
{
 
283
#ifdef HAVE_LIBZ
 
284
        m_zlibStreamActive[0] = m_zlibStreamActive[1] = m_zlibStreamActive[2] =
 
285
                                                m_zlibStreamActive[3] = FALSE;
 
286
#endif
 
287
        isdConnection::close();
 
288
}
 
289
 
 
290
 
 
291
 
 
292
 
 
293
bool ivsConnection::takeSnapshot( void )
 
294
{
 
295
        if( user().isEmpty() || state() != ivsConnection::Connected )
 
296
        {
 
297
                return( FALSE );
 
298
        }
 
299
 
 
300
        // construct text
 
301
        QString txt = user() + "@" + host() + " " +
 
302
                        QDate( QDate::currentDate() ).toString( Qt::ISODate ) +
 
303
                        " " + QTime( QTime::currentTime() ).
 
304
                                                        toString( Qt::ISODate );
 
305
        const QString dir = localSystem::snapshotDir();
 
306
        if( !localSystem::ensurePathExists( dir ) )
 
307
        {
 
308
                messageBox::information( tr( "Snapshot" ),
 
309
                        tr( "Could not take a snapshot as directory %1 doesn't "
 
310
                                "exist and couldn't be created." ).arg( dir ) );
 
311
                return( FALSE );
 
312
        }
 
313
 
 
314
        // construct filename
 
315
        QString file_name =  "_" + host() + "_" + QDate( QDate::currentDate() ).
 
316
                                                toString( Qt::ISODate ) +
 
317
                                "_" + QTime( QTime::currentTime() ).
 
318
                                        toString( Qt::ISODate ) + ".png";
 
319
        file_name.replace( ':', '-' );
 
320
        file_name = dir + user().section( '(', 1, 1 ).section( ')', 0, 0 ) +
 
321
                                                                file_name;
 
322
        const int FONT_SIZE = 14;
 
323
        const int RECT_MARGIN = 10;
 
324
        const int RECT_INNER_MARGIN = 5;
 
325
 
 
326
        QImage img( screen() );
 
327
 
 
328
        QPixmap italc_icon( QPixmap(
 
329
                        ":/resources/client_observed.png" ) );
 
330
 
 
331
        QPainter p( &img );
 
332
        QFont fnt = p.font();
 
333
        fnt.setPointSize( FONT_SIZE );
 
334
        fnt.setBold( TRUE );
 
335
        p.setFont( fnt );
 
336
        QFontMetrics fm( p.font() );
 
337
 
 
338
        const int rx = RECT_MARGIN;
 
339
        const int ry = img.height() - RECT_MARGIN - 2 * RECT_INNER_MARGIN -
 
340
                                                                FONT_SIZE;
 
341
        const int rw = RECT_MARGIN + 4 * RECT_INNER_MARGIN +
 
342
                                fm.size( Qt::TextSingleLine, txt ).width() +
 
343
                                                        italc_icon.width();
 
344
        const int rh = 2 * RECT_INNER_MARGIN + FONT_SIZE;
 
345
        const int ix = rx + RECT_INNER_MARGIN;
 
346
        const int iy = ry + RECT_INNER_MARGIN;
 
347
        const int tx = ix + italc_icon.width() + 2 * RECT_INNER_MARGIN;
 
348
        const int ty = ry + RECT_INNER_MARGIN + FONT_SIZE - 2;
 
349
 
 
350
        p.fillRect( rx, ry, rw, rh, QColor( 255, 255, 255, 128 ) );
 
351
        p.drawPixmap( ix, iy, italc_icon );
 
352
        p.drawText( tx, ty, txt );
 
353
        img.save( file_name, "PNG", 50 );
 
354
 
 
355
        return( TRUE );
 
356
}
 
357
 
 
358
 
 
359
 
 
360
 
 
361
bool ivsConnection::sendFramebufferUpdateRequest( void )
 
362
{
 
363
        return( sendFramebufferUpdateRequest( 0, 0, m_si.framebufferWidth,
 
364
                                        m_si.framebufferHeight, FALSE ) );
 
365
}
 
366
 
 
367
 
 
368
 
 
369
 
 
370
bool ivsConnection::sendIncrementalFramebufferUpdateRequest( void )
 
371
{
 
372
        return( sendFramebufferUpdateRequest( 0, 0, m_si.framebufferWidth,
 
373
                                        m_si.framebufferHeight, TRUE ) );
 
374
}
 
375
 
 
376
 
 
377
 
 
378
 
 
379
bool ivsConnection::sendFramebufferUpdateRequest( Q_UINT16 _x, Q_UINT16 _y,
 
380
                                Q_UINT16 _w, Q_UINT16 _h, bool _incremental )
 
381
{
 
382
        if( state() != Connected )
 
383
        {
 
384
                return( FALSE );
 
385
        }
 
386
 
 
387
        rfbFramebufferUpdateRequestMsg fur;
 
388
 
 
389
        fur.type = rfbFramebufferUpdateRequest;
 
390
        fur.incremental = ( _incremental ) ? 1 : 0;
 
391
        fur.x = swap16IfLE( _x );
 
392
        fur.y = swap16IfLE( _y );
 
393
        fur.w = swap16IfLE( _w );
 
394
        fur.h = swap16IfLE( _h );
 
395
 
 
396
        return( writeToServer( (char *) &fur, sizeof( fur ) ) );
 
397
}
 
398
 
 
399
 
 
400
 
 
401
 
 
402
bool ivsConnection::sendPointerEvent( Q_UINT16 _x, Q_UINT16 _y,
 
403
                                                        Q_UINT16 _button_mask )
 
404
{
 
405
        if( state() != Connected )
 
406
        {
 
407
                return( FALSE );
 
408
        }
 
409
 
 
410
        rfbPointerEventMsg pe;
 
411
 
 
412
        pe.type = rfbPointerEvent;
 
413
        pe.buttonMask = _button_mask;
 
414
        //if (_x < 0) _x = 0;
 
415
        //if (_y < 0) _y = 0;
 
416
        pe.x = swap16IfLE( _x );
 
417
        pe.y = swap16IfLE( _y );
 
418
 
 
419
        // make sure our own pointer is updated when remote-controlling
 
420
        handleCursorPos( _x, _y );
 
421
 
 
422
        return( writeToServer( (char *) &pe, sizeof( pe ) ) );
 
423
}
 
424
 
 
425
 
 
426
 
 
427
 
 
428
bool ivsConnection::sendKeyEvent( Q_UINT32 key, bool down )
 
429
{
 
430
        if( state() != Connected )
 
431
        {
 
432
                return( FALSE );
 
433
        }
 
434
 
 
435
        rfbKeyEventMsg ke;
 
436
 
 
437
        ke.type = rfbKeyEvent;
 
438
        ke.down = ( down )? 1 : 0;
 
439
        ke.key = swap32IfLE( key );
 
440
 
 
441
        return( writeToServer( (char *) &ke, sizeof( ke ) ) );
 
442
}
 
443
 
 
444
 
 
445
 
 
446
 
 
447
void ivsConnection::postRegionChangedEvent( const QRegion & _rgn )
 
448
{
 
449
        if( parent() != NULL )
 
450
        {
 
451
                regionChangedEvent * rche = new regionChangedEvent( _rgn );
 
452
                QCoreApplication::postEvent( parent(), rche );
 
453
        }
 
454
}
 
455
 
 
456
 
 
457
 
 
458
 
 
459
void ivsConnection::rescaleScreen( void )
 
460
{
 
461
        if( m_scaledScreenNeedsUpdate )
 
462
        {
 
463
                QWriteLocker swl( &m_scaledImageLock );
 
464
                if( m_scaledScreen.size() != m_scaledSize )
 
465
                {
 
466
                        m_scaledScreen = QImage( m_scaledSize,
 
467
                                                        QImage::Format_RGB32 );
 
468
                }
 
469
                if( m_screen.size().isValid() )
 
470
                {
 
471
                        m_screen.scaleTo( m_scaledScreen );
 
472
                }
 
473
                else
 
474
                {
 
475
                        m_scaledScreen.fill( Qt::black );
 
476
                }
 
477
                m_scaledScreenNeedsUpdate = FALSE;
 
478
        }
 
479
}
 
480
 
 
481
 
 
482
 
 
483
 
 
484
bool ivsConnection::handleServerMessages( bool _send_screen_update, int _tries )
 
485
{
 
486
        while( hasData() && --_tries >= 0 )
 
487
        {
 
488
 
 
489
        rfbServerToClientMsg msg;
 
490
        if( !readFromServer( (char *) &msg, sizeof( Q_UINT8 ) ) )
 
491
        {
 
492
                qWarning( "ivsConnection::handleServerMessage(...): "
 
493
                                                "reading message-type failed" );
 
494
                return( FALSE );
 
495
        }
 
496
        switch( msg.type )
 
497
        {
 
498
                case rfbSetColourMapEntries:
 
499
                        qWarning( "ivsConnection::handleServerMessage(...): "
 
500
                        "setting colormap entries requested - ignoring" );
 
501
                        break;
 
502
 
 
503
                case rfbFramebufferUpdate:
 
504
                {
 
505
                        QWriteLocker wl( &m_imageLock );
 
506
                        if( !readFromServer( ( (char *)&msg.fu ) + 1,
 
507
                                sizeof( rfbFramebufferUpdateMsg ) - 1 ) )
 
508
                        {
 
509
        qCritical( "ivsConnection::handleServerMessage(...): "
 
510
                        "reading framebuffer-update-msg failed" );
 
511
                                return( FALSE );
 
512
                        }
 
513
 
 
514
                        msg.fu.nRects = swap16IfLE( msg.fu.nRects );
 
515
 
 
516
                        QRegion updated_region;
 
517
 
 
518
                        rfbFramebufferUpdateRectHeader rect;
 
519
                        for( Q_UINT16 i = 0; i < msg.fu.nRects; i++ )
 
520
                        {
 
521
                                if( !readFromServer( (char *)&rect,
 
522
                                                        sizeof( rect ) ) )
 
523
                                {
 
524
                                        return( FALSE );
 
525
                                }
 
526
 
 
527
                                rect.r.x = swap16IfLE( rect.r.x );
 
528
                                rect.r.y = swap16IfLE( rect.r.y );
 
529
                                rect.r.w = swap16IfLE( rect.r.w );
 
530
                                rect.r.h = swap16IfLE( rect.r.h );
 
531
 
 
532
                                rect.encoding = swap32IfLE( rect.encoding );
 
533
                                if( rect.encoding == rfbEncodingLastRect )
 
534
                                {
 
535
                                        break;
 
536
                                }
 
537
 
 
538
                                if( ( rect.r.x + rect.r.w >
 
539
                                                m_si.framebufferWidth ) ||
 
540
                                    ( rect.r.y + rect.r.h >
 
541
                                                m_si.framebufferHeight ) )
 
542
                                {
 
543
        qWarning( "ivsConnection::handleServerMessage(...): "
 
544
                        "rect too large: %dx%d at (%d, %d) (encoding: %d)",
 
545
                        rect.r.w, rect.r.h, rect.r.x, rect.r.y, rect.encoding );
 
546
                                        return( FALSE );
 
547
                                }
 
548
 
 
549
                                if ( rect.encoding != rfbEncodingPointerPos &&
 
550
                                rect.encoding != rfbEncodingXCursor &&
 
551
                                rect.encoding != rfbEncodingRichCursor )
 
552
                                {
 
553
                                        if( ( rect.r.h * rect.r.w ) == 0 )
 
554
                                        {
 
555
        qWarning( "ivsConnection::handleServerMessage(...): zero size rect - "
 
556
                                                                "ignoring" );
 
557
                                                continue;
 
558
                                        }
 
559
                                        updated_region += QRect( rect.r.x,
 
560
                                                                rect.r.y,
 
561
                                                                rect.r.w,
 
562
                                                                rect.r.h );
 
563
                                }
 
564
                                else
 
565
                                {
 
566
                                        m_softwareCursor = TRUE;
 
567
                                }
 
568
 
 
569
                                switch( rect.encoding )
 
570
                                {
 
571
                                        case rfbEncodingRaw:
 
572
                if( !handleRaw( rect.r.x, rect.r.y, rect.r.w, rect.r.h ) )
 
573
                {
 
574
                        return( FALSE );
 
575
                }
 
576
                break;
 
577
 
 
578
                                        case rfbEncodingCopyRect:
 
579
                                        {
 
580
                rfbCopyRect cr;
 
581
                if( !readFromServer( (char *) &cr, sizeof( cr ) ) )
 
582
                {
 
583
                        return( FALSE );
 
584
                }
 
585
                cr.srcX = swap16IfLE( cr.srcX );
 
586
                cr.srcY = swap16IfLE( cr.srcY );
 
587
 
 
588
                m_screen.copyExistingRect( cr.srcX, cr.srcY, rect.r.w,
 
589
                                                rect.r.h, rect.r.x, rect.r.y );
 
590
                break;
 
591
                                        }
 
592
 
 
593
                                        case rfbEncodingRRE:
 
594
                if( !handleRRE( rect.r.x, rect.r.y, rect.r.w, rect.r.h ) )
 
595
                {
 
596
                        return( FALSE );
 
597
                }
 
598
                break;
 
599
 
 
600
                                        case rfbEncodingCoRRE:
 
601
                if( !handleCoRRE( rect.r.x, rect.r.y, rect.r.w, rect.r.h ) )
 
602
                {
 
603
                        return( FALSE );
 
604
                }
 
605
                break;
 
606
#ifdef HAVE_LIBZ
 
607
                                        case rfbEncodingZlib:
 
608
                if( !handleZlib( rect.r.x, rect.r.y, rect.r.w, rect.r.h ) )
 
609
                {
 
610
                                return( FALSE );
 
611
                }
 
612
                break;
 
613
                                        case rfbEncodingTight:
 
614
                if( !handleTight( rect.r.x, rect.r.y, rect.r.w, rect.r.h ) )
 
615
                {
 
616
                                return( FALSE );
 
617
                }
 
618
                break;
 
619
#endif
 
620
                                        case rfbEncodingPointerPos:
 
621
                if( !handleCursorPos( rect.r.x, rect.r.y ) )
 
622
                {
 
623
                                return( FALSE );
 
624
                }
 
625
                break;
 
626
 
 
627
                                        case rfbEncodingRichCursor:
 
628
                                        case rfbEncodingXCursor:
 
629
                if( !handleCursorShape( rect.r.x, rect.r.y, rect.r.w,
 
630
                                                rect.r.h, rect.encoding ) )
 
631
                {
 
632
                                return( FALSE );
 
633
                }
 
634
                break;
 
635
 
 
636
                                        case rfbEncodingItalc:
 
637
                if( !handleItalc( rect.r.x, rect.r.y, rect.r.w, rect.r.h ) )
 
638
                {
 
639
                        return( FALSE );
 
640
                }
 
641
                break;
 
642
 
 
643
                                        case rfbEncodingItalcCursor:
 
644
        {
 
645
                QRegion ch_reg = QRect( m_cursorPos - m_cursorHotSpot,
 
646
                                                        m_cursorShape.size() );
 
647
                m_cursorLock.lockForWrite();
 
648
                //m_cursorShape = socketDev().read().value<QImage>();
 
649
                QDataStream ds( static_cast<QTcpSocket *>(
 
650
                                                        socketDev().user() ) );
 
651
                ds >> m_cursorShape;
 
652
                m_cursorLock.unlock();
 
653
                m_cursorHotSpot = QPoint( rect.r.x, rect.r.y );
 
654
 
 
655
 
 
656
                ch_reg += QRect( m_cursorPos - m_cursorHotSpot,
 
657
                                                        m_cursorShape.size() );
 
658
 
 
659
                // make sure, area around old cursor is updated and new cursor
 
660
                // is painted
 
661
                postRegionChangedEvent( ch_reg );
 
662
                break;
 
663
        }
 
664
 
 
665
                                        default:
 
666
                qCritical( "ivsConnection::handleServerMessage(...): "
 
667
                                "unknown rect encoding %d",
 
668
                                                        (int) rect.encoding );
 
669
                close();
 
670
                return( FALSE );
 
671
                                }
 
672
                        }
 
673
 
 
674
                        if( updated_region.isEmpty() )
 
675
                        {
 
676
                                wl.unlock();
 
677
                                break;
 
678
                        }
 
679
 
 
680
                        m_scaledScreenNeedsUpdate = TRUE;
 
681
 
 
682
                        if( m_quality >= QualityDemoLow &&
 
683
                                                m_quality != QualityDemoHigh )
 
684
                        {
 
685
        const QRgb and_value = ( m_quality == QualityDemoLow ) ?
 
686
                                                        0xf8f8f8 : 0xfcfcfc;
 
687
                                // if we're providing data for demo-purposes,
 
688
                                // we perform a simple color-reduction for
 
689
                                // better compression-results
 
690
        const QVector<QRect> rects = updated_region.rects();
 
691
        for( QVector<QRect>::const_iterator it = rects.begin();
 
692
                                        it != rects.end(); ++it )
 
693
        {
 
694
                for( Q_UINT16 y = 0; y < it->height(); ++y )
 
695
                {
 
696
                        QRgb * data = ( (QRgb *) m_screen.scanLine( y +
 
697
                                                        it->y() ) ) + it->x();
 
698
                        for( Q_UINT16 x = 0; x < it->width(); ++x )
 
699
                        {
 
700
                                data[x] &= and_value;
 
701
                        }
 
702
                }
 
703
        }
 
704
                        }
 
705
                        postRegionChangedEvent( updated_region );
 
706
 
 
707
                        wl.unlock();
 
708
                        emit regionUpdated( updated_region );
 
709
 
 
710
                        break;
 
711
                }
 
712
 
 
713
                case rfbBell:
 
714
                        // FIXME: bell-action
 
715
                        break;
 
716
 
 
717
                case rfbServerCutText:
 
718
                {
 
719
                        if( !readFromServer( ( (char *) &msg ) + 1,
 
720
                                        sizeof( rfbServerCutTextMsg ) - 1 ) )
 
721
                        {
 
722
                                return( FALSE );
 
723
                        }
 
724
                        msg.sct.length = swap32IfLE( msg.sct.length );
 
725
                        char * server_cut_text = new char[msg.sct.length+1];
 
726
                        if( !readFromServer( server_cut_text, msg.sct.length ) )
 
727
                        {
 
728
                                delete[] server_cut_text;
 
729
                                return( FALSE );
 
730
                        }
 
731
                        delete[] server_cut_text;
 
732
                        break;
 
733
                }
 
734
 
 
735
                default:
 
736
                        if( !isdConnection::handleServerMessage( msg.type ) )
 
737
                        {
 
738
                                return( FALSE );
 
739
                        }
 
740
        }
 
741
 
 
742
        }       // end while( ... )
 
743
 
 
744
        if( !m_scaledSize.isEmpty() )
 
745
        {
 
746
                rescaleScreen();
 
747
        }
 
748
 
 
749
        if( _send_screen_update )
 
750
        {
 
751
                return( sendIncrementalFramebufferUpdateRequest() );
 
752
        }
 
753
 
 
754
        return( TRUE );
 
755
}
 
756
 
 
757
 
 
758
 
 
759
 
 
760
 
 
761
// =============================================================================
 
762
// functions for decoding rects
 
763
// =============================================================================
 
764
 
 
765
 
 
766
bool ivsConnection::handleRaw( Q_UINT16 rx, Q_UINT16 ry, Q_UINT16 rw,
 
767
                                                                Q_UINT16 rh )
 
768
{
 
769
        const int bytes_per_line = rw * sizeof( QRgb );
 
770
        Q_UINT16 lines_to_read = BUFFER_SIZE / bytes_per_line;
 
771
        const Q_UINT16 img_width = m_screen.width();
 
772
        while( rh > 0 )
 
773
        {
 
774
                if( lines_to_read > rh )
 
775
                {
 
776
                        lines_to_read = rh;
 
777
                }
 
778
                if( !readFromServer( m_buffer, bytes_per_line *
 
779
                                                        lines_to_read ) )
 
780
                {
 
781
                        return( FALSE );
 
782
                }
 
783
                const QRgb * src = (const QRgb *) m_buffer;
 
784
                QRgb * dst = (QRgb *) m_screen.scanLine( ry ) + rx;
 
785
                for( Q_UINT16 y = 0; y < lines_to_read; ++y )
 
786
                {
 
787
                        memcpy( dst, src, rw * sizeof( QRgb ) );
 
788
                        src += rw;
 
789
                        dst += img_width;
 
790
                }
 
791
                rh -= lines_to_read;
 
792
                ry += lines_to_read;
 
793
        }
 
794
        return( TRUE );
 
795
}
 
796
 
 
797
 
 
798
 
 
799
 
 
800
bool ivsConnection::handleCoRRE( Q_UINT16 rx, Q_UINT16 ry, Q_UINT16 rw,
 
801
                                                                Q_UINT16 rh )
 
802
{
 
803
        rfbRREHeader hdr;
 
804
 
 
805
        if( !readFromServer( (char *) &hdr, sizeof( hdr ) ) )
 
806
        {
 
807
                return( FALSE );
 
808
        }
 
809
 
 
810
        hdr.nSubrects = swap32IfLE( hdr.nSubrects );
 
811
 
 
812
        QRgb pix;
 
813
        if( !readFromServer( (char *) &pix, sizeof( pix ) ) )
 
814
        {
 
815
                return( FALSE );
 
816
        }
 
817
 
 
818
        m_screen.fillRect( rx, ry, rw, rh, pix );
 
819
 
 
820
        if( !readFromServer( m_buffer, hdr.nSubrects *
 
821
                                ( sizeof( rfbCoRRERectangle) +
 
822
                                                sizeof( Q_UINT32 ) ) ) )
 
823
        {
 
824
                return( FALSE );
 
825
        }
 
826
 
 
827
        Q_UINT8 * ptr = (Q_UINT8 *) m_buffer;
 
828
 
 
829
        for( Q_UINT32 i = 0; i < hdr.nSubrects; i++ )
 
830
        {
 
831
                pix = *(QRgb *) ptr;
 
832
                ptr += sizeof( pix );
 
833
                Q_UINT8 x = *ptr++;
 
834
                Q_UINT8 y = *ptr++;
 
835
                Q_UINT8 w = *ptr++;
 
836
                Q_UINT8 h = *ptr++;
 
837
                m_screen.fillRect( rx+x, ry+y, w, h, pix );
 
838
        }
 
839
 
 
840
        return( TRUE );
 
841
}
 
842
 
 
843
 
 
844
 
 
845
bool ivsConnection::handleRRE( Q_UINT16, Q_UINT16, Q_UINT16, Q_UINT16 )
 
846
{
 
847
        qCritical( "ivsConnection:handleRRE(...): got RRE-encoded rect. "
 
848
                                                        "Can't decode." );
 
849
        return( TRUE );
 
850
}
 
851
 
 
852
 
 
853
#define RGB_TO_PIXEL(r,g,b)                                             \
 
854
  (((Q_UINT32)(r) & __localDisplayFormat.redMax ) <<                    \
 
855
                                __localDisplayFormat.redShift |         \
 
856
   ((Q_UINT32)(g) & __localDisplayFormat.greenMax ) <<                  \
 
857
                                __localDisplayFormat.greenShift |       \
 
858
   ((Q_UINT32)(b) & __localDisplayFormat.blueMax ) <<                   \
 
859
                                __localDisplayFormat.blueShift )
 
860
 
 
861
 
 
862
#define RGB24_TO_PIXEL(r,g,b)                                           \
 
863
   ((((uint32_t)(r) & 0xFF) * __localDisplayFormat.redMax + 127) / 255             \
 
864
    << __localDisplayFormat.redShift |                                              \
 
865
    (((uint32_t)(g) & 0xFF) * __localDisplayFormat.greenMax + 127) / 255           \
 
866
    << __localDisplayFormat.greenShift |                                            \
 
867
    (((uint32_t)(b) & 0xFF) * __localDisplayFormat.blueMax + 127) / 255            \
 
868
    << __localDisplayFormat.blueShift)
 
869
 
 
870
#ifdef HAVE_LIBZ
 
871
 
 
872
 
 
873
bool ivsConnection::handleZlib( Q_UINT16 rx, Q_UINT16 ry, Q_UINT16 rw,
 
874
                                                                Q_UINT16 rh )
 
875
{
 
876
        /* First make sure we have a large enough raw buffer to hold the
 
877
        * decompressed data.  In practice, with a fixed BPP, fixed frame
 
878
        * buffer size and the first update containing the entire frame
 
879
        * buffer, this buffer allocation should only happen once, on the
 
880
        * first update.
 
881
        */
 
882
        if( m_rawBufferSize <  (int) rw * rh * 4 )
 
883
        {
 
884
                delete[] m_rawBuffer;
 
885
                m_rawBufferSize = (int) rw * rh * 4;
 
886
                m_rawBuffer = new char[m_rawBufferSize];
 
887
        }
 
888
 
 
889
        rfbZlibHeader hdr;
 
890
        if( !readFromServer( (char *) &hdr, sz_rfbZlibHeader ) )
 
891
        {
 
892
                return( FALSE );
 
893
        }
 
894
 
 
895
        int remaining = swap32IfLE( hdr.nBytes );
 
896
 
 
897
        // Need to initialize the decompressor state
 
898
        m_decompStream.next_in   = ( Bytef * ) m_buffer;
 
899
        m_decompStream.avail_in  = 0;
 
900
        m_decompStream.next_out  = ( Bytef * ) m_rawBuffer;
 
901
        m_decompStream.avail_out = m_rawBufferSize;
 
902
        m_decompStream.data_type = Z_BINARY;
 
903
 
 
904
        int inflateResult;
 
905
        // Initialize the decompression stream structures on the first
 
906
        // invocation.
 
907
        if( !m_decompStreamInited )
 
908
        {
 
909
                inflateResult = inflateInit( &m_decompStream );
 
910
 
 
911
                if ( inflateResult != Z_OK )
 
912
                {
 
913
                        qCritical( "inflateInit returned error: %d, msg: %s",
 
914
                                        inflateResult, m_decompStream.msg );
 
915
                        return( FALSE );
 
916
                }
 
917
                m_decompStreamInited = TRUE;
 
918
        }
 
919
 
 
920
        inflateResult = Z_OK;
 
921
 
 
922
        // Process buffer full of data until no more to process, or
 
923
        // some type of inflater error, or Z_STREAM_END.
 
924
        while( remaining > 0 && inflateResult == Z_OK )
 
925
        {
 
926
                int toRead;
 
927
                if( remaining > BUFFER_SIZE )
 
928
                {
 
929
                        toRead = BUFFER_SIZE;
 
930
                }
 
931
                else
 
932
                {
 
933
                        toRead = remaining;
 
934
                }
 
935
 
 
936
                // Fill the buffer, obtaining data from the server.
 
937
                if( !readFromServer( m_buffer, toRead ) )
 
938
                {
 
939
                        return( FALSE );
 
940
                }
 
941
 
 
942
                m_decompStream.next_in  = ( Bytef * ) m_buffer;
 
943
                m_decompStream.avail_in = toRead;
 
944
 
 
945
                // Need to uncompress buffer full.
 
946
                inflateResult = inflate( &m_decompStream, Z_SYNC_FLUSH );
 
947
 
 
948
                // We never supply a dictionary for compression. */
 
949
                if( inflateResult == Z_NEED_DICT )
 
950
                {
 
951
                        qCritical( "ivsConnection::handleZlib(...): "
 
952
                                        "zlib inflate needs a dictionary!" );
 
953
                        return( FALSE );
 
954
                }
 
955
                if ( inflateResult < 0 )
 
956
                {
 
957
                        qCritical( "ivsConnection::handleZlib(...): "
 
958
                                "zlib inflate returned error: %d, msg: %s",
 
959
                                        inflateResult, m_decompStream.msg );
 
960
                        return( FALSE );
 
961
                }
 
962
 
 
963
                // Result buffer allocated to be at least large enough.
 
964
                // We should never run out of space!
 
965
                if( m_decompStream.avail_in > 0 &&
 
966
                                                m_decompStream.avail_out <= 0 )
 
967
                {
 
968
                        qCritical( "ivsConnection::handleZlib(...): "
 
969
                                        "zlib inflate ran out of space!" );
 
970
                        return( FALSE );
 
971
                }
 
972
 
 
973
                remaining -= toRead;
 
974
 
 
975
        } // while ( remaining > 0 )
 
976
 
 
977
        if( inflateResult == Z_OK )
 
978
        {
 
979
                m_screen.copyRect( rx, ry, rw, rh, (QRgb *) m_rawBuffer );
 
980
        }
 
981
        else
 
982
        {
 
983
                qCritical( "ivsConnection::handleZlib(...): "
 
984
                                "zlib inflate returned error: %d, msg: %s",
 
985
                                        inflateResult, m_decompStream.msg );
 
986
                return( FALSE );
 
987
        }
 
988
 
 
989
        return( TRUE );
 
990
}
 
991
 
 
992
 
 
993
 
 
994
#define TIGHT_MIN_TO_COMPRESS 12
 
995
 
 
996
 
 
997
 
 
998
// type declarations
 
999
 
 
1000
typedef void( ivsConnection:: *filterPtr )( Q_UINT16, Q_UINT32 * );
 
1001
 
 
1002
 
 
1003
 
 
1004
// Definitions
 
1005
 
 
1006
bool ivsConnection::handleTight( Q_UINT16 rx, Q_UINT16 ry, Q_UINT16 rw,
 
1007
                                                                Q_UINT16 rh )
 
1008
{
 
1009
        QRgb fill_color;
 
1010
        Q_UINT8 comp_ctl;
 
1011
 
 
1012
        if( !readFromServer( (char *) &comp_ctl, 1 ) )
 
1013
        {
 
1014
                return( FALSE );
 
1015
        }
 
1016
 
 
1017
        // Flush zlib streams if we are told by the server to do so.
 
1018
        for( Q_UINT8 stream_id = 0; stream_id < 4; stream_id++ )
 
1019
        {
 
1020
                if( ( comp_ctl & 1 ) && m_zlibStreamActive[stream_id] )
 
1021
                {
 
1022
                        if( inflateEnd( &m_zlibStream[stream_id] ) != Z_OK &&
 
1023
                                        m_zlibStream[stream_id].msg != NULL )
 
1024
                        {
 
1025
                                qCritical( "inflateEnd: %s",
 
1026
                                                m_zlibStream[stream_id].msg );
 
1027
                        }
 
1028
                        m_zlibStreamActive[stream_id] = FALSE;
 
1029
                }
 
1030
                comp_ctl >>= 1;
 
1031
        }
 
1032
 
 
1033
        // Handle solid rectangles.
 
1034
        if( comp_ctl == rfbTightFill )
 
1035
        {
 
1036
                if( !readFromServer( (char*)&fill_color,
 
1037
                                                        sizeof( fill_color ) ) )
 
1038
                {
 
1039
                        return( FALSE );
 
1040
                }
 
1041
                m_screen.fillRect( rx, ry, rw, rh, fill_color );
 
1042
                return( TRUE );
 
1043
        }
 
1044
 
 
1045
        if( comp_ctl == rfbTightJpeg )
 
1046
        {
 
1047
#ifdef HAVE_LIBJPEG
 
1048
                return( decompressJpegRect( rx, ry, rw, rh ) );
 
1049
#else
 
1050
                return ( -1 );
 
1051
#endif
 
1052
        }
 
1053
 
 
1054
 
 
1055
        // Quit on unsupported subencoding value.
 
1056
        if( comp_ctl > rfbTightMaxSubencoding)
 
1057
        {
 
1058
                qCritical( "tight encoding: bad subencoding value received." );
 
1059
                return( FALSE );
 
1060
        }
 
1061
 
 
1062
        // Here primary compression mode handling begins.
 
1063
        // Data was processed with optional filter + zlib compression.
 
1064
        filterPtr filter_function;
 
1065
        Q_UINT8 bits_pixel;
 
1066
 
 
1067
        // First, we should identify a filter to use.
 
1068
        if( ( comp_ctl & rfbTightExplicitFilter ) != 0 )
 
1069
        {
 
1070
                Q_UINT8 filter_id;
 
1071
                if( !readFromServer( (char*) &filter_id, 1 ) )
 
1072
                {
 
1073
                        return( FALSE );
 
1074
                }
 
1075
 
 
1076
                switch( filter_id )
 
1077
                {
 
1078
                        case rfbTightFilterCopy:
 
1079
                                filter_function = &ivsConnection::filterCopy;
 
1080
                                bits_pixel = initFilterCopy( rw, rh );
 
1081
                                break;
 
1082
                        case rfbTightFilterPalette:
 
1083
                                filter_function = &ivsConnection::filterPalette;
 
1084
                                bits_pixel = initFilterPalette( rw, rh );
 
1085
                                break;
 
1086
                        case rfbTightFilterGradient:
 
1087
                                filter_function =
 
1088
                                                &ivsConnection::filterGradient;
 
1089
                                bits_pixel = initFilterGradient( rw, rh );
 
1090
                                break;
 
1091
                        default:
 
1092
                                qCritical( "Tight encoding: unknown filter "
 
1093
                                                        "code received." );
 
1094
                                return( FALSE );
 
1095
                }
 
1096
        }
 
1097
        else
 
1098
        {
 
1099
                filter_function = &ivsConnection::filterCopy;
 
1100
                bits_pixel = initFilterCopy( rw, rh );
 
1101
        }
 
1102
 
 
1103
        if( bits_pixel == 0 )
 
1104
        {
 
1105
                qCritical( "Tight encoding: error receiving palette." );
 
1106
                return( FALSE );
 
1107
        }
 
1108
 
 
1109
 
 
1110
        // Determine if the data should be decompressed or just copied.
 
1111
        Q_UINT16 row_size = ( (int) rw * bits_pixel + 7 ) / 8;
 
1112
        if( rh * row_size < TIGHT_MIN_TO_COMPRESS )
 
1113
        {
 
1114
                if( !readFromServer( (char*)m_buffer, rh * row_size ) )
 
1115
                {
 
1116
                        return( FALSE );
 
1117
                }
 
1118
 
 
1119
                QRgb * buffer2 = (QRgb *) &m_buffer[TIGHT_MIN_TO_COMPRESS * 4];
 
1120
                ( this->*( filter_function ) )( rh, (Q_UINT32 *)buffer2 );
 
1121
                m_screen.copyRect( rx, ry, rw, rh, buffer2 );
 
1122
                return( TRUE );
 
1123
        }
 
1124
 
 
1125
        // Read the length (1..3 bytes) of compressed data following.
 
1126
        int compressed_len = (int)readCompactLen();
 
1127
        if( compressed_len <= 0 )
 
1128
        {
 
1129
                qCritical( "Incorrect data received from the server." );
 
1130
                return( FALSE );
 
1131
        }
 
1132
 
 
1133
 
 
1134
        // Now let's initialize compression stream if needed.
 
1135
        Q_UINT8 stream_id = comp_ctl & 0x03;
 
1136
        z_streamp zs = &m_zlibStream[stream_id];
 
1137
        if( !m_zlibStreamActive[stream_id] )
 
1138
        {
 
1139
                zs->zalloc = Z_NULL;
 
1140
                zs->zfree = Z_NULL;
 
1141
                zs->opaque = Z_NULL;
 
1142
                int err = inflateInit( zs );
 
1143
                if( err != Z_OK )
 
1144
                {
 
1145
                        if( zs->msg != NULL )
 
1146
                        {
 
1147
                                qCritical( "InflateInit error: %s", zs->msg );
 
1148
                        }
 
1149
                        return( FALSE );
 
1150
                }
 
1151
                m_zlibStreamActive[stream_id] = TRUE;
 
1152
        }
 
1153
 
 
1154
 
 
1155
        // Read, decode and draw actual pixel data in a loop.
 
1156
        int buffer_size = BUFFER_SIZE * bits_pixel / ( bits_pixel+32 ) &
 
1157
                                                                0xfffffffc;
 
1158
        if( row_size > buffer_size )
 
1159
        {
 
1160
                // Should be impossible when BUFFER_SIZE >= 16384
 
1161
                qCritical( "Internal error: incorrect buffer size." );
 
1162
                return( FALSE );
 
1163
        }
 
1164
        QRgb * buffer2 = (QRgb *) &m_buffer[buffer_size];
 
1165
 
 
1166
 
 
1167
        Q_UINT16 rows_processed = 0;
 
1168
        int extra_bytes = 0;
 
1169
        int portion_len;
 
1170
 
 
1171
        while( compressed_len > 0 )
 
1172
        {
 
1173
                if( compressed_len > ZLIB_BUFFER_SIZE ) 
 
1174
                {
 
1175
                        portion_len = ZLIB_BUFFER_SIZE;
 
1176
                }
 
1177
                else
 
1178
                {
 
1179
                        portion_len = compressed_len;
 
1180
                }
 
1181
 
 
1182
                if( !readFromServer( (char*)m_zlibBuffer, portion_len ) )
 
1183
                {
 
1184
                        return( FALSE );
 
1185
                }
 
1186
 
 
1187
                compressed_len -= portion_len;
 
1188
 
 
1189
                zs->next_in = (Bytef *)m_zlibBuffer;
 
1190
                zs->avail_in = portion_len;
 
1191
 
 
1192
                do
 
1193
                {
 
1194
                        zs->next_out = (Bytef *) &m_buffer[extra_bytes];
 
1195
                        zs->avail_out = buffer_size - extra_bytes;
 
1196
 
 
1197
                        int err = inflate(zs, Z_SYNC_FLUSH);
 
1198
                        if( err == Z_BUF_ERROR )        // Input exhausted --
 
1199
                                                        // no problem.
 
1200
                        {
 
1201
                                break;
 
1202
                        }
 
1203
                        if( err != Z_OK && err != Z_STREAM_END )
 
1204
                        {
 
1205
                                if( zs->msg != NULL )
 
1206
                                {
 
1207
                                        qCritical( "Inflate error: %s",
 
1208
                                                                zs->msg );
 
1209
                                }
 
1210
                                else
 
1211
                                {
 
1212
                                        qCritical( "Inflate error: %d", err );
 
1213
                                }
 
1214
                                return( FALSE );
 
1215
                        }
 
1216
 
 
1217
                        const Q_UINT16 num_rows = (Q_UINT16)( ( buffer_size -
 
1218
                                                        zs->avail_out ) /
 
1219
                                                                (int)row_size );
 
1220
 
 
1221
                        ( this->*( filter_function ) )( num_rows,
 
1222
                                                        (Q_UINT32 *)buffer2 );
 
1223
                        extra_bytes = buffer_size - zs->avail_out - num_rows *
 
1224
                                                                row_size;
 
1225
                        if( extra_bytes > 0 )
 
1226
                        {
 
1227
                                memcpy( m_buffer,
 
1228
                                                &m_buffer[num_rows * row_size],
 
1229
                                                                extra_bytes );
 
1230
                        }
 
1231
                        if( num_rows > 0 )
 
1232
                        {
 
1233
                                m_screen.copyRect( rx, ry+rows_processed, rw,
 
1234
                                                        num_rows, buffer2 );
 
1235
                        }
 
1236
                        rows_processed += num_rows;
 
1237
                }
 
1238
                while( zs->avail_out == 0 );
 
1239
        }
 
1240
 
 
1241
        if( rows_processed != rh )
 
1242
        {
 
1243
                qCritical( "Incorrect number of scan lines after "
 
1244
                                                        "decompression" );
 
1245
                return( FALSE );
 
1246
        }
 
1247
 
 
1248
        return( TRUE );
 
1249
}
 
1250
 
 
1251
 
 
1252
 
 
1253
/*----------------------------------------------------------------------------
 
1254
 *
 
1255
 * Filter stuff.
 
1256
 *
 
1257
 */
 
1258
 
 
1259
int ivsConnection::initFilterCopy( Q_UINT16 rw, Q_UINT16/* rh*/ )
 
1260
{
 
1261
        m_rectWidth = rw;
 
1262
 
 
1263
        return( 32 );
 
1264
}
 
1265
 
 
1266
 
 
1267
 
 
1268
 
 
1269
void ivsConnection::filterCopy( Q_UINT16 num_rows, Q_UINT32 * dst )
 
1270
{
 
1271
        memcpy( dst, m_buffer, num_rows * m_rectWidth * 4 );
 
1272
}
 
1273
 
 
1274
 
 
1275
 
 
1276
 
 
1277
int ivsConnection::initFilterGradient( Q_UINT16 rw, Q_UINT16/* rh*/ )
 
1278
{
 
1279
        const int bits = initFilterCopy( rw, 0 );
 
1280
        memset( m_tightPrevRow, 0, rw * 3 * sizeof( uint16_t ) );
 
1281
        return( bits );
 
1282
}
 
1283
 
 
1284
 
 
1285
 
 
1286
 
 
1287
void ivsConnection::filterGradient( Q_UINT16 num_rows, Q_UINT32 * dst )
 
1288
{
 
1289
        Q_UINT32 * src = (Q_UINT32 *) m_buffer;
 
1290
        Q_UINT16 * that_row = (Q_UINT16 *) m_tightPrevRow;
 
1291
        Q_UINT16 this_row[2048*3];
 
1292
        Q_UINT16 pix[3];
 
1293
        const Q_UINT16 max[3] =
 
1294
        {
 
1295
                __localDisplayFormat.redMax,
 
1296
                __localDisplayFormat.greenMax,
 
1297
                __localDisplayFormat.blueMax
 
1298
        } ;
 
1299
        const int shift[3] =
 
1300
        {
 
1301
                __localDisplayFormat.redShift,
 
1302
                __localDisplayFormat.greenShift,
 
1303
                __localDisplayFormat.blueShift
 
1304
        } ;
 
1305
        int est[3];
 
1306
 
 
1307
 
 
1308
        for( Q_UINT16 y = 0; y < num_rows; ++y )
 
1309
        {
 
1310
                // First pixel in a row
 
1311
                for( Q_UINT8 c = 0; c < 3; ++c )
 
1312
                {
 
1313
                        pix[c] = (Q_UINT16)(((src[y*m_rectWidth] >> shift[c]) +
 
1314
                                                        that_row[c]) & max[c]);
 
1315
                        this_row[c] = pix[c];
 
1316
                }
 
1317
                dst[y*m_rectWidth] = RGB_TO_PIXEL( pix[0], pix[1], pix[2] );
 
1318
                // Remaining pixels of a row 
 
1319
                for( Q_UINT16 x = 1; x < m_rectWidth; ++x )
 
1320
                {
 
1321
                        for( Q_UINT8 c = 0; c < 3; ++c )
 
1322
                        {
 
1323
                                est[c] = (int)that_row[x*3+c] +
 
1324
                                                (int)pix[c] -
 
1325
                                                (int)that_row[(x-1)*3+c];
 
1326
                                if( est[c] > (int)max[c] )
 
1327
                                {
 
1328
                                        est[c] = (int)max[c];
 
1329
                                }
 
1330
                                else if( est[c] < 0 )
 
1331
                                {
 
1332
                                        est[c] = 0;
 
1333
                                }
 
1334
                                pix[c] = (Q_UINT16)(((src[y*m_rectWidth+x] >>
 
1335
                                                shift[c]) + est[c]) & max[c]);
 
1336
                                this_row[x*3+c] = pix[c];
 
1337
                        }
 
1338
                        dst[y*m_rectWidth+x] = RGB_TO_PIXEL( pix[0], pix[1],
 
1339
                                                                pix[2] );
 
1340
                }
 
1341
                memcpy( that_row, this_row, m_rectWidth * 3 *
 
1342
                                                        sizeof( Q_UINT16 ) );
 
1343
        }
 
1344
}
 
1345
 
 
1346
 
 
1347
 
 
1348
 
 
1349
int ivsConnection::initFilterPalette( Q_UINT16 rw, Q_UINT16/* rh*/ )
 
1350
{
 
1351
        Q_UINT8 num_colors;
 
1352
 
 
1353
        m_rectWidth = rw;
 
1354
 
 
1355
        if( !readFromServer( (char*)&num_colors, 1 ) )
 
1356
        {
 
1357
                return( 0 );
 
1358
        }
 
1359
 
 
1360
        m_rectColors = (Q_UINT16) num_colors;
 
1361
        if( ++m_rectColors < 2 )
 
1362
        {
 
1363
                return( 0 );
 
1364
        }
 
1365
 
 
1366
        if( !readFromServer( (char*)&m_tightPalette, m_rectColors *
 
1367
                                                        sizeof( Q_UINT32 ) ) )
 
1368
        {
 
1369
                return( 0 );
 
1370
        }
 
1371
 
 
1372
        return( ( m_rectColors == 2 ) ? 1 : 8 );
 
1373
}
 
1374
 
 
1375
 
 
1376
 
 
1377
 
 
1378
void ivsConnection::filterPalette( Q_UINT16 num_rows, Q_UINT32 * dst )
 
1379
{
 
1380
        Q_UINT8 * src = (Q_UINT8 *)m_buffer;
 
1381
        Q_UINT32 * palette = (Q_UINT32 *) m_tightPalette;
 
1382
 
 
1383
        if( m_rectColors == 2 )
 
1384
        {
 
1385
                const Q_UINT16 w = (m_rectWidth + 7) / 8;
 
1386
                for( Q_UINT16 y = 0; y < num_rows; ++y )
 
1387
                {
 
1388
                        int x;
 
1389
                        for( x = 0; x < m_rectWidth/8; x++ )
 
1390
                        {
 
1391
                                for( int b = 7; b >= 0; b-- )
 
1392
                                {
 
1393
                                        dst[y*m_rectWidth+x*8+7-b] =
 
1394
                                                palette[src[y*w+x] >> b & 1];
 
1395
                                }
 
1396
                        }
 
1397
                        for( int b = 7; b >= 8 - m_rectWidth % 8; b-- )
 
1398
                        {
 
1399
                                dst[y*m_rectWidth+x*8+7-b] =
 
1400
                                                palette[src[y*w+x] >> b & 1];
 
1401
                        }
 
1402
                }
 
1403
        }
 
1404
        else
 
1405
        {
 
1406
                for( Q_UINT16 y = 0; y < num_rows; y++ )
 
1407
                {
 
1408
                        for( Q_UINT16 x = 0; x < m_rectWidth; x++ )
 
1409
                        {
 
1410
                                dst[y*m_rectWidth+x] =
 
1411
                                        palette[(int)src[y*m_rectWidth+x]];
 
1412
                        }
 
1413
                }
 
1414
        }
 
1415
}
 
1416
 
 
1417
 
 
1418
#ifdef HAVE_LIBJPEG
 
1419
/*----------------------------------------------------------------------------
 
1420
 *
 
1421
 * JPEG decompression.
 
1422
 *
 
1423
 */
 
1424
 
 
1425
 
 
1426
void jpegInitSource( jpeglib::j_decompress_ptr )
 
1427
{
 
1428
}
 
1429
 
 
1430
 
 
1431
 
 
1432
 
 
1433
jpeglib::boolean jpegFillInputBuffer( jpeglib::j_decompress_ptr )
 
1434
{
 
1435
        qWarning( "jpegFillInputBuffer(...) called (not implemented, "
 
1436
                                        "because it should not be needed" );
 
1437
        return( 0 );
 
1438
}
 
1439
 
 
1440
 
 
1441
 
 
1442
 
 
1443
void jpegSkipInputData( jpeglib::j_decompress_ptr, long )
 
1444
{
 
1445
        qWarning( "jpegSkipInputData(...) called (not implemented, "
 
1446
                                        "because it should not be needed" );
 
1447
}
 
1448
 
 
1449
 
 
1450
 
 
1451
 
 
1452
void jpegTermSource( jpeglib::j_decompress_ptr )
 
1453
{
 
1454
}
 
1455
 
 
1456
 
 
1457
 
 
1458
using jpeglib::jpeg_decompress_struct;
 
1459
 
 
1460
bool ivsConnection::decompressJpegRect( Q_UINT16 x, Q_UINT16 y, Q_UINT16 w,
 
1461
                                                                Q_UINT16 h )
 
1462
{
 
1463
        int compressed_len = (int) readCompactLen();
 
1464
        if( compressed_len <= 0 )
 
1465
        {
 
1466
                qCritical( "ivsConnection::decompressJpegRect(...): "
 
1467
                                "Incorrect data received from the server." );
 
1468
                return( FALSE );
 
1469
        }
 
1470
 
 
1471
        Q_UINT8 * compressed_data = new Q_UINT8[compressed_len];
 
1472
 
 
1473
        if( !readFromServer( (char*)compressed_data, compressed_len ) )
 
1474
        {
 
1475
                delete[] compressed_data;
 
1476
                return( FALSE );
 
1477
        }
 
1478
 
 
1479
        struct jpeglib::jpeg_error_mgr jerr;
 
1480
        struct jpeglib::jpeg_decompress_struct cinfo;
 
1481
        cinfo.err = jpeglib::jpeg_std_error( &jerr );
 
1482
        jpeglib::jpeg_create_decompress( &cinfo );
 
1483
 
 
1484
        //jpegSetSrcManager (&cinfo, compressed_data, compressed_len);
 
1485
        m_jpegSrcManager.init_source = jpegInitSource;
 
1486
        m_jpegSrcManager.fill_input_buffer = jpegFillInputBuffer;
 
1487
        m_jpegSrcManager.skip_input_data = jpegSkipInputData;
 
1488
        m_jpegSrcManager.resync_to_restart = jpeglib::jpeg_resync_to_restart;
 
1489
        m_jpegSrcManager.term_source = jpegTermSource;
 
1490
        m_jpegSrcManager.next_input_byte = (jpeglib::JOCTET *) compressed_data;
 
1491
        m_jpegSrcManager.bytes_in_buffer = (size_t) compressed_len;
 
1492
 
 
1493
        cinfo.src = &m_jpegSrcManager;
 
1494
 
 
1495
 
 
1496
        jpeglib::jpeg_read_header( &cinfo, TRUE );
 
1497
        cinfo.out_color_space = jpeglib::JCS_RGB;
 
1498
 
 
1499
        jpeglib::jpeg_start_decompress( &cinfo );
 
1500
        if( cinfo.output_width != w || cinfo.output_height != h ||
 
1501
                                                cinfo.output_components != 3 )
 
1502
        {
 
1503
                qCritical( "Tight Encoding: Wrong JPEG data received." );
 
1504
                delete[] compressed_data;
 
1505
                jpeglib::jpeg_destroy_decompress( &cinfo );
 
1506
                return( FALSE );
 
1507
        }
 
1508
 
 
1509
        jpeglib::JSAMPROW row_pointer[1];
 
1510
        row_pointer[0] = (jpeglib::JSAMPROW) m_buffer;
 
1511
        int dy = 0;
 
1512
        while( cinfo.output_scanline < cinfo.output_height )
 
1513
        {
 
1514
                jpeglib::jpeg_read_scanlines( &cinfo, row_pointer, 1 );
 
1515
                Q_UINT32 * pixel_ptr = (Q_UINT32 *) &m_buffer[BUFFER_SIZE / 2];
 
1516
                for( Q_UINT16 dx = 0; dx < w; dx++ )
 
1517
                {
 
1518
                        *pixel_ptr++ = RGB_TO_PIXEL( m_buffer[dx*3],
 
1519
                                                        m_buffer[dx*3+1],
 
1520
                                                        m_buffer[dx*3+2] );
 
1521
                }
 
1522
                m_screen.copyRect( x, y+dy, w, 1, (QRgb *)
 
1523
                                                &m_buffer[BUFFER_SIZE / 2] );
 
1524
                dy++;
 
1525
        }
 
1526
 
 
1527
        jpeglib::jpeg_finish_decompress( &cinfo );
 
1528
 
 
1529
        jpeglib::jpeg_destroy_decompress( &cinfo );
 
1530
 
 
1531
        delete[] compressed_data;
 
1532
 
 
1533
        return( TRUE );
 
1534
}
 
1535
 
 
1536
#endif  /* LIBJPEG */
 
1537
 
 
1538
#endif  /* LIBZ */
 
1539
 
 
1540
 
 
1541
 
 
1542
 
 
1543
bool ivsConnection::handleCursorPos( const Q_UINT16 _x, const Q_UINT16 _y )
 
1544
{
 
1545
        // move cursor and update appropriate region
 
1546
        QRegion ch_reg = QRect( m_cursorPos - m_cursorHotSpot,
 
1547
                                                        m_cursorShape.size() );
 
1548
        m_cursorPos = QPoint( _x, _y );
 
1549
        ch_reg += QRect( m_cursorPos - m_cursorHotSpot, m_cursorShape.size() );
 
1550
 
 
1551
        postRegionChangedEvent( ch_reg );
 
1552
 
 
1553
        if( m_quality < QualityDemoLow )
 
1554
        {
 
1555
                emit regionUpdated( ch_reg );
 
1556
        }
 
1557
 
 
1558
        return( TRUE );
 
1559
}
 
1560
 
 
1561
 
 
1562
 
 
1563
 
 
1564
bool ivsConnection::handleCursorShape( const Q_UINT16 _xhot,
 
1565
                                        const Q_UINT16 _yhot,
 
1566
                                        const Q_UINT16 _width,
 
1567
                                        const Q_UINT16 _height,
 
1568
                                        const Q_UINT32 _enc )
 
1569
{
 
1570
        const int bytesPerPixel = __localDisplayFormat.bitsPerPixel / 8;
 
1571
        const int bytesPerRow = ( _width + 7 ) / 8;
 
1572
        const int bytesMaskData = bytesPerRow * _height;
 
1573
        if( _width * _height == 0 )
 
1574
        {
 
1575
                return( TRUE );
 
1576
        }
 
1577
 
 
1578
        // Allocate memory for pixel data and temporary mask data.
 
1579
 
 
1580
        Q_UINT8 * rcSource = new Q_UINT8[_width * _height * bytesPerPixel];
 
1581
        if( rcSource == NULL )
 
1582
        {
 
1583
                return( FALSE );
 
1584
        }
 
1585
 
 
1586
        Q_UINT8 * rcMask = new Q_UINT8[bytesMaskData];
 
1587
        if( rcMask == NULL )
 
1588
        {
 
1589
                delete[] rcSource;
 
1590
                return( FALSE );
 
1591
        }
 
1592
 
 
1593
        // Read and decode cursor pixel data, depending on the encoding type.
 
1594
 
 
1595
        if( _enc == rfbEncodingXCursor )
 
1596
        {
 
1597
                rfbXCursorColors rgb;
 
1598
                // Read and convert background and foreground colors.
 
1599
                if( !readFromServer( (char *) &rgb, sz_rfbXCursorColors ) )
 
1600
                {
 
1601
                        delete[] rcSource;
 
1602
                        delete[] rcMask;
 
1603
                        return( FALSE );
 
1604
                }
 
1605
                const Q_UINT32 colors[2] = {
 
1606
        RGB24_TO_PIXEL( rgb.backRed, rgb.backGreen, rgb.backBlue ),
 
1607
        RGB24_TO_PIXEL( rgb.foreRed, rgb.foreGreen, rgb.foreBlue )
 
1608
                                        } ;
 
1609
 
 
1610
                // Read 1bpp pixel data into a temporary buffer.
 
1611
                if( !readFromServer( (char*) rcMask, bytesMaskData ) )
 
1612
                {
 
1613
                        delete[] rcSource;
 
1614
                        delete[] rcMask;
 
1615
                        return( FALSE );
 
1616
                }
 
1617
 
 
1618
                // Convert 1bpp data to byte-wide color indices.
 
1619
                Q_UINT8 * ptr = rcSource;
 
1620
                for( int y = 0; y < _height; ++y )
 
1621
                {
 
1622
                        int x = 0;
 
1623
                        for( ; x < _width / 8; ++x )
 
1624
                        {
 
1625
                                for( int b = 7; b >= 0; --b )
 
1626
                                {
 
1627
                                        *ptr = rcMask[y * bytesPerRow + x]
 
1628
                                                                >> b & 1;
 
1629
                                        ptr += bytesPerPixel;
 
1630
                                }
 
1631
                        }
 
1632
                        for( int b = 7; b > 7 - _width % 8; --b )
 
1633
                        {
 
1634
                                *ptr = rcMask[y * bytesPerRow + x] >> b & 1;
 
1635
                                ptr += bytesPerPixel;
 
1636
                        }
 
1637
                }
 
1638
 
 
1639
                // Convert indices into the actual pixel values.
 
1640
                switch( bytesPerPixel )
 
1641
                {
 
1642
                        case 1:
 
1643
                        {
 
1644
                                for( int x = 0; x < _width * _height; ++x )
 
1645
                                {
 
1646
                                        rcSource[x] = (Q_UINT8)
 
1647
                                                        colors[rcSource[x]];
 
1648
                                }
 
1649
                                break;
 
1650
                        }
 
1651
                        case 2:
 
1652
                        {
 
1653
                                for( int x = 0; x < _width * _height; ++x )
 
1654
                                {
 
1655
                                        ((Q_UINT16*) rcSource)[x] =
 
1656
                                                (Q_UINT16)colors[rcSource[x*2]];
 
1657
                                }
 
1658
                                break;
 
1659
                        }
 
1660
                        case 4:
 
1661
                        {
 
1662
                                for( int x = 0; x < _width * _height; ++x )
 
1663
                                {
 
1664
                                        ((Q_UINT32 *) rcSource)[x] =
 
1665
                                                        colors[rcSource[x*4]];
 
1666
                                        break;
 
1667
                                }
 
1668
                        }
 
1669
                }
 
1670
        }
 
1671
        else    // rich-cursor encoding
 
1672
        {
 
1673
                if( !readFromServer((char *) rcSource, _width * _height *
 
1674
                                                        bytesPerPixel ) )
 
1675
                {
 
1676
                        delete[] rcSource;
 
1677
                        delete[] rcMask;
 
1678
                        return( FALSE );
 
1679
                }
 
1680
        }
 
1681
 
 
1682
        // Read mask data.
 
1683
 
 
1684
        if( !readFromServer( (char*) rcMask, bytesMaskData ) )
 
1685
        {
 
1686
                delete[] rcSource;
 
1687
                delete[] rcMask;
 
1688
                return( FALSE );
 
1689
        }
 
1690
 
 
1691
        QImage alpha( _width, _height, QImage::Format_Mono );
 
1692
        // make data 32-bit-aligned for making it usable with QImage
 
1693
        for( Q_UINT16 y = 0; y < _height; ++y )
 
1694
        {
 
1695
                memcpy( alpha.scanLine( y ), rcMask + bytesPerRow*y,
 
1696
                                                                bytesPerRow );
 
1697
        }
 
1698
 
 
1699
 
 
1700
        QRegion ch_reg = QRect( m_cursorPos - m_cursorHotSpot,
 
1701
                                                        m_cursorShape.size() );
 
1702
        m_cursorLock.lockForWrite();
 
1703
        m_cursorShape = QImage( rcSource, _width, _height,
 
1704
                                                        QImage::Format_RGB32 ).
 
1705
                                convertToFormat( QImage::Format_ARGB32 );
 
1706
        m_cursorShape.setAlphaChannel( alpha );
 
1707
        m_cursorLock.unlock();
 
1708
 
 
1709
        m_cursorHotSpot = QPoint( _xhot, _yhot );
 
1710
 
 
1711
 
 
1712
        ch_reg += QRect( m_cursorPos - m_cursorHotSpot, m_cursorShape.size() );
 
1713
 
 
1714
        // make sure, area around old cursor is updated and new cursor is
 
1715
        // painted
 
1716
        postRegionChangedEvent( ch_reg );
 
1717
 
 
1718
        emit cursorShapeChanged();
 
1719
        if( m_quality < QualityDemoLow )
 
1720
        {
 
1721
                emit regionUpdated( ch_reg );
 
1722
        }
 
1723
 
 
1724
        delete[] rcSource;
 
1725
        delete[] rcMask;
 
1726
 
 
1727
 
 
1728
        return( TRUE );
 
1729
}
 
1730
 
 
1731
 
 
1732
 
 
1733
bool ivsConnection::handleItalc( Q_UINT16 rx, Q_UINT16 ry, Q_UINT16 rw,
 
1734
                                                                Q_UINT16 rh )
 
1735
{
 
1736
        italcRectEncodingHeader hdr;
 
1737
        if( !readFromServer( (char *) &hdr, sizeof( hdr ) ) )
 
1738
        {
 
1739
                return( FALSE );
 
1740
        }
 
1741
 
 
1742
        if( !hdr.compressed )
 
1743
        {
 
1744
                return( handleRaw( rx, ry, rw, rh ) );
 
1745
        }
 
1746
 
 
1747
        hdr.bytesLZO = swap32IfLE( hdr.bytesLZO );
 
1748
        hdr.bytesRLE = swap32IfLE( hdr.bytesRLE );
 
1749
 
 
1750
        Q_UINT8 * lzo_data = new Q_UINT8[hdr.bytesLZO];
 
1751
 
 
1752
        if( !readFromServer( (char *) lzo_data, hdr.bytesLZO ) )
 
1753
        {
 
1754
                delete[] lzo_data;
 
1755
                return( FALSE );
 
1756
        }
 
1757
 
 
1758
        Q_UINT8 * rle_data = new Q_UINT8[hdr.bytesRLE];
 
1759
 
 
1760
        lzo_uint decomp_bytes = 0;
 
1761
        lzo1x_decompress( (const unsigned char *) lzo_data,
 
1762
                                (lzo_uint) hdr.bytesLZO,
 
1763
                                (unsigned char *) rle_data,
 
1764
                                (lzo_uint *) &decomp_bytes, NULL );
 
1765
        if( decomp_bytes != hdr.bytesRLE )
 
1766
        {
 
1767
                qCritical( "ivsConnection::handleItalc(...): expected and real "
 
1768
                                "size of decompressed data do not match!" );
 
1769
                return( FALSE );
 
1770
        }
 
1771
 
 
1772
        QRgb * dst = (QRgb *) m_screen.scanLine( ry ) + rx;
 
1773
        Q_UINT16 dx = 0;
 
1774
        bool done = FALSE;
 
1775
        const Q_UINT16 sh = m_screen.height();
 
1776
        for( Q_UINT32 i = 0; i < hdr.bytesRLE && done == FALSE; i+=4 )
 
1777
        {
 
1778
                const QRgb val = swap32IfBE( *( (QRgb*)( rle_data + i ) ) ) &
 
1779
                                                                0xffffff;
 
1780
                for( Q_UINT16 j = 0; j <= rle_data[i+3]; ++j )
 
1781
                {
 
1782
                        *dst = val;//[i+1];
 
1783
                        if( ++dx >= rw )
 
1784
                        {
 
1785
                                dx = 0;
 
1786
                                if( ry+1 < sh )
 
1787
                                {
 
1788
                                        dst = (QRgb *)
 
1789
                                                m_screen.scanLine( ++ry ) + rx;
 
1790
                                }
 
1791
                                else
 
1792
                                {
 
1793
                                        done = TRUE;
 
1794
                                        break;
 
1795
                                }
 
1796
                        }
 
1797
                        else
 
1798
                        {
 
1799
                                ++dst;
 
1800
                        }
 
1801
                }
 
1802
        }
 
1803
 
 
1804
        if( dx != 0 )
 
1805
        {
 
1806
                qWarning( "ivsConnection::handleItalc(...): dx(%d) != 0", dx );
 
1807
        }
 
1808
 
 
1809
        delete[] lzo_data;
 
1810
        delete[] rle_data;
 
1811
 
 
1812
        return( TRUE );
 
1813
}
 
1814
 
 
1815
 
 
1816
 
 
1817
#include "ivs_connection.moc"
 
1818