aboutsummaryrefslogtreecommitdiff
path: root/nx-X11/programs/Xserver/hw/nxagent/compext
diff options
context:
space:
mode:
authorMike Gabriel <mike.gabriel@das-netzwerkteam.de>2016-11-03 00:19:26 +0100
committerMike Gabriel <mike.gabriel@das-netzwerkteam.de>2016-11-15 16:38:26 +0100
commit80b5de3f55fd493ee85f2a78b731ff05e6363e43 (patch)
tree29930f1da570f462521557ee426a96d53eef1e2c /nx-X11/programs/Xserver/hw/nxagent/compext
parentcae394b45f499817ef5caa9876a8e40db6484b83 (diff)
downloadnx-libs-80b5de3f55fd493ee85f2a78b731ff05e6363e43.tar.gz
nx-libs-80b5de3f55fd493ee85f2a78b731ff05e6363e43.tar.bz2
nx-libs-80b5de3f55fd493ee85f2a78b731ff05e6363e43.zip
nxcompext: Move code into Xserver subtree, as nxcompext requires Xserver includes at build time.
Fixes ArcticaProject/nx-libs#276.
Diffstat (limited to 'nx-X11/programs/Xserver/hw/nxagent/compext')
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/compext/Alpha.c50
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/compext/Alpha.h45
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/compext/Bitmap.c120
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/compext/Bitmap.h44
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/compext/Clean.c349
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/compext/Clean.h44
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/compext/Colormap.c50
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/compext/Colormap.h45
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/compext/Compext.c4778
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/compext/Compext.h912
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/compext/Imakefile48
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/compext/Jpeg.c480
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/compext/Jpeg.h46
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/compext/Mask.c802
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/compext/Mask.h48
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/compext/Png.c730
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/compext/Png.h76
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/compext/Rgb.c51
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/compext/Rgb.h44
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/compext/Rle.c51
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/compext/Rle.h44
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/compext/Z.c309
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/compext/Z.h60
23 files changed, 9226 insertions, 0 deletions
diff --git a/nx-X11/programs/Xserver/hw/nxagent/compext/Alpha.c b/nx-X11/programs/Xserver/hw/nxagent/compext/Alpha.c
new file mode 100644
index 000000000..11450d69d
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/compext/Alpha.c
@@ -0,0 +1,50 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXCOMPEXT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#include <zlib.h>
+
+#include "Compext.h"
+
+#include "Alpha.h"
+#include "Z.h"
+
+#define PANIC
+#define WARNING
+#undef TEST
+#undef DEBUG
+
+#define ALPHA_COMPRESSION_LEVEL 1
+#define ALPHA_COMPRESSION_THRESHOLD 32
+#define ALPHA_COMPRESSION_STRATEGY Z_RLE
+
+static int alphaCompressionLevel = ALPHA_COMPRESSION_LEVEL;
+static int alphaCompressionThreshold = ALPHA_COMPRESSION_THRESHOLD;
+static int alphaCompressionStrategy = ALPHA_COMPRESSION_STRATEGY;
+
+char *AlphaCompressData(const char *data, unsigned int size, unsigned int *compressed_size)
+{
+ return ZCompressData(data, size, alphaCompressionThreshold, alphaCompressionLevel,
+ alphaCompressionStrategy, compressed_size);
+}
diff --git a/nx-X11/programs/Xserver/hw/nxagent/compext/Alpha.h b/nx-X11/programs/Xserver/hw/nxagent/compext/Alpha.h
new file mode 100644
index 000000000..d7ac4e78e
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/compext/Alpha.h
@@ -0,0 +1,45 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXCOMPEXT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#ifndef Alpha_H
+#define Alpha_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern char *AlphaCompressData(
+#if NeedFunctionPrototypes
+ const char* /* data */,
+ unsigned int /* size */,
+ unsigned int* /* compressed_size */
+#endif
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* Alpha_H */
diff --git a/nx-X11/programs/Xserver/hw/nxagent/compext/Bitmap.c b/nx-X11/programs/Xserver/hw/nxagent/compext/Bitmap.c
new file mode 100644
index 000000000..d906118d0
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/compext/Bitmap.c
@@ -0,0 +1,120 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXCOMPEXT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "Compext.h"
+
+#include "Bitmap.h"
+
+#define PANIC
+#define WARNING
+#undef TEST
+#undef DEBUG
+
+char *BitmapCompressData(XImage *image, unsigned int *size)
+{
+ if (image -> bits_per_pixel != 32)
+ {
+ #ifdef TEST
+ fprintf(stderr, "******BitmapCompressData: Nothing to do with image of [%d] bpp and size [%d].\n",
+ image -> bits_per_pixel, image -> bytes_per_line * image -> height);
+ #endif
+
+ *size = image -> bytes_per_line * image -> height;
+
+ return image -> data;
+ }
+ else
+ {
+ /*
+ * Remove the 4th byte from the bitmap.
+ */
+
+ char *data;
+
+ char *next_src;
+ char *next_dst;
+
+ #ifdef TEST
+
+ if (image -> bytes_per_line != 4 * image -> width)
+ {
+ fprintf(stderr, "******BitmapCompressData: PANIC! Image as [%d] bytes per line with expected [%d].\n",
+ image -> bytes_per_line, 4 * image -> width);
+
+ return NULL;
+ }
+
+ #endif
+
+ *size = image -> width * image -> height * 3;
+
+ data = Xmalloc(*size);
+
+ if (data == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******BitmapCompressData: PANIC! Failed to allocate [%d] bytes for the destination.\n",
+ *size);
+ #endif
+
+ *size = image -> bytes_per_line * image -> height;
+
+ return image -> data;
+ }
+
+ next_src = image -> data;
+ next_dst = data;
+
+ if (image -> byte_order == LSBFirst)
+ {
+ while (next_src < image -> data +
+ image -> bytes_per_line * image -> height)
+ {
+ *next_dst++ = *next_src++;
+ *next_dst++ = *next_src++;
+ *next_dst++ = *next_src++;
+
+ next_src++;
+ }
+ }
+ else
+ {
+ while (next_src < image -> data +
+ image -> bytes_per_line * image -> height)
+ {
+ next_src++;
+
+ *next_dst++ = *next_src++;
+ *next_dst++ = *next_src++;
+ *next_dst++ = *next_src++;
+ }
+ }
+
+ return data;
+ }
+}
diff --git a/nx-X11/programs/Xserver/hw/nxagent/compext/Bitmap.h b/nx-X11/programs/Xserver/hw/nxagent/compext/Bitmap.h
new file mode 100644
index 000000000..e45836d11
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/compext/Bitmap.h
@@ -0,0 +1,44 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXCOMPEXT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#ifndef Bitmap_H
+#define Bitmap_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern char *BitmapCompressData(
+#if NeedFunctionPrototypes
+ XImage* /* image */,
+ unsigned int* /* compressed_size */
+#endif
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* Bitmap_H */
diff --git a/nx-X11/programs/Xserver/hw/nxagent/compext/Clean.c b/nx-X11/programs/Xserver/hw/nxagent/compext/Clean.c
new file mode 100644
index 000000000..7a6d81b6b
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/compext/Clean.c
@@ -0,0 +1,349 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXCOMPEXT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#include <stdio.h>
+#include <signal.h>
+
+#include "os.h"
+
+#include "Compext.h"
+
+#include "Clean.h"
+
+#define PANIC
+#define WARNING
+#undef TEST
+#undef DEBUG
+
+int CleanXYImage(XImage *image)
+{
+ int i, j, k, plane;
+
+ int bitsToClean = (image -> bytes_per_line << 3) - image -> width - image -> xoffset;
+
+ unsigned int bytesToClean = bitsToClean >> 3;
+
+ bitsToClean &= 7;
+
+ for (k = 0; k < image -> depth; k++)
+ {
+ plane = k * (image -> bytes_per_line * image -> height);
+
+ for (i = 1; i <= image -> height; i++)
+ {
+ if (image -> byte_order == image -> bitmap_bit_order)
+ {
+ for (j = 1; j <= bytesToClean; j++)
+ {
+ image -> data[plane + i * (image -> bytes_per_line) - j] = 0x00;
+ }
+ }
+ else
+ {
+ for (j = bytesToClean; j >= 1; j--)
+ {
+ image -> data[plane + i * (image -> bytes_per_line) - j] = 0x00;
+ }
+ }
+
+ if (image -> bitmap_bit_order == MSBFirst)
+ {
+ image -> data[plane + i * (image -> bytes_per_line) - j] &= 0xff << bitsToClean;
+ }
+ else
+ {
+ image -> data[plane + i * (image -> bytes_per_line) - j] &= 0xff >> bitsToClean;
+ }
+ }
+ }
+
+ return 1;
+}
+
+int CleanZImage(XImage *image)
+{
+ unsigned int bytesToClean;
+ unsigned int j;
+ unsigned int imageLength;
+
+ #ifdef TEST
+ fprintf(stderr, "*****CleanZImage: Going to clean image of [%d] bits per pixel.\n",
+ image -> bits_per_pixel);
+ #endif
+
+ switch (image -> bits_per_pixel)
+ {
+ case 32:
+ {
+ /*
+ * The caller should pay attention at extracting
+ * the alpha channel prior to cleaning the image.
+ * Cleaning an image which is carrying the alpha
+ * channel will result in the image being treated
+ * as fully transparent.
+ */
+
+ register int i;
+
+ bytesToClean = image -> bytes_per_line * image -> height;
+
+ #ifdef DEBUG
+ fprintf(stderr, "*****CleanZImage: Cleaning [%d] bytes with bits per pixel [%d] "
+ "width [%d] bytes per line [%d] height [%d].\n", bytesToClean,
+ image -> bits_per_pixel, image -> width, image ->
+ bytes_per_line, image -> height);
+ #endif
+
+ if (image -> byte_order == LSBFirst)
+ {
+ for (i = 3; i < bytesToClean; i += 4)
+ {
+ ((unsigned char *) image -> data)[i] = 0x00;
+ }
+ }
+ else
+ {
+ for (i = 0; i < bytesToClean; i += 4)
+ {
+ ((unsigned char *) image -> data)[i] = 0x00;
+ }
+ }
+
+ break;
+ }
+ case 24:
+ case 15:
+ case 16:
+ case 8:
+ {
+ register int i, j;
+
+ bytesToClean = image -> bytes_per_line -
+ ((image -> width * image -> bits_per_pixel) >> 3);
+
+ for (i = 1; i <= image -> height; i++)
+ {
+ for (j = bytesToClean; j > 0; j--)
+ {
+ ((unsigned char *) image -> data)[(i * image -> bytes_per_line) - j] = 0x00;
+ }
+ }
+
+ break;
+ }
+ default:
+ {
+ #ifdef PANIC
+ fprintf(stderr, "*****CleanZImage: PANIC! Cannot clean image with [%d] bits per pixel.\n",
+ image -> bits_per_pixel);
+ #endif
+ }
+ }
+
+ /*
+ * Clean the padding bytes at the real
+ * end of the buffer.
+ */
+
+ imageLength = image -> bytes_per_line * image -> height;
+
+ bytesToClean = imageLength % 4;
+
+ for (j = 0; j < bytesToClean; j++)
+ {
+ ((unsigned char *)image -> data)[(imageLength + j)] = 0x00;
+ }
+
+ return 1;
+}
+
+/*
+ * Copy a clean version of src_image into dst_image.
+ * This code is not taking care of the image format.
+ * The agent doesn't use it and you have to consider
+ * it unsupported.
+ */
+
+int CopyAndCleanImage(XImage *src_image, XImage *dst_image)
+{
+ register long data_size;
+ register int i;
+
+ data_size = (src_image -> bytes_per_line * src_image -> height) >> 2;
+
+ #ifdef WARNING
+ fprintf(stderr, "******CleanImage: WARNING! Function called with image of [%d] bits per pixel.\n",
+ src_image -> bits_per_pixel);
+ #endif
+
+ switch (src_image -> bits_per_pixel)
+ {
+ case 32:
+ {
+ unsigned int mask;
+
+ if (src_image -> byte_order == MSBFirst)
+ {
+ mask = 0xffffff00;
+ }
+ else
+ {
+ mask = 0x00ffffff;
+ }
+ for (i = 0; i < data_size; i++)
+ {
+ ((unsigned int *)dst_image -> data)[i] = ((unsigned int *)src_image -> data)[i] & mask;
+ }
+
+ break;
+ }
+
+ case 24:
+ {
+ unsigned int bytes_to_clean;
+
+ for (i = 0; i < data_size; i++)
+ {
+ ((unsigned int *)dst_image -> data)[i] = ((unsigned int *)src_image -> data)[i];
+ }
+
+ bytes_to_clean = dst_image -> bytes_per_line - ((dst_image -> width *
+ dst_image -> bits_per_pixel) >> 3);
+
+ if (bytes_to_clean)
+ {
+ register unsigned int mask = 0xffffffff;
+ register int line_size;
+ register int i;
+
+ line_size = dst_image -> bytes_per_line >> 2;
+
+ if (dst_image -> byte_order == MSBFirst)
+ {
+ mask = mask << (bytes_to_clean << 3);
+ }
+ else
+ {
+ mask = mask >> (bytes_to_clean << 3);
+ }
+
+ for (i = 0; i < dst_image -> height;)
+ {
+ ((unsigned char *)dst_image -> data)[(++i * line_size) -1] &= mask;
+ }
+ }
+
+ break;
+ }
+
+ case 15:
+ case 16:
+ {
+ for (i = 0; i < data_size; i++)
+ {
+ ((unsigned int *) dst_image -> data)[i] = ((unsigned int *) src_image -> data)[i];
+ }
+
+ if (src_image -> width & 0x00000001)
+ {
+ int card32_per_line = dst_image -> bytes_per_line >> 2;
+
+ for (i = 0; i < dst_image -> height;)
+ {
+ ((unsigned int *) dst_image -> data)[(++i * card32_per_line) -1] &= 0x0000ffff;
+ }
+ }
+
+ break;
+ }
+
+ case 8:
+ {
+ unsigned int mask = 0x00000000;
+
+ switch (dst_image -> width % 4)
+ {
+ case 3:
+ {
+ mask = 0x00ffffff;
+
+ break;
+ }
+ case 2:
+ {
+ mask = 0x0000ffff;
+
+ break;
+ }
+ case 1:
+ {
+ mask = 0x000000ff;
+
+ break;
+ }
+ default:
+ {
+ /*
+ * Nothing to clean.
+ */
+
+ break;
+ }
+ }
+
+ for (i = 0; i < data_size; i++)
+ {
+ ((unsigned int *) dst_image -> data)[i] = ((unsigned int *) src_image -> data)[i];
+ }
+
+ if (mask)
+ {
+ int card32_per_line;
+ int i;
+
+ card32_per_line = dst_image -> bytes_per_line >> 2;
+
+ for (i = 0; i < dst_image -> height; i++)
+ {
+ ((unsigned int *) dst_image -> data)[(++i * card32_per_line) -1] &= mask;
+ }
+ }
+
+ break;
+ }
+
+ default:
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******CleanImage: PANIC! Cannot clean image of [%d] bits per pixel.\n",
+ src_image -> bits_per_pixel);
+ #endif
+
+ return 0;
+ }
+ }
+
+ return 1;
+}
diff --git a/nx-X11/programs/Xserver/hw/nxagent/compext/Clean.h b/nx-X11/programs/Xserver/hw/nxagent/compext/Clean.h
new file mode 100644
index 000000000..510af1dfb
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/compext/Clean.h
@@ -0,0 +1,44 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXCOMPEXT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#ifndef Clean_H
+#define Clean_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <nx-X11/Xlib.h>
+
+int CleanXYImage(XImage *image);
+int CleanZImage(XImage *image);
+
+int CopyAndCleanImage(XImage *src_image, XImage *dst_image);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* Clean_H */
diff --git a/nx-X11/programs/Xserver/hw/nxagent/compext/Colormap.c b/nx-X11/programs/Xserver/hw/nxagent/compext/Colormap.c
new file mode 100644
index 000000000..6b025542d
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/compext/Colormap.c
@@ -0,0 +1,50 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXCOMPEXT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#include <zlib.h>
+
+#include "Compext.h"
+
+#include "Colormap.h"
+#include "Z.h"
+
+#define PANIC
+#define WARNING
+#undef TEST
+#undef DEBUG
+
+#define COLORMAP_COMPRESSION_LEVEL 4
+#define COLORMAP_COMPRESSION_THRESHOLD 32
+#define COLORMAP_COMPRESSION_STRATEGY Z_DEFAULT_STRATEGY
+
+static int colormapCompressionLevel = COLORMAP_COMPRESSION_LEVEL;
+static int colormapCompressionThreshold = COLORMAP_COMPRESSION_THRESHOLD;
+static int colormapCompressionStrategy = COLORMAP_COMPRESSION_STRATEGY;
+
+char *ColormapCompressData(const char *data, unsigned int size, unsigned int *compressed_size)
+{
+ return ZCompressData(data, size, colormapCompressionThreshold, colormapCompressionLevel,
+ colormapCompressionStrategy, compressed_size);
+}
diff --git a/nx-X11/programs/Xserver/hw/nxagent/compext/Colormap.h b/nx-X11/programs/Xserver/hw/nxagent/compext/Colormap.h
new file mode 100644
index 000000000..e30f4fdab
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/compext/Colormap.h
@@ -0,0 +1,45 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXCOMPEXT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#ifndef ColormapComp_H
+#define ColormapComp_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern char *ColormapCompressData(
+#if NeedFunctionPrototypes
+ const char* /* data */,
+ unsigned int /* size */,
+ unsigned int* /* compressed_size */
+#endif
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ColormapComp_H */
diff --git a/nx-X11/programs/Xserver/hw/nxagent/compext/Compext.c b/nx-X11/programs/Xserver/hw/nxagent/compext/Compext.c
new file mode 100644
index 000000000..a91b0c568
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/compext/Compext.c
@@ -0,0 +1,4778 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXCOMPEXT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#undef _XSERVER64
+
+#include <sys/socket.h>
+
+#ifndef __sun
+#include <strings.h>
+#endif
+
+#include "dix.h"
+#include "os.h"
+
+/*
+ * Needed to enable definition of the callback
+ * functions.
+ */
+
+#define NX_TRANS_SOCKET
+
+#include <nx-X11/Xlib.h>
+#include <nx-X11/Xutil.h>
+#include <nx-X11/Xlibint.h>
+
+#include "Compext.h"
+
+#include <nx/NX.h>
+#include <nx/NXproto.h>
+#include <nx/NXpack.h>
+#include <nx/MD5.h>
+
+#include "Clean.h"
+#include "Mask.h"
+#include "Colormap.h"
+#include "Alpha.h"
+#include "Bitmap.h"
+#include "Jpeg.h"
+#include "Png.h"
+#include "Rgb.h"
+#include "Rle.h"
+#include "Z.h"
+
+
+#define PANIC
+#define WARNING
+#undef TEST
+#undef DEBUG
+#undef DUMP
+
+/*
+ * Maximum number of colors allowed in
+ * Png encoding.
+ */
+
+#define NB_COLOR_MAX 256
+
+/*
+ * Dummy error handlers used internally to catch
+ * Xlib failures in replies.
+ */
+
+static int _NXInternalReplyErrorFunction(Display *dpy, XErrorEvent *error);
+
+static void _NXInternalLostSequenceFunction(Display *dpy, unsigned long newseq,
+ unsigned long lastseq, unsigned int type);
+
+/*
+ * Resource ids that can be requested by
+ * the client for use in split or unpack
+ * operations.
+ */
+
+static unsigned char _NXSplitResources[NXNumberOfResources];
+static unsigned char _NXUnpackResources[NXNumberOfResources];
+
+static Display *_NXDisplayInitialized = NULL;
+
+/*
+ * Used in asynchronous handling of
+ * GetImage replies.
+ */
+
+typedef struct
+{
+ unsigned long sequence;
+ unsigned int resource;
+ unsigned long mask;
+ int format;
+ int width;
+ int height;
+ _XAsyncHandler *handler;
+ XImage *image;
+} _NXCollectImageState;
+
+static _NXCollectImageState *_NXCollectedImages[NXNumberOfResources];
+
+/*
+ * Used in asynchronous handling of
+ * GetProperty replies.
+ */
+
+typedef struct
+{
+ unsigned long sequence;
+ unsigned int resource;
+ Window window;
+ Atom property;
+ Atom type;
+ int format;
+ unsigned long items;
+ unsigned long after;
+ _XAsyncHandler *handler;
+ char *data;
+} _NXCollectPropertyState;
+
+static _NXCollectPropertyState *_NXCollectedProperties[NXNumberOfResources];
+
+/*
+ * Used in asynchronous handling of
+ * GrabPointer replies.
+ */
+
+typedef struct
+{
+ unsigned long sequence;
+ unsigned int resource;
+ int status;
+ _XAsyncHandler *handler;
+} _NXCollectGrabPointerState;
+
+static _NXCollectGrabPointerState *_NXCollectedGrabPointers[NXNumberOfResources];
+
+/*
+ * Used in asynchronous handling of
+ * GetInputFocus replies.
+ */
+
+typedef struct
+{
+ unsigned long sequence;
+ unsigned int resource;
+ Window focus;
+ int revert_to;
+ _XAsyncHandler *handler;
+} _NXCollectInputFocusState;
+
+static _NXCollectInputFocusState *_NXCollectedInputFocuses[NXNumberOfResources];
+
+/*
+ * Used by functions handling cache of
+ * packed images.
+ */
+
+#define MD5_LENGTH 16
+
+typedef struct
+{
+ md5_byte_t *md5;
+ XImage *image;
+ unsigned int method;
+} _NXImageCacheEntry;
+
+int NXImageCacheSize = 0;
+int NXImageCacheHits = 0;
+int NXImageCacheOps = 0;
+
+_NXImageCacheEntry *NXImageCache = NULL;
+
+#ifdef DUMP
+
+void _NXCacheDump(const char *label);
+
+void _NXDumpData(const unsigned char *buffer, unsigned int size);
+
+#endif
+
+/*
+ * From X11/PutImage.c.
+ *
+ * Cancel a GetReq operation, before doing
+ * _XSend or Data.
+ */
+
+#if (defined(__STDC__) && !defined(UNIXCPP)) || defined(ANSICPP)
+#define UnGetReq(name)\
+ dpy->bufptr -= SIZEOF(x##name##Req);\
+ dpy->request--
+#else
+#define UnGetReq(name)\
+ dpy->bufptr -= SIZEOF(x/**/name/**/Req);\
+ dpy->request--
+#endif
+
+#if (defined(__STDC__) && !defined(UNIXCPP)) || defined(ANSICPP)
+#define UnGetEmptyReq()\
+ dpy->bufptr -= 4;\
+ dpy->request--
+#else
+#define UnGetEmptyReq(name)\
+ dpy->bufptr -= 4;\
+ dpy->request--
+#endif
+
+/*
+ * From X11/ImUtil.c.
+ */
+
+extern int _XGetBitsPerPixel(Display *dpy, int depth);
+extern int _XGetScanlinePad(Display *dpy, int depth);
+
+#define ROUNDUP(nbytes, pad) (((nbytes) + ((pad) - 1)) & \
+ ~(long)((pad) - 1))
+
+static unsigned int DepthOnes(unsigned long mask)
+{
+ register unsigned long y;
+
+ y = (mask >> 1) &033333333333;
+ y = mask - y - ((y >>1) & 033333333333);
+ return ((unsigned int) (((y + (y >> 3)) &
+ 030707070707) % 077));
+}
+
+#define CanMaskImage(image, mask) \
+\
+(image -> format == ZPixmap && mask != NULL && \
+ (image -> depth == 32 || image -> depth == 24 || \
+ (image -> depth == 16 && (image -> red_mask == 0xf800 && \
+ image -> green_mask == 0x7e0 && image -> blue_mask == 0x1f))))
+
+#define ShouldMaskImage(image, mask) (mask -> color_mask != 0xff)
+
+/*
+ * Initialize and reset the internal structures.
+ */
+
+extern int _NXInternalInitResources(Display *dpy);
+extern int _NXInternalResetResources(Display *dpy);
+extern int _NXInternalInitEncoders(Display *dpy);
+extern int _NXInternalResetEncoders(Display *dpy);
+
+int NXInitDisplay(Display *dpy)
+{
+ #ifdef TEST
+ fprintf(stderr, "******NXInitDisplay: Called for display at [%p].\n", (void *) dpy);
+ #endif
+
+ if (_NXDisplayInitialized == NULL)
+ {
+ _NXInternalInitResources(dpy);
+
+ _NXInternalInitEncoders(dpy);
+
+ _NXDisplayInitialized = dpy;
+
+ return 1;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "******NXInitDisplay: WARNING! Internal structures already initialized.\n");
+ #endif
+
+ return 0;
+}
+
+int NXResetDisplay(Display *dpy)
+{
+ #ifdef TEST
+ fprintf(stderr, "******NXResetDisplay: Called for display at [%p].\n", (void *) dpy);
+ #endif
+
+ if (_NXDisplayInitialized != NULL)
+ {
+ _NXInternalResetResources(dpy);
+
+ _NXInternalResetEncoders(dpy);
+
+ _NXDisplayInitialized = NULL;
+
+ return 1;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "******NXResetDisplay: WARNING! Internal structures already reset.\n");
+ #endif
+
+ return 0;
+}
+
+int _NXInternalInitResources(Display *dpy)
+{
+ return _NXInternalResetResources(dpy);
+}
+
+int _NXInternalResetResources(Display *dpy)
+{
+ int i;
+
+ #ifdef TEST
+ fprintf(stderr, "******_NXInternalResetResources: Clearing all the internal structures.\n");
+ #endif
+
+ for (i = 0; i < NXNumberOfResources; i++)
+ {
+ _NXSplitResources[i] = 0;
+ _NXUnpackResources[i] = 0;
+
+ if (_NXCollectedImages[i] != NULL)
+ {
+ #ifdef TEST
+ fprintf(stderr, "******_NXInternalResetResources: WARNING! Clearing collect image data "
+ "for resource [%d].\n", i);
+ #endif
+
+ if (_NXCollectedImages[i] -> handler != NULL)
+ {
+ DeqAsyncHandler(dpy, _NXCollectedImages[i] -> handler);
+
+ Xfree(_NXCollectedImages[i] -> handler);
+ }
+
+ if (_NXCollectedImages[i] -> image != NULL)
+ {
+ XDestroyImage(_NXCollectedImages[i] -> image);
+ }
+
+ Xfree(_NXCollectedImages[i]);
+
+ _NXCollectedImages[i] = NULL;
+ }
+
+ if (_NXCollectedProperties[i] != NULL)
+ {
+ #ifdef TEST
+ fprintf(stderr, "******_NXInternalResetResources: WARNING! Clearing collect property data "
+ "for resource [%d].\n", i);
+ #endif
+
+ if (_NXCollectedProperties[i] -> handler != NULL)
+ {
+ DeqAsyncHandler(dpy, _NXCollectedProperties[i] -> handler);
+
+ Xfree(_NXCollectedProperties[i] -> handler);
+ }
+
+ if (_NXCollectedProperties[i] -> data != NULL)
+ {
+ Xfree(_NXCollectedProperties[i] -> data);
+ }
+
+ Xfree(_NXCollectedProperties[i]);
+
+ _NXCollectedProperties[i] = NULL;
+ }
+
+ if (_NXCollectedGrabPointers[i] != NULL)
+ {
+ #ifdef TEST
+ fprintf(stderr, "******_NXInternalResetResources: WARNING! Clearing grab pointer data "
+ "for resource [%d].\n", i);
+ #endif
+
+ if (_NXCollectedGrabPointers[i] -> handler != NULL)
+ {
+ DeqAsyncHandler(dpy, _NXCollectedGrabPointers[i] -> handler);
+
+ Xfree(_NXCollectedGrabPointers[i] -> handler);
+ }
+
+ Xfree(_NXCollectedGrabPointers[i]);
+
+ _NXCollectedGrabPointers[i] = NULL;
+ }
+
+ if (_NXCollectedInputFocuses[i] != NULL)
+ {
+ #ifdef TEST
+ fprintf(stderr, "******_NXInternalResetResources: WARNING! Clearing collect input focus data "
+ "for resource [%d].\n", i);
+ #endif
+
+ if (_NXCollectedInputFocuses[i] -> handler != NULL)
+ {
+ DeqAsyncHandler(dpy, _NXCollectedInputFocuses[i] -> handler);
+
+ Xfree(_NXCollectedInputFocuses[i] -> handler);
+ }
+
+ Xfree(_NXCollectedInputFocuses[i]);
+
+ _NXCollectedInputFocuses[i] = NULL;
+ }
+ }
+
+ return 1;
+}
+
+int _NXInternalInitEncoders(Display *dpy)
+{
+ ZInitEncoder();
+
+ return 1;
+}
+
+int _NXInternalResetEncoders(Display *dpy)
+{
+ ZResetEncoder();
+
+ return 1;
+}
+
+int NXSetDisplayPolicy(Display *dpy, int policy)
+{
+ if (policy == NXPolicyImmediate)
+ {
+ return NXTransPolicy(NX_FD_ANY, NX_POLICY_IMMEDIATE);
+ }
+ else
+ {
+ return NXTransPolicy(NX_FD_ANY, NX_POLICY_DEFERRED);
+ }
+}
+
+int NXSetDisplayBuffer(Display *dpy, int size)
+{
+ /*
+ * This is not multi-thread safe, so,
+ * if you have threads, be sure that
+ * they are stopped.
+ */
+
+ char *buffer;
+
+ XFlush(dpy);
+
+ if (dpy -> bufmax - size == dpy -> buffer)
+ {
+ #ifdef TEST
+ fprintf(stderr, "******NXSetDisplayBuffer: Nothing to do with buffer size matching.\n");
+ #endif
+
+ return 1;
+ }
+ else if (dpy -> bufptr != dpy -> buffer)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXSetDisplayBuffer: PANIC! The display buffer is not empty.\n");
+ #endif
+
+ return -1;
+ }
+ else if ((buffer = Xcalloc(1, size)) == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXSetDisplayBuffer: PANIC! Can't allocate [%d] bytes for the buffer.\n",
+ size);
+ #endif
+
+ return -1;
+ }
+
+ if (dpy -> buffer != NULL)
+ {
+ Xfree(dpy -> buffer);
+ }
+
+ dpy -> buffer = buffer;
+ dpy -> bufptr = dpy -> buffer;
+ dpy -> bufmax = dpy -> bufptr + size;
+
+ #ifdef TEST
+ fprintf(stderr, "******NXSetDisplayBuffer: Set the display output buffer size to [%d].\n",
+ size);
+ #endif
+
+ return 1;
+}
+
+/*
+ * If set, the Popen() function in the X server
+ * wil remove the LD_LIBRARY_PATH variable from
+ * the environment before calling the execl()
+ * function on the child process.
+ */
+
+int NXUnsetLibraryPath(int value)
+{
+ int previous = _NXUnsetLibraryPath;
+
+ _NXUnsetLibraryPath = value;
+
+ #ifdef TEST
+ fprintf(stderr, "******NXUnsetLibraryPath: Set the flag to [%d] with previous value [%d].\n",
+ value, previous);
+ #endif
+
+ return previous;
+}
+
+/*
+ * If set, the Xlib I/O error handler will simply
+ * return, instead of quitting the program. This
+ * leaves to the application the responsibility
+ * of checking the state of the XlibDisplayIOEr-
+ * ror flag.
+ */
+
+int NXHandleDisplayError(int value)
+{
+ int previous = _NXHandleDisplayError;
+
+ _NXHandleDisplayError = value;
+
+ #ifdef TEST
+ fprintf(stderr, "******NXHandleDisplayError: Set the flag to [%d] with previous value [%d].\n",
+ value, previous);
+ #endif
+
+ return previous;
+}
+
+/*
+ * Shutdown the display descriptor and force Xlib
+ * to set the I/O error flag.
+ */
+
+Bool NXForceDisplayError(Display *dpy)
+{
+ if (dpy != NULL)
+ {
+ NXTransClose(dpy -> fd);
+
+ if (!(dpy -> flags & XlibDisplayIOError))
+ {
+ shutdown(dpy -> fd, SHUT_RDWR);
+
+ _XIOError(dpy);
+ }
+
+ return 1;
+ }
+
+ return 0;
+}
+
+/*
+ * Check if the display has become invalid. Similarly
+ * to the modified Xlib, we call the predicate funct-
+ * ion with the value of the XlibDisplayIOError flag
+ * only if the I/O error was not encountered already.
+ * The application can use this function to query the
+ * XlibDisplayIOError flag because Xlib doesn't expose
+ * the internals of the display structure to the appli-
+ * cation.
+ */
+
+int NXDisplayError(Display *dpy)
+{
+ if (dpy != NULL)
+ {
+ return (_XGetIOError(dpy) ||
+ (_NXDisplayErrorFunction != NULL &&
+ (*_NXDisplayErrorFunction)(dpy, _XGetIOError(dpy))));
+ }
+
+ return 1;
+}
+
+/*
+ * Various queries related to the state of the
+ * display connection.
+ */
+
+int NXDisplayReadable(Display *dpy)
+{
+ int result;
+ int readable;
+
+ result = NXTransReadable(dpy -> fd, &readable);
+
+ if (result == 0)
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "******NXDisplayReadable: Returning [%d] bytes readable from fd [%d].\n",
+ readable, dpy -> fd);
+ #endif
+
+ return readable;
+ }
+
+ #ifdef DEBUG
+ fprintf(stderr, "******NXDisplayReadable: WARNING! Error detected on display fd [%d].\n",
+ dpy -> fd);
+ #endif
+
+ return -1;
+}
+
+int NXDisplayFlushable(Display *dpy)
+{
+ #ifdef DEBUG
+
+ int flushable;
+
+ flushable = NXTransFlushable(dpy -> fd) +
+ (dpy -> bufptr - dpy -> buffer);
+
+ fprintf(stderr, "******NXDisplayFlushable: Returning [%d+%d=%d] bytes flushable "
+ "to fd [%d].\n", (int) (dpy -> bufptr - dpy -> buffer),
+ (int) (flushable - (dpy -> bufptr - dpy -> buffer)),
+ flushable, dpy -> fd);
+
+ return flushable;
+
+ #else
+
+ return NXTransFlushable(dpy -> fd) + (dpy -> bufptr - dpy -> buffer);
+
+ #endif
+}
+
+int NXDisplayCongestion(Display *dpy)
+{
+ #ifdef DEBUG
+
+ int congestion = NXTransCongestion(dpy -> fd);
+
+ fprintf(stderr, "******NXDisplayCongestion: Returning [%d] as congestion level for fd [%d].\n",
+ congestion, dpy -> fd);
+
+ return congestion;
+
+ #else
+
+ return NXTransCongestion(dpy -> fd);
+
+ #endif
+}
+
+int NXFlushDisplay(Display *dpy, int what)
+{
+ if (!(dpy -> flags & XlibDisplayWriting) &&
+ dpy -> bufptr - dpy -> buffer > 0)
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "******NXFlushDisplay: Writing with [%d] bytes in the buffer.\n",
+ (int) (dpy -> bufptr - dpy -> buffer));
+ #endif
+
+ XFlush(dpy);
+ }
+
+ if (what == NXFlushBuffer)
+ {
+ return 0;
+ }
+
+ #ifdef DEBUG
+ fprintf(stderr, "******NXFlushDisplay: Flushing with [%d] bytes in the NX transport.\n",
+ NXDisplayFlushable(dpy));
+ #endif
+
+ return NXTransFlush(dpy -> fd);
+}
+
+NXDisplayErrorPredicate NXSetDisplayErrorPredicate(NXDisplayErrorPredicate predicate)
+{
+ NXDisplayErrorPredicate previous = _NXDisplayErrorFunction;
+
+ _NXDisplayErrorFunction = predicate;
+
+ #ifdef TEST
+ fprintf(stderr, "******NXSetDisplayErrorPredicate: Set the predicate to [%p] with previous value [%p].\n",
+ predicate, previous);
+ #endif
+
+ return previous;
+}
+
+NXDisplayBlockHandler NXSetDisplayBlockHandler(NXDisplayBlockHandler handler)
+{
+ NXDisplayBlockHandler previous = _NXDisplayBlockFunction;
+
+ _NXDisplayBlockFunction = handler;
+
+ #ifdef TEST
+ fprintf(stderr, "******NXSetDisplayBlockHandler: Set the handler to [%p] with previous value [%p].\n",
+ handler, previous);
+ #endif
+
+ return previous;
+}
+
+NXDisplayWriteHandler NXSetDisplayWriteHandler(NXDisplayWriteHandler handler)
+{
+ NXDisplayWriteHandler previous = _NXDisplayWriteFunction;
+
+ _NXDisplayWriteFunction = handler;
+
+ #ifdef TEST
+ fprintf(stderr, "******NXSetDisplayWriteHandler: Set the handler to [%p] with previous value [%p].\n",
+ handler, previous);
+ #endif
+
+ return previous;
+}
+
+NXDisplayFlushHandler NXSetDisplayFlushHandler(NXDisplayFlushHandler handler, Display *display)
+{
+ NXDisplayFlushHandler previous = _NXDisplayFlushFunction;
+
+ _NXDisplayFlushFunction = handler;
+
+ NXTransHandler(NX_FD_ANY, NX_HANDLER_FLUSH,
+ (void (*)(void *, int)) handler, (void *) display);
+
+ #ifdef TEST
+ fprintf(stderr, "******NXSetDisplayFlushHandler: Set the handler to [%p] with display [%p] "
+ "and previous value [%p].\n", handler, display, previous);
+ #endif
+
+ return previous;
+}
+
+NXDisplayStatisticsHandler NXSetDisplayStatisticsHandler(NXDisplayStatisticsHandler handler, char **buffer)
+{
+ NXDisplayStatisticsHandler previous = _NXDisplayStatisticsFunction;
+
+ _NXDisplayStatisticsFunction = handler;
+
+ /*
+ * Propagate the handler.
+ */
+
+ NXTransHandler(NX_FD_ANY, NX_HANDLER_STATISTICS,
+ (void (*)(void *, int)) handler, (void *) buffer);
+
+ #ifdef TEST
+ fprintf(stderr, "******NXSetDisplayStatisticsHandler: Set the handler to [%p] with buffer pointer [%p] "
+ "and previous value [%p].\n", handler, buffer, previous);
+ #endif
+
+ return previous;
+}
+
+NXLostSequenceHandler NXSetLostSequenceHandler(NXLostSequenceHandler handler)
+{
+ NXLostSequenceHandler previous = _NXLostSequenceFunction;
+
+ _NXLostSequenceFunction = handler;
+
+ #ifdef TEST
+ fprintf(stderr, "******NXSetLostSequenceHandler: Set the handler to [%p] with previous value [%p].\n",
+ handler, previous);
+ #endif
+
+ return previous;
+}
+
+int _NXInternalReplyErrorFunction(Display *dpy, XErrorEvent *error)
+{
+ #ifdef TEST
+ fprintf(stderr, "******_NXInternalReplyErrorFunction: Internal error handler called.\n");
+ #endif
+
+ return 0;
+}
+
+void _NXInternalLostSequenceFunction(Display *dpy, unsigned long newseq,
+ unsigned long lastseq, unsigned int type)
+{
+ #ifdef TEST
+
+ fprintf(stderr, "******_NXInternalLostSequenceFunction: WARNING! Sequence lost with new "
+ "sequence %ld last request %ld.\n", newseq, dpy -> request);
+
+ /*
+ * TODO: Reply or event info must be implemented.
+ *
+ * fprintf(stderr, "******_NXInternalLostSequenceFunction: WARNING! Expected event or reply "
+ * "was %ld with sequence %ld.\n", (long) rep -> type, (long) rep -> sequenceNumber);
+ */
+
+ fprintf(stderr, "******_NXInternalLostSequenceFunction: WARNING! Last sequence read "
+ "was %ld display request is %ld.\n", lastseq & 0xffff, dpy -> request & 0xffff);
+
+ #endif
+}
+
+Status NXGetControlParameters(Display *dpy, unsigned int *link_type, unsigned int *local_major,
+ unsigned int *local_minor, unsigned int *local_patch,
+ unsigned int *remote_major, unsigned int *remote_minor,
+ unsigned int *remote_patch, int *split_timeout, int *motion_timeout,
+ int *split_mode, int *split_size, unsigned int *pack_method,
+ unsigned int *pack_quality, int *data_level, int *stream_level,
+ int *delta_level, unsigned int *load_cache,
+ unsigned int *save_cache, unsigned int *startup_cache)
+{
+ xNXGetControlParametersReply rep;
+
+ register xReq *req;
+
+ LockDisplay(dpy);
+
+ GetEmptyReq(NXGetControlParameters, req);
+
+ #ifdef TEST
+ fprintf(stderr, "******NXGetControlParameters: Sending message opcode [%d].\n",
+ X_NXGetControlParameters);
+ #endif
+
+ if (_XReply(dpy, (xReply *) &rep, 0, xTrue) == xFalse)
+ {
+ #ifdef TEST
+ fprintf(stderr, "******NXGetControlParameters: Error receiving reply.\n");
+ #endif
+
+ UnlockDisplay(dpy);
+
+ SyncHandle();
+
+ return 0;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "******NXGetControlParameters: Got reply with link type [%u].\n", rep.linkType);
+
+ fprintf(stderr, "******NXGetControlParameters: Local protocol major [%u] minor [%u] patch [%u].\n",
+ rep.localMajor, rep.localMinor, rep.localPatch);
+
+ fprintf(stderr, "******NXGetControlParameters: Remote protocol major [%u] minor [%u] patch [%u].\n",
+ rep.remoteMajor, rep.remoteMinor, rep.remotePatch);
+
+ fprintf(stderr, "******NXGetControlParameters: Split timeout [%d] motion timeout [%d].\n",
+ (int) rep.splitTimeout, (int) rep.motionTimeout);
+
+ fprintf(stderr, "******NXGetControlParameters: Split mode [%d] split size [%d].\n",
+ (int) rep.splitMode, (int) rep.splitSize);
+
+ fprintf(stderr, "******NXGetControlParameters: Preferred pack method [%d] pack quality [%d].\n",
+ (int) rep.packMethod, (int) rep.packQuality);
+
+ fprintf(stderr, "******NXGetControlParameters: Data level [%d] stream level [%d] delta level [%d].\n",
+ rep.dataLevel, rep.streamLevel, rep.deltaLevel);
+ #endif
+
+ *link_type = rep.linkType;
+
+ *local_major = rep.localMajor;
+ *local_minor = rep.localMinor;
+ *local_patch = rep.localPatch;
+
+ *remote_major = rep.remoteMajor;
+ *remote_minor = rep.remoteMinor;
+ *remote_patch = rep.remotePatch;
+
+ *split_timeout = rep.splitTimeout;
+ *motion_timeout = rep.motionTimeout;
+
+ *split_mode = rep.splitMode;
+ *split_size = rep.splitSize;
+
+ *pack_method = rep.packMethod;
+ *pack_quality = rep.packQuality;
+
+ *data_level = rep.dataLevel;
+ *stream_level = rep.streamLevel;
+ *delta_level = rep.deltaLevel;
+
+ *load_cache = rep.loadCache;
+ *save_cache = rep.saveCache;
+ *startup_cache = rep.startupCache;
+
+ UnlockDisplay(dpy);
+
+ SyncHandle();
+
+ /*
+ * Install our internal out-of-sync handler.
+ */
+
+ _NXLostSequenceFunction = _NXInternalLostSequenceFunction;
+
+ return 1;
+}
+
+/*
+ * Which unpack methods are supported by the
+ * remote proxy?
+ */
+
+Status NXGetUnpackParameters(Display *dpy, unsigned int *entries, unsigned char supported_methods[])
+{
+ register xNXGetUnpackParametersReq *req;
+
+ xNXGetUnpackParametersReply rep;
+
+ register unsigned n;
+
+ #ifdef TEST
+ register unsigned i;
+ #endif
+
+ if (*entries < NXNumberOfPackMethods)
+ {
+ #ifdef TEST
+ fprintf(stderr, "******NXGetUnpackParameters: Requested only [%d] entries while they should be [%d].\n",
+ *entries, NXNumberOfPackMethods);
+ #endif
+
+ return 0;
+ }
+
+ LockDisplay(dpy);
+
+ GetReq(NXGetUnpackParameters, req);
+
+ req -> entries = *entries;
+
+ #ifdef TEST
+ fprintf(stderr, "******NXGetUnpackParameters: Sending message opcode [%d] with [%d] requested entries.\n",
+ X_NXGetUnpackParameters, *entries);
+ #endif
+
+ if (_XReply(dpy, (xReply *) &rep, 0, xFalse) == xFalse || rep.length == 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "******NXGetUnpackParameters: Error receiving reply.\n");
+ #endif
+
+ UnlockDisplay(dpy);
+
+ SyncHandle();
+
+ return 0;
+ }
+
+ if ((n = rep.length << 2) > *entries)
+ {
+ #ifdef TEST
+ fprintf(stderr, "******NXGetUnpackParameters: Got [%d] bytes of reply data while they should be [%d].\n",
+ n, *entries);
+ #endif
+
+ _XEatData(dpy, (unsigned long) n);
+
+ UnlockDisplay(dpy);
+
+ SyncHandle();
+
+ return 0;
+ }
+
+ *entries = n;
+
+ #ifdef TEST
+ fprintf(stderr, "******NXGetUnpackParameters: Reading [%d] bytes of reply data.\n", n);
+ #endif
+
+ _XReadPad(dpy, (char *) supported_methods, n);
+
+ #ifdef TEST
+
+ fprintf(stderr, "******NXGetUnpackParameters: Got reply with methods: ");
+
+ for (i = 0; i < n; i++)
+ {
+ if (supported_methods[i] != 0)
+ {
+ fprintf(stderr, "[%d]", i);
+ }
+ }
+
+ fprintf(stderr, ".\n");
+
+ #endif
+
+ UnlockDisplay(dpy);
+
+ SyncHandle();
+
+ return 1;
+}
+
+/*
+ * Query and enable the MIT-SHM support between the
+ * proxy and the X server. The 'enable' flags must be
+ * true if shared memory PutImages and PutPackedImages
+ * are desired. On return the flags will say if support
+ * has been successfully enabled.
+ *
+ * Note that the the client part is not useful and not
+ * implemented. The size of the segment is chosen by
+ * the proxy. The main purpose of the message is to
+ * reserve the XID that will be used by the remote.
+ */
+
+Status NXGetShmemParameters(Display *dpy, unsigned int *enable_client,
+ unsigned int *enable_server, unsigned int *client_segment,
+ unsigned int *server_segment, unsigned int *client_size,
+ unsigned int *server_size)
+{
+ register xNXGetShmemParametersReq *req;
+
+ register int stage;
+
+ xNXGetShmemParametersReply rep;
+
+ /*
+ * Save the previous handler.
+ */
+
+ int (*handler)(Display *, XErrorEvent *) = _XErrorFunction;
+
+ *client_segment = 0;
+ *server_segment = 0;
+
+ if (*enable_client)
+ {
+ *client_segment = XAllocID(dpy);
+ }
+
+ if (*enable_server)
+ {
+ *server_segment = XAllocID(dpy);
+ }
+
+ LockDisplay(dpy);
+
+ _XErrorFunction = _NXInternalReplyErrorFunction;
+
+ for (stage = 0; stage < 3; stage++)
+ {
+ GetReq(NXGetShmemParameters, req);
+
+ req -> stage = stage;
+
+ req -> enableClient = (*enable_client != 0 ? 1 : 0);
+ req -> enableServer = (*enable_server != 0 ? 1 : 0);
+
+ req -> clientSegment = *client_segment;
+ req -> serverSegment = *server_segment;
+
+ #ifdef TEST
+ fprintf(stderr, "******NXGetShmemParameters: Sending message opcode [%d] at stage [%d].\n",
+ X_NXGetShmemParameters, stage);
+ #endif
+
+ #ifdef TEST
+
+ if (stage == 0)
+ {
+ fprintf(stderr, "******NXGetShmemParameters: Enable client is [%u] enable server is [%u].\n",
+ *enable_client, *enable_server);
+
+ fprintf(stderr, "******NXGetShmemParameters: Client segment is [%u] server segment is [%u].\n",
+ *client_segment, *server_segment);
+ }
+
+ #endif
+
+ /*
+ * There isn't X server reply in the second stage.
+ * The procedure followed at X server side is:
+ *
+ * Stage 0: Send X_QueryExtension and masquerade
+ * the reply.
+ *
+ * Stage 1: Allocate the shared memory and send
+ * X_ShmAttach to the X server.
+ *
+ * Stage 2: Send X_GetInputFocus and masquerade
+ * the reply.
+ *
+ * The last message is used to force a reply and
+ * collect any X error caused by a failure in the
+ * shared memory initialization.
+ */
+
+ if (stage != 1)
+ {
+ /*
+ * We are only interested in the final reply.
+ */
+
+ if (_XReply(dpy, (xReply *) &rep, 0, xTrue) == xFalse)
+ {
+ #ifdef TEST
+ fprintf(stderr, "******NXGetShmemParameters: Error receiving reply.\n");
+ #endif
+
+ _XErrorFunction = handler;
+
+ UnlockDisplay(dpy);
+
+ SyncHandle();
+
+ return 0;
+ }
+ }
+ }
+
+ /*
+ * Return the settings to client.
+ */
+
+ *enable_client = rep.clientEnabled;
+ *enable_server = rep.serverEnabled;
+
+ *client_size = rep.clientSize;
+ *server_size = rep.serverSize;
+
+ #ifdef TEST
+ fprintf(stderr, "******NXGetShmemParameters: Got final reply with enabled client [%u] and server [%u].\n",
+ *enable_client, *enable_server);
+
+ fprintf(stderr, "******NXGetShmemParameters: Client segment size [%u] server segment size [%u].\n",
+ *client_size, *server_size);
+ #endif
+
+ _XErrorFunction = handler;
+
+ UnlockDisplay(dpy);
+
+ SyncHandle();
+
+ return 1;
+}
+
+/*
+ * Get the path to the font server that can be used by the X
+ * server to tunnel the font connections across the NX link.
+ * The path actually represents the TCP port where the proxy
+ * on the NX client side is listening. The agent can tempora-
+ * rily enable the tunneling when it needs a font that is not
+ * available on the client, for example when the session is
+ * migrated from a different X server.
+ *
+ * Note that it is not advisable to use the font server chan-
+ * nel for other purposes than restoring a font that is found
+ * missing at the time the session is migrated to a different
+ * display. This is because the agent implements a caching of
+ * the list of fonts supported by the client as it needs to
+ * advertise only the fonts that can be opened at both sides.
+ */
+
+Status NXGetFontParameters(Display *dpy, unsigned int path_length, char path_data[])
+{
+ register xNXGetFontParametersReq *req;
+
+ xNXGetFontParametersReply rep;
+
+ register unsigned n;
+
+ #ifdef TEST
+ register unsigned i;
+ #endif
+
+ if (path_length < 1)
+ {
+ #ifdef TEST
+ fprintf(stderr, "******NXGetFontParameters: No room to store the reply.\n");
+ #endif
+
+ return 0;
+ }
+
+ *path_data = '\0';
+
+ LockDisplay(dpy);
+
+ GetReq(NXGetFontParameters, req);
+
+ #ifdef TEST
+ fprintf(stderr, "******NXGetFontParameters: Sending message opcode [%d].\n",
+ X_NXGetFontParameters);
+ #endif
+
+ if (_XReply(dpy, (xReply *) &rep, 0, xFalse) == xFalse || rep.length == 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "******NXGetFontParameters: Error receiving reply.\n");
+ #endif
+
+ UnlockDisplay(dpy);
+
+ SyncHandle();
+
+ return 0;
+ }
+
+ if ((n = rep.length << 2) > path_length)
+ {
+ #ifdef TEST
+ fprintf(stderr, "******NXGetFontParameters: Got [%d] bytes of reply data with only room for [%d].\n",
+ n, path_length);
+ #endif
+
+ _XEatData(dpy, (unsigned long) n);
+
+ UnlockDisplay(dpy);
+
+ SyncHandle();
+
+ return 0;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "******NXGetFontParameters: Reading [%d] bytes of reply data.\n", n);
+ #endif
+
+ _XReadPad(dpy, (char *) path_data, n);
+
+ /*
+ * Check if the string can be fully
+ * contained by the buffer.
+ */
+
+ if (*path_data > path_length - 1)
+ {
+ #ifdef TEST
+ fprintf(stderr, "******NXGetFontParameters: Inconsistent length in the returned string.\n");
+ #endif
+
+ UnlockDisplay(dpy);
+
+ SyncHandle();
+
+ return 0;
+ }
+
+ #ifdef TEST
+
+ fprintf(stderr, "******NXGetFontParameters: Got font path of [%d] bytes and value [",
+ (int) *path_data);
+
+ for (i = 0; i < *path_data; i++)
+ {
+ fprintf(stderr, "%c", *(path_data + i + 1));
+ }
+
+ fprintf(stderr, "].\n");
+
+ #endif
+
+ UnlockDisplay(dpy);
+
+ SyncHandle();
+
+ return 1;
+}
+
+unsigned int NXAllocSplit(Display *dpy, unsigned int resource)
+{
+ if (resource == NXAnyResource)
+ {
+ for (resource = 0; resource < NXNumberOfResources; resource++)
+ {
+ if (_NXSplitResources[resource] == 0)
+ {
+ _NXSplitResources[resource] = 1;
+
+ #ifdef TEST
+ fprintf(stderr, "******NXAllocSplit: Reserved resource [%u].\n",
+ resource);
+ #endif
+
+ return resource;
+ }
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "******NXAllocSplit: WARNING! Resource limit exausted.\n");
+ #endif
+
+ return NXNoResource;
+ }
+ else if (resource >= 0 && resource < NXNumberOfResources)
+ {
+ #ifdef TEST
+
+ if (_NXSplitResources[resource] == 0)
+ {
+ fprintf(stderr, "******NXAllocSplit: Reserved requested resource [%u].\n",
+ resource);
+ }
+ else
+ {
+ fprintf(stderr, "******NXAllocSplit: Requested resource [%u] already reserved.\n",
+ resource);
+ }
+
+ #endif
+
+ _NXSplitResources[resource] = 1;
+ }
+
+ #ifdef PANIC
+ fprintf(stderr, "******NXAllocSplit: PANIC! Can't reserve requested resource [%u].\n",
+ resource);
+ #endif
+
+ return NXNoResource;
+}
+
+/*
+ * Tell the proxy to split the next messages.
+ */
+
+int NXStartSplit(Display *dpy, unsigned int resource, unsigned int mode)
+{
+ register xNXStartSplitReq *req;
+
+ LockDisplay(dpy);
+
+ GetReq(NXStartSplit, req);
+
+ req -> resource = resource;
+ req -> mode = mode;
+
+ #ifdef TEST
+ fprintf(stderr, "******NXStartSplit: Sending opcode [%d] with resource [%d] mode [%d].\n",
+ X_NXStartSplit, resource, mode);
+ #endif
+
+ UnlockDisplay(dpy);
+
+ SyncHandle();
+
+ return 1;
+}
+
+/*
+ * Send the closure of the split sequence and
+ * tell the proxy to send the results.
+ */
+
+int NXEndSplit(Display *dpy, unsigned int resource)
+{
+ register xNXEndSplitReq *req;
+
+ LockDisplay(dpy);
+
+ GetReq(NXEndSplit, req);
+
+ req -> resource = resource;
+
+ #ifdef TEST
+ fprintf(stderr, "******NXEndSplit: Sending opcode [%d] with resource [%d].\n",
+ X_NXStartSplit, resource);
+ #endif
+
+ UnlockDisplay(dpy);
+
+ SyncHandle();
+
+ return 1;
+}
+
+/*
+ * This message must be sent whenever the proxy notifies
+ * the client of the completion of a split. If the 'pro-
+ * pagate' field is 0, the proxy will not send the ori-
+ * ginal request to the X server, but will only free the
+ * internal state.
+ */
+
+int NXCommitSplit(Display *dpy, unsigned int resource, unsigned int propagate,
+ unsigned char request, unsigned int position)
+{
+ register xNXCommitSplitReq *req;
+
+ LockDisplay(dpy);
+
+ GetReq(NXCommitSplit, req);
+
+ req -> resource = resource;
+ req -> propagate = propagate;
+ req -> request = request;
+ req -> position = position;
+
+ #ifdef TEST
+ fprintf(stderr, "******NXCommitSplit: Sending opcode [%d] with resource [%d] propagate [%d] "
+ "request [%d] position [%d].\n", X_NXCommitSplit, resource,
+ propagate, request, position);
+ #endif
+
+ UnlockDisplay(dpy);
+
+ SyncHandle();
+
+ return 1;
+}
+
+int NXAbortSplit(Display *dpy, unsigned int resource)
+{
+ register xNXAbortSplitReq *req;
+
+ LockDisplay(dpy);
+
+ GetReq(NXAbortSplit, req);
+
+ #ifdef TEST
+ fprintf(stderr, "******NXAbortSplit: Sending message opcode [%d] with resource [%u].\n",
+ X_NXAbortSplit, resource);
+ #endif
+
+ req -> resource = resource;
+
+ UnlockDisplay(dpy);
+
+ SyncHandle();
+
+ return 1;
+}
+
+int NXFinishSplit(Display *dpy, unsigned int resource)
+{
+ register xNXFinishSplitReq *req;
+
+ LockDisplay(dpy);
+
+ GetReq(NXFinishSplit, req);
+
+ #ifdef TEST
+ fprintf(stderr, "******NXFinishSplit: Sending message opcode [%d] with resource [%u].\n",
+ X_NXFinishSplit, resource);
+ #endif
+
+ req -> resource = resource;
+
+ UnlockDisplay(dpy);
+
+ SyncHandle();
+
+ return 1;
+}
+
+int NXFreeSplit(Display *dpy, unsigned int resource)
+{
+ register xNXFreeSplitReq *req;
+
+ if (_NXSplitResources[resource] != 0)
+ {
+ LockDisplay(dpy);
+
+ GetReq(NXFreeSplit, req);
+
+ #ifdef TEST
+ fprintf(stderr, "******NXFreeSplit: Sending message opcode [%d] with resource [%u].\n",
+ X_NXFreeSplit, resource);
+ #endif
+
+ req -> resource = resource;
+
+ UnlockDisplay(dpy);
+
+ SyncHandle();
+
+ #ifdef TEST
+ fprintf(stderr, "******NXFreeSplit: Making the resource [%u] newly available.\n",
+ resource);
+ #endif
+
+ _NXSplitResources[resource] = 0;
+ }
+ #ifdef TEST
+ else
+ {
+ fprintf(stderr, "******NXFreeSplit: Nothing to do for resource [%u].\n",
+ resource);
+ }
+ #endif
+
+ return 1;
+}
+
+/*
+ * Tell to remote proxy to discard expose events
+ * of one or more types.
+ */
+
+int NXSetExposeParameters(Display *dpy, int expose, int graphics_expose, int no_expose)
+{
+ register xNXSetExposeParametersReq *req;
+
+ LockDisplay(dpy);
+
+ GetReq(NXSetExposeParameters, req);
+
+ req -> expose = expose;
+ req -> graphicsExpose = graphics_expose;
+ req -> noExpose = no_expose;
+
+ #ifdef TEST
+ fprintf(stderr, "******NXSetExposeParameters: Sending message opcode [%d] with flags [%d][%d][%d].\n",
+ X_NXSetExposeParameters, req -> expose, req -> graphicsExpose, req -> noExpose);
+ #endif
+
+ UnlockDisplay(dpy);
+
+ SyncHandle();
+
+ return 1;
+}
+
+/*
+ * Tell to the local proxy how to handle the next requests.
+ */
+
+int NXSetCacheParameters(Display *dpy, int enable_cache, int enable_split,
+ int enable_save, int enable_load)
+{
+ register xNXSetCacheParametersReq *req;
+
+ LockDisplay(dpy);
+
+ GetReq(NXSetCacheParameters, req);
+
+ req -> enableCache = enable_cache;
+ req -> enableSplit = enable_split;
+ req -> enableSave = enable_save;
+ req -> enableLoad = enable_load;
+
+ #ifdef TEST
+ fprintf(stderr, "******NXSetCacheParameters: Sending message opcode [%d] with "
+ "flags [%d][%d][%d][%d].\n", X_NXSetCacheParameters, req -> enableCache,
+ req -> enableSplit, req -> enableSave, req -> enableLoad);
+ #endif
+
+ UnlockDisplay(dpy);
+
+ SyncHandle();
+
+ return 1;
+}
+
+unsigned int NXAllocUnpack(Display *dpy, unsigned int resource)
+{
+ if (resource == NXAnyResource)
+ {
+ for (resource = 0; resource < NXNumberOfResources; resource++)
+ {
+ if (_NXUnpackResources[resource] == 0)
+ {
+ _NXUnpackResources[resource] = 1;
+
+ #ifdef TEST
+ fprintf(stderr, "******NXAllocUnpack: Reserved resource [%u].\n",
+ resource);
+ #endif
+
+ return resource;
+ }
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "******NXAllocUnpack: WARNING! Resource limit exausted.\n");
+ #endif
+
+ return NXNoResource;
+ }
+ else if (resource >= 0 && resource < NXNumberOfResources)
+ {
+ #ifdef TEST
+
+ if (_NXUnpackResources[resource] == 0)
+ {
+ fprintf(stderr, "******NXAllocUnpack: Reserved requested resource [%u].\n",
+ resource);
+ }
+ else
+ {
+ fprintf(stderr, "******NXAllocUnpack: Requested resource [%u] already reserved.\n",
+ resource);
+ }
+
+ #endif
+
+ _NXUnpackResources[resource] = 1;
+ }
+
+ #ifdef PANIC
+ fprintf(stderr, "******NXAllocUnpack: PANIC! Can't reserve requested resource [%u].\n",
+ resource);
+ #endif
+
+ return NXNoResource;
+}
+
+int NXSetUnpackGeometry(Display *dpy, unsigned int resource, Visual *visual)
+{
+ register xNXSetUnpackGeometryReq *req;
+
+ LockDisplay(dpy);
+
+ GetReq(NXSetUnpackGeometry, req);
+
+ req -> resource = resource;
+
+ req -> depth1Bpp = _XGetBitsPerPixel(dpy, 1);
+ req -> depth4Bpp = _XGetBitsPerPixel(dpy, 4);
+ req -> depth8Bpp = _XGetBitsPerPixel(dpy, 8);
+ req -> depth16Bpp = _XGetBitsPerPixel(dpy, 16);
+ req -> depth24Bpp = _XGetBitsPerPixel(dpy, 24);
+ req -> depth32Bpp = _XGetBitsPerPixel(dpy, 32);
+
+ if (visual != NULL)
+ {
+ req -> redMask = visual -> red_mask;
+ req -> greenMask = visual -> green_mask;
+ req -> blueMask = visual -> blue_mask;
+ }
+ else
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXSetUnpackGeometry: PANIC! Can't set the geometry without a visual.\n");
+ #endif
+
+ UnGetReq(NXSetUnpackGeometry);
+
+ UnlockDisplay(dpy);
+
+ return -1;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "******NXSetUnpackGeometry: Resource [%u] Depth/Bpp [1/%d][4/%d][8/%d]"
+ "[16/%d][24/%d][32/%d].\n", resource, req -> depth1Bpp, req -> depth4Bpp,
+ req -> depth8Bpp, req -> depth16Bpp, req -> depth24Bpp, req -> depth32Bpp);
+
+ fprintf(stderr, "******NXSetUnpackGeometry: red [0x%x] green [0x%x] blue [0x%x].\n",
+ (unsigned) req -> redMask, (unsigned) req -> greenMask, (unsigned) req -> blueMask);
+ #endif
+
+ UnlockDisplay(dpy);
+
+ SyncHandle();
+
+ return 1;
+}
+
+/*
+ * Store a colormap table on the remote side.
+ * The colormap can then be used to unpack
+ * an image.
+ */
+
+int NXSetUnpackColormap(Display *dpy, unsigned int resource, unsigned int method,
+ unsigned int entries, const char *data, unsigned int data_length)
+{
+ register xNXSetUnpackColormapReq *req;
+
+ register int dst_data_length;
+
+ LockDisplay(dpy);
+
+ GetReq(NXSetUnpackColormap, req);
+
+ req -> resource = resource;
+ req -> method = method;
+
+ req -> srcLength = data_length;
+ req -> dstLength = entries << 2;
+
+ dst_data_length = ROUNDUP(data_length, 4);
+
+ req -> length += (dst_data_length >> 2);
+
+ #ifdef TEST
+ fprintf(stderr, "******NXSetUnpackColormap: Resource [%u] data size [%u] destination "
+ "data size [%u].\n", resource, data_length, dst_data_length);
+ #endif
+
+ if (data_length > 0)
+ {
+ if (dpy -> bufptr + dst_data_length <= dpy -> bufmax)
+ {
+ /*
+ * Clean the padding bytes in the request.
+ */
+
+ *((int *) (dpy -> bufptr + dst_data_length - 4)) = 0x0;
+
+ memcpy(dpy -> bufptr, data, data_length);
+
+ dpy -> bufptr += dst_data_length;
+ }
+ else
+ {
+ /*
+ * The _XSend() will pad the request for us.
+ */
+
+ _XSend(dpy, data, data_length);
+ }
+ }
+
+ UnlockDisplay(dpy);
+
+ SyncHandle();
+
+ return 1;
+}
+
+/*
+ * Store data of the alpha blending channel
+ * that will be combined with the next image
+ * to be unpacked.
+ */
+
+int NXSetUnpackAlpha(Display *dpy, unsigned int resource, unsigned int method,
+ unsigned int entries, const char *data, unsigned int data_length)
+{
+ register xNXSetUnpackAlphaReq *req;
+
+ register unsigned int dst_data_length;
+
+ LockDisplay(dpy);
+
+ GetReq(NXSetUnpackAlpha, req);
+
+ req -> resource = resource;
+ req -> method = method;
+
+ req -> srcLength = data_length;
+ req -> dstLength = entries;
+
+ dst_data_length = ROUNDUP(data_length, 4);
+
+ req -> length += (dst_data_length >> 2);
+
+ #ifdef TEST
+ fprintf(stderr, "******NXSetUnpackAlpha: Resource [%u] data size [%u] destination data size [%u].\n",
+ resource, data_length, dst_data_length);
+ #endif
+
+ if (data_length > 0)
+ {
+ if (dpy -> bufptr + dst_data_length <= dpy -> bufmax)
+ {
+ /*
+ * Clean the padding bytes in the request.
+ */
+
+ *((int *) (dpy -> bufptr + dst_data_length - 4)) = 0x0;
+
+ memcpy(dpy -> bufptr, data, data_length);
+
+ dpy -> bufptr += dst_data_length;
+ }
+ else
+ {
+ /*
+ * The _XSend() will pad the request for us.
+ */
+
+ _XSend(dpy, data, data_length);
+ }
+ }
+
+ UnlockDisplay(dpy);
+
+ SyncHandle();
+
+ return 1;
+}
+
+/*
+ * Compatibility versions to be used when
+ * connected to a 1.X.X proxy.
+ */
+
+/*
+ * These are for compatibility with the 1.X.X
+ * versions.
+ */
+
+#define sz_xNXSetUnpackColormapCompatReq 8
+
+typedef struct _NXSetUnpackColormapCompatReq {
+ CARD8 reqType;
+ CARD8 resource;
+ CARD16 length B16;
+ CARD32 entries B32;
+} xNXSetUnpackColormapCompatReq;
+
+#define X_NXSetUnpackColormapCompat X_NXSetUnpackColormap
+
+int NXSetUnpackColormapCompat(Display *dpy, unsigned int resource,
+ unsigned int entries, const char *data)
+{
+ register xNXSetUnpackColormapCompatReq *req;
+
+ register char *dst_data;
+
+ register int dst_data_length;
+
+ #ifdef DUMP
+
+ int i;
+
+ #endif
+
+ LockDisplay(dpy);
+
+ GetReq(NXSetUnpackColormapCompat, req);
+
+ req -> resource = resource;
+ req -> entries = entries;
+
+ dst_data_length = entries << 2;
+
+ req -> length += (dst_data_length >> 2);
+
+ #ifdef TEST
+ fprintf(stderr, "******NXSetUnpackColormapCompat: Resource [%u] number of entries [%u] "
+ "destination data size [%u].\n", resource, entries, dst_data_length);
+ #endif
+
+ if (entries > 0)
+ {
+ if ((dpy -> bufptr + dst_data_length) <= dpy -> bufmax)
+ {
+ dst_data = dpy -> bufptr;
+ }
+ else
+ {
+ if ((dst_data = _XAllocScratch(dpy, dst_data_length)) == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXSetUnpackColormapCompat: PANIC! Cannot allocate memory.\n");
+ #endif
+
+ UnGetReq(NXSetUnpackColormapCompat);
+
+ UnlockDisplay(dpy);
+
+ return -1;
+ }
+ }
+
+ memcpy(dst_data, data, entries << 2);
+
+ #ifdef DUMP
+
+ fprintf(stderr, "******NXSetUnpackColormapCompat: Dumping colormap entries:\n");
+
+ for (i = 0; i < entries; i++)
+ {
+ fprintf(stderr, "******NXSetUnpackColormapCompat: [%d] -> [0x%x].\n",
+ i, *((int *) (dst_data + (i * 4))));
+ }
+
+ #endif
+
+ if (dst_data == dpy -> bufptr)
+ {
+ dpy -> bufptr += dst_data_length;
+ }
+ else
+ {
+ _XSend(dpy, dst_data, dst_data_length);
+ }
+ }
+
+ UnlockDisplay(dpy);
+
+ SyncHandle();
+
+ return 1;
+}
+
+#define sz_xNXSetUnpackAlphaCompatReq 8
+
+typedef struct _NXSetUnpackAlphaCompatReq {
+ CARD8 reqType;
+ CARD8 resource;
+ CARD16 length B16;
+ CARD32 entries B32;
+} xNXSetUnpackAlphaCompatReq;
+
+#define X_NXSetUnpackAlphaCompat X_NXSetUnpackAlpha
+
+int NXSetUnpackAlphaCompat(Display *dpy, unsigned int resource,
+ unsigned int entries, const char *data)
+{
+ register xNXSetUnpackAlphaCompatReq *req;
+
+ register char *dst_data;
+
+ register unsigned int dst_data_length;
+
+ #ifdef DUMP
+
+ int i;
+
+ #endif
+
+ LockDisplay(dpy);
+
+ GetReq(NXSetUnpackAlphaCompat, req);
+
+ req -> resource = resource;
+ req -> entries = entries;
+
+ dst_data_length = ROUNDUP(entries, 4);
+
+ req -> length += (dst_data_length >> 2);
+
+ #ifdef TEST
+ fprintf(stderr, "******NXSetUnpackAlphaCompat: Resource [%u] number of entries [%u] "
+ "destination data size [%u].\n", resource, entries, dst_data_length);
+ #endif
+
+ if (entries > 0)
+ {
+ if ((dpy -> bufptr + dst_data_length) <= dpy -> bufmax)
+ {
+ dst_data = dpy -> bufptr;
+ }
+ else
+ {
+ if ((dst_data = _XAllocScratch(dpy, dst_data_length)) == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXSetUnpackAlphaCompat: PANIC! Cannot allocate memory.\n");
+ #endif
+
+ UnGetReq(NXSetUnpackAlphaCompat);
+
+ UnlockDisplay(dpy);
+
+ return -1;
+ }
+ }
+
+ memcpy(dst_data, data, entries);
+
+ if (dst_data_length != entries)
+ {
+ memset(dst_data + entries, 0, dst_data_length - entries);
+ }
+
+ #ifdef DUMP
+
+ fprintf(stderr, "******NXSetUnpackAlphaCompat: Dumping alpha channel data:\n");
+
+ for (i = 0; i < dst_data_length; i++)
+ {
+ fprintf(stderr, "******NXSetUnpackAlphaCompat: [%d] -> [0x%02x].\n",
+ i, ((unsigned int) *(dst_data + i)) & 0xff);
+ }
+
+ #endif
+
+ if (dst_data == dpy -> bufptr)
+ {
+ dpy -> bufptr += dst_data_length;
+ }
+ else
+ {
+ _XSend(dpy, dst_data, dst_data_length);
+ }
+ }
+
+ UnlockDisplay(dpy);
+
+ SyncHandle();
+
+ return 1;
+}
+
+/*
+ * Free any geometry, colormap and alpha channel
+ * data stored by the remote proxy to unpack the
+ * image. Resource, as usual, must be a value
+ * between 0 and 255.
+ */
+
+int NXFreeUnpack(Display *dpy, unsigned int resource)
+{
+ register xNXFreeUnpackReq *req;
+
+ if (_NXUnpackResources[resource] != 0)
+ {
+ LockDisplay(dpy);
+
+ GetReq(NXFreeUnpack, req);
+
+ #ifdef TEST
+ fprintf(stderr, "******NXFreeUnpack: Sending message opcode [%d] with resource [%u].\n",
+ X_NXFreeUnpack, resource);
+ #endif
+
+ req -> resource = resource;
+
+ UnlockDisplay(dpy);
+
+ SyncHandle();
+
+ #ifdef TEST
+ fprintf(stderr, "******NXFreeUnpack: Making the resource [%u] newly available.\n",
+ resource);
+ #endif
+
+ _NXUnpackResources[resource] = 0;
+ }
+ #ifdef TEST
+ else
+ {
+ fprintf(stderr, "******NXFreeUnpack: Nothing to do for resource [%u].\n",
+ resource);
+ }
+ #endif
+
+ return 1;
+}
+
+/*
+ * Wrapper of XCreateImage(). Note that we use offset
+ * field of XImage to store size of source image in
+ * packed format. Note also that method is currently
+ * not stored in the NXignored.
+ */
+
+NXPackedImage *NXCreatePackedImage(Display *dpy, Visual *visual, unsigned int method,
+ unsigned int depth, int format, char *data,
+ int data_length, unsigned int width,
+ unsigned int height, int bitmap_pad,
+ int bytes_per_line)
+{
+ XImage* image;
+
+ image = XCreateImage(dpy, visual, depth, format, 0, data,
+ width, height, bitmap_pad, bytes_per_line);
+
+ if (image != NULL)
+ {
+ image -> xoffset = data_length;
+ }
+
+ return (NXPackedImage *) image;
+}
+
+/*
+ * Wrapper of XDestroyImage().
+ */
+
+int NXDestroyPackedImage(NXPackedImage *image)
+{
+ return XDestroyImage((XImage *) image);
+}
+
+/*
+ * Clean the image data directly in the current buffer.
+ */
+
+int NXCleanImage(XImage *image)
+{
+ #ifdef TEST
+ fprintf(stderr, "******NXCleanImage: Cleaning image with format [%d] depth [%d] "
+ "bits per pixel [%d].\n", image -> format, image -> depth,
+ image -> bits_per_pixel);
+ #endif
+
+ if (image -> format == ZPixmap)
+ {
+ if (image -> depth == 1)
+ {
+ return CleanXYImage(image);
+ }
+ else
+ {
+ return CleanZImage(image);
+ }
+ }
+ else
+ {
+ return CleanXYImage(image);
+ }
+}
+
+NXPackedImage *NXPackImage(Display *dpy, XImage *src_image, unsigned int method)
+{
+ XImage *dst_image;
+
+ const ColorMask *mask;
+
+ unsigned int dst_data_size;
+ unsigned int dst_packed_data_size;
+
+ unsigned int dst_bits_per_pixel;
+ unsigned int dst_packed_bits_per_pixel;
+
+ #ifdef TEST
+ fprintf(stderr, "******NXPackImage: Going to pack a new image with method [%d].\n",
+ method);
+ #endif
+
+ /*
+ * Get the mask out of the method and
+ * check if the visual is supported by
+ * the color reduction algorithm.
+ */
+
+ mask = MethodColorMask(method);
+
+ if (mask == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXPackImage: WARNING! No mask to apply for pack method [%d].\n",
+ method);
+ #endif
+
+ return NULL;
+ }
+ else if (CanMaskImage(src_image, mask) == 0)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXPackImage: PANIC! Invalid source with format [%d] depth [%d] bits per pixel [%d].\n",
+ src_image -> format, src_image -> depth, src_image -> bits_per_pixel);
+
+ fprintf(stderr, "******NXPackImage: PANIC! Visual colormask is red 0x%lx green 0x%lx blue 0x%lx.\n",
+ src_image -> red_mask, src_image -> green_mask, src_image -> blue_mask);
+ #endif
+
+ return NULL;
+ }
+
+ /*
+ * Create a destination image from
+ * source and apply the color mask.
+ */
+
+ if ((dst_image = (XImage *) Xmalloc(sizeof(XImage))) == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXPackImage: PANIC! Cannot allocate [%d] bytes for the image.\n",
+ (int) sizeof(XImage));
+ #endif
+
+ return NULL;
+ }
+
+ *dst_image = *src_image;
+
+ #ifdef TEST
+ fprintf(stderr, "******NXPackImage: Source width [%d], bytes per line [%d] with depth [%d].\n",
+ src_image -> width, src_image -> bytes_per_line, src_image -> depth);
+ #endif
+
+ dst_data_size = src_image -> bytes_per_line * src_image -> height;
+
+ dst_image -> data = Xmalloc(dst_data_size);
+
+ if (dst_image -> data == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXPackImage: PANIC! Cannot allocate [%d] bytes for masked image data.\n",
+ dst_data_size);
+ #endif
+
+ Xfree(dst_image);
+
+ return NULL;
+ }
+
+ /*
+ * If the pixel resulting from the mask
+ * needs more bits than available, then
+ * just clean the padding bits in the
+ * image.
+ */
+
+ dst_bits_per_pixel = dst_image -> bits_per_pixel;
+ dst_packed_bits_per_pixel = MethodBitsPerPixel(method);
+
+ #ifdef TEST
+ fprintf(stderr, "******NXPackImage: Destination depth [%d], bits per pixel [%d], packed bits per pixel [%d].\n",
+ dst_image -> depth, dst_bits_per_pixel, dst_packed_bits_per_pixel);
+ #endif
+
+ if (dst_packed_bits_per_pixel > dst_bits_per_pixel ||
+ ShouldMaskImage(src_image, mask) == 0)
+ {
+ /*
+ * Should use the same data for source
+ * and destination to avoid the memcpy.
+ */
+
+ if (CopyAndCleanImage(src_image, dst_image) <= 0)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXPackImage: PANIC! Failed to clean the image.\n");
+ #endif
+
+ Xfree(dst_image -> data);
+
+ Xfree(dst_image);
+
+ return NULL;
+ }
+ }
+ else if (MaskImage(mask, src_image, dst_image) <= 0)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXPackImage: PANIC! Failed to apply the color mask.\n");
+ #endif
+
+ Xfree(dst_image -> data);
+
+ Xfree(dst_image);
+
+ return NULL;
+ }
+
+ /*
+ * Let's pack the same pixels in fewer bytes.
+ * Note that we save a new memory allocation
+ * by using the same image as source and des-
+ * tination. This means that PackImage() must
+ * be able to handle ovelapping areas.
+ */
+
+ #ifdef TEST
+ fprintf(stderr, "******NXPackImage: Plain bits per pixel [%d], data size [%d].\n",
+ dst_bits_per_pixel, dst_data_size);
+ #endif
+
+ dst_packed_data_size = dst_data_size * dst_packed_bits_per_pixel /
+ dst_bits_per_pixel;
+
+ #ifdef TEST
+ fprintf(stderr, "******NXPackImage: Packed bits per pixel [%d], data size [%d].\n",
+ dst_packed_bits_per_pixel, dst_packed_data_size);
+ #endif
+
+ if (PackImage(method, dst_data_size, dst_image,
+ dst_packed_data_size, dst_image) <= 0)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXPackImage: PANIC! Failed to pack image from [%d] to [%d] bits per pixel.\n",
+ dst_bits_per_pixel, dst_packed_bits_per_pixel);
+ #endif
+
+ Xfree(dst_image -> data);
+
+ Xfree(dst_image);
+
+ return NULL;
+ }
+
+ /*
+ * Save data size in xoffset field
+ * to comply with NX packed images.
+ */
+
+ dst_image -> xoffset = dst_packed_data_size;
+
+ return dst_image;
+}
+
+/*
+ * NXInPlacePackImage creates a NXPackedImage
+ * from a XImage, sharing the same data buffer.
+ * Is up to the caller to free the data buffer
+ * only once.
+ */
+
+XImage *NXInPlacePackImage(Display *dpy, XImage *src_image, unsigned int method)
+{
+ XImage *dst_image;
+
+ const ColorMask *mask;
+
+ unsigned int dst_data_size;
+ unsigned int dst_packed_data_size;
+
+ unsigned int dst_bits_per_pixel;
+ unsigned int dst_packed_bits_per_pixel;
+
+ #ifdef TEST
+ fprintf(stderr, "******NXInPlacePackImage: Going to pack a new image with method [%d].\n",
+ method);
+ #endif
+
+ /*
+ * Get mask out of method and check if
+ * visual is supported by current color
+ * reduction algorithm.
+ */
+
+ mask = MethodColorMask(method);
+
+ if (mask == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXInPlacePackImage: WARNING! No mask to apply for pack method [%d].\n",
+ method);
+ #endif
+
+ return NULL;
+ }
+ else if (CanMaskImage(src_image, mask) == 0)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXInPlacePackImage: PANIC! Invalid source with format [%d] depth [%d] bits per pixel [%d].\n",
+ src_image -> format, src_image -> depth, src_image -> bits_per_pixel);
+
+ fprintf(stderr, "******NXInPlacePackImage: PANIC! Visual colormask is red 0x%lx green 0x%lx blue 0x%lx.\n",
+ src_image -> red_mask, src_image -> green_mask, src_image -> blue_mask);
+ #endif
+ return NULL;
+ }
+
+ /*
+ * Create a destination image from
+ * source and apply the color mask.
+ */
+
+ if ((dst_image = (XImage *) Xmalloc(sizeof(XImage))) == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXInPlacePackImage: PANIC! Cannot allocate [%d] bytes for the image.\n",
+ (int) sizeof(XImage));
+ #endif
+
+ return NULL;
+ }
+
+ *dst_image = *src_image;
+
+ #ifdef TEST
+ fprintf(stderr, "******NXInPlacePackImage: Source width [%d], bytes per line [%d] with depth [%d].\n",
+ src_image -> width, src_image -> bytes_per_line, src_image -> depth);
+ #endif
+
+ dst_data_size = src_image -> bytes_per_line * src_image -> height;
+
+ dst_image -> data = src_image -> data;
+
+ /*
+ * If pixel resulting from mask needs
+ * more bits than available, then just
+ * clean the pad bits in image.
+ */
+
+ dst_bits_per_pixel = dst_image -> bits_per_pixel;
+ dst_packed_bits_per_pixel = MethodBitsPerPixel(method);
+
+ #ifdef TEST
+ fprintf(stderr, "******NXInPlacePackImage: Destination depth [%d], bits per pixel [%d], packed bits per pixel [%d].\n",
+ dst_image -> depth, dst_bits_per_pixel, dst_packed_bits_per_pixel);
+ #endif
+
+ if (dst_packed_bits_per_pixel > dst_bits_per_pixel ||
+ ShouldMaskImage(src_image, mask) == 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "******NXInPlacePackImage: Just clean image packed_bits_per_pixel[%d], bits_per_pixel[%d].\n",
+ dst_packed_bits_per_pixel, dst_bits_per_pixel);
+ #endif
+
+ if (NXCleanImage(dst_image) <= 0)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXInPlacePackImage: PANIC! Failed to clean the image.\n");
+ #endif
+
+ Xfree(dst_image);
+
+ return NULL;
+ }
+ }
+ else if (MaskInPlaceImage(mask, dst_image) <= 0)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXInPlacePackImage: PANIC! Failed to apply the color mask.\n");
+ #endif
+
+ Xfree(dst_image);
+
+ return NULL;
+ }
+
+ /*
+ * Let's pack the same pixels in fewer bytes.
+ * Note that we save a new memory allocation
+ * by using the same image as source and des-
+ * tination. This means that PackImage() must
+ * be able to handle ovelapping areas.
+ */
+
+ #ifdef TEST
+ fprintf(stderr, "******NXInPlacePackImage: Plain bits per pixel [%d], data size [%d].\n",
+ dst_bits_per_pixel, dst_data_size);
+ #endif
+
+ dst_packed_data_size = dst_data_size * dst_packed_bits_per_pixel /
+ dst_bits_per_pixel;
+
+ #ifdef TEST
+ fprintf(stderr, "******NXInPlacePackImage: Packed bits per pixel [%d], data size [%d].\n",
+ dst_packed_bits_per_pixel, dst_packed_data_size);
+ #endif
+
+ /*
+ * Save data size in xoffset field
+ * to comply with NX packed images.
+ */
+
+ dst_image -> xoffset = dst_packed_data_size;
+
+ return dst_image;
+}
+
+int NXPutPackedImage(Display *dpy, unsigned int resource, Drawable drawable,
+ void *gc, NXPackedImage *image, unsigned int method,
+ unsigned int depth, int src_x, int src_y, int dst_x,
+ int dst_y, unsigned int width, unsigned int height)
+{
+ register xNXPutPackedImageReq *req;
+
+ register unsigned int src_data_length;
+ register unsigned int dst_data_length;
+
+ LockDisplay(dpy);
+
+ FlushGC(dpy, (GC) gc);
+
+ GetReq(NXPutPackedImage, req);
+
+ req -> resource = resource;
+ req -> drawable = drawable;
+ req -> gc = ((GC) gc) -> gid;
+
+ #ifdef TEST
+ fprintf(stderr, "******NXPutPackedImage: Image resource [%d] drawable [%d] gc [%d].\n",
+ req -> resource, (int) req -> drawable, (int) req -> gc);
+ #endif
+
+ /*
+ * There is no leftPad field in request. We only
+ * support a leftPad of 0. Anyway, X imposes a
+ * leftPad of 0 in case of ZPixmap format.
+ */
+
+ req -> format = image -> format;
+
+ /*
+ * Source depth, as well as width and height,
+ * are taken from the image structure.
+ */
+
+ req -> srcDepth = image -> depth;
+
+ req -> srcX = src_x;
+ req -> srcY = src_y;
+
+ req -> srcWidth = image -> width;
+ req -> srcHeight = image -> height;
+
+ /*
+ * The destination depth is provided
+ * by the caller.
+ */
+
+ req -> dstDepth = depth;
+
+ req -> dstX = dst_x;
+ req -> dstY = dst_y;
+
+ req -> dstWidth = width;
+ req -> dstHeight = height;
+
+ req -> method = method;
+
+ #ifdef TEST
+ fprintf(stderr, "******NXPutPackedImage: Source image depth [%d] destination depth [%d] "
+ "method [%d].\n", req -> srcDepth, req -> dstDepth, req -> method);
+ #endif
+
+ /*
+ * Source data length is the size of image in packed format,
+ * as stored in xoffset field of XImage. Destination data
+ * size is calculated according to bytes per line of target
+ * image, so the caller must provide the right depth at the
+ * time XImage structure is created.
+ */
+
+ req -> srcLength = image -> xoffset;
+
+ if (image -> width == (int) width &&
+ image -> height == (int) height)
+ {
+ req -> dstLength = image -> bytes_per_line * image -> height;
+ }
+ else if (image -> format == ZPixmap)
+ {
+ req -> dstLength = ROUNDUP((image -> bits_per_pixel * width),
+ image -> bitmap_pad) * height >> 3;
+ }
+ else
+ {
+ req -> dstLength = ROUNDUP(width, image -> bitmap_pad) * height >> 3;
+ }
+
+ src_data_length = image -> xoffset;
+
+ dst_data_length = ROUNDUP(src_data_length, 4);
+
+ #ifdef TEST
+ fprintf(stderr, "******NXPutPackedImage: Source data length [%d] request data length [%d].\n",
+ src_data_length, dst_data_length);
+ #endif
+
+ req -> length += (dst_data_length >> 2);
+
+ if (src_data_length > 0)
+ {
+ if (dpy -> bufptr + dst_data_length <= dpy -> bufmax)
+ {
+ /*
+ * Clean the padding bytes in the request.
+ */
+
+ *((int *) (dpy -> bufptr + dst_data_length - 4)) = 0x0;
+
+ memcpy(dpy -> bufptr, image -> data, src_data_length);
+
+ dpy -> bufptr += dst_data_length;
+ }
+ else
+ {
+ /*
+ * The _XSend() will pad the request for us.
+ */
+
+ _XSend(dpy, image -> data, src_data_length);
+ }
+ }
+
+ UnlockDisplay(dpy);
+
+ SyncHandle();
+
+ return 1;
+}
+
+int NXAllocColors(Display *dpy, Colormap colormap, unsigned int entries,
+ XColor screens_in_out[], Bool results_in_out[])
+{
+ Status result = 0;
+ xAllocColorReply rep;
+ register xAllocColorReq *req;
+
+ Bool alloc_error = False;
+
+ register unsigned int i;
+
+ LockDisplay(dpy);
+
+ for (i = 0; i < entries; i++)
+ {
+ GetReq(AllocColor, req);
+
+ req -> cmap = colormap;
+
+ req -> red = screens_in_out[i].red;
+ req -> green = screens_in_out[i].green;
+ req -> blue = screens_in_out[i].blue;
+ }
+
+ for (i = 0; i < entries; i++)
+ {
+ result = _XReply(dpy, (xReply *) &rep, 0, xTrue);
+
+ if (result)
+ {
+ screens_in_out[i].pixel = rep.pixel;
+
+ screens_in_out[i].red = rep.red;
+ screens_in_out[i].green = rep.green;
+ screens_in_out[i].blue = rep.blue;
+
+ results_in_out[i] = True;
+ }
+ else
+ {
+ results_in_out[i] = False;
+
+ alloc_error = True;
+ }
+ }
+
+ UnlockDisplay(dpy);
+
+ SyncHandle();
+
+ return (alloc_error == False);
+}
+
+char *NXEncodeColormap(const char *src_data, unsigned int src_size, unsigned int *dst_size)
+{
+ return ColormapCompressData(src_data, src_size, dst_size);
+}
+
+char *NXEncodeAlpha(const char *src_data, unsigned int src_size, unsigned int *dst_size)
+{
+ return AlphaCompressData(src_data, src_size, dst_size);
+}
+
+NXPackedImage *NXEncodeRgb(XImage *src_image, unsigned int method, unsigned int quality)
+{
+ NXPackedImage *dst_image = NULL;
+
+ unsigned int dst_size;
+
+ /*
+ * Create a new image structure as a copy
+ * of the source.
+ */
+
+ if ((dst_image = (NXPackedImage *) Xmalloc(sizeof(NXPackedImage))) == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXEncodeRgb: PANIC! Cannot allocate [%d] bytes for the image.\n",
+ (int) sizeof(XImage));
+ #endif
+
+ return NULL;
+ }
+
+ *dst_image = *src_image;
+
+ dst_image -> data = RgbCompressData(src_image, &dst_size);
+
+ if (dst_image -> data == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXEncodeRgb: PANIC! Rgb compression failed.\n");
+ #endif
+
+ Xfree(dst_image);
+
+ return NULL;
+ }
+
+ /*
+ * Store the Rgb size in the xoffset field.
+ */
+
+ dst_image -> xoffset = dst_size;
+
+ return dst_image;
+}
+
+NXPackedImage *NXEncodeRle(XImage *src_image, unsigned int method, unsigned int quality)
+{
+ NXPackedImage *dst_image = NULL;
+
+ unsigned int dst_size;
+
+ /*
+ * Create a new image structure as a copy
+ * of the source.
+ */
+
+ if ((dst_image = (NXPackedImage *) Xmalloc(sizeof(NXPackedImage))) == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXEncodeRle: PANIC! Cannot allocate [%d] bytes for the image.\n",
+ (int) sizeof(XImage));
+ #endif
+
+ return NULL;
+ }
+
+ *dst_image = *src_image;
+
+ dst_image -> data = RleCompressData(src_image, &dst_size);
+
+ if (dst_image -> data == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXEncodeRle: PANIC! Rle compression failed.\n");
+ #endif
+
+ Xfree(dst_image);
+
+ return NULL;
+ }
+
+ /*
+ * Store the Rle size in the xoffset field.
+ */
+
+ dst_image -> xoffset = dst_size;
+
+ return dst_image;
+}
+
+NXPackedImage *NXEncodeBitmap(XImage *src_image, unsigned int method, unsigned int quality)
+{
+ NXPackedImage *dst_image = NULL;
+
+ unsigned int dst_size;
+
+ /*
+ * Create a new image structure as a copy
+ * of the source.
+ */
+
+ if ((dst_image = (NXPackedImage *) Xmalloc(sizeof(NXPackedImage))) == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXEncodeBitmap: PANIC! Cannot allocate [%d] bytes for the image.\n",
+ (int) sizeof(XImage));
+ #endif
+
+ return NULL;
+ }
+
+ *dst_image = *src_image;
+
+ dst_image -> data = BitmapCompressData(src_image, &dst_size);
+
+ if (dst_image -> data == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXEncodeBitmap: PANIC! Bitmap compression failed.\n");
+ #endif
+
+ Xfree(dst_image);
+
+ return NULL;
+ }
+
+ /*
+ * Store the bitmap size in the xoffset field.
+ */
+
+ dst_image -> xoffset = dst_size;
+
+ return dst_image;
+}
+
+NXPackedImage *NXEncodeJpeg(XImage *src_image, unsigned int method, unsigned int quality)
+{
+ NXPackedImage *dst_image = NULL;
+
+ int size;
+
+ /*
+ * Check if the bpp of the image is valid
+ * for the Jpeg compression.
+ */
+
+ if (src_image -> bits_per_pixel < 15)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXEncodeJpeg: PANIC! Invalid bpp for Jpeg compression [%d]\n.",
+ src_image -> bits_per_pixel);
+ #endif
+
+ return NULL;
+ }
+
+ /*
+ * Create the destination image as a copy
+ * of the source.
+ */
+
+ if ((dst_image = (NXPackedImage *) Xmalloc(sizeof(NXPackedImage))) == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXEncodeJpeg: PANIC! Cannot allocate [%d] bytes for the Jpeg image.\n",
+ (int) sizeof(NXPackedImage));
+ #endif
+
+ return NULL;
+ }
+
+ *dst_image = *src_image;
+
+ dst_image -> data = JpegCompressData(src_image, quality, &size);
+
+ if (dst_image -> data == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXEncodeJpeg: PANIC! Jpeg compression failed.\n");
+ #endif
+
+ Xfree(dst_image);
+
+ return NULL;
+ }
+
+ /*
+ * Store the Jpeg size in the xoffset field.
+ */
+
+ dst_image -> xoffset = size;
+
+ return dst_image;
+}
+
+NXPackedImage *NXEncodePng(XImage *src_image, unsigned int method, unsigned int quality)
+{
+ NXPackedImage *dst_image = NULL;
+
+ int size;
+
+ /*
+ * Check if the bpp of the image is valid
+ * for png compression.
+ */
+
+ if (src_image -> bits_per_pixel < 15)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXEncodePng: PANIC! Invalid bpp for Png compression [%d].\n",
+ src_image -> bits_per_pixel);
+ #endif
+
+ return NULL;
+ }
+
+ if ((dst_image = (NXPackedImage *) Xmalloc(sizeof(NXPackedImage))) == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXEncodePng: PANIC! Cannot allocate [%d] bytes for the Png image.\n",
+ (int) sizeof(NXPackedImage));
+ #endif
+
+ return NULL;
+ }
+
+ *dst_image = *src_image;
+
+ dst_image -> data = PngCompressData(dst_image, &size);
+
+ if (dst_image -> data == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXEncodePng: PANIC! Png compression failed.\n");
+ #endif
+
+ Xfree(dst_image);
+
+ return NULL;
+ }
+
+ /*
+ * Store the Png size in the xoffset field.
+ */
+
+ dst_image -> xoffset = size;
+
+ return dst_image;
+}
+
+int NXEncodeColors(XImage *src_image, NXColorTable *color_table, int nb_max)
+{
+ int x, y, t, p;
+
+ long pixel;
+
+ /*
+ * We need a smarter way to extract
+ * the colors from the image and
+ * create a color table.
+ */
+
+ memset(color_table, 0, nb_max * sizeof(NXColorTable));
+
+ for (x = 0, p = 0; x < src_image -> width; x++)
+ {
+ for (y = 0; y < src_image -> height; y++)
+ {
+ pixel = XGetPixel(src_image, x, y);
+
+ for (t = 0; t < nb_max; t++)
+ {
+ if ( color_table[t].found == 0)
+ {
+ color_table[t].pixel = pixel;
+ color_table[t].found = 1;
+
+ p++;
+
+ break;
+ }
+ else if ((color_table[t].pixel) == pixel)
+ {
+ break;
+ }
+ }
+
+ if (p == nb_max)
+ {
+ return nb_max + 1;
+ }
+ }
+ }
+
+ return p;
+}
+
+void NXMaskImage(XImage *image, unsigned int method)
+{
+ unsigned int maskMethod;
+
+ const ColorMask *mask;
+
+ /*
+ * Choose the correct mask method
+ */
+
+ switch(method)
+ {
+ case PACK_JPEG_8_COLORS:
+ case PACK_PNG_8_COLORS:
+ {
+ maskMethod = MASK_8_COLORS;
+
+ #ifdef DEBUG
+ fprintf(stderr, "******NXMaskImage: Method is MASK_8_COLORS\n");
+ #endif
+
+ break;
+ }
+ case PACK_JPEG_64_COLORS:
+ case PACK_PNG_64_COLORS:
+ {
+ maskMethod = MASK_64_COLORS;
+
+ #ifdef DEBUG
+ fprintf(stderr, "******NXMaskImage: Method is MASK_64K_COLORS\n");
+ #endif
+
+ break;
+ }
+ case PACK_JPEG_256_COLORS:
+ case PACK_PNG_256_COLORS:
+ {
+ maskMethod = MASK_256_COLORS;
+
+ #ifdef DEBUG
+ fprintf(stderr, "******NXMaskImage: Method is MASK_256_COLORS\n");
+ #endif
+
+ break;
+ }
+ case PACK_JPEG_512_COLORS:
+ case PACK_PNG_512_COLORS:
+ {
+ maskMethod = MASK_512_COLORS;
+
+ #ifdef DEBUG
+ fprintf(stderr, "******NXMaskImage: Method is MASK_512K_COLORS\n");
+ #endif
+
+ break;
+ }
+ case PACK_JPEG_4K_COLORS:
+ case PACK_PNG_4K_COLORS:
+ {
+ maskMethod = MASK_4K_COLORS;
+
+ #ifdef DEBUG
+ fprintf(stderr, "******NXMaskImage: Method is MASK_4K_COLORS\n");
+ #endif
+
+ break;
+ }
+ case PACK_JPEG_32K_COLORS:
+ case PACK_PNG_32K_COLORS:
+ {
+ maskMethod = MASK_32K_COLORS;
+
+ #ifdef DEBUG
+ fprintf(stderr, "******NXMaskImage: Method is MASK_32K_COLORS\n");
+ #endif
+
+ break;
+ }
+ case PACK_JPEG_64K_COLORS:
+ case PACK_PNG_64K_COLORS:
+ {
+ maskMethod = MASK_64K_COLORS;
+
+ #ifdef DEBUG
+ fprintf(stderr, "******NXMaskImage: Method is MASK_64K_COLORS\n");
+ #endif
+
+ break;
+ }
+ case PACK_JPEG_256K_COLORS:
+ case PACK_PNG_256K_COLORS:
+ {
+ maskMethod = MASK_256K_COLORS;
+
+ #ifdef DEBUG
+ fprintf(stderr, "******NXMaskImage: Method is MASK_256K_COLORS\n");
+ #endif
+
+ break;
+ }
+ case PACK_JPEG_2M_COLORS:
+ case PACK_PNG_2M_COLORS:
+ {
+ maskMethod = MASK_2M_COLORS;
+
+ #ifdef DEBUG
+ fprintf(stderr, "******NXMaskImage: Method is MASK_2M_COLORS\n");
+ #endif
+
+ break;
+ }
+ case PACK_JPEG_16M_COLORS:
+ case PACK_PNG_16M_COLORS:
+ {
+ maskMethod = MASK_16M_COLORS;
+
+ #ifdef DEBUG
+ fprintf(stderr, "******NXMaskImage: Method is MASK_16M_COLORS\n");
+ #endif
+
+ break;
+ }
+ default:
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXMaskImage: PANIC! Cannot find mask method for pack method [%d]\n",
+ method);
+ #endif
+
+ return;
+ }
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "******NXMaskImage: packMethod[%d] => maskMethod[%d]\n",
+ method, maskMethod);
+ #endif
+
+ /*
+ * Get mask out of method and check if
+ * visual is supported by current color
+ * reduction algorithm.
+ */
+
+ mask = MethodColorMask(maskMethod);
+
+ if (mask == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXMaskImage: PANIC! No mask to apply for pack method [%d].\n",
+ method);
+ #endif
+
+ return;
+ }
+ else if (CanMaskImage(image, mask) == 0)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXMaskImage: PANIC! Invalid source with format [%d] depth [%d] bits per pixel [%d].\n",
+ image -> format, image -> depth, image -> bits_per_pixel);
+
+ fprintf(stderr, "******NXMaskImage: PANIC! Visual colormask is red 0x%lx green 0x%lx blue 0x%lx.\n",
+ image -> red_mask, image -> green_mask, image -> blue_mask);
+ #endif
+
+ return;
+ }
+
+ /*
+ * Calling ShouldMaskImage you get 0 in the case
+ * of MASK_256_COLORS and MASK_64K_COLORS, which
+ * means that the image should not be masked.
+ */
+
+ if (ShouldMaskImage(image, mask) == 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "******NXMaskImage: the image will not be masked\n");
+ #endif
+ }
+ else
+ {
+ if (MaskInPlaceImage(mask, image) <= 0)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXMaskImage: PANIC! Failed to apply the color mask in place.\n");
+ #endif
+ }
+ }
+}
+
+/*
+ * The display parameter is ignored.
+ */
+
+void NXInitCache(Display *dpy, int entries)
+{
+ if (NXImageCache != NULL && NXImageCacheSize == entries)
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "******NXInitCache: Nothing to do with image cache at [%p] and [%d] entries.\n",
+ NXImageCache, NXImageCacheSize);
+ #endif
+
+ return;
+ }
+
+ #ifdef DEBUG
+ fprintf(stderr, "******NXInitCache: Initializing the cache with [%d] entries.\n",
+ entries);
+ #endif
+
+ NXImageCacheSize = 0;
+
+ if (NXImageCache != NULL)
+ {
+ Xfree(NXImageCache);
+
+ NXImageCache = NULL;
+ }
+
+ if (entries > 0)
+ {
+ NXImageCache = Xmalloc(entries * sizeof(_NXImageCacheEntry));
+
+ if (NXImageCache != NULL)
+ {
+ memset(NXImageCache, 0, entries * sizeof(_NXImageCacheEntry));
+
+ NXImageCacheSize = entries;
+
+ #ifdef DEBUG
+ fprintf(stderr, "******NXInitCache: Image cache initialized with [%d] entries.\n", entries);
+ #endif
+ }
+ }
+}
+
+#ifdef DUMP
+
+void _NXCacheDump(const char *label)
+{
+ char s[MD5_LENGTH * 2 + 1];
+
+ int i;
+ int j;
+
+ #ifdef DEBUG
+ fprintf(stderr, "%s: Dumping the content of image cache:\n", label);
+ #endif
+
+ for (i = 0; i < NXImageCacheSize; i++)
+ {
+ if (NXImageCache[i].image == NULL)
+ {
+ break;
+ }
+
+ for (j = 0; j < MD5_LENGTH; j++)
+ {
+ sprintf(s + (j * 2), "%02X", ((unsigned char *) NXImageCache[i].md5)[j]);
+ }
+
+ #ifdef DEBUG
+ fprintf(stderr, "%s: [%d][%s].\n", label, i, s);
+ #endif
+ }
+}
+
+#endif
+
+XImage *NXCacheFindImage(NXPackedImage *src_image, unsigned int *method, unsigned char **md5)
+{
+ md5_state_t new_state;
+ md5_byte_t *new_md5;
+ unsigned int data_size, i;
+
+ if (NXImageCache == NULL)
+ {
+ return NULL;
+ }
+
+ /*
+ * Will return the allocated checksum
+ * if the image is not found.
+ */
+
+ *md5 = NULL;
+
+ if ((new_md5 = Xmalloc(MD5_LENGTH)) == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXCacheFindImage: Can't allocate memory for the checksum.\n");
+ #endif
+
+ return NULL;
+ }
+
+ data_size = (src_image -> bytes_per_line * src_image -> height);
+
+ md5_init(&new_state);
+
+ md5_append(&new_state, (unsigned char *) &src_image -> width, sizeof(int));
+ md5_append(&new_state, (unsigned char *) &src_image -> height, sizeof(int));
+
+ md5_append(&new_state, (unsigned char *) src_image -> data, data_size);
+
+ md5_finish(&new_state, new_md5);
+
+ for (i = 0; i < NXImageCacheSize; i++)
+ {
+ if (NXImageCache[i].image != NULL)
+ {
+ if (memcmp(NXImageCache[i].md5, new_md5, MD5_LENGTH) == 0)
+ {
+ _NXImageCacheEntry found;
+
+ found.image = NXImageCache[i].image;
+ found.method = NXImageCache[i].method;
+ found.md5 = NXImageCache[i].md5;
+
+ *method = found.method;
+
+ NXImageCacheHits++;
+
+ #ifdef DEBUG
+ fprintf(stderr, "******NXCacheFindImage: Found at position [%d] with hits [%d] and [%d] packs.\n",
+ i, NXImageCacheHits, NXImageCacheOps);
+ #endif
+
+ Xfree(new_md5);
+
+ /*
+ * Move the images down one slot, from
+ * the head of the list, and place the
+ * image just found at top.
+ */
+
+ if (i > 16)
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "******NXCacheFindImage: Moving the image at the head of the list.\n");
+ #endif
+
+ memmove(&NXImageCache[1], &NXImageCache[0], (i * sizeof(_NXImageCacheEntry)));
+
+ NXImageCache[0].image = found.image;
+ NXImageCache[0].method = found.method;
+ NXImageCache[0].md5 = found.md5;
+
+ #ifdef DUMP
+
+ _NXCacheDump("******NXCacheFindImage");
+
+ #endif
+ }
+
+ /*
+ * Return the checksum and image
+ * structure allocated in cache.
+ */
+
+ *md5 = found.md5;
+
+ return found.image;
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ *md5 = new_md5;
+
+ return NULL;
+}
+
+/*
+ * Add a packed image to the cache. A new image
+ * structure is allocated and copied, data and
+ * checksum are inherited from the passed image.
+ */
+
+int NXCacheAddImage(NXPackedImage *image, unsigned int method, unsigned char *md5)
+{
+ unsigned int i;
+
+ if (image == NULL || image -> data == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXCacheAddImage: PANIC! Invalid image passed to function.\n");
+ #endif
+
+ return -1;
+ }
+
+ i = (NXImageCacheOps < NXImageCacheSize) ? NXImageCacheOps : NXImageCacheSize;
+
+ if (NXImageCacheOps >= NXImageCacheSize)
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "******NXCacheAddImage: Freeing up the oldest entry.\n");
+ #endif
+
+ i--;
+
+ Xfree(NXImageCache[NXImageCacheSize - 1].image -> data);
+ Xfree(NXImageCache[NXImageCacheSize - 1].image);
+ Xfree(NXImageCache[NXImageCacheSize - 1].md5);
+ }
+
+ if (i > 0)
+ {
+ memmove(&NXImageCache[1], &NXImageCache[0], i * sizeof(_NXImageCacheEntry));
+ }
+
+ NXImageCacheOps++;
+
+ #ifdef DEBUG
+ fprintf(stderr, "******NXCacheAddImage: Going to add new image with data size [%d].\n",
+ image -> xoffset);
+ #endif
+
+ NXImageCache[0].image = image;
+ NXImageCache[0].method = method;
+ NXImageCache[0].md5 = md5;
+
+ #ifdef DUMP
+
+ _NXCacheDump("******NXCacheAddImage");
+
+ #endif
+
+ return 1;
+}
+
+/*
+ * The display parameter is ignored.
+ */
+
+void NXFreeCache(Display *dpy)
+{
+ int i;
+
+ if (NXImageCache == NULL)
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "******NXFreeCache: Nothing to do with a null image cache.\n");
+ #endif
+
+ return;
+ }
+
+ #ifdef DEBUG
+ fprintf(stderr, "******NXFreeCache: Freeing the cache with [%d] entries.\n",
+ NXImageCacheSize);
+ #endif
+
+ for (i = 0; i < NXImageCacheSize; i++)
+ {
+ if (NXImageCache[i].image != NULL)
+ {
+ if (NXImageCache[i].image -> data != NULL)
+ {
+ Xfree(NXImageCache[i].image -> data);
+ }
+
+ Xfree(NXImageCache[i].image);
+
+ NXImageCache[i].image = NULL;
+ }
+
+ if (NXImageCache[i].md5 != NULL)
+ {
+ Xfree(NXImageCache[i].md5);
+
+ NXImageCache[i].md5 = NULL;
+ }
+ }
+
+ Xfree(NXImageCache);
+
+ NXImageCache = NULL;
+
+ NXImageCacheSize = 0;
+ NXImageCacheHits = 0;
+ NXImageCacheOps = 0;
+}
+
+static void _NXNotifyImage(Display *dpy, int resource, Bool success)
+{
+ XEvent async_event;
+
+ /*
+ * Enqueue an event to tell client
+ * the result of GetImage.
+ */
+
+ async_event.type = ClientMessage;
+
+ async_event.xclient.serial = _NXCollectedImages[resource] -> sequence;
+
+ async_event.xclient.window = 0;
+ async_event.xclient.message_type = 0;
+ async_event.xclient.format = 32;
+
+ async_event.xclient.data.l[0] = NXCollectImageNotify;
+ async_event.xclient.data.l[1] = resource;
+ async_event.xclient.data.l[2] = success;
+
+ XPutBackEvent(dpy, &async_event);
+}
+
+static Bool _NXCollectImageHandler(Display *dpy, xReply *rep, char *buf,
+ int len, XPointer data)
+{
+ register _NXCollectImageState *state;
+
+ register xGetImageReply *async_rep;
+
+ char *async_head;
+ char *async_data;
+
+ int async_size;
+
+ state = (_NXCollectImageState *) data;
+
+ if ((rep -> generic.sequenceNumber % 65536) !=
+ ((int)(state -> sequence) % 65536))
+ {
+ #ifdef TEST
+ fprintf(stderr, "******_NXCollectImageHandler: Unmatched sequence [%d] for opcode [%d] "
+ "with length [%d].\n", rep -> generic.sequenceNumber, rep -> generic.type,
+ (int) rep -> generic.length << 2);
+ #endif
+
+ return False;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "******_NXCollectImageHandler: Going to handle asynchronous GetImage reply.\n");
+ #endif
+
+ /*
+ * As even reply data is managed asynchronously,
+ * we can use state to get to vector and vector
+ * to get to handler. In this way, we can safely
+ * dequeue and free the handler itself.
+ */
+
+ DeqAsyncHandler(dpy, state -> handler);
+
+ Xfree(state -> handler);
+
+ state -> handler = NULL;
+
+ if (rep -> generic.type == X_Error)
+ {
+ #ifdef TEST
+ fprintf(stderr, "******_NXCollectImageHandler: Error received from X server for resource [%d].\n",
+ state -> resource);
+ #endif
+
+ _NXNotifyImage(dpy, state -> resource, False);
+
+ _NXCollectedImages[state -> resource] = NULL;
+
+ Xfree(state);
+
+ return False;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "******_NXCollectImageHandler: Matched request with sequence [%ld].\n",
+ state -> sequence);
+ #endif
+
+ async_size = SIZEOF(xGetImageReply);
+
+ async_head = Xmalloc(async_size);
+
+ if (async_head == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******_NXCollectImageHandler: PANIC! Failed to allocate memory with resource [%d].\n",
+ state -> resource);
+ #endif
+
+ _NXNotifyImage(dpy, state -> resource, False);
+
+ _NXCollectedImages[state -> resource] = NULL;
+
+ Xfree(state);
+
+ return False;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "******_NXCollectImageHandler: Going to get reply with size [%d].\n",
+ (int) rep -> generic.length << 2);
+ #endif
+
+ async_rep = (xGetImageReply *) _XGetAsyncReply(dpy, async_head, rep, buf, len, 0, False);
+
+ if (async_rep == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******_NXCollectImageHandler: PANIC! Failed to get reply with resource [%d].\n",
+ state -> resource);
+ #endif
+
+ _NXNotifyImage(dpy, state -> resource, False);
+
+ _NXCollectedImages[state -> resource] = NULL;
+
+ Xfree(state);
+
+ Xfree(async_head);
+
+ return False;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "******_NXCollectImageHandler: Got reply with depth [%d] visual [%d] size [%d].\n",
+ async_rep -> depth, (int) async_rep -> visual, (int) async_rep -> length << 2);
+ #endif
+
+ async_size = async_rep -> length << 2;
+
+ if (async_size > 0)
+ {
+ async_data = Xmalloc(async_size);
+
+ if (async_data == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******_NXCollectImageHandler: PANIC! Failed to allocate memory with resource [%d].\n",
+ state -> resource);
+ #endif
+
+ _NXNotifyImage(dpy, state -> resource, False);
+
+ _NXCollectedImages[state -> resource] = NULL;
+
+ Xfree(state);
+
+ Xfree(async_head);
+
+ return False;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "******_NXCollectImageHandler: Going to get data with size [%d].\n",
+ async_size);
+ #endif
+
+ _XGetAsyncData(dpy, async_data, buf, len, SIZEOF(xGetImageReply), async_size, async_size);
+
+ /*
+ * From now on we can return True, as all
+ * data has been consumed from buffer.
+ */
+
+ if (state -> format == XYPixmap)
+ {
+ unsigned long depth = DepthOnes(state -> mask & (((unsigned long)0xFFFFFFFF) >>
+ (32 - async_rep -> depth)));
+
+ state -> image = XCreateImage(dpy, _XVIDtoVisual(dpy, async_rep -> visual),
+ depth, XYPixmap, 0, async_data, state -> width,
+ state -> height, dpy -> bitmap_pad, 0);
+ }
+ else
+ {
+ state -> image = XCreateImage(dpy, _XVIDtoVisual(dpy, async_rep -> visual),
+ async_rep -> depth, ZPixmap, 0, async_data, state -> width,
+ state -> height, _XGetScanlinePad(dpy, async_rep -> depth), 0);
+ }
+
+ if (state -> image == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******_NXCollectImageHandler: PANIC! Failed to create image for resource [%d].\n",
+ state -> resource);
+ #endif
+
+ _NXNotifyImage(dpy, state -> resource, False);
+
+ _NXCollectedImages[state -> resource] = NULL;
+
+ Xfree(state);
+
+ Xfree(async_head);
+ Xfree(async_data);
+
+ return True;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "******_NXCollectImageHandler: Successfully stored image data for resource [%d].\n",
+ state -> resource);
+ #endif
+ }
+ #ifdef WARNING
+ else
+ {
+ fprintf(stderr, "******_NXCollectImageHandler: WARNING! Null image data stored for resource [%d].\n",
+ state -> resource);
+ }
+ #endif
+
+ _NXNotifyImage(dpy, state -> resource, True);
+
+ Xfree(async_head);
+
+ return True;
+}
+
+int NXGetCollectImageResource(Display *dpy)
+{
+ int i;
+
+ for (i = 0; i < NXNumberOfResources; i++)
+ {
+ if (_NXCollectedImages[i] == NULL)
+ {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+int NXCollectImage(Display *dpy, unsigned int resource, Drawable drawable,
+ int src_x, int src_y, unsigned int width, unsigned int height,
+ unsigned long plane_mask, int format)
+{
+ register xGetImageReq *req;
+
+ _NXCollectImageState *state;
+ _XAsyncHandler *handler;
+
+ if (resource >= NXNumberOfResources)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXCollectImage: PANIC! Provided resource [%u] is out of range.\n",
+ resource);
+ #endif
+
+ return -1;
+ }
+
+ state = _NXCollectedImages[resource];
+
+ if (state != NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXCollectImage: PANIC! Having to remove previous state for resource [%u].\n",
+ resource);
+ #endif
+
+ if (state -> handler != NULL)
+ {
+ DeqAsyncHandler(dpy, state -> handler);
+
+ Xfree(state -> handler);
+ }
+
+ if (state -> image != NULL)
+ {
+ XDestroyImage(state -> image);
+ }
+
+ Xfree(state);
+
+ _NXCollectedImages[resource] = NULL;
+ }
+
+ LockDisplay(dpy);
+
+ GetReq(GetImage, req);
+
+ req -> format = format;
+ req -> drawable = drawable;
+ req -> x = src_x;
+ req -> y = src_y;
+ req -> width = width;
+ req -> height = height;
+ req -> planeMask = plane_mask;
+
+ #ifdef TEST
+ fprintf(stderr, "******NXCollectImage: Sending message opcode [%d] sequence [%ld] for resource [%d].\n",
+ X_GetImage, dpy -> request, resource);
+
+ fprintf(stderr, "******NXCollectImage: Format [%d] drawable [%d] src_x [%d] src_y [%d].\n",
+ req -> format, (int) req -> drawable, req -> x, req -> y);
+
+ fprintf(stderr, "******NXCollectImage: Width [%d] height [%d] plane_mask [%x].\n",
+ req -> width, req -> height, (int) req -> planeMask);
+ #endif
+
+ state = Xmalloc(sizeof(_NXCollectImageState));
+ handler = Xmalloc(sizeof(_XAsyncHandler));
+
+ if (state == NULL || handler == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXCollectImage: PANIC! Failed to allocate memory with resource [%d].\n",
+ resource);
+ #endif
+
+ UnGetReq(GetImage);
+
+ if (state != NULL)
+ {
+ Xfree(state);
+ }
+
+ if (handler != NULL)
+ {
+ Xfree(handler);
+ }
+
+ UnlockDisplay(dpy);
+
+ return -1;
+ }
+
+ state -> sequence = dpy -> request;
+ state -> resource = resource;
+ state -> mask = plane_mask;
+ state -> format = format;
+ state -> width = width;
+ state -> height = height;
+ state -> image = NULL;
+
+ state -> handler = handler;
+
+ handler -> next = dpy -> async_handlers;
+ handler -> handler = _NXCollectImageHandler;
+ handler -> data = (XPointer) state;
+ dpy -> async_handlers = handler;
+
+ _NXCollectedImages[resource] = state;
+
+ UnlockDisplay(dpy);
+
+ SyncHandle();
+
+ return 1;
+}
+
+int NXGetCollectedImage(Display *dpy, unsigned int resource, XImage **image)
+{
+ register _NXCollectImageState *state;
+
+ state = _NXCollectedImages[resource];
+
+ if (state == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXGetCollectedImage: PANIC! No image collected for resource [%u].\n",
+ resource);
+ #endif
+
+ return 0;
+ }
+
+ _NXCollectedImages[resource] = NULL;
+
+ *image = state -> image;
+
+ Xfree(state);
+
+ #ifdef TEST
+ fprintf(stderr, "******NXGetCollectedImage: Returning GetImage data for resource [%u].\n",
+ resource);
+ #endif
+
+ return 1;
+}
+
+static void _NXNotifyProperty(Display *dpy, int resource, Bool success)
+{
+ XEvent async_event;
+
+ /*
+ * Enqueue an event to tell client
+ * the result of GetProperty.
+ */
+
+ async_event.type = ClientMessage;
+
+ async_event.xclient.serial = _NXCollectedProperties[resource] -> sequence;
+
+ async_event.xclient.window = 0;
+ async_event.xclient.message_type = 0;
+ async_event.xclient.format = 32;
+
+ async_event.xclient.data.l[0] = NXCollectPropertyNotify;
+ async_event.xclient.data.l[1] = resource;
+ async_event.xclient.data.l[2] = success;
+
+ XPutBackEvent(dpy, &async_event);
+}
+
+static Bool _NXCollectPropertyHandler(Display *dpy, xReply *rep, char *buf,
+ int len, XPointer data)
+{
+ register _NXCollectPropertyState *state;
+
+ register xGetPropertyReply *async_rep;
+
+ char *async_head;
+ char *async_data;
+
+ int async_size;
+
+ state = (_NXCollectPropertyState *) data;
+
+ if ((rep -> generic.sequenceNumber % 65536) !=
+ ((int)(state -> sequence) % 65536))
+ {
+ #ifdef TEST
+ fprintf(stderr, "******_NXCollectPropertyHandler: Unmatched sequence [%d] for opcode [%d] "
+ "with length [%d].\n", rep -> generic.sequenceNumber, rep -> generic.type,
+ (int) rep -> generic.length << 2);
+ #endif
+
+ return False;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "******_NXCollectPropertyHandler: Going to handle asynchronous GetProperty reply.\n");
+ #endif
+
+ /*
+ * Reply data is managed asynchronously. We can
+ * use state to get to vector and vector to get
+ * to handler. In this way, we can dequeue and
+ * free the handler itself.
+ */
+
+ DeqAsyncHandler(dpy, state -> handler);
+
+ Xfree(state -> handler);
+
+ state -> handler = NULL;
+
+ if (rep -> generic.type == X_Error)
+ {
+ #ifdef TEST
+ fprintf(stderr, "******_NXCollectPropertyHandler: Error received from X server for resource [%d].\n",
+ state -> resource);
+ #endif
+
+ _NXNotifyProperty(dpy, state -> resource, False);
+
+ _NXCollectedProperties[state -> resource] = NULL;
+
+ Xfree(state);
+
+ return False;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "******_NXCollectPropertyHandler: Matched request with sequence [%ld].\n",
+ state -> sequence);
+ #endif
+
+ async_size = SIZEOF(xGetPropertyReply);
+
+ async_head = Xmalloc(async_size);
+
+ if (async_head == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******_NXCollectPropertyHandler: PANIC! Failed to allocate memory with resource [%d].\n",
+ state -> resource);
+ #endif
+
+ _NXNotifyProperty(dpy, state -> resource, False);
+
+ _NXCollectedProperties[state -> resource] = NULL;
+
+ Xfree(state);
+
+ return False;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "******_NXCollectPropertyHandler: Going to get reply with size [%d].\n",
+ (int) rep -> generic.length << 2);
+ #endif
+
+ async_rep = (xGetPropertyReply *) _XGetAsyncReply(dpy, async_head, rep, buf, len, 0, False);
+
+ if (async_rep == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******_NXCollectPropertyHandler: PANIC! Failed to get reply with resource [%d].\n",
+ state -> resource);
+ #endif
+
+ _NXNotifyProperty(dpy, state -> resource, False);
+
+ _NXCollectedProperties[state -> resource] = NULL;
+
+ Xfree(state);
+
+ Xfree(async_head);
+
+ return False;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "******_NXCollectPropertyHandler: Got reply with format [%d] type [%d] size [%d].\n",
+ async_rep -> format, (int) async_rep -> propertyType, (int) async_rep -> length << 2);
+
+ fprintf(stderr, "******_NXCollectPropertyHandler: Bytes after [%d] number of items [%d].\n",
+ (int) async_rep -> bytesAfter, (int) async_rep -> nItems);
+ #endif
+
+ state -> format = async_rep -> format;
+ state -> type = async_rep -> propertyType;
+ state -> items = async_rep -> nItems;
+ state -> after = async_rep -> bytesAfter;
+
+ async_size = async_rep -> length << 2;
+
+ if (async_size > 0)
+ {
+ async_data = Xmalloc(async_size);
+
+ if (async_data == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******_NXCollectPropertyHandler: PANIC! Failed to allocate memory with resource [%d].\n",
+ state -> resource);
+ #endif
+
+ _NXNotifyProperty(dpy, state -> resource, False);
+
+ _NXCollectedProperties[state -> resource] = NULL;
+
+ Xfree(state);
+
+ Xfree(async_head);
+
+ return False;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "******_NXCollectPropertyHandler: Going to get data with size [%d].\n",
+ async_size);
+ #endif
+
+ _XGetAsyncData(dpy, async_data, buf, len, SIZEOF(xGetPropertyReply), async_size, async_size);
+
+ /*
+ * From now on we can return True, as all
+ * data has been consumed from buffer.
+ */
+
+ state -> data = async_data;
+
+ #ifdef TEST
+ fprintf(stderr, "******_NXCollectPropertyHandler: Successfully stored property data for resource [%d].\n",
+ state -> resource);
+ #endif
+ }
+ #ifdef TEST
+ else
+ {
+ fprintf(stderr, "******_NXCollectPropertyHandler: WARNING! Null property data stored for resource [%d].\n",
+ state -> resource);
+ }
+ #endif
+
+ _NXNotifyProperty(dpy, state -> resource, True);
+
+ Xfree(async_head);
+
+ return True;
+}
+
+int NXGetCollectPropertyResource(Display *dpy)
+{
+ int i;
+
+ for (i = 0; i < NXNumberOfResources; i++)
+ {
+ if (_NXCollectedProperties[i] == NULL)
+ {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+int NXCollectProperty(Display *dpy, unsigned int resource, Window window, Atom property,
+ long long_offset, long long_length, Bool delete, Atom req_type)
+{
+ register xGetPropertyReq *req;
+
+ _NXCollectPropertyState *state;
+ _XAsyncHandler *handler;
+
+ if (resource >= NXNumberOfResources)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXCollectProperty: PANIC! Provided resource [%u] is out of range.\n",
+ resource);
+ #endif
+
+ return -1;
+ }
+
+ state = _NXCollectedProperties[resource];
+
+ if (state != NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXCollectProperty: PANIC! Having to remove previous state for resource [%u].\n",
+ resource);
+ #endif
+
+ if (state -> handler != NULL)
+ {
+ DeqAsyncHandler(dpy, state -> handler);
+
+ Xfree(state -> handler);
+ }
+
+ if (state -> data != NULL)
+ {
+ Xfree(state -> data);
+ }
+
+ Xfree(state);
+
+ _NXCollectedProperties[resource] = NULL;
+ }
+
+ LockDisplay(dpy);
+
+ GetReq(GetProperty, req);
+
+ req -> delete = delete;
+ req -> window = window;
+ req -> property = property;
+ req -> type = req_type;
+ req -> longOffset = long_offset;
+ req -> longLength = long_length;
+
+ #ifdef TEST
+ fprintf(stderr, "******NXCollectProperty: Sending message opcode [%d] sequence [%ld] for resource [%d].\n",
+ X_GetProperty, dpy -> request, resource);
+
+ fprintf(stderr, "******NXCollectProperty: Delete [%u] window [%d] property [%d] type [%d].\n",
+ req -> delete, (int) req -> window, (int) req -> property, (int) req -> type);
+
+ fprintf(stderr, "******NXCollectProperty: Long offset [%d] long length [%d].\n",
+ (int) req -> longOffset, (int) req -> longLength);
+ #endif
+
+ state = Xmalloc(sizeof(_NXCollectPropertyState));
+ handler = Xmalloc(sizeof(_XAsyncHandler));
+
+ if (state == NULL || handler == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXCollectProperty: Failed to allocate memory with resource [%d].\n",
+ resource);
+ #endif
+
+ if (state != NULL)
+ {
+ Xfree(state);
+ }
+
+ if (handler != NULL)
+ {
+ Xfree(handler);
+ }
+
+ UnGetReq(GetProperty);
+
+ UnlockDisplay(dpy);
+
+ return -1;
+ }
+
+ state -> sequence = dpy -> request;
+ state -> resource = resource;
+ state -> window = window;
+ state -> property = property;
+ state -> type = 0;
+ state -> format = 0;
+ state -> items = 0;
+ state -> after = 0;
+ state -> data = NULL;
+
+ state -> handler = handler;
+
+ handler -> next = dpy -> async_handlers;
+ handler -> handler = _NXCollectPropertyHandler;
+ handler -> data = (XPointer) state;
+ dpy -> async_handlers = handler;
+
+ _NXCollectedProperties[resource] = state;
+
+ UnlockDisplay(dpy);
+
+ SyncHandle();
+
+ return True;
+}
+
+int NXGetCollectedProperty(Display *dpy, unsigned int resource, Atom *actual_type_return,
+ int *actual_format_return, unsigned long *nitems_return,
+ unsigned long *bytes_after_return, unsigned char **data)
+{
+ register _NXCollectPropertyState *state;
+
+ state = _NXCollectedProperties[resource];
+
+ if (state == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXGetCollectedProperty: PANIC! No data collected for resource [%u].\n",
+ resource);
+ #endif
+
+ return 0;
+ }
+
+ *actual_type_return = state -> type;
+ *actual_format_return = state -> format;
+ *nitems_return = state -> items;
+ *bytes_after_return = state -> after;
+
+ *data = (unsigned char *) _NXCollectedProperties[resource] -> data;
+
+ Xfree(state);
+
+ _NXCollectedProperties[resource] = NULL;
+
+ #ifdef TEST
+ fprintf(stderr, "******NXGetCollectedProperty: Returning GetProperty data for resource [%u].\n",
+ resource);
+ #endif
+
+ return True;
+}
+
+static void _NXNotifyGrabPointer(Display *dpy, int resource, Bool success)
+{
+ XEvent async_event;
+
+ async_event.type = ClientMessage;
+
+ async_event.xclient.serial = _NXCollectedGrabPointers[resource] -> sequence;
+
+ async_event.xclient.window = 0;
+ async_event.xclient.message_type = 0;
+ async_event.xclient.format = 32;
+
+ async_event.xclient.data.l[0] = NXCollectGrabPointerNotify;
+ async_event.xclient.data.l[1] = resource;
+ async_event.xclient.data.l[2] = success;
+
+ XPutBackEvent(dpy, &async_event);
+}
+
+static Bool _NXCollectGrabPointerHandler(Display *dpy, xReply *rep, char *buf,
+ int len, XPointer data)
+{
+ register _NXCollectGrabPointerState *state;
+
+ register xGrabPointerReply *async_rep;
+
+ char *async_head;
+
+ int async_size;
+
+ state = (_NXCollectGrabPointerState *) data;
+
+ if ((rep -> generic.sequenceNumber % 65536) !=
+ ((int)(state -> sequence) % 65536))
+ {
+ #ifdef TEST
+ fprintf(stderr, "******_NXCollectGrabPointerHandler: Unmatched sequence [%d] for opcode [%d] "
+ "with length [%d].\n", rep -> generic.sequenceNumber, rep -> generic.type,
+ (int) rep -> generic.length << 2);
+ #endif
+
+ return False;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "******_NXCollectGrabPointerHandler: Going to handle asynchronous GrabPointer reply.\n");
+ #endif
+
+ DeqAsyncHandler(dpy, state -> handler);
+
+ Xfree(state -> handler);
+
+ state -> handler = NULL;
+
+ if (rep -> generic.type == X_Error)
+ {
+ #ifdef TEST
+ fprintf(stderr, "******_NXCollectGrabPointerHandler: Error received from X server for resource [%d].\n",
+ state -> resource);
+ #endif
+
+ _NXNotifyGrabPointer(dpy, state -> resource, False);
+
+ _NXCollectedGrabPointers[state -> resource] = NULL;
+
+ Xfree(state);
+
+ return False;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "******_NXCollectGrabPointerHandler: Matched request with sequence [%ld].\n",
+ state -> sequence);
+ #endif
+
+ async_size = SIZEOF(xGrabPointerReply);
+
+ async_head = Xmalloc(async_size);
+
+ if (async_head == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******_NXCollectGrabPointerHandler: PANIC! Failed to allocate memory with resource [%d].\n",
+ state -> resource);
+ #endif
+
+ _NXNotifyGrabPointer(dpy, state -> resource, False);
+
+ _NXCollectedGrabPointers[state -> resource] = NULL;
+
+ Xfree(state);
+
+ return False;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "******_NXCollectGrabPointerHandler: Going to get reply with size [%d].\n",
+ (int) rep -> generic.length << 2);
+ #endif
+
+ async_rep = (xGrabPointerReply *) _XGetAsyncReply(dpy, async_head, rep, buf, len, 0, False);
+
+ if (async_rep == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******_NXCollectGrabPointerHandler: PANIC! Failed to get reply with resource [%d].\n",
+ state -> resource);
+ #endif
+
+ _NXNotifyGrabPointer(dpy, state -> resource, False);
+
+ _NXCollectedGrabPointers[state -> resource] = NULL;
+
+ Xfree(state);
+
+ Xfree(async_head);
+
+ return False;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "******_NXCollectGrabPointerHandler: Got reply with status [%d] size [%d].\n",
+ async_rep -> status, (int) async_rep -> length << 2);
+ #endif
+
+ state -> status = async_rep -> status;
+
+ _NXNotifyGrabPointer(dpy, state -> resource, True);
+
+ Xfree(async_head);
+
+ return True;
+}
+
+int NXGetCollectGrabPointerResource(Display *dpy)
+{
+ int i;
+
+ for (i = 0; i < NXNumberOfResources; i++)
+ {
+ if (_NXCollectedGrabPointers[i] == NULL)
+ {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+int NXCollectGrabPointer(Display *dpy, unsigned int resource, Window grab_window, Bool owner_events,
+ unsigned int event_mask, int pointer_mode, int keyboard_mode,
+ Window confine_to, Cursor cursor, Time time)
+{
+ register xGrabPointerReq *req;
+
+ _NXCollectGrabPointerState *state;
+ _XAsyncHandler *handler;
+
+ if (resource >= NXNumberOfResources)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXCollectGrabPointer: PANIC! Provided resource [%u] is out of range.\n",
+ resource);
+ #endif
+
+ return -1;
+ }
+
+ state = _NXCollectedGrabPointers[resource];
+
+ if (state != NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXCollectGrabPointer: PANIC! Having to remove previous state for resource [%u].\n",
+ resource);
+ #endif
+
+ if (state -> handler != NULL)
+ {
+ DeqAsyncHandler(dpy, state -> handler);
+
+ Xfree(state -> handler);
+ }
+
+ Xfree(state);
+
+ _NXCollectedGrabPointers[resource] = NULL;
+ }
+
+ LockDisplay(dpy);
+
+ GetReq(GrabPointer, req);
+
+ req -> grabWindow = grab_window;
+ req -> ownerEvents = owner_events;
+ req -> eventMask = event_mask;
+ req -> pointerMode = pointer_mode;
+ req -> keyboardMode = keyboard_mode;
+ req -> confineTo = confine_to;
+ req -> cursor = cursor;
+ req -> time = time;
+
+ #ifdef TEST
+ fprintf(stderr, "******NXCollectGrabPointer: Sending message opcode [%d] sequence [%ld] "
+ "for resource [%d].\n", X_GrabPointer, dpy -> request, resource);
+ #endif
+
+ state = Xmalloc(sizeof(_NXCollectGrabPointerState));
+ handler = Xmalloc(sizeof(_XAsyncHandler));
+
+ if (state == NULL || handler == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXCollectGrabPointer: Failed to allocate memory with resource [%d].\n",
+ resource);
+ #endif
+
+ if (state != NULL)
+ {
+ Xfree(state);
+ }
+
+ if (handler != NULL)
+ {
+ Xfree(handler);
+ }
+
+ UnGetReq(GrabPointer);
+
+ UnlockDisplay(dpy);
+
+ return -1;
+ }
+
+ state -> sequence = dpy -> request;
+ state -> resource = resource;
+ state -> status = 0;
+
+ state -> handler = handler;
+
+ handler -> next = dpy -> async_handlers;
+ handler -> handler = _NXCollectGrabPointerHandler;
+ handler -> data = (XPointer) state;
+ dpy -> async_handlers = handler;
+
+ _NXCollectedGrabPointers[resource] = state;
+
+ UnlockDisplay(dpy);
+
+ SyncHandle();
+
+ return True;
+}
+
+int NXGetCollectedGrabPointer(Display *dpy, unsigned int resource, int *status)
+{
+ register _NXCollectGrabPointerState *state;
+
+ state = _NXCollectedGrabPointers[resource];
+
+ if (state == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXGetCollectedGrabPointer: PANIC! No data collected for resource [%u].\n",
+ resource);
+ #endif
+
+ return 0;
+ }
+
+ *status = state -> status;
+
+ Xfree(state);
+
+ _NXCollectedGrabPointers[resource] = NULL;
+
+ #ifdef TEST
+ fprintf(stderr, "******NXGetCollectedGrabPointer: Returning GrabPointer data for resource [%u].\n",
+ resource);
+ #endif
+
+ return True;
+}
+
+static void _NXNotifyInputFocus(Display *dpy, int resource, Bool success)
+{
+ XEvent async_event;
+
+ async_event.type = ClientMessage;
+
+ async_event.xclient.serial = _NXCollectedInputFocuses[resource] -> sequence;
+
+ async_event.xclient.window = 0;
+ async_event.xclient.message_type = 0;
+ async_event.xclient.format = 32;
+
+ async_event.xclient.data.l[0] = NXCollectInputFocusNotify;
+ async_event.xclient.data.l[1] = resource;
+ async_event.xclient.data.l[2] = success;
+
+ XPutBackEvent(dpy, &async_event);
+}
+
+static Bool _NXCollectInputFocusHandler(Display *dpy, xReply *rep, char *buf,
+ int len, XPointer data)
+{
+ register _NXCollectInputFocusState *state;
+
+ register xGetInputFocusReply *async_rep;
+
+ char *async_head;
+
+ int async_size;
+
+ state = (_NXCollectInputFocusState *) data;
+
+ if ((rep -> generic.sequenceNumber % 65536) !=
+ ((int)(state -> sequence) % 65536))
+ {
+ #ifdef TEST
+ fprintf(stderr, "******_NXCollectInputFocusHandler: Unmatched sequence [%d] for opcode [%d] "
+ "with length [%d].\n", rep -> generic.sequenceNumber, rep -> generic.type,
+ (int) rep -> generic.length << 2);
+ #endif
+
+ return False;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "******_NXCollectInputFocusHandler: Going to handle asynchronous GetInputFocus reply.\n");
+ #endif
+
+ DeqAsyncHandler(dpy, state -> handler);
+
+ Xfree(state -> handler);
+
+ state -> handler = NULL;
+
+ if (rep -> generic.type == X_Error)
+ {
+ #ifdef TEST
+ fprintf(stderr, "******_NXCollectInputFocusHandler: Error received from X server for resource [%d].\n",
+ state -> resource);
+ #endif
+
+ _NXNotifyInputFocus(dpy, state -> resource, False);
+
+ _NXCollectedInputFocuses[state -> resource] = NULL;
+
+ Xfree(state);
+
+ return False;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "******_NXCollectInputFocusHandler: Matched request with sequence [%ld].\n",
+ state -> sequence);
+ #endif
+
+ async_size = SIZEOF(xGetInputFocusReply);
+
+ async_head = Xmalloc(async_size);
+
+ if (async_head == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******_NXCollectInputFocusHandler: PANIC! Failed to allocate memory with resource [%d].\n",
+ state -> resource);
+ #endif
+
+ _NXNotifyInputFocus(dpy, state -> resource, False);
+
+ _NXCollectedInputFocuses[state -> resource] = NULL;
+
+ Xfree(state);
+
+ return False;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "******_NXCollectInputFocusHandler: Going to get reply with size [%d].\n",
+ (int) rep -> generic.length << 2);
+ #endif
+
+ async_rep = (xGetInputFocusReply *) _XGetAsyncReply(dpy, async_head, rep, buf, len, 0, False);
+
+ if (async_rep == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******_NXCollectInputFocusHandler: PANIC! Failed to get reply with resource [%d].\n",
+ state -> resource);
+ #endif
+
+ _NXNotifyInputFocus(dpy, state -> resource, False);
+
+ _NXCollectedInputFocuses[state -> resource] = NULL;
+
+ Xfree(state);
+
+ Xfree(async_head);
+
+ return False;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "******_NXCollectInputFocusHandler: Got reply with focus [%d] revert to [%d] "
+ "size [%d].\n", (int) async_rep -> focus, (int) async_rep -> revertTo,
+ (int) async_rep -> length << 2);
+ #endif
+
+ state -> focus = async_rep -> focus;
+ state -> revert_to = async_rep -> revertTo;
+
+ _NXNotifyInputFocus(dpy, state -> resource, True);
+
+ Xfree(async_head);
+
+ return True;
+}
+
+int NXGetCollectInputFocusResource(Display *dpy)
+{
+ int i;
+
+ for (i = 0; i < NXNumberOfResources; i++)
+ {
+ if (_NXCollectedInputFocuses[i] == NULL)
+ {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+int NXCollectInputFocus(Display *dpy, unsigned int resource)
+{
+ register xReq *req;
+
+ _NXCollectInputFocusState *state;
+ _XAsyncHandler *handler;
+
+ if (resource >= NXNumberOfResources)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXCollectInputFocus: PANIC! Provided resource [%u] is out of range.\n",
+ resource);
+ #endif
+
+ return -1;
+ }
+
+ state = _NXCollectedInputFocuses[resource];
+
+ if (state != NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXCollectInputFocus: PANIC! Having to remove previous state for resource [%u].\n",
+ resource);
+ #endif
+
+ if (state -> handler != NULL)
+ {
+ DeqAsyncHandler(dpy, state -> handler);
+
+ Xfree(state -> handler);
+ }
+
+ Xfree(state);
+
+ _NXCollectedInputFocuses[resource] = NULL;
+ }
+
+ LockDisplay(dpy);
+
+ GetEmptyReq(GetInputFocus, req);
+
+ #ifdef TEST
+ fprintf(stderr, "******NXCollectInputFocus: Sending message opcode [%d] sequence [%ld] for resource [%d].\n",
+ X_GetInputFocus, dpy -> request, resource);
+ #endif
+
+ state = Xmalloc(sizeof(_NXCollectInputFocusState));
+ handler = Xmalloc(sizeof(_XAsyncHandler));
+
+ if (state == NULL || handler == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXCollectInputFocus: Failed to allocate memory with resource [%d].\n",
+ resource);
+ #endif
+
+ if (state != NULL)
+ {
+ Xfree(state);
+ }
+
+ if (handler != NULL)
+ {
+ Xfree(handler);
+ }
+
+ UnGetEmptyReq();
+
+ UnlockDisplay(dpy);
+
+ return -1;
+ }
+
+ state -> sequence = dpy -> request;
+ state -> resource = resource;
+ state -> focus = 0;
+ state -> revert_to = 0;
+
+ state -> handler = handler;
+
+ handler -> next = dpy -> async_handlers;
+ handler -> handler = _NXCollectInputFocusHandler;
+ handler -> data = (XPointer) state;
+ dpy -> async_handlers = handler;
+
+ _NXCollectedInputFocuses[resource] = state;
+
+ UnlockDisplay(dpy);
+
+ SyncHandle();
+
+ return True;
+}
+
+int NXGetCollectedInputFocus(Display *dpy, unsigned int resource,
+ Window *focus_return, int *revert_to_return)
+{
+ register _NXCollectInputFocusState *state;
+
+ state = _NXCollectedInputFocuses[resource];
+
+ if (state == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXGetCollectedInputFocus: PANIC! No data collected for resource [%u].\n",
+ resource);
+ #endif
+
+ return 0;
+ }
+
+ *focus_return = state -> focus;
+ *revert_to_return = state -> revert_to;
+
+ Xfree(state);
+
+ _NXCollectedInputFocuses[resource] = NULL;
+
+ #ifdef TEST
+ fprintf(stderr, "******NXGetCollectedInputFocus: Returning GetInputFocus data for resource [%u].\n",
+ resource);
+ #endif
+
+ return True;
+}
+
+#ifdef DUMP
+
+void _NXDumpData(const unsigned char *buffer, unsigned int size)
+{
+ if (buffer != NULL)
+ {
+ unsigned int i = 0;
+
+ unsigned int ii;
+
+ while (i < size)
+ {
+ fprintf(stderr, "[%d]\t", i);
+
+ for (ii = 0; i < size && ii < 8; i++, ii++)
+ {
+ fprintf(stderr, "%d\t", (unsigned int) (buffer[i]));
+ }
+
+ fprintf(stderr, "\n");
+ }
+ }
+}
+
+#endif
diff --git a/nx-X11/programs/Xserver/hw/nxagent/compext/Compext.h b/nx-X11/programs/Xserver/hw/nxagent/compext/Compext.h
new file mode 100644
index 000000000..ecd7d1e18
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/compext/Compext.h
@@ -0,0 +1,912 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXCOMPEXT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#ifndef NXlib_H
+#define NXlib_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <nx-X11/X.h>
+#include <nx-X11/Xlib.h>
+
+#include <nx/NX.h>
+#include <nx/NXpack.h>
+#include <nx/NXproto.h>
+#include <nx/NXvars.h>
+
+/*
+ * All the NX code should use these.
+ */
+
+#define Xmalloc(size) malloc((size))
+#define Xfree(ptr) free((ptr))
+
+/*
+ * Maximum number of supported pack methods.
+ */
+
+#define NXNumberOfPackMethods 128
+
+/*
+ * Assume this as the limit of resources that
+ * can be provided to the split and unpack
+ * requests.
+ */
+
+#define NXNumberOfResources 256
+
+#define NXNoResource 256 + 1
+#define NXAnyResource 256 + 2
+
+/*
+ * Initialize the internal structures used by
+ * the library. Should be executed again after
+ * having reopened the display.
+ */
+
+extern int NXInitDisplay(
+#if NeedFunctionPrototypes
+ Display* /* display */
+#endif
+);
+
+/*
+ * Reset all the internal structures. Should be
+ * executed after closing the display.
+ */
+
+extern int NXResetDisplay(
+#if NeedFunctionPrototypes
+ Display* /* display */
+#endif
+);
+
+/*
+ * Set the NX display flush policy. The policy can
+ * be either NXFlushDeferred or NXFlushImmediate.
+ */
+
+extern int NXSetDisplayPolicy(
+#if NeedFunctionPrototypes
+ Display* /* display */,
+ int /* policy */
+#endif
+);
+
+/*
+ * Set the display output buffer size.
+ */
+
+extern int NXSetDisplayBuffer(
+#if NeedFunctionPrototypes
+ Display* /* display */,
+ int /* size */
+#endif
+);
+
+/*
+ * If set, the Popen() function in the X server
+ * wil remove the LD_LIBRARY_PATH variable from
+ * the environment before calling the execl()
+ * function on the child process. The function
+ * returns the previous value.
+ */
+
+extern int NXUnsetLibraryPath(
+#if NeedFunctionPrototypes
+ int /* value */
+#endif
+);
+
+/*
+ * If the parameter is true, the Xlib I/O error
+ * handler will return, instead of quitting the
+ * program. The function returns the previous
+ * value.
+ */
+
+extern int NXHandleDisplayError(
+#if NeedFunctionPrototypes
+ int /* value */
+#endif
+);
+
+/*
+ * Shutdown the display descriptor and force Xlib
+ * to set the I/O error flag.
+ */
+
+extern Bool NXForceDisplayError(
+#if NeedFunctionPrototypes
+ Display* /* display */
+#endif
+);
+
+/*
+ * Check the value of the XlibDisplayIOError flag.
+ * If not set, try to call the display error hand-
+ * ler to give to the application a chance to see
+ * whether it needs to close the connection.
+ */
+
+extern int NXDisplayError(
+#if NeedFunctionPrototypes
+ Display* /* display */
+#endif
+);
+
+/*
+ * Query the number of bytes readable from the
+ * display connection.
+ */
+
+extern int NXDisplayReadable(
+#if NeedFunctionPrototypes
+ Display* /* display */
+#endif
+);
+
+/*
+ * Query the number of the outstanding bytes to
+ * flush to the display connection.
+ */
+
+extern int NXDisplayFlushable(
+#if NeedFunctionPrototypes
+ Display* /* display */
+#endif
+);
+
+/*
+ * Return a value between 0 and 9 indicating the
+ * congestion level of the NX transport based on
+ * the tokens remaining. A value of 9 means that
+ * the link is congested and no further data can
+ * be sent.
+ */
+
+extern int NXDisplayCongestion(
+#if NeedFunctionPrototypes
+ Display* /* display */
+#endif
+);
+
+/*
+ * Flush the Xlib display buffer and/or the
+ * outstanding data accumulated by the NX
+ * transport.
+ */
+
+extern int NXFlushDisplay(
+#if NeedFunctionPrototypes
+ Display* /* display */,
+ int /* what */
+#endif
+);
+
+/*
+ * Public interfaces used to set the handlers.
+ * They all return the previous handler.
+ */
+
+extern NXDisplayErrorPredicate NXSetDisplayErrorPredicate(
+#if NeedFunctionPrototypes
+ NXDisplayErrorPredicate /* predicate */
+#endif
+);
+
+/*
+ * Called when the display blocks waiting to read or
+ * write more data.
+ */
+
+extern NXDisplayBlockHandler NXSetDisplayBlockHandler(
+#if NeedFunctionPrototypes
+ NXDisplayBlockHandler /* handler */
+#endif
+);
+
+/*
+ * Called after more data is written to the display.
+ * When the NX transport is running, data may be queued
+ * until an explicit flush.
+ */
+
+extern NXDisplayWriteHandler NXSetDisplayWriteHandler(
+#if NeedFunctionPrototypes
+ NXDisplayWriteHandler /* handler */
+#endif
+);
+
+/*
+ * Called after more data is sent to the remote proxy.
+ *
+ * Here the display pointer is passed as the second
+ * parameter to make clear that the function does not
+ * tie the callback to the display, but, similarly to
+ * all the Xlib error handlers, to a global variable
+ * shared by all the Xlib functions. The display
+ * pointer will be passed back by nxcomp at the time
+ * it will call the handler. This is because nxcomp
+ * doesn't have access to the display structure.
+ */
+
+extern NXDisplayFlushHandler NXSetDisplayFlushHandler(
+#if NeedFunctionPrototypes
+ NXDisplayFlushHandler /* handler */,
+ Display* /* display */
+#endif
+);
+
+/*
+ * Get an arbitrary null terminated buffer to be added
+ * to the NX statistics.
+ */
+
+extern NXDisplayStatisticsHandler NXSetDisplayStatisticsHandler(
+#if NeedFunctionPrototypes
+ NXDisplayStatisticsHandler /* handler */,
+ char ** /* buffer */
+#endif
+);
+
+/*
+ * Redefine the function called by Xlib in the case of
+ * an out-of-order sequence number received in the X
+ * protocol stream.
+ */
+
+extern NXLostSequenceHandler NXSetLostSequenceHandler(
+#if NeedFunctionPrototypes
+ NXLostSequenceHandler /* handler */
+#endif
+);
+
+/*
+ * The agent should get the NX parameters at startup, just after
+ * having opened the display. If the agent is not able to satisfy
+ * the pack method set by user (because a method is not applica-
+ * ble, it is not supported by the remote or it simply requires a
+ * screen depth greater than the depth available), it should fall
+ * back to the nearest method of the same type.
+ */
+
+extern Status NXGetControlParameters(
+#if NeedFunctionPrototypes
+ Display* /* display */,
+ unsigned int* /* link_type */,
+ unsigned int* /* local_major */,
+ unsigned int* /* local_minor */,
+ unsigned int* /* local_patch */,
+ unsigned int* /* remote_major */,
+ unsigned int* /* remote_minor */,
+ unsigned int* /* remote_patch */,
+ int* /* frame_timeout */,
+ int* /* ping_timeout */,
+ int* /* split_mode */,
+ int* /* split_size */,
+ unsigned int* /* pack_method */,
+ unsigned int* /* pack_quality */,
+ int* /* data_level */,
+ int* /* stream_level */,
+ int* /* delta_level */,
+ unsigned int* /* load_cache */,
+ unsigned int* /* save_cache */,
+ unsigned int* /* startup_cache */
+#endif
+);
+
+/*
+ * Which unpack methods are supported by the remote proxy?
+ */
+
+extern Status NXGetUnpackParameters(
+#if NeedFunctionPrototypes
+ Display* /* display */,
+ unsigned int* /* entries */,
+ unsigned char[] /* supported_methods */
+#endif
+);
+
+/*
+ * Query and enable shared memory support on path agent to X
+ * client proxy and X server proxy to real X server. At the
+ * moment only the path proxy to real X server is implemented.
+ * On return flags will say if support has been successfully
+ * activated. Segments will contain the XID associated to the
+ * shared memory blocks. A MIT-SHM compliant protocol is used
+ * between proxy and the real server, while a simplified
+ * version is used between the agent and the client proxy to
+ * accomodate both packed images and plain X bitmaps.
+ */
+
+extern Status NXGetShmemParameters(
+#if NeedFunctionPrototypes
+ Display* /* display */,
+ unsigned int* /* enable_client */,
+ unsigned int* /* enable_server */,
+ unsigned int* /* client_segment */,
+ unsigned int* /* server_segment */,
+ unsigned int* /* client_size */,
+ unsigned int* /* server_size */
+#endif
+);
+
+/*
+ * Get the path to the font server that can be used by the X
+ * server to tunnel the font connections across the NX link.
+ * The path actually represents the TCP port where the proxy
+ * on the NX client side is listening. The agent can tempora-
+ * rily enable the tunneling when it needs a font that is not
+ * available on the client, for example when the session is
+ * migrated from a different X server.
+ */
+
+extern Status NXGetFontParameters(
+#if NeedFunctionPrototypes
+ Display* /* display */,
+ unsigned int /* path_length */,
+ char[] /* path_data */
+#endif
+);
+
+/*
+ * This set of functions is used to leverage the image stream-
+ * ing capabilities built in nxcomp. An image can be streamed
+ * by sending a start-split message, followed by the X messages
+ * that will have to be split by the proxy, followed by an end-
+ * split closure. Usually, in the middle of a start-split/end-
+ * split sequence there will be a single PutImage() or PutPack-
+ * edImage(), that, in turn, can generate multiple partial
+ * requests, like a SetUnpackColormap() and SetUnpackAlpha()
+ * that will be later used to decompress the image to its ori-
+ * ginal form. Multiple requests may be also generated because
+ * of the maximum size of a X request being exceeded, so that
+ * Xlib has to divide the single image in multiple sub-image re-
+ * quests. The agent doesn't need to take care of these details
+ * but will rather have to track the result of the split opera-
+ * tion. By monitoring the notify events sent by the proxy, the
+ * agent will have to implement its own strategy to deal with
+ * the resources. For example, it will be able to:
+ *
+ * - Mark a drawable as dirty, if the image was not sent
+ * synchronously, in the main X oputput stream.
+ *
+ * - Choose to commit or discard the original image, at the
+ * time it will be recomposed at the remote side. This may
+ * include all the messages that were part of the split
+ * (the colormap, the alpha channel, etc.)
+ *
+ * - Mark the drawable as clean again, if the image was
+ * committed and the drawable didn't change in the mean-
+ * while.
+ *
+ * At the time the proxy receives the end-split, it reports the
+ * result of the operation to the agent. The agent will be able
+ * to identify the original split operation (the one referenced
+ * in the start-split/end-split sequence) by the small integer
+ * number (0-255) named 'resource' sent in the events.
+ *
+ * One of the following cases may be encountered:
+ *
+ *
+ * NXNoSplitNotify All messages were sent in the main out-
+ * put stream, so that no split actually
+ * took place.
+ *
+ * NXStartSplitNotify One or more messages were split, so,
+ * at discrection of the agent, the client
+ * may be suspended until the transferral
+ * is completed.
+ *
+ * NXCommitSplitNotify One of the requests that made up the
+ * split was recomposed. The agent should
+ * either commit the given request or tell
+ * the proxy to discard it.
+ *
+ * NXEndSplitNotify The split was duly completed. The agent
+ * can restart the client.
+ *
+ * NXEmptySplitNotify No more split operation are pending.
+ * The agent can use this information to
+ * implement specific strategies requiring
+ * that all messages have been recomposed
+ * at the remote end, like updating the
+ * drawables that were not synchronized
+ * because of the lazy encoding.
+ *
+ * The 'mode' field that is sent by the agent in the start-split
+ * request, determines the strategy that the proxy will adopt to
+ * deal with the image. If set to 'eager', the proxy will only
+ * split the messages whose size exceeds the split threshold (the
+ * current threshold can be found in the NXGetControlParameters()
+ * reply). If the mode is set to lazy, the proxy will split any
+ * image that would have generated an actual transfer of the data
+ * part (in practice all images that are not found in the cache).
+ * This second strategy can be leveraged by an agent to further
+ * reduce the bandwidth requirements. For example, by setting the
+ * mode to lazy and by monitoring the result, an agent can easi-
+ * ly verify if the drawable was successfully updated, mark the
+ * drawable if not, and synchronize it at later time.
+ *
+ * See NXproto.h for the definition of the available modes.
+ */
+
+extern unsigned int NXAllocSplit(
+#if NeedFunctionPrototypes
+ Display* /* display */,
+ unsigned int /* resource */
+#endif
+);
+
+extern int NXStartSplit(
+#if NeedFunctionPrototypes
+ Display* /* display */,
+ unsigned int /* resource */,
+ unsigned int /* mode */
+#endif
+);
+
+extern int NXEndSplit(
+#if NeedFunctionPrototypes
+ Display* /* display */,
+ unsigned int /* resource */
+#endif
+);
+
+extern int NXCommitSplit(
+#if NeedFunctionPrototypes
+ Display* /* display */,
+ unsigned int /* resource */,
+ unsigned int /* propagate */,
+ unsigned char /* request */,
+ unsigned int /* position */
+#endif
+);
+
+extern int NXAbortSplit(
+#if NeedFunctionPrototypes
+ Display* /* display */,
+ unsigned int /* resource */
+#endif
+);
+
+extern int NXFinishSplit(
+#if NeedFunctionPrototypes
+ Display* /* display */,
+ unsigned int /* resource */
+#endif
+);
+
+extern int NXFreeSplit(
+#if NeedFunctionPrototypes
+ Display* /* display */,
+ unsigned int /* resource */
+#endif
+);
+
+extern int NXSetExposeParameters(
+#if NeedFunctionPrototypes
+ Display* /* display */,
+ int /* expose */,
+ int /* graphics_expose */,
+ int /* no_expose */
+#endif
+);
+
+extern int NXSetCacheParameters(
+#if NeedFunctionPrototypes
+ Display* /* display */,
+ int /* enable_cache */,
+ int /* enable_split */,
+ int /* enable_save */,
+ int /* enable_load */
+#endif
+);
+
+extern unsigned int NXAllocUnpack(
+#if NeedFunctionPrototypes
+ Display* /* display */,
+ unsigned int /* resource */
+#endif
+);
+
+extern int NXSetUnpackGeometry(
+#if NeedFunctionPrototypes
+ Display* /* display */,
+ unsigned int /* resource */,
+ Visual* /* visual */
+#endif
+);
+
+extern int NXSetUnpackColormap(
+#if NeedFunctionPrototypes
+ Display* /* display */,
+ unsigned int /* resource */,
+ unsigned int /* method */,
+ unsigned int /* entries */,
+ const char* /* data */,
+ unsigned int /* data_length */
+#endif
+);
+
+extern int NXSetUnpackAlpha(
+#if NeedFunctionPrototypes
+ Display* /* display */,
+ unsigned int /* resource */,
+ unsigned int /* method */,
+ unsigned int /* entries */,
+ const char* /* data */,
+ unsigned int /* data_length */
+#endif
+);
+
+extern int NXSetUnpackColormapCompat(
+#if NeedFunctionPrototypes
+ Display* /* display */,
+ unsigned int /* resource */,
+ unsigned int /* entries */,
+ const char* /* data */
+#endif
+);
+
+extern int NXSetUnpackAlphaCompat(
+#if NeedFunctionPrototypes
+ Display* /* display */,
+ unsigned int /* resource */,
+ unsigned int /* entries */,
+ const char* /* data */
+#endif
+);
+
+extern int NXFreeUnpack(
+#if NeedFunctionPrototypes
+ Display* /* display */,
+ unsigned int /* resource */
+#endif
+);
+
+/*
+ * A packed image is a XImage but with
+ * offset field containing total amount
+ * of packed image data.
+ */
+
+typedef XImage NXPackedImage;
+
+NXPackedImage *NXCreatePackedImage(
+#if NeedFunctionPrototypes
+ Display* /* display */,
+ Visual* /* visual */,
+ unsigned int /* method */,
+ unsigned int /* depth */,
+ int /* format */,
+ char* /* data */,
+ int /* data_length */,
+ unsigned int /* width */,
+ unsigned int /* height */,
+ int /* bitmap_pad */,
+ int /* bytes_per_line */
+#endif
+);
+
+extern int NXDestroyPackedImage(
+#if NeedFunctionPrototypes
+ NXPackedImage* /* image */
+#endif
+);
+
+NXPackedImage *NXPackImage(
+#if NeedFunctionPrototypes
+ Display* /* display */,
+ XImage* /* src_image */,
+ unsigned int /* method */
+#endif
+);
+
+NXPackedImage *NXInPlacePackImage(
+#if NeedFunctionPrototypes
+ Display* /* display */,
+ XImage* /* src_image */,
+ unsigned int /* method */
+#endif
+);
+
+/*
+ * GC is declared void * to get rid of mess
+ * with different GC definitions in some X
+ * server code (like in nxagent).
+ */
+
+extern int NXPutPackedImage(
+#if NeedFunctionPrototypes
+ Display* /* display */,
+ unsigned int /* resource */,
+ Drawable /* drawable */,
+ void* /* gc */,
+ NXPackedImage* /* image */,
+ unsigned int /* method */,
+ unsigned int /* depth */,
+ int /* src_x */,
+ int /* src_y */,
+ int /* dst_x */,
+ int /* dst_y */,
+ unsigned int /* width */,
+ unsigned int /* height */
+#endif
+);
+
+/*
+ * Get multiple colors with a single call by
+ * pipelining X_AllocColor requests/replies.
+ */
+
+extern int NXAllocColors(
+#if NeedFunctionPrototypes
+ Display* /* display */,
+ Colormap /* colormap */,
+ unsigned int /* entries */,
+ XColor[] /* screens_in_out */,
+ Bool [] /* flags allocation errors */
+#endif
+);
+
+/*
+ * Encode the data in the given format.
+ */
+
+extern char *NXEncodeColormap(
+#if NeedFunctionPrototypes
+ const char* /* src_data */,
+ unsigned int /* src_size */,
+ unsigned int* /* dst_size */
+#endif
+);
+
+extern char *NXEncodeAlpha(
+#if NeedFunctionPrototypes
+ const char* /* src_data */,
+ unsigned int /* src_size */,
+ unsigned int* /* dst_size */
+#endif
+);
+
+extern NXPackedImage *NXEncodeRgb(
+#if NeedFunctionPrototypes
+ XImage* /* src_image */,
+ unsigned int /* method */,
+ unsigned int /* quality */
+#endif
+);
+
+extern NXPackedImage *NXEncodeRle(
+#if NeedFunctionPrototypes
+ XImage* /* src_image */,
+ unsigned int /* method */,
+ unsigned int /* quality */
+#endif
+);
+
+extern NXPackedImage *NXEncodeJpeg(
+#if NeedFunctionPrototypes
+ XImage* /* src_image */,
+ unsigned int /* method */,
+ unsigned int /* quality */
+#endif
+);
+
+typedef struct
+{
+ long pixel;
+ int found;
+
+} NXColorTable;
+
+extern int NXEncodeColors(
+#if NeedFunctionPrototypes
+ XImage* /* src_image */,
+ NXColorTable* /* color_table */,
+ int /* nb_max */
+#endif
+);
+
+extern NXPackedImage *NXEncodePng(
+#if NeedFunctionPrototypes
+ XImage* /* src_image */,
+ unsigned int /* method */,
+ unsigned int /* quality */
+#endif
+);
+
+extern NXPackedImage *NXEncodeBitmap(
+#if NeedFunctionPrototypes
+ XImage* /* src_image */,
+ unsigned int /* method */,
+ unsigned int /* quality */
+#endif
+);
+
+extern int NXCleanImage(
+#if NeedFunctionPrototypes
+ XImage*
+#endif
+);
+
+extern void NXMaskImage(
+#if NeedFunctionPrototypes
+ XImage* /* pointer to image to mask */ ,
+ unsigned int /* method */
+#endif
+);
+
+extern int NXImageCacheSize;
+
+extern void NXInitCache(
+#if NeedFunctionPrototypes
+ Display* /* display */,
+ int /* entries in image cache */
+#endif
+);
+
+extern void NXFreeCache(
+#if NeedFunctionPrototypes
+ Display* /* display */
+#endif
+);
+
+extern XImage *NXCacheFindImage(
+#if NeedFunctionPrototypes
+ NXPackedImage* /* packed image to find */,
+ unsigned int* /* pointer to the pack method if found */,
+ unsigned char** /* pointer to the calculated MD5 if found */
+#endif
+);
+
+extern int NXCacheAddImage(
+#if NeedFunctionPrototypes
+ NXPackedImage* /* packed image to be added to the cache */,
+ unsigned int /* pack method of the image to add */,
+ unsigned char* /* pointer to MD5 of the original unpacked image */
+#endif
+);
+
+
+extern int NXGetCollectImageResource(
+#if NeedFunctionPrototypes
+ Display* /* display */
+#endif
+);
+
+extern int NXCollectImage(
+#if NeedFunctionPrototypes
+ Display* /* display */,
+ unsigned int /* resource */,
+ Drawable /* drawable */,
+ int /* src_x */,
+ int /* src_y */,
+ unsigned int /* width */,
+ unsigned int /* height */,
+ unsigned long /* plane_mask */,
+ int /* format */
+#endif
+);
+
+extern int NXGetCollectedImage(
+#if NeedFunctionPrototypes
+ Display* /* display */,
+ unsigned int /* resource */,
+ XImage** /* image */
+#endif
+);
+
+extern int NXGetCollectPropertyResource(
+#if NeedFunctionPrototypes
+ Display* /* display */
+#endif
+);
+
+extern int NXCollectProperty(
+#if NeedFunctionPrototypes
+ Display* /* display */,
+ unsigned int /* resource */,
+ Window /* window */,
+ Atom /* property */,
+ long /* long_offset */,
+ long /* long_length */,
+ Bool /* delete */,
+ Atom /* req_type */
+#endif
+);
+
+extern int NXGetCollectedProperty(
+#if NeedFunctionPrototypes
+ Display* /* display */,
+ unsigned int /* resource */,
+ Atom* /* actual_type_return */,
+ int* /* actual_format_return */,
+ unsigned long* /* nitems_return */,
+ unsigned long* /* bytes_after_return */,
+ unsigned char** /* data */
+#endif
+);
+
+extern int NXGetCollectGrabPointerResource(
+#if NeedFunctionPrototypes
+ Display* /* display */
+#endif
+);
+
+extern int NXCollectGrabPointer(
+#if NeedFunctionPrototypes
+ Display* /* display */,
+ unsigned int /* resource */,
+ Window /* grab_window */,
+ Bool /* owner_events */,
+ unsigned int /* event_mask */,
+ int /* pointer_mode */,
+ int /* keyboard_mode */,
+ Window /* confine_to */,
+ Cursor /* cursor */,
+ Time /* time */
+#endif
+);
+
+extern int NXGetCollectedGrabPointer(
+#if NeedFunctionPrototypes
+ Display* /* display */,
+ unsigned int /* resource */,
+ int* /* status */
+#endif
+);
+
+extern int NXGetCollectInputFocusResource(
+#if NeedFunctionPrototypes
+ Display* /* display */
+#endif
+);
+
+extern int NXCollectInputFocus(
+#if NeedFunctionPrototypes
+ Display* /* display */,
+ unsigned int /* resource */
+#endif
+);
+
+extern int NXGetCollectedInputFocus(
+#if NeedFunctionPrototypes
+ Display* /* display */,
+ unsigned int /* resource */,
+ Window* /* focus_return */,
+ int* /* revert_to_return */
+#endif
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* NXlib_H */
diff --git a/nx-X11/programs/Xserver/hw/nxagent/compext/Imakefile b/nx-X11/programs/Xserver/hw/nxagent/compext/Imakefile
new file mode 100644
index 000000000..8f0f17d1e
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/compext/Imakefile
@@ -0,0 +1,48 @@
+NULL =
+
+#include <Server.tmpl>
+
+SRCS = \
+ Alpha.c \
+ Bitmap.c \
+ Clean.c \
+ Colormap.c \
+ Compext.c \
+ Jpeg.c \
+ Mask.c \
+ Png.c \
+ Rgb.c \
+ Rle.c \
+ Z.c \
+ $(NULL)
+
+OBJS = \
+ Alpha.o \
+ Bitmap.o \
+ Clean.o \
+ Colormap.o \
+ Compext.o \
+ Jpeg.o \
+ Mask.o \
+ Png.o \
+ Rgb.o \
+ Rle.o \
+ Z.o \
+ $(NULL)
+
+ INCLUDES = -I$(SERVERSRC)/include \
+ -I$(XBUILDINCDIR) \
+ `pkg-config --cflags-only-I pixman-1` \
+ `pkg-config --cflags-only-I zlib` \
+ `pkg-config --cflags-only-I libpng` \
+ $(NULL)
+
+ LINTLIBS = $(SERVERSRC)/dix/llib-ldix.ln \
+ $(NULL)
+
+NormalLibraryObjectRule()
+NormalLibraryTarget(compext,$(OBJS))
+LintLibraryTarget(compext,$(SRCS))
+NormalLintTarget($(SRCS))
+
+DependTarget()
diff --git a/nx-X11/programs/Xserver/hw/nxagent/compext/Jpeg.c b/nx-X11/programs/Xserver/hw/nxagent/compext/Jpeg.c
new file mode 100644
index 000000000..690a934f6
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/compext/Jpeg.c
@@ -0,0 +1,480 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXCOMPEXT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <nx-X11/X.h>
+#include <nx-X11/Xlib.h>
+#include <nx-X11/Xmd.h>
+
+#include <jpeglib.h>
+
+#include "Compext.h"
+
+#include "Mask.h"
+#include "Jpeg.h"
+
+#define PANIC
+#define WARNING
+#undef TEST
+#undef DEBUG
+
+#define JPEG_DEST_SIZE(width, height) ((width) * 3 * (height) + 1024)
+
+/*
+ * Local function prototypes.
+ */
+
+static void PrepareRowForJpeg(CARD8 *dst, int y, int count);
+static void PrepareRowForJpeg24(CARD8 *dst, int y, int count);
+static void PrepareRowForJpeg16(CARD8 *dst, int y, int count);
+static void PrepareRowForJpeg32(CARD8 *dst, int y, int count);
+
+static int JpegEmptyOutputBuffer(j_compress_ptr cinfo);
+
+static void JpegInitDestination(j_compress_ptr cinfo);
+static void JpegTermDestination(j_compress_ptr cinfo);
+static void JpegSetDstManager(j_compress_ptr cinfo);
+
+/*
+ * Quality levels.
+ */
+
+static int jpegQuality[10] = {20, 30, 40, 50, 55, 60, 65, 70, 75, 80};
+
+/*
+ * Image characteristics.
+ */
+
+static int bytesPerLine;
+
+static CARD8 bitsPerPixel;
+static CARD16 redMax, greenMax, blueMax;
+static CARD8 redShift, greenShift, blueShift;
+static int byteOrder;
+
+/*
+ * Other variables used for the Jpeg
+ * encoding.
+ */
+
+static char *jpegBeforeBuf = NULL;
+static char *jpegCompBuf;
+static int jpegCompBufSize;
+static int jpegError;
+static int jpegDstDataLen;
+
+static struct jpeg_destination_mgr jpegDstManager;
+
+/*
+ * Just for debugging purpose.
+ */
+
+#ifdef DEBUG
+
+static int jpegId;
+static char jpegName[10];
+static FILE *jpegFile;
+
+#endif
+
+/*
+ * Function declarations
+ */
+
+char *JpegCompressData(XImage *image, int level, int *compressed_size)
+{
+ struct jpeg_compress_struct cinfo;
+ struct jpeg_error_mgr jerr;
+
+ CARD8 *srcBuf;
+ JSAMPROW rowPointer[1];
+
+ int dy, w, h;
+
+ *compressed_size = 0;
+
+ /*
+ * Initialize the image stuff
+ */
+
+ bitsPerPixel = image -> bits_per_pixel;
+ bytesPerLine = image -> bytes_per_line;
+ byteOrder = image -> byte_order;
+
+ #ifdef TEST
+ fprintf(stderr, "******JpegCompressData: Image byte order [%d] bitmap bit order [%d].\n",
+ image -> byte_order, image -> bitmap_bit_order);
+
+ fprintf(stderr, "******JpegCompressData: Bits per pixel [%d] bytes per line [%d].\n",
+ bitsPerPixel, bytesPerLine);
+ #endif
+
+ redShift = FindLSB(image -> red_mask) - 1;
+ greenShift = FindLSB(image -> green_mask) - 1;
+ blueShift = FindLSB(image -> blue_mask) - 1;
+
+ #ifdef TEST
+ fprintf(stderr, "******JpegCompressData: Red mask [0x%lx] green mask [0x%lx] blue mask [0x%lx].\n",
+ image -> red_mask, image -> green_mask, image -> blue_mask);
+
+ fprintf(stderr, "******JpegCompressData: Red shift [%d] green shift [%d] blue shift [%d].\n",
+ redShift, greenShift, blueShift);
+ #endif
+
+ redMax = image -> red_mask >> redShift;
+ greenMax = image -> green_mask >> greenShift;
+ blueMax = image -> blue_mask >> blueShift;
+
+ #ifdef TEST
+ fprintf(stderr, "******JpegCompressData: Red max [0x%x] green max [0x%x] blue max [0x%x].\n",
+ redMax, greenMax, blueMax);
+ #endif
+
+ w = image -> width;
+ h = image -> height;
+
+ jpegBeforeBuf = image -> data;
+
+ #ifdef DEBUG
+ fprintf(stderr, "******JpegCompressData: Width [%d] height [%d] level [%d].\n",
+ w, h, level);
+ #endif
+
+ if (bitsPerPixel == 1 ||
+ bitsPerPixel == 8)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******JpegCompressData: PANIC! Invalid bits per pixel [%d].\n",
+ bitsPerPixel);
+ #endif
+
+ return NULL;
+ }
+
+ /*
+ * Allocate space for one line of the
+ * resulting image, 3 bytes per pixel.
+ */
+
+ #ifdef DEBUG
+ fprintf(stderr, "******JpegCompressData: Allocating [%d] bytes for the scanline.\n",
+ w * 3);
+ #endif
+
+ srcBuf = (CARD8 *) malloc(w * 3);
+
+ if (srcBuf == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******JpegCompressData: PANIC! Cannot allocate [%d] bytes.\n",
+ w * 3);
+ #endif
+
+ return NULL;
+ }
+
+ rowPointer[0] = srcBuf;
+
+ cinfo.err = jpeg_std_error(&jerr);
+
+ jpeg_create_compress(&cinfo);
+
+ cinfo.image_width = w;
+ cinfo.image_height = h;
+ cinfo.input_components = 3;
+ cinfo.in_color_space = JCS_RGB;
+
+ jpeg_set_defaults(&cinfo);
+ jpeg_set_quality(&cinfo, jpegQuality[level], 1);
+
+ /*
+ * Allocate memory for the destination
+ * buffer.
+ */
+
+ jpegCompBufSize = JPEG_DEST_SIZE(w, h);
+
+ #ifdef TEST
+ fprintf(stderr, "******JpegCompressData: Allocating [%d] bytes for the destination data.\n",
+ jpegCompBufSize);
+ #endif
+
+ jpegCompBuf = malloc(jpegCompBufSize);
+
+ if (jpegCompBuf == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******JpegCompressData: PANIC! Error allocating [%d] bytes for the Jpeg data.\n",
+ jpegCompBufSize);
+ #endif
+
+ return NULL;
+ }
+
+ JpegSetDstManager(&cinfo);
+
+ jpeg_start_compress(&cinfo, 1);
+
+ #ifdef DEBUG
+ fprintf(stderr, "******JpegCompressedData: Initialization finished.\n");
+ #endif
+
+ for (dy = 0; dy < h; dy++)
+ {
+ PrepareRowForJpeg(srcBuf, dy, w);
+
+ jpeg_write_scanlines(&cinfo, rowPointer, 1);
+
+ if (jpegError != 0)
+ {
+ break;
+ }
+ }
+
+ #ifdef DEBUG
+ fprintf(stderr, "******JpegCompressedData: Compression finished. Lines handled [%d,%d]. Error is [%d].\n",
+ dy, h, jpegError);
+ #endif
+
+ if (jpegError == 0)
+ {
+ jpeg_finish_compress(&cinfo);
+ }
+
+ jpeg_destroy_compress(&cinfo);
+
+ free((char *) srcBuf);
+
+ if (jpegError != 0)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******JpegCompressedData: PANIC! Compression failed. Error is [%d].\n",
+ jpegError);
+ #endif
+
+ free(jpegCompBuf);
+
+ return NULL;
+ }
+
+ /*
+ * Check the size of the resulting data.
+ */
+
+ if (jpegDstDataLen > 0)
+ {
+ /*
+ * Save the image on disk to help with
+ * the debug.
+ */
+
+ #ifdef DEBUG
+
+ int i = 0;
+
+ fprintf(stderr, "******JpegCompressedData: Compressed size [%d].\n",
+ jpegDstDataLen);
+
+ jpegId++;
+
+ sprintf(jpegName, "jpeg%d", jpegId);
+
+ jpegFile = fopen(jpegName, "w");
+
+ for (i = 0; i < jpegDstDataLen; i++)
+ {
+ fprintf(jpegFile, "%c", *(jpegCompBuf + i));
+ }
+
+ fclose(jpegFile);
+
+ #endif
+
+ *compressed_size = jpegDstDataLen;
+
+ return jpegCompBuf;
+ }
+ else
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******JpegCompressedData: PANIC! Invalid size of the compressed data [%d].\n",
+ jpegDstDataLen);
+ #endif
+
+ free(jpegCompBuf);
+
+ return NULL;
+ }
+}
+
+void PrepareRowForJpeg(CARD8 *dst, int y, int count)
+{
+ if (bitsPerPixel == 32)
+ {
+ if (redMax == 0xff &&
+ greenMax == 0xff &&
+ blueMax == 0xff)
+ {
+ PrepareRowForJpeg24(dst, y, count);
+ }
+ else
+ {
+ PrepareRowForJpeg32(dst, y, count);
+ }
+ }
+ else if (bitsPerPixel == 24)
+ {
+ memcpy(dst, jpegBeforeBuf + y * bytesPerLine, count * 3);
+ }
+ else
+ {
+ /*
+ * 16 bpp assumed.
+ */
+
+ PrepareRowForJpeg16(dst, y, count);
+ }
+}
+
+void PrepareRowForJpeg24(CARD8 *dst, int y, int count)
+{
+ CARD8 *fbptr;
+ CARD32 pix;
+
+ fbptr = (CARD8 *) (jpegBeforeBuf + y * bytesPerLine);
+
+ while (count--)
+ {
+ if (byteOrder == LSBFirst)
+ {
+ pix = (CARD32) *(fbptr + 2);
+ pix = (pix << 8) | (CARD32) *(fbptr+1);
+ pix = (pix << 8) | (CARD32) *fbptr;
+ }
+ else
+ {
+ pix = (CARD32) *(fbptr + 1);
+ pix = (pix << 8) | (CARD32) *(fbptr + 2);
+ pix = (pix << 8) | (CARD32) *(fbptr + 3);
+ }
+
+ *dst++ = (CARD8)(pix >> redShift);
+ *dst++ = (CARD8)(pix >> greenShift);
+ *dst++ = (CARD8)(pix >> blueShift);
+
+ fbptr+=4;
+ }
+}
+
+#define DEFINE_JPEG_GET_ROW_FUNCTION(bpp) \
+ \
+void PrepareRowForJpeg##bpp(CARD8 *dst, int y, int count) \
+{ \
+ CARD8 *fbptr; \
+ CARD##bpp pix; \
+ int inRed, inGreen, inBlue; \
+ int i; \
+ \
+ fbptr = (CARD8 *) (jpegBeforeBuf + y * bytesPerLine); \
+ \
+ while (count--) \
+ { \
+ pix = 0; \
+ \
+ if (byteOrder == LSBFirst) \
+ { \
+ for (i = (bpp >> 3) - 1; i >= 0; i--) \
+ { \
+ pix = (pix << 8) | (CARD32) *(fbptr + i); \
+ } \
+ } \
+ else \
+ { \
+ for (i = 0; i < (bpp >> 3); i++) \
+ { \
+ pix = (pix << 8) | (CARD32) *(fbptr + i); \
+ } \
+ } \
+ \
+ fbptr += bpp >> 3; \
+ \
+ inRed = (int) \
+ (pix >> redShift & redMax); \
+ inGreen = (int) \
+ (pix >> greenShift & greenMax); \
+ inBlue = (int) \
+ (pix >> blueShift & blueMax); \
+ \
+ *dst++ = (CARD8)((inRed * 255 + redMax / 2) / \
+ redMax); \
+ *dst++ = (CARD8)((inGreen * 255 + greenMax / 2) / \
+ greenMax); \
+ *dst++ = (CARD8)((inBlue * 255 + blueMax / 2) / \
+ blueMax); \
+ } \
+}
+
+DEFINE_JPEG_GET_ROW_FUNCTION(16)
+DEFINE_JPEG_GET_ROW_FUNCTION(32)
+
+/*
+ * Destination manager implementation for JPEG library.
+ */
+
+void JpegInitDestination(j_compress_ptr cinfo)
+{
+ jpegError = 0;
+
+ jpegDstManager.next_output_byte = (JOCTET *) jpegCompBuf;
+ jpegDstManager.free_in_buffer = (size_t) jpegCompBufSize;
+}
+
+int JpegEmptyOutputBuffer(j_compress_ptr cinfo)
+{
+ jpegError = 1;
+
+ jpegDstManager.next_output_byte = (JOCTET *) jpegCompBuf;
+ jpegDstManager.free_in_buffer = (size_t) jpegCompBufSize;
+
+ return 1;
+}
+
+void JpegTermDestination(j_compress_ptr cinfo)
+{
+ jpegDstDataLen = jpegCompBufSize - jpegDstManager.free_in_buffer;
+}
+
+void JpegSetDstManager(j_compress_ptr cinfo)
+{
+ jpegDstManager.init_destination = JpegInitDestination;
+ jpegDstManager.empty_output_buffer = JpegEmptyOutputBuffer;
+ jpegDstManager.term_destination = JpegTermDestination;
+
+ cinfo -> dest = &jpegDstManager;
+}
+
diff --git a/nx-X11/programs/Xserver/hw/nxagent/compext/Jpeg.h b/nx-X11/programs/Xserver/hw/nxagent/compext/Jpeg.h
new file mode 100644
index 000000000..b50efd3ec
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/compext/Jpeg.h
@@ -0,0 +1,46 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXCOMPEXT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#ifndef Jpeg_H
+#define Jpeg_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern char *JpegCompressData(
+#if NeedFunctionPrototypes
+ XImage* /* image */,
+ int /* level */,
+ int* /* compressed_size */
+#endif
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* Jpeg_H */
+
diff --git a/nx-X11/programs/Xserver/hw/nxagent/compext/Mask.c b/nx-X11/programs/Xserver/hw/nxagent/compext/Mask.c
new file mode 100644
index 000000000..cdcb8d3c0
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/compext/Mask.c
@@ -0,0 +1,802 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXCOMPEXT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#include <stdio.h>
+
+#include <nx-X11/Xlib.h>
+
+#include <nx/NXpack.h>
+
+#include "Mask.h"
+
+#define PANIC
+#define WARNING
+#undef TEST
+#undef DEBUG
+
+/*
+ * Try first to reduce to a white or black
+ * pixel. If not possible, apply the mask.
+ * Note that correction is applied at the
+ * time pixel is unpacked.
+ */
+
+#define MaskPixel(red, green, blue, mask) \
+\
+if (red > mask -> white_threshold && \
+ green > mask -> white_threshold && \
+ blue > mask -> white_threshold) \
+{ \
+ red = green = blue = 0xff; \
+} \
+else if (red < mask -> black_threshold && \
+ green < mask -> black_threshold && \
+ blue < mask -> black_threshold) \
+{ \
+ red = green = blue = 0x00; \
+} \
+else \
+{ \
+ red = red & mask -> color_mask; \
+ green = green & mask -> color_mask; \
+ blue = blue & mask -> color_mask; \
+}
+
+int MaskImage(const ColorMask *mask, XImage *src_image, XImage *dst_image)
+{
+ unsigned long pixel;
+
+ register unsigned int red;
+ register unsigned int green;
+ register unsigned int blue;
+
+ register unsigned long data_size;
+
+ register unsigned int i;
+
+ data_size = (src_image -> bytes_per_line * src_image -> height) >> 2;
+
+ #ifdef TEST
+ fprintf(stderr, "******MaskImage: Going to mask image with [%d] bits per pixel.\n",
+ src_image -> bits_per_pixel);
+ #endif
+
+ if (src_image -> bits_per_pixel == 24 || src_image -> bits_per_pixel == 32)
+ {
+ register unsigned char *pixel_addr;
+
+ for (i = 0; i < data_size; i++)
+ {
+ pixel = ((unsigned long *) src_image -> data)[i];
+
+ pixel_addr = (unsigned char *) &pixel;
+
+ red = pixel_addr[2];
+ green = pixel_addr[1];
+ blue = pixel_addr[0];
+
+ #ifdef DEBUG
+ fprintf(stderr, "******MaskImage: 24/32 bits original R [%d] G [%d] B [%d] A [%d].\n",
+ red, green, blue, pixel_addr[3]);
+ #endif
+
+ MaskPixel(red, green, blue, mask);
+
+ #ifdef DEBUG
+ fprintf(stderr, "******MaskImage: 24/32 bits masked R [%d] G [%d] B [%d] A [%d].\n",
+ red, green, blue, pixel_addr[3]);
+ #endif
+
+ #ifdef DEBUG
+ fprintf(stderr, "******MaskImage: 24/32 bits pixel 0x%lx", pixel);
+ #endif
+
+ pixel_addr[2] = red;
+ pixel_addr[1] = green;
+ pixel_addr[0] = blue;
+
+ ((unsigned long*)dst_image -> data)[i] = pixel;
+
+ #ifdef DEBUG
+ fprintf(stderr, " -> 0x%lx\n", pixel);
+ #endif
+ }
+
+ return 1;
+ }
+ else if (src_image -> bits_per_pixel == 16)
+ {
+ /*
+ * FIXME: Masking doesn't work in 16 bpp.
+ *
+
+ unsigned long src_addr, *dst_addr;
+ unsigned short *src_pixels_addr, *dst_pixels_addr;
+
+ for (i = 0; i < data_size; i++)
+ {
+ src_addr = ((unsigned long *)src_image -> data)[i];
+ dst_addr = (unsigned long *)((unsigned long *)dst_image -> data + i);
+
+ src_pixels_addr = ((unsigned short *) &src_addr);
+ dst_pixels_addr = ((unsigned short *) dst_addr);
+
+ red = (src_pixels_addr[0] & src_image -> red_mask) >> 8;
+ green = (src_pixels_addr[0] & src_image -> green_mask) >> 3;
+ blue = (src_pixels_addr[0] & src_image -> blue_mask) << 3;
+
+ #ifdef DEBUG
+ fprintf(stderr, "******MaskImage: 16 bits original R [%d] G [%d] B [%d].\n",
+ red, green, blue);
+ #endif
+
+ MaskPixel(red, green, blue, mask);
+
+ #ifdef DEBUG
+ fprintf(stderr, "******MaskImage: 16 bits masked R [%d] G [%d] B [%d].\n",
+ red, green, blue);
+ #endif
+
+ dst_pixels_addr[0] = ((red << 8) & src_image -> red_mask) |
+ ((green << 3) & src_image -> green_mask) |
+ ((blue >> 3) & src_image -> blue_mask);
+
+ #ifdef DEBUG
+ fprintf(stderr, "******MaskImage: 16 bits pixel 0x%x", dst_pixels_addr[0]);
+ #endif
+
+ red = (src_pixels_addr[1] & src_image -> red_mask) >> 8;
+ green = (src_pixels_addr[1] & src_image -> green_mask) >> 3;
+ blue = (src_pixels_addr[1] & src_image -> blue_mask) << 3;
+
+ #ifdef DEBUG
+ fprintf(stderr, "******MaskImage: 16 bits original R [%d] G [%d] B [%d].\n",
+ red, green, blue);
+ #endif
+
+ MaskPixel(red, green, blue, mask);
+
+ #ifdef DEBUG
+ fprintf(stderr, "******MaskImage: 16 bits masked R [%d] G [%d] B [%d].\n",
+ red, green, blue);
+ #endif
+
+ dst_pixels_addr[1] = ((red << 8) & src_image -> red_mask) |
+ ((green << 3) & src_image -> green_mask) |
+ ((blue >> 3) & src_image -> blue_mask);
+
+ #ifdef DEBUG
+ fprintf(stderr, "******MaskImage: 16 bits pixel 0x%x", dst_pixels_addr[0]);
+ #endif
+ }
+
+ if (dst_image -> width & 0x00000001)
+ {
+ int card32_per_line;
+ int i;
+
+ card32_per_line = dst_image -> bytes_per_line >> 2;
+
+ for (i = 0; i < dst_image -> height;)
+ {
+ ((CARD32 *) dst_image -> data)[(++i * card32_per_line) - 1] &= 0x0000ffff;
+ }
+ }
+
+ *
+ * End of FIXME.
+ */
+ }
+ else
+ {
+ #ifdef TEST
+ fprintf(stderr, "******MaskImage: PANIC! Cannot apply mask with [%d] bits per pixel.\n",
+ src_image -> bits_per_pixel);
+ #endif
+
+ return 0;
+ }
+
+ return 1;
+}
+
+int MaskInPlaceImage(const ColorMask *mask, XImage *image)
+{
+ unsigned long pixel;
+
+ register unsigned int red;
+ register unsigned int green;
+ register unsigned int blue;
+
+ register unsigned int i;
+
+ register unsigned long data_size;
+
+ data_size = (image -> bytes_per_line * image -> height)>>2;
+
+ #ifdef TEST
+ fprintf(stderr, "******MaskInPlaceImage: Going to mask image with [%d] bits per pixel.\n",
+ image -> bits_per_pixel);
+ #endif
+
+ if (image -> bits_per_pixel == 24 || image -> bits_per_pixel == 32)
+ {
+ register unsigned char *pixel_addr;
+
+ for (i = 0; i < data_size; i++)
+ {
+ pixel = ((unsigned long *) image -> data)[i];
+
+ pixel_addr = (unsigned char *) &pixel;
+
+ red = pixel_addr[2];
+ green = pixel_addr[1];
+ blue = pixel_addr[0];
+
+ #ifdef DEBUG
+ fprintf(stderr, "******MaskInPlaceImage: 24/32 bits original R [%d] G [%d] B [%d] A [%d].\n",
+ red, green, blue, pixel_addr[3]);
+ #endif
+
+ MaskPixel(red, green, blue, mask);
+
+ #ifdef DEBUG
+ fprintf(stderr, "******MaskInPlaceImage: 24/32 bits masked R [%d] G [%d] B [%d] A [%d].\n",
+ red, green, blue, pixel_addr[3]);
+ #endif
+
+ #ifdef DEBUG
+ fprintf(stderr, "******MaskInPlaceImage: 24/32 bits pixel 0x%lx", pixel);
+ #endif
+
+ pixel_addr[2] = red;
+ pixel_addr[1] = green;
+ pixel_addr[0] = blue;
+
+ ((unsigned long *) image -> data)[i] = pixel;
+
+ #ifdef DEBUG
+ fprintf(stderr, " -> 0x%lx\n", pixel);
+ #endif
+ }
+
+ return 1;
+ }
+ else if (image -> bits_per_pixel == 16)
+ {
+ /*
+ * FIXME: Mask doesn't still work for 16 bits.
+ *
+
+ unsigned long addr;
+ register unsigned short *pixels_addr;
+
+ for (i = 0; i < data_size; i++)
+ {
+ addr = ((unsigned long *) image -> data)[i];
+
+ pixels_addr = ((unsigned short *) &addr);
+
+ red = (pixels_addr[0] & image -> red_mask) >> 8;
+ green = (pixels_addr[0] & image -> green_mask) >> 3;
+ blue = (pixels_addr[0] & image -> blue_mask) << 3;
+
+ #ifdef DEBUG
+ fprintf(stderr, "******MaskInPlaceImage: 16 bits original R [%d] G [%d] B [%d].\n",
+ red, green, blue);
+ #endif
+
+ MaskPixel(red, green, blue, mask);
+
+ #ifdef DEBUG
+ fprintf(stderr, "******MaskInPlaceImage: 16 bits masked R [%d] G [%d] B [%d].\n",
+ red, green, blue);
+ #endif
+
+ pixels_addr[0] = ((red << 8) & image -> red_mask) |
+ ((green << 3) & image -> green_mask) |
+ ((blue >> 3) & image -> blue_mask);
+
+ #ifdef DEBUG
+ fprintf(stderr, "******MaskInPlaceImage: 16 bits pixel 0x%x", pixels_addr[0]);
+ #endif
+
+ red = (pixels_addr[1] & image -> red_mask) >> 8;
+ green = (pixels_addr[1] & image -> green_mask) >> 3;
+ blue = (pixels_addr[1] & image -> blue_mask) << 3;
+
+ #ifdef DEBUG
+ fprintf(stderr, "******MaskInPlaceImage: 16 bits original R [%d] G [%d] B [%d].\n",
+ red, green, blue);
+ #endif
+
+ MaskPixel(red, green, blue, mask);
+
+ #ifdef DEBUG
+ fprintf(stderr, "******MaskInPlaceImage: 16 bits masked R [%d] G [%d] B [%d].\n",
+ red, green, blue);
+ #endif
+
+ pixels_addr[1] = ((red << 8) & image -> red_mask) |
+ ((green << 3) & image -> green_mask) |
+ ((blue >> 3) & image -> blue_mask);
+
+ #ifdef DEBUG
+ fprintf(stderr, "******MaskInPlaceImage: 16 bits pixel 0x%x", pixels_addr[1]);
+ #endif
+ }
+
+ if (image -> width & 0x00000001)
+ {
+ int card32_per_line;
+ int i;
+
+ card32_per_line = image -> bytes_per_line >> 2;
+
+ for (i = 0; i < image -> height;)
+ {
+ ((CARD32 *) image -> data)[(++i * card32_per_line) - 1] &= 0x0000ffff;
+ }
+ }
+
+ *
+ * End of FIXME.
+ */
+ }
+ else
+ {
+ #ifdef TEST
+ fprintf(stderr, "******MaskImage: PANIC! Cannot apply mask with [%d] bits per pixel.\n",
+ image -> bits_per_pixel);
+ #endif
+
+ return 0;
+ }
+
+ return 1;
+}
+
+static int Pack16To8(unsigned int src_data_size, XImage *src_image, XImage *dst_image)
+{
+ unsigned short *src_pixel = (unsigned short *) src_image -> data;
+ unsigned char *dst_pixel = (unsigned char *) dst_image -> data;
+
+ #ifdef DEBUG
+ unsigned int counter = 0;
+ #endif
+
+ while (src_pixel < ((unsigned short *) (src_image -> data + src_data_size)))
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "******PackImage: Pixel [%d] value [0x%x] red [0x%x] green [0x%x] blue [0x%x].\n",
+ counter, *src_pixel, (*src_pixel & 0xc000) >> 8,
+ ((*src_pixel & 0x600) >> 3), (*src_pixel & 0x18) << 3);
+ #endif
+
+ if (*src_pixel == 0x0)
+ {
+ *dst_pixel = 0x0;
+ }
+ else if (*src_pixel == 0xffff)
+ {
+ *dst_pixel = 0xff;
+ }
+ else
+ {
+ *dst_pixel = ((*src_pixel & 0xc000) >> 10) |
+ ((*src_pixel & 0x600) >> 7) |
+ ((*src_pixel & 0x18) >> 3);
+ }
+
+ #ifdef DEBUG
+ fprintf(stderr, "******PackImage: Pixel [%d] destination [0x%x].\n",
+ counter++, *dst_pixel);
+ #endif
+
+ src_pixel++;
+ dst_pixel++;
+ }
+
+ return 1;
+}
+
+static int Pack24To8(unsigned int src_data_size, XImage *src_image, XImage *dst_image)
+{
+ unsigned char *src_pixel = (unsigned char *) src_image -> data;
+ unsigned char *dst_pixel = (unsigned char *) dst_image -> data;
+
+ int i;
+
+ unsigned int bytes_per_line = src_image -> bytes_per_line;
+
+ unsigned char *end_of_line = (unsigned char *) (src_pixel + bytes_per_line);
+
+
+ #ifdef DEBUG
+ unsigned int counter = 0;
+ #endif
+
+ for (i = 0; i < src_image -> height; i++ )
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "******PackImage: Pixel [%d] value [0x%x%x%x] red [0x%x] green [0x%x] blue [0x%x].\n",
+ counter, src_pixel[0], src_pixel[1], src_pixel[2], src_pixel[0] & 0xc0,
+ src_pixel[1] & 0xc0, src_pixel[2] & 0xc0);
+ #endif
+
+ while(src_pixel < end_of_line - 2)
+ {
+ if (src_pixel[0] == 0x00 &&
+ src_pixel[1] == 0x00 &&
+ src_pixel[2] == 0x00)
+ {
+ *dst_pixel = 0x0;
+ }
+ else if (src_pixel[0] == 0xff &&
+ src_pixel[1] == 0xff &&
+ src_pixel[2] == 0xff)
+ {
+ *dst_pixel = 0xff;
+ }
+ else
+ {
+ /*
+ * Pixel layout:
+ *
+ * 24 bit RRRRR000 GGGGG000 BBBBB000 -> 8 bit 00RRGGBB
+ */
+
+ *dst_pixel = (src_pixel[0] & 0xc0) >> 2 |
+ ((src_pixel[1] & 0xc0) >> 4) |
+ ((src_pixel[2] & 0xc0) >> 6);
+ }
+
+ #ifdef DEBUG
+ fprintf(stderr, "******PackImage: Pixel [%d] destination [0x%x].\n",
+ counter++, *dst_pixel);
+ #endif
+
+ src_pixel += 3;
+ dst_pixel += 1;
+ }
+
+ src_pixel = end_of_line;
+ end_of_line += bytes_per_line;
+ }
+
+ return 1;
+}
+
+static int Pack24To16(unsigned int src_data_size, XImage *src_image, XImage *dst_image)
+{
+ unsigned char *src_pixel = (unsigned char *) src_image -> data;
+ unsigned short *dst_pixel = (unsigned short *) dst_image -> data;
+
+ int i;
+
+ unsigned int bytes_per_line = src_image -> bytes_per_line;
+
+ unsigned char *end_of_line = (unsigned char *) (src_pixel + bytes_per_line);
+
+ #ifdef DEBUG
+ unsigned int counter = 0;
+ #endif
+
+ for (i = 0; i < src_image -> height; i++ )
+ {
+ while(src_pixel < end_of_line - 2)
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "******PackImage: Pixel [%d] value [0x%x%x%x] red [0x%x] green [0x%x] blue [0x%x].\n",
+ counter, src_pixel[0], src_pixel[1], src_pixel[2], src_pixel[0] & 0xf8,
+ src_pixel[1] & 0xf8, src_pixel[2] & 0xf8);
+ #endif
+
+ if (src_pixel[0] == 0x00 &&
+ src_pixel[1] == 0x00 &&
+ src_pixel[2] == 0x00)
+ {
+ *dst_pixel = 0x0;
+ }
+ else if (src_pixel[0] == 0xff &&
+ src_pixel[1] == 0xff &&
+ src_pixel[2] == 0xff)
+ {
+ *dst_pixel = 0xffff;
+ }
+ else
+ {
+ /*
+ * Pixel layout:
+ *
+ * 24 bit RRRRR000 GGGGG000 BBBBB000 -> 16 bit 0RRRRRGG GGGBBBBB
+ */
+
+ *dst_pixel = ((src_pixel[0] & 0xf8) << 7) |
+ ((src_pixel[1] & 0xf8) << 2) |
+ ((src_pixel[2] & 0xf8) >> 3);
+ }
+
+ #ifdef DEBUG
+ fprintf(stderr, "******PackImage: Pixel [%d] destination [0x%x].\n",
+ counter++, *dst_pixel);
+ #endif
+
+ src_pixel += 3;
+ dst_pixel += 1;
+ }
+
+ src_pixel = end_of_line;
+ end_of_line += bytes_per_line;
+ }
+
+ return 1;
+}
+
+static int Pack32To8(unsigned int src_data_size, XImage *src_image, XImage *dst_image)
+{
+ unsigned int *src_pixel = (unsigned int *) src_image -> data;
+ unsigned char *dst_pixel = (unsigned char *) dst_image -> data;
+
+ #ifdef DEBUG
+ unsigned int counter = 0;
+ #endif
+
+ while (src_pixel < ((unsigned int *) (src_image -> data + src_data_size)))
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "******PackImage: Pixel [%d] value [0x%x] red [0x%x] green [0x%x] blue [0x%x].\n",
+ counter, *src_pixel, (*src_pixel & 0xc00000),
+ (*src_pixel & 0xc000), (*src_pixel & 0xc0));
+ #endif
+
+ if (*src_pixel == 0x0)
+ {
+ *dst_pixel = 0x0;
+ }
+ else if (*src_pixel == 0xffffff)
+ {
+ *dst_pixel = 0xff;
+ }
+ else
+ {
+ *dst_pixel = ((*src_pixel & 0xc00000) >> 18) |
+ ((*src_pixel & 0xc000) >> 12) |
+ ((*src_pixel & 0xc0) >> 6);
+ }
+
+ #ifdef DEBUG
+ fprintf(stderr, "******PackImage: Pixel [%d] destination [0x%x].\n",
+ counter++, *dst_pixel);
+ #endif
+
+ src_pixel++;
+ dst_pixel++;
+ }
+
+ return 1;
+}
+
+static int Pack32To16(unsigned int src_data_size, XImage *src_image, XImage *dst_image)
+{
+ unsigned int *src_pixel = (unsigned int *) src_image -> data;
+ unsigned short *dst_pixel = (unsigned short *) dst_image -> data;
+
+ #ifdef DEBUG
+ unsigned int counter = 0;
+ #endif
+
+ while (src_pixel < ((unsigned int *) (src_image -> data + src_data_size)))
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "******PackImage: Pixel [%d] value [0x%x] red [0x%x] green [0x%x] blue [0x%x].\n",
+ counter, *src_pixel, (*src_pixel & 0xf80000),
+ (*src_pixel & 0xf800), (*src_pixel & 0xf8));
+ #endif
+
+ if (*src_pixel == 0x0)
+ {
+ *dst_pixel = 0x0;
+ }
+ else if (*src_pixel == 0xffffff)
+ {
+ *dst_pixel = 0xffff;
+ }
+ else
+ {
+ *dst_pixel = ((*src_pixel & 0xf80000) >> 9) |
+ ((*src_pixel & 0xf800) >> 6) |
+ ((*src_pixel & 0xf8) >> 3);
+ }
+
+ #ifdef DEBUG
+ fprintf(stderr, "******PackImage: Pixel [%d] destination [0x%x].\n",
+ counter++, *dst_pixel);
+ #endif
+
+ src_pixel++;
+ dst_pixel++;
+ }
+
+ return 1;
+}
+
+static int Pack32To24(unsigned int src_data_size, XImage *src_image, XImage *dst_image)
+{
+ unsigned int *src_pixel = (unsigned int *) src_image -> data;
+ unsigned char *dst_pixel = (unsigned char *) dst_image -> data;
+
+ #ifdef DEBUG
+ unsigned int counter = 0;
+ #endif
+
+ while (src_pixel < ((unsigned int *) (src_image -> data + src_data_size)))
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "******PackImage: Pixel [%d] value [0x%x] red [0x%x] green [0x%x] blue [0x%x].\n",
+ counter, *src_pixel, ((*src_pixel & 0xff0000) >> 16),
+ ((*src_pixel & 0x00ff00) >> 8), (*src_pixel & 0xff));
+ #endif
+
+ if (*src_pixel == 0x0)
+ {
+ dst_pixel[0] = dst_pixel[1] = dst_pixel[2] = 0x0;
+ }
+ else if (*src_pixel == 0xffffff)
+ {
+ dst_pixel[0] = dst_pixel[1] = dst_pixel[2] = 0xff;
+ }
+ else
+ {
+ dst_pixel[0] = (*src_pixel & 0xff0000) >> 16;
+ dst_pixel[1] = (*src_pixel & 0x00ff00) >> 8;
+ dst_pixel[2] = (*src_pixel & 0x0000ff);
+ }
+
+ #ifdef DEBUG
+ fprintf(stderr, "******PackImage: Pixel [%d] destination [0x%x], [0x%x], [0x%x].\n",
+ counter++, dst_pixel[0], dst_pixel[1], dst_pixel[2]);
+ #endif
+
+ src_pixel += 1;
+ dst_pixel += 3;
+ }
+
+ return 1;
+}
+
+int PackImage(unsigned int method, unsigned int src_data_size, XImage *src_image,
+ unsigned int dst_data_size, XImage *dst_image)
+{
+ unsigned int src_bits_per_pixel;
+ unsigned int dst_bits_per_pixel;
+
+ src_bits_per_pixel = src_image -> bits_per_pixel;
+ dst_bits_per_pixel = MethodBitsPerPixel(method);
+
+ #ifdef TEST
+ fprintf(stderr, "******PackImage: Source bits per pixel [%d], destination bits per pixel [%d].\n",
+ src_bits_per_pixel, dst_bits_per_pixel);
+
+ fprintf(stderr, "******PackImage: Source data size [%d], destination data size [%d].\n",
+ src_data_size, dst_data_size);
+ #endif
+
+ if (dst_bits_per_pixel >= src_bits_per_pixel)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******PackImage: PANIC! Cannot pack image from [%d] to [%d] bytes per pixel.\n",
+ src_bits_per_pixel, dst_bits_per_pixel);
+ #endif
+
+ return 0;
+ }
+
+ switch (src_bits_per_pixel)
+ {
+ case 16:
+ {
+ switch (dst_bits_per_pixel)
+ {
+ case 8:
+ {
+ return Pack16To8(src_data_size, src_image, dst_image);
+ }
+ default:
+ {
+ return 0;
+ }
+ }
+ }
+ case 24:
+ {
+ switch (dst_bits_per_pixel)
+ {
+ case 8:
+ {
+ return Pack24To8(src_data_size, src_image, dst_image);
+ }
+ case 16:
+ {
+ return Pack24To16(src_data_size, src_image, dst_image);
+ }
+ default:
+ {
+ return 0;
+ }
+ }
+ }
+ case 32:
+ {
+ switch (dst_bits_per_pixel)
+ {
+ case 8:
+ {
+ return Pack32To8(src_data_size, src_image, dst_image);
+ }
+ case 16:
+ {
+ return Pack32To16(src_data_size, src_image, dst_image);
+ }
+ case 24:
+ {
+ return Pack32To24(src_data_size, src_image, dst_image);
+ }
+ default:
+ {
+ return 0;
+ }
+ }
+ }
+ default:
+ {
+ return 0;
+ }
+ }
+}
+
+/*
+ * Replace the ffs() call that may be not
+ * present on some systems.
+ */
+
+int FindLSB(int word)
+{
+ int t = word;
+
+ int m = 1;
+ int i = 0;
+
+ for (; i < sizeof(word) << 3; i++, m <<= 1)
+ {
+ if (t & m)
+ {
+ return i + 1;
+ }
+ }
+
+ return 0;
+}
+
diff --git a/nx-X11/programs/Xserver/hw/nxagent/compext/Mask.h b/nx-X11/programs/Xserver/hw/nxagent/compext/Mask.h
new file mode 100644
index 000000000..1b6fe6d99
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/compext/Mask.h
@@ -0,0 +1,48 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXCOMPEXT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#ifndef Mask_H
+#define Mask_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "Xlib.h"
+
+extern int MaskImage(const ColorMask *mask, XImage *src_image, XImage *dst_image);
+
+extern int MaskInPlaceImage(const ColorMask *mask, XImage *image);
+
+extern int PackImage(unsigned int method, unsigned int src_data_size, XImage *src_image,
+ unsigned int dst_data_size, XImage *dst_image);
+
+int FindLSB(int word);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* Mask_H */
diff --git a/nx-X11/programs/Xserver/hw/nxagent/compext/Png.c b/nx-X11/programs/Xserver/hw/nxagent/compext/Png.c
new file mode 100644
index 000000000..b235e095e
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/compext/Png.c
@@ -0,0 +1,730 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXCOMPEXT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <nx-X11/Xutil.h>
+
+#include "Compext.h"
+
+#include "Mask.h"
+#include "Png.h"
+
+#define PANIC
+#define WARNING
+#undef TEST
+#undef DEBUG
+
+/*
+ * Selected ZLIB compression level.
+ */
+
+#define PNG_Z_LEVEL 4
+
+/*
+ * Local function prototypes.
+ */
+
+static void PrepareRowForPng(CARD8 *dst, int y, int count);
+static void PrepareRowForPng24(CARD8 *dst, int y, int count);
+static void PrepareRowForPng16(CARD8 *dst, int y, int count);
+static void PrepareRowForPng32(CARD8 *dst, int y, int count);
+
+static void PngWriteData(png_structp png_ptr, png_bytep data, png_size_t length);
+static void PngFlushData(png_structp png_ptr);
+
+/*
+ * Image characteristics.
+ */
+
+static int bytesPerLine;
+static int byteOrder;
+
+static CARD8 bitsPerPixel;
+static CARD16 redMax, greenMax, blueMax;
+static CARD8 redShift, greenShift, blueShift;
+
+/*
+ * Other variables used for the Png
+ * encoding.
+ */
+
+png_byte color_type;
+png_structp png_ptr;
+png_infop info_ptr;
+png_colorp palette;
+static char *pngCompBuf;
+static int pngDataLen;
+static char *pngBeforeBuf = NULL;
+
+/*
+ * Allocate data for the compressed image.
+ * We need to ensure that there is enough
+ * space to include the palette and the
+ * header.
+ */
+
+#define PNG_DEST_SIZE(width, height) ((width) * 3 * (height) + 1024 + 256)
+
+/*
+ * Just for debug purposes.
+ */
+
+#ifdef DEBUG
+
+static int pngId;
+static char pngName[10];
+static FILE *pngFile;
+
+#endif
+
+int PngCompareColorTable(NXColorTable *c1, NXColorTable *c2)
+{
+ return (c1 -> pixel - c2 -> pixel);
+}
+
+#define NB_COLOR_MAX 256
+
+int NXCreatePalette32(XImage *src_image, NXColorTable *color_table, CARD8 *image_index, int nb_max)
+{
+ int x, y, t, p;
+ CARD8 *fbptr;
+ CARD32 pixel;
+
+ fbptr = (CARD8 *) (src_image -> data);
+
+ /*
+ * TODO: Find a more intelligent way to
+ * estimate the number of colors.
+ */
+
+ memset(color_table, 0, nb_max * sizeof(NXColorTable));
+
+ for (x = 0, p = 0; x < src_image -> height; x++)
+ {
+ for (y = 0; y < src_image -> width; y++)
+ {
+ if (byteOrder == LSBFirst)
+ {
+ pixel = (CARD32) *(fbptr + 3);
+ pixel = (pixel << 8) | (CARD32) *(fbptr + 2);
+ pixel = (pixel << 8) | (CARD32) *(fbptr + 1);
+ pixel = (pixel << 8) | (CARD32) *fbptr;
+ }
+ else
+ {
+ pixel = (CARD32) *fbptr;
+ pixel = (pixel << 8) | (CARD32) *(fbptr + 1);
+ pixel = (pixel << 8) | (CARD32) *(fbptr + 2);
+ pixel = (pixel << 8) | (CARD32) *(fbptr + 3);
+ }
+
+ fbptr += 4;
+
+ for (t = 0; t < nb_max; t++)
+ {
+ if (color_table[t].found == 0)
+ {
+ color_table[t].pixel = pixel;
+ color_table[t].found = 1;
+ p++;
+ image_index[((x * src_image -> width) + y)] = t;
+
+ break;
+ }
+ else if ((CARD32)(color_table[t].pixel) == pixel)
+ {
+ image_index[((x * src_image -> width) + y)] = t;
+
+ break;
+ }
+ }
+
+ if (p == nb_max)
+ {
+ return nb_max + 1;
+ }
+ }
+ }
+ return p;
+}
+
+int NXCreatePalette16(XImage *src_image, NXColorTable *color_table, CARD8 *image_index, int nb_max)
+{
+ int x, y, t, p;
+ CARD8 *fbptr;
+ CARD16 pixel;
+
+ fbptr = (CARD8 *) (src_image -> data);
+
+ /*
+ * TODO: Find a more intelligent way to
+ * estimate the number of colors.
+ */
+
+ memset(color_table, 0, nb_max * sizeof(NXColorTable));
+
+ for (x = 0, p = 0; x < src_image -> height; x++)
+ {
+ for (y = 0; y < src_image -> width; y++)
+ {
+ if (byteOrder == LSBFirst)
+ {
+ pixel = (CARD16) *(fbptr + 1);
+ pixel = (pixel << 8) | (CARD16) *fbptr;
+ }
+ else
+ {
+ pixel = (CARD16) *fbptr;
+ pixel = (pixel << 8) | (CARD16) *(fbptr + 1);
+ }
+
+ fbptr += 2;
+
+ for (t = 0; t < nb_max; t++)
+ {
+ if (color_table[t].found == 0)
+ {
+ color_table[t].pixel = pixel;
+ color_table[t].found = 1;
+ p++;
+ image_index[((x * src_image -> width) + y)] = t;
+
+ break;
+ }
+ else if ((color_table[t].pixel) == pixel)
+ {
+ image_index[((x * src_image -> width) + y)] = t;
+
+ break;
+ }
+ }
+
+ /*
+ * In case the number of 16bit words is not even
+ * we have 2 padding bytes that we have to skip.
+ */
+
+ if ((y == src_image -> width - 1) && (src_image -> width % 2 == 1)) fbptr += 2;
+
+ if (p == nb_max)
+ {
+ return nb_max + 1;
+ }
+ }
+ }
+
+ return p;
+}
+
+char *PngCompressData(XImage *image, int *compressed_size)
+{
+ unsigned int num = 0;
+ CARD8 *srcBuf;
+
+ int dy, w, h;
+
+ int nb_colors;
+
+ NXColorTable color_table[NB_COLOR_MAX];
+ CARD8 *image_index;
+
+ image_index = (CARD8 *) malloc((image -> height) * (image -> width) * sizeof(CARD8));
+
+ /*
+ * TODO: Be sure the padded bytes are cleaned.
+ * It would be better to set to zero the bytes
+ * that are not alligned to the word boundary
+ * at the end of the procedure.
+ */
+
+ memset(image_index, 0, (image -> height) * (image -> width) * sizeof(CARD8));
+
+ *compressed_size = 0;
+
+ pngDataLen = 0;
+
+ /*
+ * Initialize the image stuff.
+ */
+
+ bitsPerPixel = image -> bits_per_pixel;
+ bytesPerLine = image -> bytes_per_line;
+ byteOrder = image -> byte_order;
+
+ if (bitsPerPixel < 15)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******PngCompressData: PANIC! Can't compress images with [%d] bits per pixel.\n",
+ bitsPerPixel);
+ #endif
+
+ return NULL;
+ }
+
+ redShift = FindLSB(image -> red_mask) - 1;
+ greenShift = FindLSB(image -> green_mask) - 1;
+ blueShift = FindLSB(image -> blue_mask) - 1;
+
+ redMax = image -> red_mask >> redShift;
+ greenMax = image -> green_mask >> greenShift;
+ blueMax = image -> blue_mask >> blueShift;
+
+ w = image -> width;
+ h = image -> height;
+ pngBeforeBuf = image -> data;
+
+ #ifdef DEBUG
+ fprintf(stderr, "******PngCompressData: Compressing image with width [%d] height [%d].\n",
+ w, h );
+ #endif
+
+ /*
+ * Initialize the PNG stuff.
+ */
+
+ png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+
+ if (png_ptr == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******PngCompressData: PANIC! Failed creating the png_create_write_struct.\n");
+ #endif
+
+ return NULL;
+ }
+
+ info_ptr = png_create_info_struct(png_ptr);
+
+ if (info_ptr == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******PngCompressData: PANIC! Failed creating the png_create_info_struct.\n");
+ #endif
+
+ png_destroy_write_struct(&png_ptr, NULL);
+
+ return NULL;
+ }
+
+ if (setjmp(png_jmpbuf(png_ptr)))
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******PngCompressData: PANIC! Error during compression initialization.\n");
+ #endif
+
+ png_destroy_write_struct(&png_ptr, &info_ptr);
+
+ return NULL;
+ }
+
+ /*
+ * Be sure we allocate enough data.
+ */
+
+ #ifdef TEST
+ fprintf(stderr, "******PngCompressData: Allocating [%d] bytes for the destination data.\n",
+ PNG_DEST_SIZE(w, h));
+ #endif
+
+ pngCompBuf = malloc(PNG_DEST_SIZE(w, h));
+
+ if (pngCompBuf == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******PngCompressData: PANIC! Error allocating [%d] bytes for the Png data.\n",
+ PNG_DEST_SIZE(w, h));
+ #endif
+
+ return NULL;
+ }
+
+ png_set_write_fn(png_ptr, (void *) pngCompBuf, PngWriteData, PngFlushData);
+
+ if (setjmp(png_jmpbuf(png_ptr)))
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******PngCompressData: PANIC! Error writing the header.\n");
+ #endif
+
+ png_destroy_write_struct(&png_ptr, &info_ptr);
+
+ free(pngCompBuf);
+
+ return NULL;
+ }
+
+ png_set_compression_level(png_ptr, PNG_Z_LEVEL);
+
+ if (bitsPerPixel == 16)
+ {
+ nb_colors = NXCreatePalette16(image, color_table, image_index, NB_COLOR_MAX);
+ }
+ else
+ {
+ nb_colors = NXCreatePalette32(image, color_table, image_index, NB_COLOR_MAX);
+ }
+
+ if (nb_colors <= NB_COLOR_MAX)
+ {
+ color_type = PNG_COLOR_TYPE_PALETTE;
+ }
+ else
+ {
+ color_type = PNG_COLOR_TYPE_RGB;
+ }
+
+ png_set_IHDR(png_ptr, info_ptr, w, h,
+ 8, color_type, PNG_INTERLACE_NONE,
+ PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
+
+ if (color_type == PNG_COLOR_TYPE_PALETTE)
+ {
+ palette = png_malloc(png_ptr, sizeof(*palette) * 256);
+
+ /*
+ * TODO: Do we need to clean these bytes?
+ *
+ * memset(palette, 0, sizeof(*palette) * 256);
+ */
+
+ for (num = 0; num < 256 && color_table[num].found != 0; num++)
+ {
+ if (bitsPerPixel == 24)
+ {
+ palette[num].red = (color_table[num].pixel >> redShift) & redMax;
+ palette[num].green = (color_table[num].pixel >> greenShift) & greenMax;
+ palette[num].blue = color_table[num].pixel >> blueShift & blueMax;
+ }
+ else
+ {
+ int inRed, inGreen, inBlue;
+
+ inRed = (color_table[num].pixel >> redShift) & redMax;
+ inGreen = (color_table[num].pixel >> greenShift) & greenMax;
+ inBlue = color_table[num].pixel >> blueShift & blueMax;
+
+ palette[num].red = (CARD8)((inRed * 255 + redMax / 2) / redMax);
+ palette[num].green = (CARD8)((inGreen * 255 + greenMax / 2) / greenMax);
+ palette[num].blue = (CARD8)((inBlue * 255 + blueMax / 2) / blueMax);
+ }
+
+ #ifdef DEBUG
+ fprintf(stderr, "******PngCompressData: pixel[%d] r[%d] g[%d] b[%d].\n",
+ (int) color_table[num].pixel,palette[num].red,palette[num].green,palette[num].blue);
+ #endif
+ }
+
+ png_set_PLTE(png_ptr, info_ptr, palette, num);
+
+ #ifdef DEBUG
+ fprintf(stderr, "******PngCompressedData: Setting palette.\n");
+ #endif
+ }
+
+ /*
+ * End of palette.
+ */
+
+ png_write_info(png_ptr, info_ptr);
+
+ /*
+ * Allocate space for one line of
+ * the image, 3 bytes per pixel.
+ */
+
+ #ifdef DEBUG
+ fprintf(stderr, "******PngCompressedData: Initialization finished.\n");
+ #endif
+
+ if (setjmp(png_jmpbuf(png_ptr)))
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******PngCompressData: PANIC! Error while writing the image rows.\n");
+ #endif
+
+ png_destroy_write_struct(&png_ptr, &info_ptr);
+
+ free(pngCompBuf);
+
+ return NULL;
+ }
+
+ if (color_type == PNG_COLOR_TYPE_PALETTE)
+ {
+ srcBuf = (CARD8 *) malloc(w * sizeof(CARD8));
+
+ if (srcBuf == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******PngCompressData: PANIC! Cannot allocate [%d] bytes.\n",
+ (int) (w * sizeof(CARD8)));
+ #endif
+
+ return NULL;
+ }
+
+ /*
+ * TODO: Be sure the padded bytes are cleaned.
+ * It would be better to set to zero the bytes
+ * that are not alligned to the word boundary
+ * at the end of the procedure.
+ */
+
+ memset(srcBuf, 0, w * sizeof(CARD8));
+ }
+ else
+ {
+ srcBuf = (CARD8 *) malloc(w * 3 * sizeof(CARD8));
+
+ /*
+ * TODO: See above.
+ */
+
+ memset(srcBuf, 0, w * 3 * sizeof(CARD8));
+ }
+
+ if (srcBuf == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******PngCompressData: PANIC! Cannot allocate [%d] bytes.\n",
+ w * 3);
+ #endif
+
+ free(pngCompBuf);
+
+ return NULL;
+ }
+
+ for (dy = 0; dy < h; dy++)
+ {
+ if (color_type == PNG_COLOR_TYPE_RGB)
+ {
+ PrepareRowForPng(srcBuf, dy, w);
+ }
+ else
+ {
+ memcpy(srcBuf, image_index + (dy * w), w);
+ }
+
+ png_write_row(png_ptr, srcBuf);
+ }
+
+ #ifdef DEBUG
+ fprintf(stderr, "******PngCompressedData: Compression finished. Lines handled [%d,%d].\n",
+ dy, h);
+ #endif
+
+ free(srcBuf);
+ free(image_index);
+
+ if (setjmp(png_jmpbuf(png_ptr)))
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******PngCompressData: PANIC! error during end of write.\n");
+ #endif
+
+ png_destroy_write_struct(&png_ptr, &info_ptr);
+
+ free(pngCompBuf);
+
+ return NULL;
+ }
+
+ png_write_end(png_ptr, NULL);
+
+ if (color_type == PNG_COLOR_TYPE_PALETTE)
+ {
+ png_free(png_ptr, palette);
+ }
+
+ png_destroy_write_struct(&png_ptr, &info_ptr);
+
+ /*
+ * Check the size of the resulting data.
+ */
+
+ if (pngDataLen > 0)
+ {
+ #ifdef DEBUG
+
+ int i = 0;
+
+ fprintf(stderr, "******PngCompressedData: Compressed size [%d].\n",
+ pngDataLen);
+
+ pngId++;
+ sprintf(pngName, "png%d", pngId);
+ pngFile = fopen(pngName, "w");
+
+ for (i = 0; i < pngDataLen; i++)
+ {
+ fprintf(pngFile, "%c", *(pngCompBuf + i));
+ }
+
+ fclose(pngFile);
+
+ #endif
+
+ *compressed_size = pngDataLen;
+
+ return pngCompBuf;
+ }
+ else
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "******PngCompressedData: PANIC! Invalid size of the compressed data [%d].\n",
+ pngDataLen);
+ #endif
+
+ free(pngCompBuf);
+
+ return NULL;
+ }
+}
+
+static void PngWriteData(png_structp png_ptr, png_bytep data, png_size_t length)
+{
+ memcpy(((char *) png_get_io_ptr(png_ptr) + pngDataLen), data, length);
+
+ pngDataLen += length;
+}
+
+static void PngFlushData(png_structp png_ptr)
+{
+}
+
+void PrepareRowForPng(CARD8 *dst, int y, int count)
+{
+ if (bitsPerPixel == 32)
+ {
+ if (redMax == 0xff &&
+ greenMax == 0xff &&
+ blueMax == 0xff)
+ {
+ PrepareRowForPng24(dst, y, count);
+ }
+ else
+ {
+ PrepareRowForPng32(dst, y, count);
+ }
+ }
+ else if (bitsPerPixel == 24)
+ {
+ memcpy(dst, pngBeforeBuf + y * bytesPerLine, count * 3);
+ }
+ else
+ {
+ /*
+ * 16 bpp assumed.
+ */
+
+ PrepareRowForPng16(dst, y, count);
+ }
+}
+
+
+
+void PrepareRowForPng24(CARD8 *dst, int y, int count)
+{
+ CARD8 *fbptr;
+ CARD32 pix;
+
+ fbptr = (CARD8 *) (pngBeforeBuf + y * bytesPerLine);
+
+ while (count--)
+ {
+ if (byteOrder == LSBFirst)
+ {
+ pix = (CARD32) *(fbptr + 2);
+ pix = (pix << 8) | (CARD32) *(fbptr+1);
+ pix = (pix << 8) | (CARD32) *fbptr;
+ }
+ else
+ {
+ pix = (CARD32) *(fbptr + 1);
+ pix = (pix << 8) | (CARD32) *(fbptr + 2);
+ pix = (pix << 8) | (CARD32) *(fbptr + 3);
+ }
+
+ *dst++ = (CARD8)(pix >> redShift);
+ *dst++ = (CARD8)(pix >> greenShift);
+ *dst++ = (CARD8)(pix >> blueShift);
+
+ fbptr+=4;
+ }
+}
+
+#define DEFINE_PNG_GET_ROW_FUNCTION(bpp) \
+ \
+void PrepareRowForPng##bpp(CARD8 *dst, int y, int count) \
+{ \
+ CARD8 *fbptr; \
+ CARD##bpp pix; \
+ int inRed, inGreen, inBlue; \
+ int i; \
+ \
+ fbptr = (CARD8 *) (pngBeforeBuf + y * bytesPerLine); \
+ \
+ while (count--) \
+ { \
+ pix = 0; \
+ \
+ if (byteOrder == LSBFirst) \
+ { \
+ for (i = (bpp >> 3) - 1; i >= 0; i--) \
+ { \
+ pix = (pix << 8) | (CARD32) *(fbptr + i); \
+ } \
+ } \
+ else \
+ { \
+ for (i = 0; i < (bpp >> 3); i++) \
+ { \
+ pix = (pix << 8) | (CARD32) *(fbptr + i); \
+ } \
+ } \
+ \
+ fbptr += (bpp >> 3); \
+ \
+ inRed = (int) \
+ (pix >> redShift & redMax); \
+ inGreen = (int) \
+ (pix >> greenShift & greenMax); \
+ inBlue = (int) \
+ (pix >> blueShift & blueMax); \
+ *dst++ = (CARD8)((inRed * 255 + redMax / 2) / \
+ redMax); \
+ *dst++ = (CARD8)((inGreen * 255 + greenMax / 2) / \
+ greenMax); \
+ *dst++ = (CARD8)((inBlue * 255 + blueMax / 2) / \
+ blueMax); \
+ } \
+}
+
+DEFINE_PNG_GET_ROW_FUNCTION(16)
+DEFINE_PNG_GET_ROW_FUNCTION(32)
diff --git a/nx-X11/programs/Xserver/hw/nxagent/compext/Png.h b/nx-X11/programs/Xserver/hw/nxagent/compext/Png.h
new file mode 100644
index 000000000..0e0621627
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/compext/Png.h
@@ -0,0 +1,76 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXCOMPEXT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#ifndef Png_H
+#define Png_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <nx-X11/X.h>
+#include <nx-X11/Xlib.h>
+#include <nx-X11/Xmd.h>
+
+#include <png.h>
+
+extern int PngCompareColorTable(
+#if NeedFunctionPrototypes
+ NXColorTable* /* color_table_1 */,
+ NXColorTable* /* color_table_2 */
+#endif
+);
+
+extern char *PngCompressData(
+#if NeedFunctionPrototypes
+ XImage* /* image */,
+ int* /* compressed_size */
+#endif
+);
+
+int NXCreatePalette16(
+#if NeedFunctionPrototypes
+ XImage* /* src_image */,
+ NXColorTable* /* color_table */,
+ CARD8* /* image_index */,
+ int /* nb_max */
+#endif
+);
+
+int NXCreatePalette32(
+#if NeedFunctionPrototypes
+ XImage* /* src_image */,
+ NXColorTable* /* color_table */,
+ CARD8* /* image_index */,
+ int /* nb_max */
+#endif
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* Png_H */
+
diff --git a/nx-X11/programs/Xserver/hw/nxagent/compext/Rgb.c b/nx-X11/programs/Xserver/hw/nxagent/compext/Rgb.c
new file mode 100644
index 000000000..fc53ded92
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/compext/Rgb.c
@@ -0,0 +1,51 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXCOMPEXT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#include <zlib.h>
+
+#include "Compext.h"
+
+#include "Rgb.h"
+#include "Z.h"
+
+#define PANIC
+#define WARNING
+#undef TEST
+#undef DEBUG
+
+#define RGB_COMPRESSION_LEVEL 4
+#define RGB_COMPRESSION_THRESHOLD 32
+#define RGB_COMPRESSION_STRATEGY Z_DEFAULT_STRATEGY
+
+static int rgbCompressionLevel = RGB_COMPRESSION_LEVEL;
+static int rgbCompressionThreshold = RGB_COMPRESSION_THRESHOLD;
+static int rgbCompressionStrategy = RGB_COMPRESSION_STRATEGY;
+
+char *RgbCompressData(XImage *image, unsigned int *size)
+{
+ return ZCompressData(image -> data, image -> bytes_per_line * image -> height,
+ rgbCompressionThreshold, rgbCompressionLevel,
+ rgbCompressionStrategy, size);
+}
diff --git a/nx-X11/programs/Xserver/hw/nxagent/compext/Rgb.h b/nx-X11/programs/Xserver/hw/nxagent/compext/Rgb.h
new file mode 100644
index 000000000..fd53ffbf9
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/compext/Rgb.h
@@ -0,0 +1,44 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXCOMPEXT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#ifndef Rgb_H
+#define Rgb_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern char *RgbCompressData(
+#if NeedFunctionPrototypes
+ XImage* /* image */,
+ unsigned int* /* compressed_size */
+#endif
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* Rgb_H */
diff --git a/nx-X11/programs/Xserver/hw/nxagent/compext/Rle.c b/nx-X11/programs/Xserver/hw/nxagent/compext/Rle.c
new file mode 100644
index 000000000..3f1da0de4
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/compext/Rle.c
@@ -0,0 +1,51 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXCOMPEXT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#include <zlib.h>
+
+#include "Compext.h"
+
+#include "Rle.h"
+#include "Z.h"
+
+#define PANIC
+#define WARNING
+#undef TEST
+#undef DEBUG
+
+#define RLE_COMPRESSION_LEVEL 1
+#define RLE_COMPRESSION_THRESHOLD 32
+#define RLE_COMPRESSION_STRATEGY Z_RLE
+
+static int rleCompressionLevel = RLE_COMPRESSION_LEVEL;
+static int rleCompressionThreshold = RLE_COMPRESSION_THRESHOLD;
+static int rleCompressionStrategy = RLE_COMPRESSION_STRATEGY;
+
+char *RleCompressData(XImage *image, unsigned int *size)
+{
+ return ZCompressData(image -> data, image -> bytes_per_line * image -> height,
+ rleCompressionThreshold, rleCompressionLevel,
+ rleCompressionStrategy, size);
+}
diff --git a/nx-X11/programs/Xserver/hw/nxagent/compext/Rle.h b/nx-X11/programs/Xserver/hw/nxagent/compext/Rle.h
new file mode 100644
index 000000000..a32812657
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/compext/Rle.h
@@ -0,0 +1,44 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXCOMPEXT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#ifndef Rle_H
+#define Rle_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern char *RleCompressData(
+#if NeedFunctionPrototypes
+ XImage* /* image */,
+ unsigned int* /* compressed_size */
+#endif
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* Rle_H */
diff --git a/nx-X11/programs/Xserver/hw/nxagent/compext/Z.c b/nx-X11/programs/Xserver/hw/nxagent/compext/Z.c
new file mode 100644
index 000000000..6ee08e236
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/compext/Z.c
@@ -0,0 +1,309 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXCOMPEXT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <zlib.h>
+
+#include "Compext.h"
+
+#include "Z.h"
+
+#define PANIC
+#define WARNING
+#undef TEST
+#undef DEBUG
+
+#define Z_COMPRESSION_LEVEL 4
+#define Z_COMPRESSION_THRESHOLD 32
+#define Z_COMPRESSION_STRATEGY Z_DEFAULT_STRATEGY
+
+static int zCompressionLevel = Z_COMPRESSION_LEVEL;
+static int zCompressionStrategy = Z_COMPRESSION_STRATEGY;
+
+static z_stream *zStream;
+
+static int zInitialized;
+
+static int ZConfigure(int level, int strategy);
+
+static int ZDeflate(char *dest, unsigned int *destLen,
+ const char *source, unsigned int sourceLen);
+
+char *ZCompressData(const char *plainData, unsigned int plainSize, int threshold,
+ int level, int strategy, unsigned int *compressedSize)
+{
+ char *compressedData;
+
+ /*
+ * Determine the size of the source image
+ * data and make sure there is enough
+ * space in the destination buffer.
+ */
+
+ *compressedSize = plainSize + (plainSize / 1000) + 12 + 1;
+
+ compressedData = Xmalloc(*compressedSize);
+
+ if (compressedData == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******ZCompressData: PANIC! Failed to allocate [%d] bytes for the destination.\n",
+ *compressedSize);
+ #endif
+
+ *compressedSize = 0;
+
+ return NULL;
+ }
+
+ if (level == Z_NO_COMPRESSION || plainSize < threshold)
+ {
+ #ifdef TEST
+ fprintf(stderr, "******ZCompressData: Not compressing [%d] bytes with level [%d] and "
+ "threshold [%d].\n", plainSize, level, threshold);
+ #endif
+
+ /*
+ * Tell in the first byte of the buffer
+ * if the remaining data is compressed
+ * or not. This same byte can be used
+ * in future to store some other flag.
+ */
+
+ *compressedData = 0;
+
+ memcpy(compressedData + 1, plainData, plainSize);
+
+ *compressedSize = plainSize + 1;
+
+ return compressedData;
+ }
+ else
+ {
+ int result;
+
+ /*
+ * Reconfigure the stream if needed.
+ */
+
+ if (zCompressionLevel != level ||
+ zCompressionStrategy != strategy)
+ {
+ ZConfigure(level, strategy);
+
+ zCompressionLevel = level;
+ zCompressionStrategy = strategy;
+ }
+
+ result = ZDeflate(compressedData + 1, compressedSize, plainData, plainSize);
+
+ if (result != Z_OK)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******ZCompressData: PANIC! Failed to compress [%d] bytes with error [%s].\n",
+ plainSize, zError(result));
+ #endif
+
+ Xfree(compressedData);
+
+ *compressedSize = 0;
+
+ return NULL;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "******ZCompressData: Source data of [%d] bytes compressed to [%d].\n",
+ plainSize, *compressedSize);
+ #endif
+
+ *compressedData = 1;
+
+ *compressedSize = *compressedSize + 1;
+
+ return compressedData;
+ }
+}
+
+int ZConfigure(int level, int strategy)
+{
+ /*
+ * ZLIB wants the avail_out to be
+ * non zero, even if the stream was
+ * already flushed.
+ */
+
+ unsigned char dest[1];
+
+ zStream -> next_out = dest;
+ zStream -> avail_out = 1;
+
+ if (deflateParams(zStream, level, strategy) != Z_OK)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******ZConfigure: PANIC! Failed to set level to [%d] and strategy to [%d].\n",
+ level, strategy);
+ #endif
+
+ return -1;
+ }
+ #ifdef TEST
+ else
+ {
+ fprintf(stderr, "******ZConfigure: Reconfigured the stream with level [%d] and strategy [%d].\n",
+ level, strategy);
+ }
+ #endif
+
+ return 1;
+}
+
+int ZDeflate(char *dest, unsigned int *destLen, const char *source, unsigned int sourceLen)
+{
+ int saveOut;
+ int result;
+
+ /*
+ * Deal with the possible overflow.
+ */
+
+ if (zStream -> total_out & 0x80000000)
+ {
+ #ifdef TEST
+ fprintf(stderr, "******ZDeflate: Reset Z stream counters with total in [%ld] total out [%ld].\n",
+ zStream -> total_in, zStream -> total_out);
+ #endif
+
+ zStream -> total_in = 0;
+ zStream -> total_out = 0;
+ }
+
+ saveOut = zStream -> total_out;
+
+ zStream -> next_in = (Bytef *) source;
+ zStream -> avail_in = (uInt) sourceLen;
+
+ #ifdef MAXSEG_64K
+
+ /*
+ * Check if the source is greater
+ * than 64K on a 16-bit machine.
+ */
+
+ if ((uLong) zStream -> avail_in != sourceLen) return Z_BUF_ERROR;
+
+ #endif
+
+ zStream -> next_out = (unsigned char *) dest;
+ zStream -> avail_out = (uInt) *destLen;
+
+ if ((uLong) zStream -> avail_out != *destLen) return Z_BUF_ERROR;
+
+ result = deflate(zStream, Z_FINISH);
+
+ if (result != Z_STREAM_END)
+ {
+ deflateReset(zStream);
+
+ return (result == Z_OK ? Z_BUF_ERROR : result);
+ }
+
+ *destLen = zStream -> total_out - saveOut;
+
+ result = deflateReset(zStream);
+
+ return result;
+}
+
+int ZInitEncoder()
+{
+ if (zInitialized == 0)
+ {
+ int result;
+
+ zStream = Xmalloc(sizeof(z_stream));
+
+ if (zStream == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******ZInitEncoder: PANIC! Failed to allocate memory for the stream.\n");
+ #endif
+
+ return -1;
+ }
+
+ zStream -> zalloc = (alloc_func) 0;
+ zStream -> zfree = (free_func) 0;
+ zStream -> opaque = (voidpf) 0;
+
+ #ifdef TEST
+ fprintf(stderr, "******ZInitEncoder: Initializing compressor with level [%d] and startegy [%d].\n",
+ zCompressionLevel, zCompressionStrategy);
+ #endif
+
+ result = deflateInit2(zStream, zCompressionLevel, Z_DEFLATED,
+ 15, 9, zCompressionStrategy);
+
+ if (result != Z_OK)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******ZInitEncoder: Failed to initialize the compressor with error [%s].\n",
+ zError(result));
+ #endif
+
+ return -1;
+ }
+
+ zInitialized = 1;
+ }
+
+ return zInitialized;
+}
+
+int ZResetEncoder()
+{
+ int result;
+
+ if (zInitialized == 1)
+ {
+ result = deflateEnd(zStream);
+
+ if (result != Z_OK)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "******ZResetEncoder: WARNING! Failed to deinitialize the compressor with error [%s].\n",
+ zError(result));
+ #endif
+ }
+
+ Xfree(zStream);
+ }
+
+ zInitialized = 0;
+
+ return 1;
+}
diff --git a/nx-X11/programs/Xserver/hw/nxagent/compext/Z.h b/nx-X11/programs/Xserver/hw/nxagent/compext/Z.h
new file mode 100644
index 000000000..8133f0c73
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/compext/Z.h
@@ -0,0 +1,60 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXCOMPEXT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#ifndef Z_H
+#define Z_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int ZInitEncoder(
+#if NeedFunctionPrototypes
+void
+#endif
+);
+
+int ZResetEncoder(
+#if NeedFunctionPrototypes
+void
+#endif
+);
+
+extern char *ZCompressData(
+#if NeedFunctionPrototypes
+ const char* /* data */,
+ unsigned int /* size */,
+ int /* threshold */,
+ int /* level */,
+ int /* strategy */,
+ unsigned int* /* compressed_size */
+#endif
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* Z_H */