aboutsummaryrefslogtreecommitdiff
path: root/doc/nx-X11_vs_XOrg69_patches/NXdispatch.c.NX.patch
diff options
context:
space:
mode:
Diffstat (limited to 'doc/nx-X11_vs_XOrg69_patches/NXdispatch.c.NX.patch')
-rw-r--r--doc/nx-X11_vs_XOrg69_patches/NXdispatch.c.NX.patch1036
1 files changed, 1036 insertions, 0 deletions
diff --git a/doc/nx-X11_vs_XOrg69_patches/NXdispatch.c.NX.patch b/doc/nx-X11_vs_XOrg69_patches/NXdispatch.c.NX.patch
new file mode 100644
index 000000000..d9e35f7ae
--- /dev/null
+++ b/doc/nx-X11_vs_XOrg69_patches/NXdispatch.c.NX.patch
@@ -0,0 +1,1036 @@
+--- ./nx-X11/programs/Xserver/hw/nxagent/X/NXdispatch.c.X.original 2015-02-13 14:03:44.740441589 +0100
++++ ./nx-X11/programs/Xserver/hw/nxagent/X/NXdispatch.c 2015-02-13 14:03:44.740441589 +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. */
++/* */
++/**************************************************************************/
++
+ /* $XdotOrg: xc/programs/Xserver/dix/dispatch.c,v 1.13 2005/09/13 01:33:19 daniels Exp $ */
+ /* $Xorg: dispatch.c,v 1.5 2001/02/09 02:04:40 xorgcvs Exp $ */
+ /************************************************************
+@@ -87,6 +104,15 @@
+ int ProcInitialConnection();
+ #endif
+
++#ifdef __sun
++#define False 0
++#define True 1
++#endif
++
++#define GC XlibGC
++#include <X11/Xlib.h>
++#undef GC
++
+ #include "windowstr.h"
+ #include <X11/fonts/fontstruct.h>
+ #include "dixfontstr.h"
+@@ -100,7 +126,7 @@
+ #include "servermd.h"
+ #include "extnsionst.h"
+ #include "dixfont.h"
+-#include "dispatch.h"
++#include "../../dix/dispatch.h"
+ #include "swaprep.h"
+ #include "swapreq.h"
+ #ifdef PANORAMIX
+@@ -119,8 +145,69 @@
+ #include "inputstr.h"
+ #include <X11/extensions/XKBsrv.h>
+ #endif
++
++#include "Atoms.h"
++#include "Splash.h"
++#include "Client.h"
++#include "Clipboard.h"
++#include "Reconnect.h"
++#include "Millis.h"
++#include "Font.h"
++#include "Shadow.h"
++#include "Handlers.h"
++#include "Keyboard.h"
++
++const int nxagentMaxFontNames = 10000;
++
++char dispatchExceptionAtReset = DE_RESET;
++
++/*
++ * This allows the agent to exit if no
++ * client is connected within a timeout.
++ */
++
++int nxagentClients = 0;
++
++void nxagentWaitDisplay(void);
++
++void nxagentListRemoteFonts(const char *, int);
++
++unsigned int nxagentWMtimeout = 0;
++Bool nxagentWMPassed = 0;
++
++/*
++ * Timeouts based on screen saver time.
++ */
++
++int nxagentAutoDisconnectTimeout = 0;
++
+ #ifdef LBX
+-#include "lbxserve.h"
++#include "../../lbx/lbxserve.h"
++#endif
++
++#include "Xatom.h"
++
++/*
++ * Set here the required log level.
++ */
++
++#define PANIC
++#define WARNING
++#undef TEST
++#undef WATCH
++
++/*
++ * Log begin and end of the important handlers.
++ */
++
++#undef BLOCKS
++
++#ifdef WATCH
++#include "unistd.h"
++#endif
++
++#ifdef TEST
++#include "Literals.h"
+ #endif
+
+ #define mskcnt ((MAXCLIENTS + 31) / 32)
+@@ -138,6 +225,28 @@
+ int NumCurrentSelections;
+ CallbackListPtr SelectionCallback = NULL;
+
++#ifdef VIEWPORT_FRAME
++
++extern WindowPtr nxagentViewportFrameLeft;
++extern WindowPtr nxagentViewportFrameRight;
++extern WindowPtr nxagentViewportFrameAbove;
++extern WindowPtr nxagentViewportFrameBelow;
++
++#define IsViewportFrame(pWin) ((pWin) == nxagentViewportFrameLeft || \
++ (pWin) == nxagentViewportFrameRight || \
++ (pWin) == nxagentViewportFrameAbove || \
++ (pWin) == nxagentViewportFrameBelow)
++
++#else
++
++#define IsViewportFrame(pWin) (0)
++
++#endif /* #ifdef VIEWPORT_FRAME */
++
++extern int nxagentMaxAllowedResets;
++
++extern int nxagentFindClientResource(int, RESTYPE, pointer);
++
+ static ClientPtr grabClient;
+ #define GrabNone 0
+ #define GrabActive 1
+@@ -222,6 +331,30 @@
+ xfree(CurrentSelections);
+ CurrentSelections = (Selection *)NULL;
+ NumCurrentSelections = 0;
++
++#ifdef NXAGENT_CLIPBOARD
++ {
++ Selection *newsels;
++ newsels = (Selection *)xalloc(2 * sizeof(Selection));
++ if (!newsels)
++ return;
++ NumCurrentSelections += 2;
++ CurrentSelections = newsels;
++
++ CurrentSelections[0].selection = XA_PRIMARY;
++ CurrentSelections[0].lastTimeChanged = ClientTimeToServerTime(0);
++ CurrentSelections[0].window = WindowTable[0]->drawable.id;
++ CurrentSelections[0].pWin = NULL;
++ CurrentSelections[0].client = NullClient;
++
++ CurrentSelections[1].selection = MakeAtom("CLIPBOARD", 9, 1);
++ CurrentSelections[1].lastTimeChanged = ClientTimeToServerTime(0);
++ CurrentSelections[1].window = WindowTable[0]->drawable.id;
++ CurrentSelections[1].pWin = NULL;
++ CurrentSelections[1].client = NullClient;
++ }
++#endif
++
+ }
+
+ void
+@@ -369,14 +502,72 @@
+ long start_tick;
+ #endif
+
++ unsigned long currentDispatch = 0;
++
+ nextFreeClientID = 1;
+ InitSelections();
+ nClients = 0;
+
++ /*
++ * The agent initialization was successfully
++ * completed. We can now handle our clients.
++ */
++
++ #ifdef XKB
++
++ nxagentInitXkbWrapper();
++
++ nxagentTuneXkbWrapper();
++
++ #endif
++
++ #ifdef NXAGENT_ONSTART
++
++ /*
++ * Set NX_WM property (used by NX client to identify
++ * the agent's window) three seconds since the first
++ * client connects.
++ */
++
++ nxagentWMtimeout = GetTimeInMillis() + 3000;
++
++ #endif
++
+ clientReady = (int *) ALLOCATE_LOCAL(sizeof(int) * MaxClients);
+ if (!clientReady)
+ return;
+
++ #ifdef WATCH
++
++ fprintf(stderr, "Dispatch: Watchpoint 12.\n");
++
++/*
++Reply Total Cached Bits In Bits Out Bits/Reply Ratio
++------- ----- ------ ------- -------- ---------- -----
++#3 1 352 bits (0 KB) -> 236 bits (0 KB) -> 352/1 -> 236/1 = 1.492:1
++#14 1 256 bits (0 KB) -> 101 bits (0 KB) -> 256/1 -> 101/1 = 2.535:1
++#16 1 256 bits (0 KB) -> 26 bits (0 KB) -> 256/1 -> 26/1 = 9.846:1
++#20 2 2 12256 bits (1 KB) -> 56 bits (0 KB) -> 6128/1 -> 28/1 = 218.857:1
++#43 1 256 bits (0 KB) -> 45 bits (0 KB) -> 256/1 -> 45/1 = 5.689:1
++#47 2 2 42304 bits (5 KB) -> 49 bits (0 KB) -> 21152/1 -> 24/1 = 863.347:1
++#98 1 256 bits (0 KB) -> 34 bits (0 KB) -> 256/1 -> 34/1 = 7.529:1
++*/
++
++ sleep(30);
++
++ #endif
++
++ #ifdef TEST
++ fprintf(stderr, "Dispatch: Value of dispatchException is [%x].\n",
++ dispatchException);
++
++ fprintf(stderr, "Dispatch: Value of dispatchExceptionAtReset is [%x].\n",
++ dispatchExceptionAtReset);
++ #endif
++
++ if (!(dispatchException & DE_TERMINATE))
++ dispatchException = 0;
++
+ while (!dispatchException)
+ {
+ if (*icheck[0] != *icheck[1])
+@@ -385,8 +576,75 @@
+ FlushIfCriticalOutputPending();
+ }
+
++ /*
++ * Ensure we remove the splash after the timeout.
++ * Initializing clientReady[0] to -1 will tell
++ * WaitForSomething() to yield control after the
++ * timeout set in clientReady[1].
++ */
++
++ clientReady[0] = 0;
++
++ if (nxagentSplashWindow != None || (nxagentOption(Xdmcp) == 1 && nxagentXdmcpUp == 0))
++ {
++ #ifdef TEST
++ fprintf(stderr, "******Dispatch: Requesting a timeout of [%d] Ms.\n",
++ NXAGENT_WAKEUP);
++ #endif
++
++ clientReady[0] = -1;
++ clientReady[1] = NXAGENT_WAKEUP;
++ }
++
++ if (serverGeneration > nxagentMaxAllowedResets &&
++ nxagentSessionState == SESSION_STARTING &&
++ (nxagentOption(Xdmcp) == 0 || nxagentXdmcpUp == 1))
++ {
++ #ifdef NX_DEBUG_INPUT
++ fprintf(stderr, "Session: Session started at '%s' timestamp [%lu].\n",
++ GetTimeAsString(), GetTimeInMillis());
++ #else
++ fprintf(stderr, "Session: Session started at '%s'.\n",
++ GetTimeAsString());
++ #endif
++
++ nxagentSessionState = SESSION_UP;
++ }
++
++ #ifdef BLOCKS
++ fprintf(stderr, "[End dispatch]\n");
++ #endif
++
+ nready = WaitForSomething(clientReady);
+
++ #ifdef BLOCKS
++ fprintf(stderr, "[Begin dispatch]\n");
++ #endif
++
++ #ifdef TEST
++ fprintf(stderr, "******Dispatch: Running with [%d] clients ready.\n",
++ nready);
++ #endif
++
++ #ifdef NXAGENT_ONSTART
++
++ currentDispatch = GetTimeInMillis();
++
++ /*
++ * If the timeout is expired set the
++ * selection informing the NX client
++ * that the agent is ready.
++ */
++
++ if (!nxagentWMPassed && (nxagentWMtimeout < currentDispatch))
++ {
++ nxagentRemoveSplashWindow(NULL);
++ }
++
++ nxagentClients = nClients;
++
++ #endif
++
+ #ifdef SMART_SCHEDULE
+ if (nready && !SmartScheduleDisable)
+ {
+@@ -438,6 +696,11 @@
+ #endif
+ /* now, finally, deal with client requests */
+
++ #ifdef TEST
++ fprintf(stderr, "******Dispatch: Reading request from client [%d].\n",
++ client->index);
++ #endif
++
+ result = ReadRequestFromClient(client);
+ if (result <= 0)
+ {
+@@ -445,6 +708,29 @@
+ CloseDownClient(client);
+ break;
+ }
++#ifdef NXAGENT_SERVER
++
++ #ifdef TEST
++
++ else
++ {
++
++ if (MAJOROP > 127)
++ {
++ fprintf(stderr, "******Dispatch: Read [Extension] request OPCODE#%d MINOR#%d "
++ "size [%d] client [%d].\n", MAJOROP, *((char *) client->requestBuffer + 1),
++ client->req_len << 2, client->index);
++ }
++ else
++ {
++ fprintf(stderr, "******Dispatch: Read [%s] request OPCODE#%d size [%d] client [%d].\n",
++ nxagentRequestLiteral[MAJOROP], MAJOROP, client->req_len << 2,
++ client->index);
++ }
++ }
++
++ #endif
++#endif
+
+ client->sequence++;
+ #ifdef DEBUG
+@@ -456,8 +742,40 @@
+ if (result > (maxBigRequestSize << 2))
+ result = BadLength;
+ else
++#ifdef NXAGENT_SERVER
++ {
++ result = (* client->requestVector[MAJOROP])(client);
++
++ #ifdef TEST
++
++ if (MAJOROP > 127)
++ {
++ fprintf(stderr, "******Dispatch: Handled [Extension] request OPCODE#%d MINOR#%d "
++ "size [%d] client [%d] result [%d].\n", MAJOROP,
++ *((char *) client->requestBuffer + 1), client->req_len << 2,
++ client->index, result);
++ }
++ else
++ {
++ fprintf(stderr, "******Dispatch: Handled [%s] request OPCODE#%d size [%d] client [%d] "
++ "result [%d].\n", nxagentRequestLiteral[MAJOROP], MAJOROP,
++ client->req_len << 2, client->index, result);
++ }
++
++ #endif
++
++ /*
++ * Can set isItTimeToYield to force
++ * the dispatcher to pay attention
++ * to another client.
++ */
++
++ nxagentDispatchHandler(client, client->req_len << 2, 0);
++ }
++#else
+ result = (* client->requestVector[MAJOROP])(client);
+-
++#endif
++
+ if (result != Success)
+ {
+ if (client->noClientException != Success)
+@@ -485,6 +803,37 @@
+ #if defined(DDXBEFORERESET)
+ ddxBeforeReset ();
+ #endif
++ if ((dispatchException & DE_RESET) &&
++ (serverGeneration > nxagentMaxAllowedResets))
++ {
++ dispatchException &= ~DE_RESET;
++ dispatchException |= DE_TERMINATE;
++
++ fprintf(stderr, "Info: Reached threshold of maximum allowed resets.\n");
++ }
++
++ nxagentResetAtomMap();
++
++ if (serverGeneration > nxagentMaxAllowedResets)
++ {
++ /*
++ * The session is terminating. Force an I/O
++ * error on the display and wait until the
++ * NX transport is gone.
++ */
++
++ fprintf(stderr, "Session: Terminating session at '%s'.\n", GetTimeAsString());
++
++ nxagentWaitDisplay();
++
++ fprintf(stderr, "Session: Session terminated at '%s'.\n", GetTimeAsString());
++ }
++
++ if (nxagentOption(Shadow) == 1)
++ {
++ NXShadowDestroy();
++ }
++
+ KillAllClients();
+ DEALLOCATE_LOCAL(clientReady);
+ dispatchException &= ~DE_RESET;
+@@ -656,6 +1005,12 @@
+ SecurityWriteAccess);
+ if (!pWin)
+ return(BadWindow);
++
++ if (!nxagentWMPassed)
++ {
++ nxagentRemoveSplashWindow(pWin);
++ }
++
+ pParent = (WindowPtr)SecurityLookupWindow(stuff->parent, client,
+ SecurityWriteAccess);
+ if (!pParent)
+@@ -724,6 +1079,7 @@
+ return(BadWindow);
+ UnmapWindow(pWin, FALSE);
+ /* update cache to say it is mapped */
++
+ return(client->noClientException);
+ }
+
+@@ -760,6 +1116,7 @@
+ return BadLength;
+ result = ConfigureWindow(pWin, (Mask)stuff->mask, (XID *) &stuff[1],
+ client);
++
+ if (client->noClientException != Success)
+ return(client->noClientException);
+ else
+@@ -865,7 +1222,12 @@
+ reply.parent = (Window)None;
+ pHead = RealChildHead(pWin);
+ for (pChild = pWin->lastChild; pChild != pHead; pChild = pChild->prevSib)
++ {
++ if (!IsViewportFrame(pChild))
++ {
+ numChildren++;
++ }
++ }
+ if (numChildren)
+ {
+ int curChild = 0;
+@@ -874,7 +1236,12 @@
+ if (!childIDs)
+ return BadAlloc;
+ for (pChild = pWin->lastChild; pChild != pHead; pChild = pChild->prevSib)
++ {
++ if (!IsViewportFrame(pChild))
++ {
+ childIDs[curChild++] = pChild->drawable.id;
++ }
++ }
+ }
+
+ reply.nChildren = numChildren;
+@@ -1038,6 +1405,16 @@
+ info.kind= SelectionSetOwner;
+ CallCallbacks(&SelectionCallback, &info);
+ }
++
++#ifdef NXAGENT_CLIPBOARD
++ if ((CurrentSelections[i].pWin != NULL) &&
++ (nxagentOption(Clipboard) != ClipboardNone) &&
++ ((CurrentSelections[i].selection == XA_PRIMARY) ||
++ (CurrentSelections[i].selection == MakeAtom("CLIPBOARD", 9, 0))))
++ {
++ nxagentSetSelectionOwner(&CurrentSelections[i]);
++ }
++#endif
+ return (client->noClientException);
+ }
+ else
+@@ -1092,6 +1469,27 @@
+ if (!pWin)
+ return(BadWindow);
+
++#ifdef NXAGENT_CLIPBOARD
++ if (((stuff->selection == XA_PRIMARY) ||
++ (stuff->selection == MakeAtom("CLIPBOARD", 9, 0))) &&
++ nxagentOption(Clipboard) != ClipboardNone)
++ {
++ int i = 0;
++
++ while ((i < NumCurrentSelections) &&
++ CurrentSelections[i].selection != stuff->selection) i++;
++
++ if ((i < NumCurrentSelections) && (CurrentSelections[i].window != None))
++ {
++ if (nxagentConvertSelection(client, pWin, stuff->selection, stuff->requestor,
++ stuff->property, stuff->target, stuff->time))
++ {
++ return (client->noClientException);
++ }
++ }
++ }
++#endif
++
+ paramsOkay = (ValidAtom(stuff->selection) && ValidAtom(stuff->target));
+ if (stuff->property != None)
+ paramsOkay &= ValidAtom(stuff->property);
+@@ -1103,7 +1501,7 @@
+ while ((i < NumCurrentSelections) &&
+ CurrentSelections[i].selection != stuff->selection) i++;
+ if ((i < NumCurrentSelections) &&
+- (CurrentSelections[i].window != None)
++ (CurrentSelections[i].window != None) && (CurrentSelections[i].client != NullClient)
+ #ifdef XCSECURITY
+ && (!client->CheckAccess ||
+ (* client->CheckAccess)(client, CurrentSelections[i].window,
+@@ -1286,11 +1684,26 @@
+ ProcOpenFont(register ClientPtr client)
+ {
+ int err;
++ char fontReq[256];
+ REQUEST(xOpenFontReq);
+
+ REQUEST_FIXED_SIZE(xOpenFontReq, stuff->nbytes);
+ client->errorValue = stuff->fid;
+ LEGAL_NEW_RESOURCE(stuff->fid, client);
++
++ memcpy(fontReq,(char *)&stuff[1],(stuff->nbytes<256)?stuff->nbytes:255);
++ fontReq[stuff->nbytes]=0;
++ if (strchr(fontReq,'*') || strchr(fontReq,'?'))
++ {
++ extern int nxOpenFont(ClientPtr, XID, Mask, unsigned, char*);
++#ifdef NXAGENT_FONTMATCH_DEBUG
++ fprintf(stderr, "Dispatch: ProcOpenFont try to find a common font with font pattern=%s\n",fontReq);
++#endif
++ nxagentListRemoteFonts(fontReq, nxagentMaxFontNames);
++ err = nxOpenFont(client, stuff->fid, (Mask) 0,
++ stuff->nbytes, (char *)&stuff[1]);
++ }
++ else
+ err = OpenFont(client, stuff->fid, (Mask) 0,
+ stuff->nbytes, (char *)&stuff[1]);
+ if (err == Success)
+@@ -1310,8 +1723,43 @@
+ REQUEST_SIZE_MATCH(xResourceReq);
+ pFont = (FontPtr)SecurityLookupIDByType(client, stuff->id, RT_FONT,
+ SecurityDestroyAccess);
+- if ( pFont != (FontPtr)NULL) /* id was valid */
++ if (pFont != (FontPtr)NULL)
+ {
++ #ifdef NXAGENT_SERVER
++
++ /*
++ * When a client closes a font the resource
++ * should not be lost if the reference counter
++ * is not 0, otherwise the server will not be
++ * able to find this font looping through the
++ * resources.
++ */
++
++ if (pFont -> refcnt > 0)
++ {
++ if (nxagentFindClientResource(serverClient -> index, RT_NX_FONT, pFont) == 0)
++ {
++ #ifdef TEST
++ fprintf(stderr, "ProcCloseFont: Switching resource for font at [%p].\n",
++ (void *) pFont);
++ #endif
++
++ nxagentFontPriv(pFont) -> mirrorID = FakeClientID(serverClient -> index);
++
++ AddResource(nxagentFontPriv(pFont) -> mirrorID, RT_NX_FONT, pFont);
++
++ }
++ #ifdef TEST
++ else
++ {
++ fprintf(stderr, "ProcCloseFont: Found duplicated font at [%p], "
++ "resource switching skipped.\n", (void *) pFont);
++ }
++ #endif
++ }
++
++ #endif
++
+ FreeResource(stuff->id, RT_NONE);
+ return(client->noClientException);
+ }
+@@ -1332,6 +1780,8 @@
+
+ REQUEST_SIZE_MATCH(xResourceReq);
+ client->errorValue = stuff->id; /* EITHER font or gc */
++
++ pFont = NULL;
+ pFont = (FontPtr)SecurityLookupIDByType(client, stuff->id, RT_FONT,
+ SecurityReadAccess);
+ if (!pFont)
+@@ -1347,6 +1797,33 @@
+ pFont = pGC->font;
+ }
+
++/* test
++{
++ Atom name_atom, value_atom;
++ int nprops;
++ FontPropPtr props;
++ int i;
++ char *name;
++
++ name_atom = MakeAtom("FONT", 4, True);
++ value_atom = 0L;
++
++ nprops = pFont->info.nprops;
++ props = pFont->info.props;
++
++ for (i = 0; i < nprops; i++)
++ if (props[i].name == name_atom) {
++ value_atom = props[i].value;
++ break;
++ }
++
++ if (!value_atom) return (BadFont);
++
++ name = (char *)NameForAtom(value_atom);
++ fprintf(stderr, "QueryFont: font name [%s]\n",name);
++}
++ end test */
++
+ {
+ xCharInfo *pmax = FONTINKMAX(pFont);
+ xCharInfo *pmin = FONTINKMIN(pFont);
+@@ -1364,6 +1841,7 @@
+ rlength = sizeof(xQueryFontReply) +
+ FONTINFONPROPS(FONTCHARSET(pFont)) * sizeof(xFontProp) +
+ nprotoxcistructs * sizeof(xCharInfo);
++ reply = NULL;
+ reply = (xQueryFontReply *)ALLOCATE_LOCAL(rlength);
+ if(!reply)
+ {
+@@ -1434,10 +1912,18 @@
+ int
+ ProcListFonts(register ClientPtr client)
+ {
++ char tmp[256];
++
+ REQUEST(xListFontsReq);
+
+ REQUEST_FIXED_SIZE(xListFontsReq, stuff->nbytes);
++ memcpy(tmp,(unsigned char *) &stuff[1],(stuff->nbytes<256)?stuff->nbytes:255);
++ tmp[stuff->nbytes]=0;
+
++#ifdef NXAGENT_FONTMATCH_DEBUG
++ fprintf(stderr, "Dispatch: ListFont request with pattern %s max_names=%d\n",tmp,stuff->maxNames);
++#endif
++ nxagentListRemoteFonts(tmp, stuff -> maxNames < nxagentMaxFontNames ? nxagentMaxFontNames : stuff->maxNames);
+ return ListFonts(client, (unsigned char *) &stuff[1], stuff->nbytes,
+ stuff->maxNames);
+ }
+@@ -1445,10 +1931,18 @@
+ int
+ ProcListFontsWithInfo(register ClientPtr client)
+ {
++ char tmp[256];
+ REQUEST(xListFontsWithInfoReq);
+
+ REQUEST_FIXED_SIZE(xListFontsWithInfoReq, stuff->nbytes);
+
++ memcpy(tmp,(unsigned char *) &stuff[1],(stuff->nbytes<256)?stuff->nbytes:255);
++ tmp[stuff->nbytes]=0;
++#ifdef NXAGENT_FONTMATCH_DEBUG
++ fprintf(stderr, "Dispatch: ListFont with info request with pattern %s max_names=%d\n",tmp,stuff->maxNames);
++#endif
++ nxagentListRemoteFonts(tmp, stuff -> maxNames < nxagentMaxFontNames ? nxagentMaxFontNames :stuff->maxNames);
++
+ return StartListFontsWithInfo(client, stuff->nbytes,
+ (unsigned char *) &stuff[1], stuff->maxNames);
+ }
+@@ -1535,6 +2029,40 @@
+ SecurityDestroyAccess);
+ if (pMap)
+ {
++ #ifdef NXAGENT_SERVER
++
++ /*
++ * When a client releases a pixmap the resource
++ * should not be lost if the reference counter
++ * is not 0, otherwise the server will not be
++ * able to find this pixmap looping through the
++ * resources.
++ */
++
++ if (pMap -> refcnt > 0)
++ {
++ if (nxagentFindClientResource(serverClient -> index, RT_NX_PIXMAP, pMap) == 0)
++ {
++ #ifdef TEST
++ fprintf(stderr, "ProcFreePixmap: Switching resource for pixmap at [%p].\n",
++ (void *) pMap);
++ #endif
++
++ nxagentPixmapPriv(pMap) -> mid = FakeClientID(serverClient -> index);
++
++ AddResource(nxagentPixmapPriv(pMap) -> mid, RT_NX_PIXMAP, pMap);
++ }
++ #ifdef TEST
++ else
++ {
++ fprintf(stderr, "ProcFreePixmap: Found duplicated pixmap at [%p], "
++ "resource switching skipped.\n", (void *) pMap);
++ }
++ #endif
++ }
++
++ #endif
++
+ FreeResource(stuff->id, RT_NONE);
+ return(client->noClientException);
+ }
+@@ -1819,8 +2347,10 @@
+ VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client);
+ npoint = ((client->req_len << 2) - sizeof(xPolyPointReq)) >> 2;
+ if (npoint)
++ {
+ (*pGC->ops->PolyPoint)(pDraw, pGC, stuff->coordMode, npoint,
+ (xPoint *) &stuff[1]);
++ }
+ return (client->noClientException);
+ }
+
+@@ -1842,8 +2372,10 @@
+ VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client);
+ npoint = ((client->req_len << 2) - sizeof(xPolyLineReq)) >> 2;
+ if (npoint > 1)
++ {
+ (*pGC->ops->Polylines)(pDraw, pGC, stuff->coordMode, npoint,
+ (DDXPointPtr) &stuff[1]);
++ }
+ return(client->noClientException);
+ }
+
+@@ -1862,7 +2394,9 @@
+ return(BadLength);
+ nsegs >>= 3;
+ if (nsegs)
++ {
+ (*pGC->ops->PolySegment)(pDraw, pGC, nsegs, (xSegment *) &stuff[1]);
++ }
+ return (client->noClientException);
+ }
+
+@@ -1881,8 +2415,10 @@
+ return(BadLength);
+ nrects >>= 3;
+ if (nrects)
++ {
+ (*pGC->ops->PolyRectangle)(pDraw, pGC,
+ nrects, (xRectangle *) &stuff[1]);
++ }
+ return(client->noClientException);
+ }
+
+@@ -1901,7 +2437,9 @@
+ return(BadLength);
+ narcs /= sizeof(xArc);
+ if (narcs)
++ {
+ (*pGC->ops->PolyArc)(pDraw, pGC, narcs, (xArc *) &stuff[1]);
++ }
+ return (client->noClientException);
+ }
+
+@@ -1930,9 +2468,11 @@
+ VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client);
+ things = ((client->req_len << 2) - sizeof(xFillPolyReq)) >> 2;
+ if (things)
++ {
+ (*pGC->ops->FillPolygon) (pDraw, pGC, stuff->shape,
+ stuff->coordMode, things,
+ (DDXPointPtr) &stuff[1]);
++ }
+ return(client->noClientException);
+ }
+
+@@ -1952,8 +2492,10 @@
+ things >>= 3;
+
+ if (things)
++ {
+ (*pGC->ops->PolyFillRect) (pDraw, pGC, things,
+ (xRectangle *) &stuff[1]);
++ }
+ return (client->noClientException);
+ }
+
+@@ -1972,7 +2514,9 @@
+ return(BadLength);
+ narcs /= sizeof(xArc);
+ if (narcs)
++ {
+ (*pGC->ops->PolyFillArc) (pDraw, pGC, narcs, (xArc *) &stuff[1]);
++ }
+ return (client->noClientException);
+ }
+
+@@ -3127,7 +3671,14 @@
+ stuff->backRed, stuff->backGreen, stuff->backBlue);
+
+ if (pCursor && AddResource(stuff->cid, RT_CURSOR, (pointer)pCursor))
++ {
++ #ifdef TEST
++ fprintf(stderr, "ProcCreateCursor: Created cursor at [%p].\n", (void *) pCursor);
++ #endif
++
+ return (client->noClientException);
++ }
++
+ return BadAlloc;
+ }
+
+@@ -3243,25 +3794,68 @@
+ return BadValue;
+ }
+
+- if (blankingOption == DefaultBlanking)
++ /*
++ * The NX agent uses the screen saver procedure
++ * to monitor the user activities and launch its
++ * handlers (like timeout feature), so we can't
++ * always allow the clients to change our values.
++ */
++
++ #ifdef TEST
++ fprintf(stderr, "ProcSetScreenSaver: Called with timeout [%d] interval [%d] Blanking [%d] Exposure [%d].\n",
++ stuff -> timeout, stuff -> interval, blankingOption, exposureOption);
++ #endif
++
++ if (nxagentOption(Timeout) == 0)
++ {
++ if (blankingOption == DefaultBlanking)
++ {
+ ScreenSaverBlanking = defaultScreenSaverBlanking;
+- else
++ }
++ else
++ {
+ ScreenSaverBlanking = blankingOption;
+- if (exposureOption == DefaultExposures)
++ }
++
++ if (exposureOption == DefaultExposures)
++ {
+ ScreenSaverAllowExposures = defaultScreenSaverAllowExposures;
+- else
+- ScreenSaverAllowExposures = exposureOption;
++ }
++ else
++ {
++ ScreenSaverAllowExposures = exposureOption;
++ }
++
++ if (stuff->timeout >= 0)
++ {
++ ScreenSaverTime = stuff->timeout * MILLI_PER_SECOND;
++ }
++ else
++ {
++ ScreenSaverTime = defaultScreenSaverTime;
++ }
++
++ if (stuff->interval >= 0)
++ {
++ ScreenSaverInterval = stuff->interval * MILLI_PER_SECOND;
++ }
++ else
++ {
++ ScreenSaverInterval = defaultScreenSaverInterval;
++ }
++
++ SetScreenSaverTimer();
++ }
++ #ifdef TEST
+
+- if (stuff->timeout >= 0)
+- ScreenSaverTime = stuff->timeout * MILLI_PER_SECOND;
+- else
+- ScreenSaverTime = defaultScreenSaverTime;
+- if (stuff->interval >= 0)
+- ScreenSaverInterval = stuff->interval * MILLI_PER_SECOND;
+ else
+- ScreenSaverInterval = defaultScreenSaverInterval;
++ {
++ fprintf(stderr, "ProcSetScreenSaver: Keeping auto-disconnect timeout set to [%d] seconds.\n",
++ nxagentOption(Timeout));
++ }
++
++ #endif
+
+- SetScreenSaverTimer();
+ return (client->noClientException);
+ }
+
+@@ -3481,7 +4075,30 @@
+ client->errorValue = stuff->mode;
+ return BadValue;
+ }
+- SaveScreens(SCREEN_SAVER_FORCER, (int)stuff->mode);
++
++ /*
++ * The NX agent uses the screen saver procedure
++ * to monitor the user activities and launch its
++ * handlers (like timeout feature), so we can't
++ * always allow the clients to force the screen
++ * saver handler execution.
++ */
++
++ if (nxagentOption(Timeout) == 0)
++ {
++ SaveScreens(SCREEN_SAVER_FORCER, (int)stuff->mode);
++ }
++
++ #ifdef TEST
++
++ else
++ {
++ fprintf(stderr, "ProcForceScreenSaver: Ignoring the client request with mode [%d].\n",
++ stuff -> mode);
++ }
++
++ #endif
++
+ return client->noClientException;
+ }
+
+@@ -3525,14 +4142,34 @@
+ * then killed again, the client is really destroyed.
+ *********************/
+
+-char dispatchExceptionAtReset = DE_RESET;
+-
+ void
+ CloseDownClient(register ClientPtr client)
+ {
+ Bool really_close_down = client->clientGone ||
+ client->closeDownMode == DestroyAll;
+
++ /*
++ * There must be a better way to hook a
++ * call-back function to be called any
++ * time a client is going to be closed.
++ */
++
++ nxagentClearClipboard(client, NULL);
++
++ /*
++ * Need to reset the karma counter and
++ * get rid of the pending sync replies.
++ */
++
++ nxagentWakeupByReset(client);
++
++ /*
++ * Check if the client
++ * is a shadow nxagent.
++ */
++
++ nxagentCheckIfShadowAgent(client);
++
+ if (!client->clientGone)
+ {
+ /* ungrab server if grabbing client dies */
+@@ -3673,7 +4310,7 @@
+ client->numSaved = 0;
+ client->saveSet = (SaveSetElt *)NULL;
+ client->noClientException = Success;
+-#ifdef DEBUG
++#ifdef LOG_DEBUG
+ client->requestLogIndex = 0;
+ #endif
+ client->requestVector = InitialVector;
+@@ -3746,6 +4383,13 @@
+ else
+ ppriv->ptr = (pointer)NULL;
+ }
++
++ /*
++ * Initialize the private members.
++ */
++
++ nxagentInitClientPrivates(client);
++
+ return 1;
+ }
+