From 05c8f2d4840e8e4d0166b176b8c88bfdfffcce91 Mon Sep 17 00:00:00 2001
From: dscho <dscho>
Date: Wed, 3 Oct 2001 02:11:59 +0000
Subject: upgraded to TridiaVNC 1.2.1

---
 CHANGES     |  8 +++---
 Makefile    |  2 +-
 TODO        | 14 +++++-----
 main.c      |  8 +++---
 rfb.h       |  5 +++-
 rfbserver.c | 44 +++++++++++++++++++++++---------
 sockets.c   | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
 stats.c     |  4 +++
 tight.c     | 77 ++++++++++++++++++++++++++++++++++++++-----------------
 9 files changed, 190 insertions(+), 57 deletions(-)

diff --git a/CHANGES b/CHANGES
index d9ed9c8..ccf5ee5 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,11 +1,13 @@
 0.2
-   cursors are supported
+   source is now equivalent to TridiaVNC 1.2.1
+   pthreads now work (use the iterators!)
+   cursors are supported (rfbSetCursor automatically undraws cursor)
    support for 3 bytes/pixel (slow!)
    server side colourmap support
    fixed rfbCloseClient not to close the connection (pthreads!)
-   pthreads now work
+	this is done lazily (and with proper signalling).
    cleaned up mac.c (from original OSXvnc); now compiles (untested!)
-   compiles cleanly on Linux, IRIX, BSD, Apple
+   compiles cleanly on Linux, IRIX, BSD, Apple (Darwin)
    fixed prototypes
 0.1
    rewrote API to use pseudo-methods instead of required functions.
diff --git a/Makefile b/Makefile
index 5c92c7a..c456673 100644
--- a/Makefile
+++ b/Makefile
@@ -65,7 +65,7 @@ sratest.o: sraRegion.c
 blooptest: blooptest.o libvncserver.a
 	$(CC) -o blooptest blooptest.o $(LIBS)
 
-blooptest.o: example.c
+blooptest.o: example.c rfb.h
 	$(CC) $(CFLAGS) -DBACKGROUND_LOOP_TEST -c -o blooptest.o example.c
 
 pnmshow24: pnmshow24.o libvncserver.a
diff --git a/TODO b/TODO
index 904a5fe..17ffe48 100644
--- a/TODO
+++ b/TODO
@@ -2,18 +2,16 @@ immediate:
 ----------
 
 fix bug in http (java) client with big endian server: byte swapping is broken
-update to newest TridiaVNC version.
+udp
+documentation
+	perhaps the option (or just hint) not to mark very tiny regions as
+	modified, because that is inefficient for the encodings.
+optionally dont draw rich cursors as xcursors
 
 later:
 ------
 
-udp
-documentation
-optionally dont draw rich cursors as xcursors
 autoconf? at least Sun Solaris and Windows compilation
-perhaps the option (or just hint) not to mark very tiny regions as modified,
-	because that is inefficient for the encodings.
-rfbConnect, ConnectToTcpAddr
 CORBA
 cursor "smears" sometimes when not using cursor encoding
 	(seems to be gone now; haven't debugged properly, though)
@@ -21,6 +19,8 @@ cursor "smears" sometimes when not using cursor encoding
 done:
 -----
 
+.rfbConnect, ConnectToTcpAddr
+.update to newest TridiaVNC version (1.2.1).
 .adapt rdp2vnc (rdesktop)
 .pthreads concept: How to iterate over rfbClientPtr's? So that it can be
 	 either called from rfbProcessEvents (which locks the list mutex)
diff --git a/main.c b/main.c
index 7412b30..7362e4d 100644
--- a/main.c
+++ b/main.c
@@ -48,7 +48,7 @@ rfbLog(char *format, ...)
     char buf[256];
     time_t log_clock;
 
-    IF_PTHREADS(pthread_mutex_lock(&logMutex));
+    IF_PTHREADS(LOCK(logMutex));
     va_start(args, format);
 
     time(&log_clock);
@@ -59,7 +59,7 @@ rfbLog(char *format, ...)
     fflush(stderr);
 
     va_end(args);
-    IF_PTHREADS(pthread_mutex_unlock(&logMutex));
+    IF_PTHREADS(UNLOCK(logMutex));
 }
 
 void rfbLogPerror(char *str)
@@ -314,6 +314,7 @@ rfbScreenInfoPtr rfbGetScreen(int argc,char** argv,
    if(width&3)
      fprintf(stderr,"WARNING: Width (%d) is not a multiple of 4. VncViewer has problems with that.\n",width);
 
+   rfbScreen->rfbClientHead=0;
    rfbScreen->rfbPort=5900;
    rfbScreen->socketInitDone=FALSE;
 
@@ -323,6 +324,7 @@ rfbScreenInfoPtr rfbGetScreen(int argc,char** argv,
    rfbScreen->udpSock=-1;
    rfbScreen->udpSockConnected=FALSE;
    rfbScreen->udpPort=0;
+   rfbScreen->udpClient=0;
 
    rfbScreen->maxFd=0;
    rfbScreen->rfbListenSock=-1;
@@ -419,6 +421,7 @@ void rfbInitServer(rfbScreenInfoPtr rfbScreen)
 {
   rfbInitSockets(rfbScreen);
   httpInitSockets(rfbScreen);
+  INIT_MUTEX(logMutex);
 }
 
 void
@@ -451,7 +454,6 @@ void rfbRunEventLoop(rfbScreenInfoPtr rfbScreen, long usec, Bool runInBackground
 #ifdef HAVE_PTHREADS
        pthread_t listener_thread;
 
-       pthread_mutex_init(&logMutex, NULL);
        pthread_create(&listener_thread, NULL, listenerRun, rfbScreen);
     return;
 #else
diff --git a/rfb.h b/rfb.h
index efb69d2..e67e683 100644
--- a/rfb.h
+++ b/rfb.h
@@ -221,6 +221,7 @@ typedef struct
     int rfbListenSock;
     int udpPort;
     int udpSock;
+    struct rfbClientRec* udpClient;
     Bool udpSockConnected;
     struct sockaddr_in udpRemoteAddr;
     Bool inetdInitDone;
@@ -517,6 +518,8 @@ extern void rfbCloseClient(rfbClientPtr cl);
 extern int ReadExact(rfbClientPtr cl, char *buf, int len);
 extern int WriteExact(rfbClientPtr cl, char *buf, int len);
 extern void rfbCheckFds(rfbScreenInfoPtr rfbScreen,long usec);
+extern int rfbConnect(rfbScreenInfoPtr rfbScreen, char* host, int port);
+extern int ConnectToTcpAddr(char* host, int port);
 extern int ListenOnTCPPort(int port);
 extern int ListenOnUDPPort(int port);
 
@@ -536,7 +539,7 @@ extern void rfbReleaseClientIterator(rfbClientIteratorPtr iterator);
 
 extern void rfbNewClientConnection(rfbScreenInfoPtr rfbScreen,int sock);
 extern rfbClientPtr rfbNewClient(rfbScreenInfoPtr rfbScreen,int sock);
-extern rfbClientPtr rfbReverseConnection(char *host, int port);
+extern rfbClientPtr rfbReverseConnection(rfbScreenInfoPtr rfbScreen,char *host, int port);
 extern void rfbClientConnectionGone(rfbClientPtr cl);
 extern void rfbProcessClientMessage(rfbClientPtr cl);
 extern void rfbClientConnFailed(rfbClientPtr cl, char *reason);
diff --git a/rfbserver.c b/rfbserver.c
index 930a9ed..f43ceac 100644
--- a/rfbserver.c
+++ b/rfbserver.c
@@ -34,6 +34,10 @@
 #include <netinet/in.h>
 #include <arpa/inet.h>
 
+#ifdef CORBA
+#include <vncserverctrl.h>
+#endif
+
 rfbClientPtr pointerClient = NULL;  /* Mutex for pointer events */
 
 static void rfbProcessClientProtocolVersion(rfbClientPtr cl);
@@ -124,6 +128,10 @@ rfbNewClientConnection(rfbScreen,sock)
     rfbClientPtr cl;
 
     cl = rfbNewClient(rfbScreen,sock);
+#ifdef CORBA
+    if(cl!=NULL)
+      newConnection(cl, (KEYBOARD_DEVICE|POINTER_DEVICE),1,1,1);
+#endif
 }
 
 
@@ -133,27 +141,24 @@ rfbNewClientConnection(rfbScreen,sock)
  */
 
 rfbClientPtr
-rfbReverseConnection(host, port)
+rfbReverseConnection(rfbScreen,host, port)
+    rfbScreenInfoPtr rfbScreen;
     char *host;
     int port;
 {
-    return NULL;
-
-#ifdef NOT_YET
     int sock;
     rfbClientPtr cl;
 
-    if ((sock = rfbConnect(host, port)) < 0)
+    if ((sock = rfbConnect(rfbScreen, host, port)) < 0)
         return (rfbClientPtr)NULL;
 
-    cl = rfbNewClient(sock);
+    cl = rfbNewClient(rfbScreen, sock);
 
     if (cl) {
         cl->reverseConnection = TRUE;
     }
 
     return cl;
-#endif
 }
 
 
@@ -189,6 +194,8 @@ rfbNewClient(rfbScreen,sock)
     cl->host = strdup(inet_ntoa(addr.sin_addr));
 
     INIT_MUTEX(cl->outputMutex);
+    INIT_MUTEX(cl->refCountMutex);
+    INIT_COND(cl->deleteCond);
 
     cl->state = RFB_PROTOCOL_VERSION;
 
@@ -323,6 +330,10 @@ rfbClientConnectionGone(cl)
     LOCK(cl->outputMutex);
     TINI_MUTEX(cl->outputMutex);
 
+#ifdef CORBA
+    destroyConnection(cl);
+#endif
+
     rfbPrintStats(cl);
 
     xfree(cl);
@@ -977,8 +988,10 @@ rfbSendFramebufferUpdate(cl, givenUpdateRegion)
 
    if (sendCursorShape) {
 	cl->cursorWasChanged = FALSE;
-	if (!rfbSendCursorShape(cl))
+	if (!rfbSendCursorShape(cl)) {
+	    sraRgnDestroy(updateRegion);
 	    return FALSE;
+	}
     }
    
     if (!sraRgnEmpty(updateCopyRegion)) {
@@ -1003,21 +1016,25 @@ rfbSendFramebufferUpdate(cl, givenUpdateRegion)
         switch (cl->preferredEncoding) {
         case rfbEncodingRaw:
             if (!rfbSendRectEncodingRaw(cl, x, y, w, h)) {
+	        sraRgnDestroy(updateRegion);
                 return FALSE;
             }
             break;
         case rfbEncodingRRE:
             if (!rfbSendRectEncodingRRE(cl, x, y, w, h)) {
+	        sraRgnDestroy(updateRegion);
                 return FALSE;
             }
             break;
         case rfbEncodingCoRRE:
             if (!rfbSendRectEncodingCoRRE(cl, x, y, w, h)) {
+	        sraRgnDestroy(updateRegion);
                 return FALSE;
             }
             break;
         case rfbEncodingHextile:
             if (!rfbSendRectEncodingHextile(cl, x, y, w, h)) {
+	        sraRgnDestroy(updateRegion);
                 return FALSE;
             }
             break;
@@ -1038,11 +1055,14 @@ rfbSendFramebufferUpdate(cl, givenUpdateRegion)
 
     if ( nUpdateRegionRects == 0xFFFF &&
 	 !rfbSendLastRectMarker(cl) ) {
+        sraRgnDestroy(updateRegion);
 	return FALSE;
     }
 
-    if (!rfbSendUpdateBuf(cl))
+    if (!rfbSendUpdateBuf(cl)) {
+        sraRgnDestroy(updateRegion);
         return FALSE;
+    }
 
     if(cursorWasDrawn != cl->screen->cursorIsDrawn) {
        if(cursorWasDrawn)
@@ -1051,6 +1071,7 @@ rfbSendFramebufferUpdate(cl, givenUpdateRegion)
 	  rfbUndrawCursor(cl);
     }
 
+    sraRgnDestroy(updateRegion);
     return TRUE;
 }
 
@@ -1315,7 +1336,6 @@ rfbSendServerCutText(rfbScreenInfoPtr rfbScreen,char *str, int len)
     rfbServerCutTextMsg sct;
     rfbClientIteratorPtr iterator;
 
-    /* XXX bad-- writing with client list lock held */
     iterator = rfbGetClientIterator(rfbScreen);
     while ((cl = rfbClientIteratorNext(iterator)) != NULL) {
         sct.type = rfbServerCutText;
@@ -1334,8 +1354,6 @@ rfbSendServerCutText(rfbScreenInfoPtr rfbScreen,char *str, int len)
     rfbReleaseClientIterator(iterator);
 }
 
-unsigned char ptrAcceleration = 50;
-
 /*****************************************************************************
  *
  * UDP can be used for keyboard and pointer events when the underlying
@@ -1344,6 +1362,8 @@ unsigned char ptrAcceleration = 50;
  * packets (such as 100s of pen readings per second!).
  */
 
+unsigned char ptrAcceleration = 50;
+
 void
 rfbNewUDPConnection(rfbScreen,sock)
     rfbScreenInfoPtr rfbScreen;
diff --git a/sockets.c b/sockets.c
index ef83269..3882147 100644
--- a/sockets.c
+++ b/sockets.c
@@ -56,7 +56,6 @@ struct timeval
 #include <fcntl.h>
 #include <errno.h>
 #include <unistd.h>
-#include <pthread.h>
 #include <arpa/inet.h>
 
 #include "rfb.h"
@@ -182,7 +181,6 @@ rfbCheckFds(rfbScreenInfoPtr rfbScreen,long usec)
 	    return;
 	}
 
-	fprintf(stderr,"\n");
 	rfbLog("Got connection from client %s\n", inet_ntoa(addr.sin_addr));
 
 	FD_SET(sock, &(rfbScreen->allFds));
@@ -224,8 +222,8 @@ rfbCheckFds(rfbScreenInfoPtr rfbScreen,long usec)
 		rfbNewUDPConnection(rfbScreen,rfbScreen->udpSock);
 	    }
 
-	    //TODO: UDP also needs a client
-	    //rfbProcessUDPInput(rfbScreen,rfbScreen->udpSock);
+	    /* TODO: UDP also needs a client
+	       rfbProcessUDPInput(rfbScreen,rfbScreen->udpSock); */
 	}
 
 	FD_CLR(rfbScreen->udpSock, &fds);
@@ -263,6 +261,47 @@ rfbCloseClient(cl)
 }
 
 
+/*
+ * rfbConnect is called to make a connection out to a given TCP address.
+ */
+
+int
+rfbConnect(rfbScreen, host, port)
+    rfbScreenInfoPtr rfbScreen;
+    char *host;
+    int port;
+{
+    int sock;
+    int one = 1;
+
+    rfbLog("Making connection to client on host %s port %d\n",
+	   host,port);
+
+    if ((sock = ConnectToTcpAddr(host, port)) < 0) {
+	rfbLogPerror("connection failed");
+	return -1;
+    }
+
+    if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) {
+	rfbLogPerror("fcntl failed");
+	close(sock);
+	return -1;
+    }
+
+    if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
+		   (char *)&one, sizeof(one)) < 0) {
+	rfbLogPerror("setsockopt failed");
+	close(sock);
+	return -1;
+    }
+
+    /* AddEnabledDevice(sock); */
+    FD_SET(sock, &rfbScreen->allFds);
+    rfbScreen->maxFd = max(sock,rfbScreen->maxFd);
+
+    return sock;
+}
+
 /*
  * ReadExact reads an exact number of bytes from a client.  Returns 1 if
  * those bytes have been read, 0 if the other end has closed, or -1 if an error
@@ -385,7 +424,6 @@ WriteExact(cl, buf, len)
     return 1;
 }
 
-
 int
 ListenOnTCPPort(port)
     int port;
@@ -396,7 +434,7 @@ ListenOnTCPPort(port)
 
     addr.sin_family = AF_INET;
     addr.sin_port = htons(port);
-    //addr.sin_addr.s_addr = interface.s_addr;
+    /* addr.sin_addr.s_addr = interface.s_addr; */
     addr.sin_addr.s_addr = INADDR_ANY;
 
     if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
@@ -419,6 +457,39 @@ ListenOnTCPPort(port)
     return sock;
 }
 
+int
+ConnectToTcpAddr(host, port)
+    char *host;
+    int port;
+{
+    struct hostent *hp;
+    int sock;
+    struct sockaddr_in addr;
+
+    addr.sin_family = AF_INET;
+    addr.sin_port = htons(port);
+
+    if ((addr.sin_addr.s_addr = inet_addr(host)) == -1)
+    {
+	if (!(hp = gethostbyname(host))) {
+	    errno = EINVAL;
+	    return -1;
+	}
+	addr.sin_addr.s_addr = *(unsigned long *)hp->h_addr;
+    }
+
+    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+	return -1;
+    }
+
+    if (connect(sock, (struct sockaddr *)&addr, (sizeof(addr))) < 0) {
+	close(sock);
+	return -1;
+    }
+
+    return sock;
+}
+
 int
 ListenOnUDPPort(port)
     int port;
@@ -429,7 +500,7 @@ ListenOnUDPPort(port)
 
     addr.sin_family = AF_INET;
     addr.sin_port = htons(port);
-    //addr.sin_addr.s_addr = interface.s_addr;
+    /* addr.sin_addr.s_addr = interface.s_addr; */
     addr.sin_addr.s_addr = INADDR_ANY;
 
     if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
diff --git a/stats.c b/stats.c
index f712021..b6fcf62 100644
--- a/stats.c
+++ b/stats.c
@@ -69,6 +69,10 @@ rfbPrintStats(rfbClientPtr cl)
         totalBytesSent += cl->rfbBytesSent[i];
     }
 
+    totalRectanglesSent += (cl->rfbCursorUpdatesSent +
+			    cl->rfbLastRectMarkersSent);
+    totalBytesSent += (cl->rfbCursorBytesSent + cl->rfbLastRectBytesSent);
+
     rfbLog("  framebuffer updates %d, rectangles %d, bytes %d\n",
             cl->rfbFramebufferUpdateMessagesSent, totalRectanglesSent,
             totalBytesSent);
diff --git a/tight.c b/tight.c
index 509a6d8..db0d382 100644
--- a/tight.c
+++ b/tight.c
@@ -32,6 +32,11 @@
 /* Note: The following constant should not be changed. */
 #define TIGHT_MIN_TO_COMPRESS 12
 
+/* The parameters below may be adjusted. */
+#define MIN_SPLIT_RECT_SIZE     4096
+#define MIN_SOLID_SUBRECT_SIZE  2048
+#define MAX_SPLIT_TILE_SIZE       16
+
 /* May be set to TRUE with "-lazytight" Xvnc option. */
 Bool rfbTightDisableGradient = FALSE;
 
@@ -53,7 +58,7 @@ typedef struct TIGHT_CONF_s {
 } TIGHT_CONF;
 
 static TIGHT_CONF tightConf[10] = {
-    {   512,   32,   6, 65536, 0, 0, 0, 0,   0,   0,   4, 20, 10000, 25000 },
+    {   512,   32,   6, 65536, 0, 0, 0, 0,   0,   0,   4, 20, 10000, 23000 },
     {  2048,  128,   6, 65536, 1, 1, 1, 0,   0,   0,   8, 30,  8000, 18000 },
     {  6144,  256,   8, 65536, 3, 3, 2, 0,   0,   0,  24, 40,  6500, 15000 },
     { 10240, 1024,  12, 65536, 5, 5, 3, 0,   0,   0,  32, 50,  5000, 12000 },
@@ -174,10 +179,6 @@ static void JpegSetDstManager(j_compress_ptr cinfo);
  * Tight encoding implementation.
  */
 
-#define MIN_SPLIT_RECT_SIZE     4096
-#define MIN_SOLID_SUBRECT_SIZE  2048
-#define MAX_SPLIT_TILE_SIZE       16
-
 int
 rfbNumCodedRectsTight(cl, x, y, w, h)
     rfbClientPtr cl;
@@ -209,11 +210,15 @@ rfbSendRectEncodingTight(cl, x, y, w, h)
     rfbClientPtr cl;
     int x, y, w, h;
 {
+    int nMaxRows;
     CARD32 colorValue;
     int dx, dy, dw, dh;
     int x_best, y_best, w_best, h_best;
     char *fbptr;
 
+    compressLevel = cl->tightCompressLevel;
+    qualityLevel = cl->tightQualityLevel;
+
     if ( cl->format.depth == 24 && cl->format.redMax == 0xFF &&
          cl->format.greenMax == 0xFF && cl->format.blueMax == 0xFF ) {
         usePixelFormat24 = TRUE;
@@ -224,7 +229,7 @@ rfbSendRectEncodingTight(cl, x, y, w, h)
     if (!cl->enableLastRectEncoding || w * h < MIN_SPLIT_RECT_SIZE)
         return SendRectSimple(cl, x, y, w, h);
 
-    /* Make sure we can write one pixel into tightBeforeBuf. */
+    /* Make sure we can write at least one pixel into tightBeforeBuf. */
 
     if (tightBeforeBufSize < 4) {
         tightBeforeBufSize = 4;
@@ -235,10 +240,30 @@ rfbSendRectEncodingTight(cl, x, y, w, h)
                                               tightBeforeBufSize);
     }
 
+    /* Calculate maximum number of rows in one non-solid rectangle. */
+
+    {
+        int maxRectSize, maxRectWidth, nMaxWidth;
+
+        maxRectSize = tightConf[compressLevel].maxRectSize;
+        maxRectWidth = tightConf[compressLevel].maxRectWidth;
+        nMaxWidth = (w > maxRectWidth) ? maxRectWidth : w;
+        nMaxRows = maxRectSize / nMaxWidth;
+    }
+
     /* Try to find large solid-color areas and send them separately. */
 
     for (dy = y; dy < y + h; dy += MAX_SPLIT_TILE_SIZE) {
 
+        /* If a rectangle becomes too large, send its upper part now. */
+
+        if (dy - y >= nMaxRows) {
+            if (!SendRectSimple(cl, x, y, w, nMaxRows))
+                return 0;
+            y += nMaxRows;
+            h -= nMaxRows;
+        }
+
         dh = (dy + MAX_SPLIT_TILE_SIZE <= y + h) ?
             MAX_SPLIT_TILE_SIZE : (y + h - dy);
 
@@ -462,8 +487,6 @@ SendRectSimple(cl, x, y, w, h)
     int dx, dy;
     int rw, rh;
 
-    compressLevel = cl->tightCompressLevel;
-    qualityLevel = cl->tightQualityLevel;
     maxRectSize = tightConf[compressLevel].maxRectSize;
     maxRectWidth = tightConf[compressLevel].maxRectWidth;
 
@@ -516,6 +539,12 @@ SendSubrect(cl, x, y, w, h)
     char *fbptr;
     Bool success = FALSE;
 
+    /* Send pending data if there is more than 128 bytes. */
+    if (cl->ublen > 128) {
+        if (!rfbSendUpdateBuf(cl))
+            return FALSE;
+    }
+
     if (!SendTightHeader(cl, x, y, w, h))
         return FALSE;
 
@@ -566,7 +595,7 @@ SendSubrect(cl, x, y, w, h)
         break;
     default:
         /* Up to 256 different colors */
-        if ( paletteNumColors > 64 &&
+        if ( paletteNumColors > 96 &&
              qualityLevel != -1 && qualityLevel <= 3 &&
              DetectSmoothImage(cl, &cl->format, w, h) ) {
             success = SendJpegRect(cl, x, y, w, h,
@@ -644,7 +673,8 @@ SendMonoRect(cl, w, h)
     int streamId = 1;
     int paletteLen, dataLen;
 
-    if ( cl->ublen + 6 + 2 * cl->format.bitsPerPixel / 8 > UPDATE_BUF_SIZE ) {
+    if ( cl->ublen + TIGHT_MIN_TO_COMPRESS + 6 +
+	 2 * cl->format.bitsPerPixel / 8 > UPDATE_BUF_SIZE ) {
         if (!rfbSendUpdateBuf(cl))
             return FALSE;
     }
@@ -708,7 +738,8 @@ SendIndexedRect(cl, w, h)
     int streamId = 2;
     int i, entryLen;
 
-    if ( cl->ublen + 6 + paletteNumColors * cl->format.bitsPerPixel / 8 >
+    if ( cl->ublen + TIGHT_MIN_TO_COMPRESS + 6 +
+	 paletteNumColors * cl->format.bitsPerPixel / 8 >
          UPDATE_BUF_SIZE ) {
         if (!rfbSendUpdateBuf(cl))
             return FALSE;
@@ -902,19 +933,19 @@ static Bool SendCompressedData(cl, compressedLen)
         }
     }
 
-    for (i = 0; i < compressedLen; ) {
-        portionLen = compressedLen - i;
-        if (portionLen > UPDATE_BUF_SIZE - cl->ublen)
-            portionLen = UPDATE_BUF_SIZE - cl->ublen;
-
+    portionLen = UPDATE_BUF_SIZE;
+    for (i = 0; i < compressedLen; i += portionLen) {
+        if (i + portionLen > compressedLen) {
+            portionLen = compressedLen - i;
+        }
+        if (cl->ublen + portionLen > UPDATE_BUF_SIZE) {
+            if (!rfbSendUpdateBuf(cl))
+                return FALSE;
+        }
         memcpy(&cl->updateBuf[cl->ublen], &tightAfterBuf[i], portionLen);
-
         cl->ublen += portionLen;
-        i += portionLen;
-
-        if (!rfbSendUpdateBuf(cl))
-            return FALSE;
     }
+    portionLen = UPDATE_BUF_SIZE;
     cl->rfbBytesSent[rfbEncodingTight] += compressedLen;
     return TRUE;
 }
@@ -978,7 +1009,7 @@ FillPalette##bpp(count)                                                 \
                                                                         \
     c0 = data[0];                                                       \
     for (i = 1; i < count && data[i] == c0; i++);                       \
-    if (i == count) {                                                   \
+    if (i >= count) {                                                   \
         paletteNumColors = 1;   /* Solid rectangle */                   \
         return;                                                         \
     }                                                                   \
@@ -1000,7 +1031,7 @@ FillPalette##bpp(count)                                                 \
         } else                                                          \
             break;                                                      \
     }                                                                   \
-    if (i == count) {                                                   \
+    if (i >= count) {                                                   \
         if (n0 > n1) {                                                  \
             monoBackground = (CARD32)c0;                                \
             monoForeground = (CARD32)c1;                                \
-- 
cgit v1.2.3

