--- ./nx-X11/programs/Xserver/hw/nxagent/X/NXresource.c.X.original	2015-02-13 14:03:44.748441432 +0100
+++ ./nx-X11/programs/Xserver/hw/nxagent/X/NXresource.c	2015-02-10 19:13:13.820685287 +0100
@@ -1,3 +1,20 @@
+/**************************************************************************/
+/*                                                                        */
+/* Copyright (c) 2001, 2011 NoMachine, http://www.nomachine.com/.         */
+/*                                                                        */
+/* NXAGENT, 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.                                                   */
+/*                                                                        */
+/**************************************************************************/
+
 /************************************************************
 
 Copyright 1987, 1998  The Open Group
@@ -125,6 +142,20 @@
 #endif
 #include <assert.h>
 
+#ifdef NXAGENT_SERVER
+
+#include "Agent.h"
+#include "Font.h"
+#include "Pixmaps.h"
+#include "GCs.h"
+
+#define PANIC
+#define WARNING
+#undef  TEST
+#undef  DEBUG
+
+#endif
+
 static void RebuildTable(
     int /*client*/
 );
@@ -170,6 +201,10 @@
 
 #endif
 
+#ifdef NXAGENT_SERVER
+static int nxagentResChangedFlag = 0;
+#endif
+
 RESTYPE
 CreateNewResourceType(DeleteType deleteFunc)
 {
@@ -422,13 +457,107 @@
     return id;
 }
 
+#ifdef NXAGENT_SERVER
+
+int nxagentFindClientResource(int client, RESTYPE type, pointer value)
+{
+  ResourcePtr pResource;
+  ResourcePtr *resources;
+
+  int i;
+
+  for (i = 0; i < clientTable[client].buckets; i++)
+  {
+    resources = clientTable[client].resources;
+
+    for (pResource = resources[i]; pResource; pResource = pResource -> next)
+    {
+      if (pResource -> type == type && pResource -> value == value)
+      {
+        #ifdef TEST
+        fprintf(stderr, "nxagentFindClientResource: Found resource [%p] type [%lu] "
+                    "for client [%d].\n", (void *) value,
+                        pResource -> type, client);
+        #endif
+
+        return 1;
+      }
+    }
+  }
+
+  return 0;
+}
+
+int nxagentSwitchResourceType(int client, RESTYPE type, pointer value)
+{
+  ResourcePtr pResource;
+  ResourcePtr *resources;
+
+  RESTYPE internalType = 0;
+
+  int i;
+
+  if (type == RT_PIXMAP)
+  {
+    internalType = RT_NX_PIXMAP;
+  }
+  else if (type == RT_GC)
+  {
+    internalType = RT_NX_GC;
+  }
+  else if (type == RT_FONT)
+  {
+    internalType = RT_NX_FONT;
+  }
+  else
+  {
+    return 0;
+  }
+
+  if (client == serverClient -> index)
+  {
+    #ifdef TEST
+    fprintf(stderr, "nxagentSwitchResourceType: Requesting client is [%d]. Skipping the resource switch.\n",
+                client);
+    #endif
+
+    return 0;
+  }
+
+  for (i = 0; i < clientTable[serverClient -> index].buckets; i++)
+  {
+    resources = clientTable[serverClient -> index].resources;
+
+    for (pResource = resources[i]; pResource; pResource = pResource -> next)
+    {
+      if (pResource -> type == internalType &&
+              pResource -> value == value)
+      {
+        #ifdef TEST
+        fprintf(stderr, "nxagentSwitchResourceType: Changing resource [%p] type from [%lu] to "
+                    "[%lu] for server client [%d].\n", (void *) value,
+                        (unsigned long) pResource -> type, (unsigned long) type, serverClient -> index);
+        #endif
+
+        FreeResource(pResource -> id, RT_NONE);
+
+        return 1;
+      }
+    }
+  }
+
+  return 0;
+}
+
+#endif
+
 Bool
 AddResource(XID id, RESTYPE type, pointer value)
 {
     int client;
     register ClientResourceRec *rrec;
     register ResourcePtr res, *head;
-    	
+
     client = CLIENT_ID(id);
     rrec = &clientTable[client];
     if (!rrec->buckets)
@@ -437,6 +566,18 @@
 		(unsigned long)id, type, (unsigned long)value, client);
         FatalError("client not in use\n");
     }
+
+#ifdef NXAGENT_SERVER
+
+    nxagentSwitchResourceType(client, type, value);
+
+    #ifdef TEST
+    fprintf(stderr, "AddResource: Adding resource for client [%d] type [%lu] value [%p] id [%lu].\n",
+                client, (unsigned long) type, (void *) value, (unsigned long) id);
+    #endif
+
+#endif
+
     if ((rrec->elements >= 4*rrec->buckets) &&
 	(rrec->hashsize < MAXHASHSIZE))
 	RebuildTable(client);
@@ -453,6 +594,9 @@
     res->value = value;
     *head = res;
     rrec->elements++;
+    #ifdef NXAGENT_SERVER
+    nxagentResChangedFlag = 1;
+    #endif
     if (!(id & SERVER_BIT) && (id >= rrec->expectID))
 	rrec->expectID = id + 1;
     return TRUE;
@@ -517,6 +661,14 @@
     int		elements;
     Bool	gotOne = FALSE;
 
+#ifdef NXAGENT_SERVER
+
+    #ifdef TEST
+    fprintf(stderr, "FreeResource: Freeing resource id [%lu].\n", (unsigned long) id);
+    #endif
+
+#endif
+
     if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && clientTable[cid].buckets)
     {
 	head = &clientTable[cid].resources[Hash(cid, id)];
@@ -530,6 +682,9 @@
 		RESTYPE rtype = res->type;
 		*prev = res->next;
 		elements = --*eltptr;
+                #ifdef NXAGENT_SERVER
+                nxagentResChangedFlag = 1;
+                #endif
 		if (rtype & RC_CACHED)
 		    FlushClientCaches(res->id);
 		if (rtype != skipDeleteFuncType)
@@ -570,6 +725,9 @@
 	    if (res->id == id && res->type == type)
 	    {
 		*prev = res->next;
+                #ifdef NXAGENT_SERVER
+                nxagentResChangedFlag = 1;
+                #endif
 		if (type & RC_CACHED)
 		    FlushClientCaches(res->id);
 		if (!skipFree)
@@ -634,10 +792,28 @@
     int i, elements;
     register int *eltptr;
 
+    #ifdef NXAGENT_SERVER
+    register ResourcePtr **resptr;
+    #endif
+
     if (!client)
 	client = serverClient;
 
+/*
+ * If func triggers a resource table
+ * rebuild then restart the loop.
+ */
+
+#ifdef NXAGENT_SERVER
+RestartLoop:
+#endif
+
     resources = clientTable[client->index].resources;
+
+    #ifdef NXAGENT_SERVER
+    resptr = &clientTable[client->index].resources;
+    #endif
+
     eltptr = &clientTable[client->index].elements;
     for (i = 0; i < clientTable[client->index].buckets; i++) 
     {
@@ -646,8 +822,44 @@
 	    next = this->next;
 	    if (!type || this->type == type) {
 		elements = *eltptr;
+
+                /*
+                 * FIXME:
+                 * It is not safe to let a function change the resource
+                 * table we are reading!
+                 */
+
+                #ifdef NXAGENT_SERVER
+                nxagentResChangedFlag = 0;
+                #endif
 		(*func)(this->value, this->id, cdata);
+
+                /*
+                 * Avoid that a call to RebuildTable() could invalidate the
+                 * pointer. This is safe enough, because in RebuildTable()
+                 * the new pointer is allocated just before the old one is
+                 * freed, so it can't point to the same address.
+                 */
+
+                #ifdef NXAGENT_SERVER
+                if (*resptr != resources)
+                   goto RestartLoop;
+                #endif
+
+                /*
+                 * It's not enough to check if the number of elements has
+                 * changed, beacause it could happen that the number of
+                 * resources that have been added matches the number of
+                 * the freed ones.
+                 * 'nxagentResChangedFlag' is set if a resource has been
+                 * added or freed.
+                 */
+
+                #ifdef NXAGENT_SERVER
+                if (*eltptr != elements || nxagentResChangedFlag)
+                #else
 		if (*eltptr != elements)
+                #endif
 		    next = resources[i]; /* start over */
 	    }
 	}
@@ -665,10 +877,28 @@
     int i, elements;
     register int *eltptr;
 
+    #ifdef NXAGENT_SERVER
+    register ResourcePtr **resptr;
+    #endif
+
     if (!client)
         client = serverClient;
 
+/*
+ * If func triggers a resource table
+ * rebuild then restart the loop.
+ */
+
+#ifdef NXAGENT_SERVER
+RestartLoop:
+#endif
+
     resources = clientTable[client->index].resources;
+
+    #ifdef NXAGENT_SERVER
+    resptr = &clientTable[client->index].resources;
+    #endif
+
     eltptr = &clientTable[client->index].elements;
     for (i = 0; i < clientTable[client->index].buckets; i++)
     {
@@ -676,8 +906,44 @@
         {
             next = this->next;
             elements = *eltptr;
+
+            /*
+             * FIXME:
+             * It is not safe to let a function change the resource
+             * table we are reading!
+             */
+
+            #ifdef NXAGENT_SERVER
+            nxagentResChangedFlag = 0;
+            #endif
             (*func)(this->value, this->id, this->type, cdata);
+
+            /*
+             * Avoid that a call to RebuildTable() could invalidate the
+             * pointer. This is safe enough, because in RebuildTable()
+             * the new pointer is allocated just before the old one is
+             * freed, so it can't point to the same address.
+             */
+
+            #ifdef NXAGENT_SERVER
+            if (*resptr != resources)
+                goto RestartLoop;
+            #endif
+
+            /*
+             * It's not enough to check if the number of elements has
+             * changed, beacause it could happen that the number of
+             * resources that have been added matches the number of
+             * the freed ones.
+             * 'nxagentResChangedFlag' is set if a resource has been
+             * added or freed.
+             */
+
+            #ifdef NXAGENT_SERVER
+            if (*eltptr != elements || nxagentResChangedFlag)
+            #else
             if (*eltptr != elements)
+            #endif
                 next = resources[i]; /* start over */
         }
     }
@@ -695,15 +961,44 @@
     ResourcePtr this;
     int i;
 
+    #ifdef NXAGENT_SERVER
+    ResourcePtr **resptr;
+    Bool res;
+    #endif
+
     if (!client)
 	client = serverClient;
 
+/*
+ * If func triggers a resource table
+ * rebuild then restart the loop.
+ */
+
+#ifdef NXAGENT_SERVER
+RestartLoop:
+#endif
+
     resources = clientTable[client->index].resources;
+
+    #ifdef NXAGENT_SERVER
+    resptr = &clientTable[client->index].resources;
+    #endif
+
     for (i = 0; i < clientTable[client->index].buckets; i++) {
         for (this = resources[i]; this; this = this->next) {
 	    if (!type || this->type == type) {
+                #ifdef NXAGENT_SERVER
+                res = (*func)(this->value, this->id, cdata);
+
+                if (*resptr != resources)
+                    goto RestartLoop;
+
+                if (res)
+                    return this->value;
+                #else
 		if((*func)(this->value, this->id, cdata))
 		    return this->value;
+                #endif
 	    }
 	}
     }
@@ -952,3 +1247,4 @@
 }
 
 #endif /* XCSECURITY */
+
