--- ./nx-X11/lib/X11/XlibInt.c.X.original	2015-02-13 14:03:44.624443872 +0100
+++ ./nx-X11/lib/X11/XlibInt.c	2015-02-10 19:13:12.800723493 +0100
@@ -26,6 +26,24 @@
 from The Open Group.
 
 */
+
+/**************************************************************************/
+/*                                                                        */
+/* Copyright (c) 2001, 2011 NoMachine, http://www.nomachine.com/.         */
+/*                                                                        */
+/* NX-X11, NX protocol compression and NX extensions to this software     */
+/* are copyright of NoMachine. Redistribution and use of the present      */
+/* software is allowed according to terms specified in the file LICENSE   */
+/* which comes in the source distribution.                                */
+/*                                                                        */
+/* Check http://www.nomachine.com/licensing.html for applicability.       */
+/*                                                                        */
+/* NX and NoMachine are trademarks of Medialogic S.p.A.                   */
+/*                                                                        */
+/* All rights reserved.                                                   */
+/*                                                                        */
+/**************************************************************************/
+
 /* $XFree86: xc/lib/X11/XlibInt.c,v 3.38 2003/10/30 21:55:05 alanh Exp $ */
 
 /*
@@ -100,6 +118,34 @@
 
 #endif /* XTHREADS else */ 
 
+#include "NX.h"
+
+#ifdef NX_TRANS_SOCKET
+
+#include "NX.h"
+#include "NXvars.h"
+
+static struct timeval retry;
+
+/*
+ * From Xtranssock.c. Presently the congestion state
+ * is reported by the proxy to the application, by
+ * invoking the callback directly. The function will
+ * be possibly used in the future, to be able to track
+ * the bandwidth usage even when the NX transport is
+ * not running. Note that in this sample implementation
+ * the congestion state is checked very often and can
+ * be surely optimized.
+ */
+
+#ifdef NX_TRANS_CHANGE
+
+extern int _X11TransSocketCongestionChange(XtransConnInfo, int *);
+
+#endif
+
+#endif /* #ifdef NX_TRANS_SOCKET */
+
 /* check for both EAGAIN and EWOULDBLOCK, because some supposedly POSIX
  * systems are broken and return EWOULDBLOCK when they should return EAGAIN
  */
@@ -219,6 +265,100 @@
 	0, 0, 0
 };
 
+#ifdef NX_TRANS_SOCKET
+
+/*
+ * Replace the standard Select with a version giving NX a
+ * chance to check its own descriptors. This doesn't cover
+ * the cases where the system is using poll or when system-
+ * specific defines override the Select definition (OS/2).
+ */
+
+int _XSelect(int maxfds, fd_set *readfds, fd_set *writefds,
+                 fd_set *exceptfds, struct timeval *timeout)
+{
+#ifdef NX_TRANS_TEST
+    fprintf(stderr, "_XSelect: Called with [%d][%p][%p][%p][%p].\n",
+                maxfds, (void *) readfds, (void *) writefds, (void *) exceptfds,
+                    (void *) timeout);
+#endif
+
+    if (NXTransRunning(NX_FD_ANY))
+    {
+        fd_set t_readfds, t_writefds;
+        struct timeval t_timeout;
+
+        int n, r, e;
+
+#ifdef NX_TRANS_TEST
+
+        if (exceptfds != NULL)
+        {
+            fprintf(stderr, "_XSelect: WARNING! Can't handle exception fds in select.\n");
+        }
+
+#endif
+
+        if (readfds == NULL)
+        {
+            FD_ZERO(&t_readfds);
+
+            readfds = &t_readfds;
+        }
+
+        if (writefds == NULL)
+        {
+            FD_ZERO(&t_writefds);
+
+            writefds = &t_writefds;
+        }
+
+        if (timeout == NULL)
+        {
+            t_timeout.tv_sec  = 10;
+            t_timeout.tv_usec = 0;
+
+            timeout = &t_timeout;
+        }
+
+        n = maxfds;
+
+        /*
+         * If the transport is gone avoid
+         * sleeping until the timeout.
+         */
+
+        if (NXTransPrepare(&n, readfds, writefds, timeout) != 0)
+        {
+          NXTransSelect(&r, &e, &n, readfds, writefds, timeout);
+
+          NXTransExecute(&r, &e, &n, readfds, writefds, timeout);
+
+          errno = e;
+
+          return r;
+        }
+        else
+        {
+          return 0;
+        }
+    }
+    else
+    {
+        return select(maxfds, readfds, writefds, exceptfds, timeout);
+    }
+}
+
+#else /* #ifdef NX_TRANS_SOCKET */
+
+int _XSelect(int maxfds, fd_set *readfds, fd_set *writefds,
+                 fd_set *exceptfds, struct timeval *timeout)
+{
+    return select(maxfds, readfds, writefds, exceptfds, timeout);
+}
+
+#endif /* #ifdef NX_TRANS_SOCKET */
+
 /*
  * This is an OS dependent routine which:
  * 1) returns as soon as the connection can be written on....
@@ -242,6 +382,18 @@
 #endif
     int nfound;
 
+#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_CHANGE)
+    int congestion;
+#endif
+
+#ifdef NX_TRANS_SOCKET
+
+    if (_XGetIOError(dpy)) {
+        return;
+    }
+
+#endif
+
 #ifdef USE_POLL
     filedes.fd = dpy->fd;
     filedes.events = 0;
@@ -276,6 +428,8 @@
 	     (!dpy->lock->reply_awaiters ||
 	      dpy->lock->reply_awaiters->cv == cv)))
 #endif
+
+#ifndef NX_TRANS_SOCKET
 #ifdef USE_POLL
 	    filedes.events = POLLIN;
 	filedes.events |= POLLOUT;
@@ -283,17 +437,109 @@
 	FD_SET(dpy->fd, &r_mask);
         FD_SET(dpy->fd, &w_mask);
 #endif
+#endif /* #ifndef NX_TRANS_SOCKET */
 
 	do {
+#ifdef NX_TRANS_SOCKET
+            /*
+             * Give a chance to the registered client to perform
+             * any needed operation before entering the select.
+             */
+
+#ifdef NX_TRANS_TEST
+            fprintf(stderr, "_XWaitForWritable: WAIT! Waiting for the display to become writable.\n");
+#endif
+            NXTransFlush(dpy->fd);
+
+            if (_NXDisplayBlockFunction != NULL) {
+                    (*_NXDisplayBlockFunction)(dpy, NXBlockWrite);
+            }
+
+            /*
+             * Need to set again the descriptors as we could have
+             * run multiple selects before having the possibility
+             * to read or write to the X connection.
+             */
+
+#ifdef USE_POLL
+            filedes.events = POLLIN;
+            filedes.events |= POLLOUT;
+#else
+            FD_SET(dpy->fd, &r_mask);
+            FD_SET(dpy->fd, &w_mask);
+#endif
+#endif /* #ifdef NX_TRANS_SOCKET */
+
 	    UnlockDisplay(dpy);
 #ifdef USE_POLL
+#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG)
+            fprintf(stderr, "_XWaitForWritable: Calling poll().\n");
+#endif
 	    nfound = poll (&filedes, 1, -1);
 #else
+#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG)
+            fprintf(stderr, "_XWaitForWritable: Calling select() after [%ld] ms.\n",
+                        NXTransTime());
+#endif
+#ifdef NX_TRANS_SOCKET
+            /*
+             * Give a chance to the callback to detect
+             * the failure of the display even if we
+             * miss the interrupt inside the select.
+             */
+
+            if (_NXDisplayErrorFunction != NULL) {
+                retry.tv_sec  = 5;
+                retry.tv_usec = 0;
+                nfound = Select (dpy->fd + 1, &r_mask, &w_mask, NULL, &retry);
+            } else {
+                nfound = Select (dpy->fd + 1, &r_mask, &w_mask, NULL, NULL);
+            }
+#else
 	    nfound = Select (dpy->fd + 1, &r_mask, &w_mask, NULL, NULL);
 #endif
+#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG)
+            fprintf(stderr, "_XWaitForWritable: Out of select() with [%d] after [%ld] ms.\n",
+                        nfound, NXTransTime());
+
+            if (FD_ISSET(dpy->fd, &r_mask))
+            {
+                BytesReadable_t pend;
+
+                _X11TransBytesReadable(dpy->trans_conn, &pend);
+
+                fprintf(stderr, "_XWaitForWritable: Descriptor [%d] is ready with [%ld] bytes to read.\n",
+                            dpy->fd, pend);
+            }
+
+            if (FD_ISSET(dpy->fd, &w_mask))
+            {
+              fprintf(stderr, "_XWaitForWritable: Descriptor [%d] has become writable.\n\n",
+                          dpy->fd);
+            }
+#endif
+#endif
 	    InternalLockDisplay(dpy, cv != NULL);
-	    if (nfound < 0 && !ECHECK(EINTR))
+#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_CHANGE)
+            if (_NXDisplayCongestionFunction != NULL &&
+                    _X11TransSocketCongestionChange(dpy->trans_conn, &congestion) == 1) {
+                (*_NXDisplayCongestionFunction)(dpy, congestion);
+            }
+#endif
+
+#ifdef NX_TRANS_SOCKET
+            if (nfound <= 0) {
+                if ((nfound == -1 && !ECHECK(EINTR)) ||
+                        (_NXDisplayErrorFunction != NULL &&
+                            (*_NXDisplayErrorFunction)(dpy, _XGetIOError(dpy)))) {
+                    _XIOError(dpy);
+                    return;
+                }
+              }
+#else
+          if (nfound < 0 && !ECHECK(EINTR))
 		_XIOError(dpy);
+#endif
 	} while (nfound <= 0);
 
 	if (
@@ -311,7 +557,15 @@
 
 	    /* find out how much data can be read */
 	    if (_X11TransBytesReadable(dpy->trans_conn, &pend) < 0)
+#ifdef NX_TRANS_SOCKET
+            {
+                _XIOError(dpy);
+
+                return;
+            }
+#else
 		_XIOError(dpy);
+#endif
 	    len = pend;
 
 	    /* must read at least one xEvent; if none is pending, then
@@ -464,6 +718,15 @@
     int highest_fd = fd;
 #endif
 
+#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_CHANGE)
+    int congestion;
+#endif
+#ifdef NX_TRANS_SOCKET
+    if (_XGetIOError(dpy)) {
+        return -1;
+    }
+#endif
+
 #ifdef USE_POLL
     if (dpy->im_fd_length + 1 > POLLFD_CACHE_SIZE
 	&& !(dpy->flags & XlibDisplayProcConni)) {
@@ -495,16 +758,68 @@
 #endif
 	UnlockDisplay(dpy);
 #ifdef USE_POLL
+#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG)
+        fprintf(stderr, "_XWaitForReadable: Calling poll().\n");
+#endif
 	result = poll(filedes,
 		      (dpy->flags & XlibDisplayProcConni) ? 1 : 1+dpy->im_fd_length,
 		      -1);
 #else
+#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG)
+        fprintf(stderr, "_XWaitForReadable: Calling select().\n");
+#endif
+#ifdef NX_TRANS_SOCKET
+        /*
+         * Give a chance to the registered application
+         * to perform any needed operation.
+         */
+
+#ifdef NX_TRANS_TEST
+        fprintf(stderr, "_XWaitForReadable: WAIT! Waiting for the display to become readable.\n");
+#endif
+        NXTransFlush(dpy->fd);
+
+        if (_NXDisplayBlockFunction != NULL) {
+            (*_NXDisplayBlockFunction)(dpy, NXBlockRead);
+        }
+
+        if (_NXDisplayErrorFunction != NULL) {
+            retry.tv_sec  = 5;
+            retry.tv_usec = 0;
+            result = Select(highest_fd + 1, &r_mask, NULL, NULL, &retry);
+        } else {
+            result = Select(highest_fd + 1, &r_mask, NULL, NULL, NULL);
+        }
+#else
 	result = Select(highest_fd + 1, &r_mask, NULL, NULL, NULL);
 #endif
+#endif
+#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG)
+        fprintf(stderr, "_XWaitForReadable: Out of select with result [%d] and errno [%d].\n",
+                    result, (result < 0 ? errno : 0));
+#endif
 	InternalLockDisplay(dpy, dpy->flags & XlibDisplayReply);
+#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_CHANGE)
+        if (_NXDisplayCongestionFunction != NULL &&
+                _X11TransSocketCongestionChange(dpy->trans_conn, &congestion) == 1) {
+            (*_NXDisplayCongestionFunction)(dpy, congestion);
+        }
+#endif
+#ifdef NX_TRANS_SOCKET
+        if (result <= 0) {
+            if ((result == -1 && !ECHECK(EINTR)) ||
+                    (_NXDisplayErrorFunction != NULL &&
+                        (*_NXDisplayErrorFunction)(dpy, _XGetIOError(dpy)))) {
+                _XIOError(dpy);
+                return -1;
+            }
+            continue;
+        }
+#else
 	if (result == -1 && !ECHECK(EINTR)) _XIOError(dpy);
 	if (result <= 0)
 	    continue;
+#endif
 #ifdef USE_POLL
 	if (filedes[0].revents & (POLLIN|POLLHUP|POLLERR))
 #else
@@ -562,6 +877,19 @@
     xGetInputFocusReply rep;
     register xReq *req;
 
+#ifdef NX_TRANS_SOCKET
+#ifdef NX_TRANS_DEBUG
+    fprintf(stderr, "_XSeqSyncFunction: Going to synchronize the display.\n");
+#endif
+    if (dpy->flags & XlibDisplayIOError)
+    {
+#ifdef NX_TRANS_DEBUG
+        fprintf(stderr, "_XSeqSyncFunction: Returning 0 with I/O error detected.\n");
+#endif
+        return 0;
+    }
+#endif
+
     LockDisplay(dpy);
     if ((dpy->request - dpy->last_request_read) >= (BUFSIZE / SIZEOF(xReq))) {
 	GetEmptyReq(GetInputFocus, req);
@@ -611,7 +939,14 @@
 	register int write_stat;
 	register char *bufindex;
 	_XExtension *ext;
+#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_CHANGE)
+        int congestion;
+#endif
 
+#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG)
+        fprintf(stderr, "_XFlushInt: Entering flush with [%d] bytes to write.\n",
+                    (dpy->bufptr - dpy->buffer));
+#endif
 	/* This fix resets the bufptr to the front of the buffer so
 	 * additional appends to the bufptr will not corrupt memory. Since
 	 * the server is down, these appends are no-op's anyway but 
@@ -619,13 +954,23 @@
 	 */
 	if (dpy->flags & XlibDisplayIOError)
 	{
+#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG)
+        fprintf(stderr, "_XFlushInt: Returning with I/O error detected.\n");
+#endif
 	    dpy->bufptr = dpy->buffer;
 	    dpy->last_req = (char *)&_dummy_request;
 	    return;
 	}
 
 #ifdef XTHREADS
+#ifdef NX_TRANS_SOCKET
+        while (dpy->flags & XlibDisplayWriting) {
+            if (_XGetIOError(dpy)) {
+                return;
+            }
+#else
 	while (dpy->flags & XlibDisplayWriting) {
+#endif
 	    if (dpy->lock) {
 		ConditionWait(dpy, dpy->lock->writers);
 	    } else {
@@ -653,6 +998,17 @@
 	    write_stat = _X11TransWrite(dpy->trans_conn,
 					bufindex, (int) todo);
 	    if (write_stat >= 0) {
+#ifdef NX_TRANS_SOCKET
+                if (_NXDisplayWriteFunction != NULL) {
+                    (*_NXDisplayWriteFunction)(dpy, write_stat);
+                }
+#ifdef NX_TRANS_CHANGE
+                if (_NXDisplayCongestionFunction != NULL &&
+                        _X11TransSocketCongestionChange(dpy->trans_conn, &congestion) == 1) {
+                    (*_NXDisplayCongestionFunction)(dpy, congestion);
+                }
+#endif
+#endif
 		size -= write_stat;
 		todo = size;
 		bufindex += write_stat;
@@ -682,11 +1038,25 @@
 				      );
 		}
 #endif
+#ifdef NX_TRANS_SOCKET
+            } else if (!ECHECK(EINTR) ||
+                (_NXDisplayErrorFunction != NULL &&
+                    (*_NXDisplayErrorFunction)(dpy, _XGetIOError(dpy)))) {
+                _XIOError(dpy);
+                return;
+            }
+#else
 	    } else if (!ECHECK(EINTR)) {
 		/* Write failed! */
 		/* errno set by write system call. */
 		_XIOError(dpy);
 	    }
+#endif
+#ifdef NX_TRANS_SOCKET
+            if (_XGetIOError(dpy)) {
+                return;
+            }
+#endif
 	}
 	dpy->last_req = (char *)&_dummy_request;
 	if ((dpy->request - dpy->last_request_read) >= SEQLIMIT &&
@@ -727,6 +1097,12 @@
 	    if (dpy->qlen)
 		return(dpy->qlen);
 	}
+#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG)
+        if (dpy->flags & XlibDisplayIOError) {
+            fprintf(stderr, "_XEventsQueued: Returning [%d] after display failure.\n",
+                        dpy->qlen);
+        }
+#endif
 	if (dpy->flags & XlibDisplayIOError) return(dpy->qlen);
 
 #ifdef XTHREADS
@@ -767,8 +1143,19 @@
 	}
 #endif /* XTHREADS*/
 
+#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG)
+        fprintf(stderr, "_XEventsQueued: Checking bytes readable.\n");
+#endif
 	if (_X11TransBytesReadable(dpy->trans_conn, &pend) < 0)
+#ifdef NX_TRANS_SOCKET
+        {
+            _XIOError(dpy);
+
+            return (dpy->qlen);
+        }
+#else
 	    _XIOError(dpy);
+#endif
 #ifdef XCONN_CHECK_FREQ
 	/* This is a crock, required because FIONREAD or equivalent is
 	 * not guaranteed to detect a broken connection.
@@ -785,10 +1172,16 @@
 
 	    dpy->conn_checker = 0;
 #ifdef USE_POLL
+#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG)
+            fprintf(stderr, "_XEventsQueued: Calling poll().\n");
+#endif
 	    filedes.fd = dpy->fd;
 	    filedes.events = POLLIN;
 	    if ((result = poll(&filedes, 1, 0)))
 #else
+#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG)
+            fprintf(stderr, "_XEventsQueued: Calling select().\n");
+#endif
 	    FD_ZERO(&r_mask);
 	    FD_SET(dpy->fd, &r_mask);
 	    if ((result = Select(dpy->fd + 1, &r_mask, NULL, NULL, &zero_time)))
@@ -797,13 +1190,32 @@
 		if (result > 0)
 		{
 		    if (_X11TransBytesReadable(dpy->trans_conn, &pend) < 0)
+#ifdef NX_TRANS_SOCKET
+                    {
+                        _XIOError(dpy);
+
+                        return (dpy->qlen);
+                    }
+#else
 			_XIOError(dpy);
+#endif
 		    /* we should not get zero, if we do, force a read */
 		    if (!pend)
 			pend = SIZEOF(xReply);
 		}
+#ifdef NX_TRANS_SOCKET
+                if (result <= 0) {
+                    if ((result == -1 && !ECHECK(EINTR)) ||
+                            (_NXDisplayErrorFunction != NULL &&
+                                (*_NXDisplayErrorFunction)(dpy, _XGetIOError(dpy)))) {
+                        _XIOError(dpy);
+                        return (dpy->qlen);
+                    }
+                }
+#else
 		else if (result < 0 && !ECHECK(EINTR))
 		    _XIOError(dpy);
+#endif
 	    }
 	}
 #endif /* XCONN_CHECK_FREQ */
@@ -815,6 +1227,10 @@
 	    {
 		UnlockNextEventReader(dpy);
 	    }
+
+#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG)
+            fprintf(stderr, "_XEventsQueued: Returning [%d].\n", dpy->qlen);
+#endif
 	    return(dpy->qlen);
 	}
       /* Force a read if there is not enough data.  Otherwise,
@@ -847,6 +1263,11 @@
 
 	(void) _XRead (dpy, read_buf, (long) len);
 	
+#ifdef NX_TRANS_SOCKET
+        if (_XGetIOError(dpy)) {
+            return(dpy->qlen);
+        }
+#endif
 #ifdef XTHREADS
 	/* what did we actually read: reply or event? */
 	if (dpy->lock && dpy->lock->reply_awaiters) {
@@ -945,7 +1366,15 @@
 #endif /* XTHREADS */
 	    /* find out how much data can be read */
 	    if (_X11TransBytesReadable(dpy->trans_conn, &pend) < 0)
+#ifdef NX_TRANS_SOCKET
+            {
+                _XIOError(dpy);
+
+                return;
+            }
+#else
 	    	_XIOError(dpy);
+#endif
 	    len = pend;
 
 	    /* must read at least one xEvent; if none is pending, then
@@ -995,6 +1424,15 @@
 	    dpy->flags |= XlibDisplayReadEvents;
 	    i = _XRead (dpy, read_buf, (long) len);
 	    dpy->flags &= ~XlibDisplayReadEvents;
+#ifdef NX_TRANS_SOCKET
+            if (dpy->flags & XlibDisplayIOError)
+            {
+#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG)
+                fprintf(stderr, "_XReadEvents: Returning with I/O error detected.\n");
+#endif
+                return;
+            }
+#endif
 	    if (i == -2) {
 		/* special flag from _XRead to say that internal connection has
 		   done XPutBackEvent.  Which we can use so we're done. */
@@ -1065,12 +1503,33 @@
 #ifdef XTHREADS
 	int original_size = size;
 #endif
+#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_CHANGE)
+        int congestion;
+#endif
 
 	if ((dpy->flags & XlibDisplayIOError) || size == 0)
 	    return 0;
 	ESET(0);
+#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_CHANGE)
+        while (1) {
+                /*
+                 * Need to check the congestion state
+                 * after the read so split the statement
+                 * in multiple blocks.
+                 */
+
+                bytes_read = _X11TransRead(dpy->trans_conn, data, (int)size);
+                if (_NXDisplayCongestionFunction != NULL &&
+                        _X11TransSocketCongestionChange(dpy->trans_conn, &congestion) == 1) {
+                    (*_NXDisplayCongestionFunction)(dpy, congestion);
+                }
+                if (bytes_read == size) {
+                    break;
+                }
+#else
 	while ((bytes_read = _X11TransRead(dpy->trans_conn, data, (int)size))
 		!= size) {
+#endif
 
 	    	if (bytes_read > 0) {
 		    size -= bytes_read;
@@ -1090,14 +1549,34 @@
 		else if (bytes_read == 0) {
 		    /* Read failed because of end of file! */
 		    ESET(EPIPE);
+#ifdef NX_TRANS_SOCKET
+                    _XIOError(dpy);
+
+                    return -1;
+#else
 		    _XIOError(dpy);
+#endif
 		    }
 
 		else  /* bytes_read is less than 0; presumably -1 */ {
 		    /* If it's a system call interrupt, it's not an error. */
+#ifdef NX_TRANS_SOCKET
+                    if (!ECHECK(EINTR) ||
+                        (_NXDisplayErrorFunction != NULL &&
+                            (*_NXDisplayErrorFunction)(dpy, _XGetIOError(dpy)))) {
+                        _XIOError(dpy);
+                        return -1;
+                    }
+#else
 		    if (!ECHECK(EINTR))
 		    	_XIOError(dpy);
+#endif
 		    }
+#ifdef NX_TRANS_SOCKET
+                if (_XGetIOError(dpy)) {
+                    return -1;
+                }
+#endif
 	    	 }
 #ifdef XTHREADS
        if (dpy->lock && dpy->lock->reply_bytes_left > 0)
@@ -1268,6 +1747,9 @@
 #ifdef XTHREADS
         int original_size;
 #endif
+#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_CHANGE)
+        int congestion;
+#endif
 
 	if ((dpy->flags & XlibDisplayIOError) || size == 0) return;
 	iov[0].iov_len = (int)size;
@@ -1285,7 +1767,19 @@
 	original_size = size;
 #endif
 	ESET(0);
+#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_CHANGE)
+        while (1) {
+            bytes_read = _X11TransReadv (dpy->trans_conn, iov, 2);
+            if (_NXDisplayCongestionFunction != NULL &&
+                    _X11TransSocketCongestionChange(dpy->trans_conn, &congestion) == 1) {
+                (*_NXDisplayCongestionFunction)(dpy, congestion);
+            }
+            if (bytes_read == size) {
+                break;
+            }
+#else
 	while ((bytes_read = _X11TransReadv (dpy->trans_conn, iov, 2)) != size) {
+#endif
 
 	    if (bytes_read > 0) {
 		size -= bytes_read;
@@ -1313,14 +1807,34 @@
 	    else if (bytes_read == 0) {
 		/* Read failed because of end of file! */
 		ESET(EPIPE);
+#ifdef NX_TRANS_SOCKET
+                _XIOError(dpy);
+
+                return;
+#else
 		_XIOError(dpy);
+#endif
 		}
 	    
 	    else  /* bytes_read is less than 0; presumably -1 */ {
 		/* If it's a system call interrupt, it's not an error. */
+#ifdef NX_TRANS_SOCKET
+		if (!ECHECK(EINTR) ||
+                        (_NXDisplayErrorFunction != NULL &&
+                            (*_NXDisplayErrorFunction)(dpy, _XGetIOError(dpy)))) {
+                    _XIOError(dpy);
+                    return;
+                }
+#else
 		if (!ECHECK(EINTR))
 		    _XIOError(dpy);
+#endif
 		}
+#ifdef NX_TRANS_SOCKET
+            if (_XGetIOError(dpy)) {
+                return;
+            }
+#endif
 	    }
 #ifdef XTHREADS
        if (dpy->lock && dpy->lock->reply_bytes_left > 0)
@@ -1351,8 +1865,31 @@
 
 	long skip, dbufsize, padsize, total, todo;
 	_XExtension *ext;
+#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_CHANGE)
+        int congestion;
+#endif
+
+#ifdef NX_TRANS_SOCKET
+#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG)
+    fprintf(stderr, "_XSend: Sending data with [%d] bytes to write.\n",
+                (dpy->bufptr - dpy->buffer));
+#endif
+        if (!size || (dpy->flags & XlibDisplayIOError))
+        {
+            if (dpy->flags & XlibDisplayIOError)
+            {
+#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG)
+                fprintf(stderr, "_XSend: Returning with I/O error detected.\n");
+#endif
+	        dpy->bufptr = dpy->buffer;
+	        dpy->last_req = (char *)&_dummy_request;
+            }
 
+	    return;
+	}
+#else
 	if (!size || (dpy->flags & XlibDisplayIOError)) return;
+#endif
 	dbufsize = dpy->bufptr - dpy->buffer;
 #ifdef XTHREADS
 	dpy->flags |= XlibDisplayWriting;
@@ -1418,6 +1955,17 @@
     
 	    ESET(0);
 	    if ((len = _X11TransWritev(dpy->trans_conn, iov, i)) >= 0) {
+#ifdef NX_TRANS_SOCKET
+                if (_NXDisplayWriteFunction != NULL) {
+                    (*_NXDisplayWriteFunction)(dpy, len);
+                }
+#ifdef NX_TRANS_CHANGE
+                if (_NXDisplayCongestionFunction != NULL &&
+                        _X11TransSocketCongestionChange(dpy->trans_conn, &congestion) == 1) {
+                    (*_NXDisplayCongestionFunction)(dpy, congestion);
+                }
+#endif
+#endif
 		skip += len;
 		total -= len;
 		todo = total;
@@ -1447,9 +1995,23 @@
 				      );
 		}
 #endif
+#ifdef NX_TRANS_SOCKET
+            } else if (!ECHECK(EINTR) ||
+                (_NXDisplayErrorFunction != NULL &&
+                    (*_NXDisplayErrorFunction)(dpy, _XGetIOError(dpy)))) {
+                _XIOError(dpy);
+                return;
+            }
+#else
 	    } else if (!ECHECK(EINTR)) {
 		_XIOError(dpy);
 	    }
+#endif
+#ifdef NX_TRANS_SOCKET
+            if (_XGetIOError(dpy)) {
+                return;
+            }
+#endif
 	}
 	dpy->last_req = (char *) & _dummy_request;
 	if ((dpy->request - dpy->last_request_read) >= SEQLIMIT &&
@@ -1640,10 +2202,31 @@
     if (newseq < lastseq) {
 	newseq += 0x10000;
 	if (newseq > dpy->request) {
+
+#ifdef NX_TRANS_SOCKET
+
+	    if (_NXLostSequenceFunction != NULL)
+            {
+                (*_NXLostSequenceFunction)(dpy, newseq, dpy->request,
+                                               (unsigned int) rep->type);
+            }
+            else
+            {
+                (void) fprintf (stderr, 
+                "Xlib: sequence lost (0x%lx > 0x%lx) in reply type 0x%x!\n",
+                                newseq, dpy->request, 
+                                (unsigned int) rep->type);
+            }
+
+#else /* #ifdef NX_TRANS_SOCKET */
+
 	    (void) fprintf (stderr, 
 	    "Xlib: sequence lost (0x%lx > 0x%lx) in reply type 0x%x!\n",
 			    newseq, dpy->request, 
 			    (unsigned int) rep->type);
+
+#endif /* #ifdef NX_TRANS_SOCKET */
+
 	    newseq -= 0x10000;
 	}
     }
@@ -1671,9 +2254,22 @@
 #ifdef XTHREADS
     struct _XCVList *cvl;
 #endif
+#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG)
+    fprintf(stderr, "_XReply: Going to wait for an X reply.\n");
+#endif
 
+#ifdef NX_TRANS_SOCKET
+    if (dpy->flags & XlibDisplayIOError)
+    {
+#ifdef NX_TRANS_DEBUG
+        fprintf(stderr, "_XReply: Returning 0 with I/O error detected.\n");
+#endif
+        return 0;
+    }
+#else
     if (dpy->flags & XlibDisplayIOError)
 	return 0;
+#endif
 
 #ifdef XTHREADS
     /* create our condition variable and append to list */
@@ -1689,6 +2285,9 @@
 	   XThread_Self(), cvl);
 #endif
 
+#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG)
+    fprintf(stderr, "_XReply: Going to flush the display buffer.\n");
+#endif
     _XFlushInt(dpy, cvl ? cvl->cv : NULL);
     /* if it is not our turn to read a reply off the wire,
      * wait til we're at head of list.  if there is an event waiter,
@@ -1704,6 +2303,20 @@
     _XFlush(dpy);
 #endif
 
+#ifdef NX_TRANS_SOCKET
+    /*
+     * We are going to block waiting for the remote
+     * X server. Be sure that the proxy has flushed
+     * all the data.
+     */
+
+#ifdef NX_TRANS_TEST
+    fprintf(stderr, "_XReply: Requesting a flush of the NX transport.\n");
+#endif
+
+    NXTransFlush(dpy->fd);
+#endif
+
     for (;;) {
 #ifdef XTHREADS
 	/* Did another thread's _XReadEvents get our reply by accident? */
@@ -1767,6 +2380,12 @@
 			((long) rep->generic.length) << 2);
 		dpy->flags &= ~XlibDisplayReply;
 		UnlockNextReplyReader(dpy);
+#ifdef NX_TRANS_SOCKET
+                /*
+                 * The original code has provision
+                 * for returning already.
+                 */
+#endif
 		_XIOError (dpy);
 		return (0);
 
@@ -1830,6 +2449,12 @@
 #endif
 		break;
 	    }
+#ifdef NX_TRANS_SOCKET
+            if (_XGetIOError(dpy)) {
+                UnlockNextReplyReader(dpy);
+                return 0;
+            }
+#endif
 	}
 }   
 
@@ -1849,6 +2474,14 @@
     (void) _XSetLastRequestRead(dpy, &rep->generic);
     len = SIZEOF(xReply) + (rep->generic.length << 2);
     if (len < SIZEOF(xReply)) {
+#ifdef NX_TRANS_SOCKET
+
+        /*
+         * The original code has provision
+         * for returning already.
+         */
+
+#endif
 	_XIOError (dpy);
 	buf += *lenp;
 	*lenp = 0;
@@ -1876,6 +2509,14 @@
     }
     if (len < SIZEOF(xReply))
     {
+#ifdef NX_TRANS_SOCKET
+
+        /*
+         * The original code has provision
+         * for returning already.
+         */
+
+#endif
 	_XIOError (dpy);
 	buf += *lenp;
 	*lenp = 0;
@@ -1944,6 +2585,10 @@
     struct _XConnWatchInfo *watchers;
     XPointer *wd;
 
+#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG)
+    fprintf(stderr, "_XRegisterInternalConnection: Got called.\n");
+#endif
+
     new_conni = (struct _XConnectionInfo*)Xmalloc(sizeof(struct _XConnectionInfo));
     if (!new_conni)
 	return 0;
@@ -1991,6 +2636,10 @@
     struct _XConnWatchInfo *watch;
     XPointer *wd;
 
+#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG)
+    fprintf(stderr, "_XUnregisterInternalConnection: Got called.\n");
+#endif
+
     for (prev = &dpy->im_fd_info; (info_list = *prev);
 	 prev = &info_list->next) {
 	if (info_list->fd == fd) {
@@ -2030,6 +2679,10 @@
     struct _XConnectionInfo *info_list;
     int *fd_list;
 
+#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG)
+    fprintf(stderr, "XInternalConnectionNumbers: Got called.\n");
+#endif
+
     LockDisplay(dpy);
     count = 0;
     for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next)
@@ -2088,6 +2741,10 @@
 {
     struct _XConnectionInfo *info_list;
 
+#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG)
+    fprintf(stderr, "XProcessInternalConnection: Got called.\n");
+#endif
+
     LockDisplay(dpy);
     for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) {
 	if (info_list->fd == fd) {
@@ -2116,6 +2773,10 @@
     struct _XConnectionInfo *info_list;
     XPointer *wd_array;
 
+#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG)
+    fprintf(stderr, "XAddConnectionWatch: Got called.\n");
+#endif
+
     LockDisplay(dpy);
 
     /* allocate new watch data */
@@ -2172,6 +2833,10 @@
     struct _XConnectionInfo *conni;
     int counter = 0;
 
+#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG)
+    fprintf(stderr, "XRemoveConnectionWatch: Got called.\n");
+#endif
+
     LockDisplay(dpy);
     for (watch=dpy->conn_watchers; watch; watch=watch->next) {
 	if (watch->fn == callback  &&  watch->client_data == client_data) {
@@ -2209,6 +2874,10 @@
 #define SCRATCHSIZE 2048
     char buf[SCRATCHSIZE];
 
+#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG)
+    fprintf(stderr, "_XEatData: Going to eat [%ld] bytes of data from descriptor [%d].\n",
+                n, dpy->fd);
+#endif
     while (n > 0) {
 	register long bytes_read = (n > SCRATCHSIZE) ? SCRATCHSIZE : n;
 	(void) _XRead (dpy, buf, bytes_read);
@@ -2237,7 +2906,13 @@
 	    (_XQEvent *) Xmalloc((unsigned)sizeof(_XQEvent))) == NULL) {
 		/* Malloc call failed! */
 		ESET(ENOMEM);
+#ifdef NX_TRANS_SOCKET
+                _XIOError(dpy);
+
+                return;
+#else
 		_XIOError(dpy);
+#endif
 	}
 	qelt->next = NULL;
 	/* go call through display to find proper event reformatter */
@@ -2710,7 +3385,29 @@
 			QLength(dpy));
 
 	}
-	exit(1);
+#ifdef NX_TRANS_SOCKET
+        if (_NXHandleDisplayError == 1)
+        {
+#ifdef NX_TRANS_TEST
+            fprintf(stderr, "_XDefaultIOError: Going to return from the error handler.\n");
+#endif
+            return 0;
+        }
+        else
+        {
+#ifdef NX_TRANS_TEST
+            fprintf(stderr, "_XDefaultIOError: Going to exit from the program.\n");
+#endif
+#ifdef NX_TRANS_EXIT
+            NXTransExit(1);
+#else
+            exit(1);
+#endif
+        }
+#else
+        exit(1);
+#endif /* #ifdef NX_TRANS_SOCKET */
+
         return(0); /* dummy - function should never return */
 }
 
@@ -2911,7 +3608,48 @@
 	(*_XIOErrorFunction)(dpy);
     else
 	_XDefaultIOError(dpy);
+#ifdef NX_TRANS_SOCKET
+    /*
+     * Check if we are supposed to return in the case
+     * of a display failure. The client which originated
+     * the X operation will have to check the value of
+     * the XlibDisplayIOError flag and handle appropria-
+     * tely the display disconnection.
+     */
+
+    if (_NXHandleDisplayError == 0)
+    {
+#ifdef NX_TRANS_EXIT
+        NXTransExit(1);
+#else
+        exit(1);
+#endif
+    }
+
+    /*
+     * We are going to return. Reset the display
+     * buffers. Further writes will be discarded.
+     */
+
+#ifdef NX_TRANS_TEST
+    fprintf(stderr, "_XIOError: Resetting the display buffer.\n");
+#endif
+
+    dpy->bufptr = dpy->buffer;
+    dpy->last_req = (char *) &_dummy_request;
+
+#ifdef NX_TRANS_TEST
+    fprintf(stderr, "_XIOError: Resetting the display flags.\n");
+#endif
+
+    dpy->flags &= ~XlibDisplayProcConni;
+    dpy->flags &= ~XlibDisplayPrivSync;
+    dpy->flags &= ~XlibDisplayReadEvents;
+    dpy->flags &= ~XlibDisplayWriting;
+    dpy->flags &= ~XlibDisplayReply;
+#else
     exit (1);
+#endif
     return 0;
 }
 
