summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKaleb Keithley <kaleb@freedesktop.org>2003-11-14 15:54:53 +0000
committerKaleb Keithley <kaleb@freedesktop.org>2003-11-14 15:54:53 +0000
commit83fda9598025b9abcae2ea1a3b47e1d3e9f46d95 (patch)
tree7bc604da7e547bc2b068dce954f9f116df2d3d73
R6.6 is the Xorg base-lineXORG-MAIN
-rw-r--r--config/AtomControl91
-rw-r--r--design266
-rw-r--r--di/atomcache.c272
-rw-r--r--di/cache.c353
-rw-r--r--di/cmap.c1772
-rw-r--r--di/cmaputil.c981
-rw-r--r--di/dispatch.c638
-rw-r--r--di/extensions.c319
-rw-r--r--di/gfx.c1258
-rw-r--r--di/globals.c56
-rw-r--r--di/init.c270
-rw-r--r--di/lbxfuncs.c1450
-rw-r--r--di/lbxutil.c507
-rw-r--r--di/main.c181
-rw-r--r--di/options.c808
-rw-r--r--di/pm.c491
-rw-r--r--di/props.c410
-rw-r--r--di/reqtype.c312
-rw-r--r--di/resource.c480
-rw-r--r--di/swaprep.c431
-rw-r--r--di/swapreq.c327
-rw-r--r--di/tables.c593
-rw-r--r--di/tags.c192
-rw-r--r--di/unsquish.c123
-rw-r--r--di/utils.c1017
-rw-r--r--di/wire.c1577
-rw-r--r--di/zeropad.c605
-rw-r--r--include/assert.h34
-rw-r--r--include/atomcache.h104
-rw-r--r--include/cache.h128
-rw-r--r--include/colormap.h310
-rw-r--r--include/init.h79
-rw-r--r--include/lbx.h736
-rw-r--r--include/lbxext.h167
-rw-r--r--include/misc.h120
-rw-r--r--include/os.h278
-rw-r--r--include/pm.h60
-rw-r--r--include/pmP.h117
-rw-r--r--include/proxyopts.h144
-rw-r--r--include/reqtype.h71
-rw-r--r--include/resource.h137
-rw-r--r--include/swap.h254
-rw-r--r--include/tags.h134
-rw-r--r--include/util.h227
-rw-r--r--include/wire.h419
-rw-r--r--lbxproxy.man233
-rw-r--r--os/WaitFor.c198
-rw-r--r--os/connection.c886
-rw-r--r--os/io.c1240
-rw-r--r--os/osdep.h151
-rw-r--r--os/osinit.c64
51 files changed, 22071 insertions, 0 deletions
diff --git a/config/AtomControl b/config/AtomControl
new file mode 100644
index 0000000..ddaa6ec
--- /dev/null
+++ b/config/AtomControl
@@ -0,0 +1,91 @@
+! $Xorg: AtomControl,v 1.3 2000/08/17 19:53:53 cpqbld Exp $
+!
+! z <number>
+! means do not cache property data smaller than this many bytes
+!
+! <options> <atomname>
+! where options are:
+! i = pre-intern at startup
+! w = cache only if WM is running through the proxy
+! n = never cache
+!
+! depending on the apps you use, you might not want all of these
+!
+!z 8
+i _DT_NETFILE
+i _DT_RESTORE_DIR
+i _DT_SAVE_MODE
+i _MOTIF_ATOM_0
+i _MOTIF_BINDINGS
+i _MOTIF_CLIP_DATA_DELETE
+i _MOTIF_CLIP_DATA_REQUEST
+i _MOTIF_CLIP_HEADER
+i _MOTIF_CLIP_LOCK_ACCESS_VALID
+i _MOTIF_CLIP_MESSAGE
+i _MOTIF_CLIP_NEXT_ID
+i _MOTIF_CLIP_TIME
+i _MOTIF_DEFAULT_BINDINGS
+i _MOTIF_DRAG_ATOMS
+i _MOTIF_DRAG_ATOM_PAIRS
+i _MOTIF_DRAG_INITIATOR_INFO
+i _MOTIF_DRAG_PROXY_WINDOW
+i _MOTIF_DRAG_RECEIVER_INFO
+i _MOTIF_DRAG_TARGETS
+i _MOTIF_DRAG_WINDOW
+i _MOTIF_DROP
+i _MOTIF_MESSAGE
+i _MOTIF_WM_HINTS
+i _MOTIF_WM_INFO
+i _MOTIF_WM_MENU
+i _MOTIF_WM_MESSAGES
+i _MOTIF_WM_OFFSET
+i _XIM_INPUTMETHOD
+i _XM_TEXT_I_S_PROP
+i _XT_SELECTION_0
+i ATOM_PAIR
+i AVERAGE_WIDTH
+i CLIPBOARD
+i CLIP_TEMPORARY
+i Compose
+i COMPOUND_TEXT
+i Customize Data:0
+i DELETE
+i FILE_NAME
+i INCR
+i INSERT_SELECTION
+i LENGTH
+i MOTIF_DESTINATION
+i MULTIPLE
+i Pixel Sets
+i PIXEL_SIZE
+i PRIMARY
+i RESOLUTION_Y
+i SCREEN_RESOURCES
+i SDT Pixel Set
+i SM_CLIENT_ID
+i STRING
+i TARGETS
+i TEXT
+i TIMESTAMP
+i TT_SESSION
+iw WM_CHANGE_STATE
+iw WM_CLASS
+iw WM_CLIENT_LEADER
+w WM_CLIENT_MACHINE
+iw WM_COLORMAP_WINDOWS
+i WM_DELETE_WINDOW
+w WM_ICON_NAME
+w WM_ICON_SIZE
+w WM_HINTS
+iw WM_LOCALE_NAME
+i WM_MOVED
+iw WM_NAME
+iw WM_NORMAL_HINTS
+iw WM_PROTOCOLS
+i WM_SAVE_YOURSELF
+iw WM_STATE
+i WM_TAKE_FOCUS
+iw WM_TRANSIENT_FOR
+iw WM_WINDOW_ROLE
+i XmTRANSFER_SUCCESS
+i XmTRANSFER_FAILURE
diff --git a/design b/design
new file mode 100644
index 0000000..674e572
--- /dev/null
+++ b/design
@@ -0,0 +1,266 @@
+ LBX design notes
+ ----------------
+
+Much of LBX is implemented as an extension. Some modifications have
+been made to the Xserver OS layer to support its requirements, but
+the only other impact LBX has on the core server are some hooks for
+supporting tags.
+
+Flow control
+
+ LBX multiplexes the data streams of all its clients into one, and then
+ splits them apart again when they are received. The X_LbxSwitch message
+ is used to tell each end which client is using the wire at the time.
+
+Swapping
+
+ Swapping is handled as with any X extension, with one caveat.
+ Since a proxy can be supporting clients with different byte orders,
+ and they all share the same wire, all length fields are converted
+ to be sent in the proxy byte order. This prevents any problems with
+ length computation that may occur when clients are switched.
+
+Tags
+
+ Tags are used to support large data items that are expected to be
+ queried multiple times. Such things as the keyboard map and font
+ metrics are often requested by multiple clients. Rather than send the
+ data each time, the first time the data is sent it includes a tag.
+ The proxy saves this data, so that subsequent requests can send
+ only the tag. The proxy then pulls up its local copy of the data
+ and sends it on to its clients.
+
+ To support this, the Xserver keeps track of what tags are known to
+ the proxy. The proxy can send InvalidateTag messages if it doesn't
+ store the tagged data. The server also sends InvalidateTag messages
+ when the data changes, to allow the proxy to clean out obsolete data.
+
+ If the server & proxy get out of sync, and the proxy receives a
+ tag which is cannot resolve, it can send a QueryTag message and the
+ server will respond with the requested data.
+
+ Property data makes special use of tags. A common use of properties
+ is for inter-client communication. If both clients use the proxy,
+ its wasteful to send the data to the server and then back, when
+ the server may never need it. X_LbxChangeProperty does the
+ same work as X_ChangeProperty, but it does not send the data.
+ X_LbxChangeProperty replies with a tag which points to the data.
+ If the property information is used locally, the server responds to
+ X_LbxGetProperty with a tag, and the property data need never be
+ sent to the server. If the server does require the data, it can
+ issue a QueryTag message. The proxy can also send the data on at
+ any time if it thinks its appropriate (ie, wire goes idle).
+
+ The heuristics of property handling can be complex. Because
+ X_LbxChangeProperty is a round-trip, it can take longer to use it
+ than X_ChangeProperty for some wires, especially if the amount of
+ property data is small. Using X_LbxChangeProperty can also be
+ a mistake for ICCCM properties, if the window manager is not a
+ proxy client.
+
+Tag caching
+
+ The proxy contains a tag caching system that allows it to store a
+ controlled amount of tag data. Limited proxy hosts may wish to use
+ small caches or none at all. When the cache becomes full, it will
+ throw out the oldest data (and send the appropriate InvalidateTag
+ message to the Xserver).
+
+ Currently two tag caches are used, one for properties and another
+ for other data types. This may want to be modified to separate
+ out font metrics.
+
+ All tagged data is stored in the proxy byte order.
+
+Short-circuiting
+
+ Short-circuiting is used to handle 'constant' data. This includes
+ atoms, colorname/RGB mappings, and AllocColor calls. Atoms and
+ colorname/RGB mappings stay constant for the life of the server.
+ AllocColor replies are constant for each colormap. Short-circuiting
+ replaces round-trip requests with one-way requests, and can sometimes
+ use one in place of many.
+
+ Atoms are used heavily for ICCCM communication. Once the proxy knows
+ the string<->atom mapping, it has no need to send the request on to
+ the server.
+
+ Colorname/RGB mappings are constant, so once the proxy sees the
+ response from X_LookupColor, it need not forward any subsequent
+ requests.
+
+ Clients often use the same color cells, so once a read-only color
+ allocation has occurred, the proxy knows what RGB values should
+ be returned to the client. The proxy doesn't need to forward any
+ AllocColor requests it can resolve, but it must tell the server to
+ modify the color cell's reference count. X_LbxIncrementPixel is
+ used to support this.
+
+ For all three classes of short-circuiting, the server must still
+ tell the server a request has occured, so that the request sequence
+ numbers stay in sync. This is done with X_LbxModifySequence.
+
+ Sequence numbers cause the major complication with short-circuiting.
+ X guarantees that any replies, events or errors generated by a
+ previous request will be sent before those of a later request.
+ This means that any requests that can be handled by the proxy must
+ have their reply sent after any previous events or errors.
+
+ There are 3 possible ways to support short-circuiting:
+
+ - fully correct protocol, which ensures that nothing can be out
+ of order
+ - mostly correct protocol, where only errors can be out of order
+ - poor protocol, where events & errors can be out of order.
+
+ A smart client or test suite could send a request it knows will
+ generate an event or error, followed by an InternAtom request,
+ and get the InternAtom reply before it gets the event.
+
+ Xlib hides this problem from most applications, so the 'poor'
+ protocol can be sufficient. For a fully safe environment, the proxy
+ can be compiled to use any of the three forms (or no short-circuiting
+ at all). In no case do we allow replies to come back out of order.
+ The proxy knows what can come back from all the core requests --
+ for any extensions it assumes the worst case and expects a reply.
+
+Reply matching
+
+ LBX needs to store information about certain requests to support both
+ tags and short-circuiting. To do this, it creates a Reply record for
+ each request that can return a reply. Most of these are only used
+ as place holders, but for special requests data is stashed in them
+ (eg, InternAtom needs to save the atom name, so it can store it with
+ the returned Atom.)
+
+ Using the core protocol and Xlib, there is usually only one
+ pending Reply record per client. One common exception is caused by
+ XGetWIndowAttributes(), which sends two roundtrip requests and then
+ collects the results from both.
+
+ Test suites and interfaces other than Xlib may not follow this
+ convention, and could result in a number of pending Reply records.
+
+ The worst case are extensions. If the proxy doesn't know about
+ them, it must assume the worst case, and create a Reply record for
+ each extension request. These cannot be cleaned out until data
+ comes back from the server (event, error or reply), which allows
+ the proxy to flush any Reply records with older sequence numbers.
+ This has the potential to eat a huge amount of proxy memory, if an
+ extension issues a huge number of one-way requests.
+
+Motion events
+
+ To prevent clogging the wire with MotionNotify events, the server and
+ proxy work together to minimize the number of events on the wire.
+ This is done with X_LbxAllowMotion. The proxy determines how many
+ events 'fill' the wire (currently hardcoded -- should be computed) and
+ 'allows' that many events. When the server generates a MotionEvent
+ for a proxy client, it decrements the allowed number, throwing away
+ any after the wire is full. When the proxy receives a MotionNotify,
+ it sends an X_LbxAllowMotion to the server.
+
+Delta cache
+
+ LBX takes advantage of the fact that an X message may be very similar
+ to one that has been previously sent. For example, a KeyPress event
+ may differ from a previous KeyPress event in just a few bytes. By
+ sending just the bytes that differ (or "deltas"), the number of bytes
+ sent over the wire can be substantially reduced. Delta compaction is
+ used on requests being sent by the proxy as well as on replies and
+ events being sent by the server.
+
+ Both the server and the proxy keep a cache of the N (currently
+ defaulted to 16) X messages sent and received. Only messages
+ smaller than a fixed maximum (currently defaulted to 64) are
+ saved in the delta cache.
+
+ Whenever the server has a message to send, and the message is of
+ appropriate length, the message is compared to any same-length messages
+ in its send cache. The message with the fewest number of differing
+ bytes is selected. If the number of differences is small enough and
+ the resulting X_LbxDelta message would not be longer than the original
+ message, the X_LbxDelta message is sent in place of the original.
+ The original message must also be place in the send cache. The proxy
+ uses the same algorithm when it has a message to send to the server.
+
+Compression
+ Before being passed down to the transport layer, all messages are
+ passed through a general purpose data compressor (currently only LZW is
+ supported). The LZW compressor is presented with a simple byte stream -
+ the X and LBX message boundaries are not apparent. The data is
+ broken up into fixed sized blocks. Each block is compressed, then a two
+ byte header is prepended, and then the entire packet is transmitted.
+ (NOTE: LBX is designed to allow other compression algorithms to be used
+ instead of LZW. However, there is no requirement that the packet format
+ used for LZW be used for implementations involving other compression
+ algorithms.) The LZW compressor also provides for the ability to transmit
+ data uncompressed. This is useful when the data has already been
+ compressed by some other means (eg. a bitmap may be compressed using a
+ FAX G4 encoding) and further compression would not be effective.
+
+ The LZW compressor attempts to buffer up enough raw data to fill out a
+ complete block before actually compressing the data. This improves
+ compression efficiency. However, the LZW buffers are always flushed
+ before the server/proxy goes to sleep to await more data.
+
+Master Client
+ When the initial X connection between the proxy and the server is
+ converted to LBX mode, the proxy itself becomes the "master" client.
+ New client requests and some tags related messages are sent in the
+ context of the master client.
+
+Server Grabs
+ The master client must be grab-proof because the server may need to
+ retrieve tagged data from the proxy at any time. Since the master client
+ is multiplexed onto the same connection as other clients, the other
+ clients effectively become grab-proof as well. While the server is
+ grabbed, messages for non-master clients can be buffered. However, it's
+ possible for some client to eat up a large amount of buffer space before
+ the server is ungrabbed. In order to counteract this, when the server
+ is grabbed, an X_LbxListenToOne message will be sent to the proxy. If
+ the client grabbing the server belongs to the proxy, then only master
+ client and grabbing client messages will be transmitted to the server.
+ If the grabbing client does not belong to the proxy, then only master
+ client messages will be transmitted. The server will transmit an
+ X_LbxListenToAll to the proxy when the server is ungrabbed.
+
+Graphics Re-encoding
+
+ The LBX proxy attempts to reencode X_PolyPoint, X_PolyLine, X_PolySegment,
+ X_PolyRectangle, X_PolyArc, X_FillPoly, X_PolyFillRectangle, and
+ X_PolyFillArc requests. If the request can be reencoded, it is
+ replaced by an equivalent LBX form of the request. The requests
+ are reencoded by attempting to reduce all 2-byte coordinate, length,
+ width and angle fields to 1 byte. Where applicable, the coordinate mode
+ is also converted to "previous" to improve the compressibility of the
+ resulting data.
+
+Data Flow
+
+ The LBX data stream goes through a number of layers, all of which
+ should be negotiable:
+
+ 0. client requests
+
+ 1. read by LBX proxy
+ 2. potential byte-swapping
+ 3. requests-specific processing and reencoding
+ 4. potential byte swapping
+ 5. delta replacement
+ 6. stream (LZW) compression
+
+ transport
+
+ 5. stream decompression
+ 4. delta substitution
+ 3. potential byte swapping
+ 2. re-encoding
+ 1. request processing
+
+ The reverse process occurs with X server replies/events/errors.
+
+
+--------
+$NCDId: @(#)design,v 1.4 1994/04/11 18:17:03 lemke Exp $
+$Xorg: design,v 1.3 2000/08/17 19:53:53 cpqbld Exp $
diff --git a/di/atomcache.c b/di/atomcache.c
new file mode 100644
index 0000000..dbff6ab
--- /dev/null
+++ b/di/atomcache.c
@@ -0,0 +1,272 @@
+/* $Xorg: atomcache.c,v 1.4 2001/02/09 02:05:31 xorgcvs Exp $ */
+/*
+
+Copyright 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+*/
+/*
+ * Copyright 1994 Network Computing Devices, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name Network Computing Devices, Inc. not be
+ * used in advertising or publicity pertaining to distribution of this
+ * software without specific, written prior permission.
+ *
+ * THIS SOFTWARE IS PROVIDED `AS-IS'. NETWORK COMPUTING DEVICES, INC.,
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT
+ * LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, OR NONINFRINGEMENT. IN NO EVENT SHALL NETWORK
+ * COMPUTING DEVICES, INC., BE LIABLE FOR ANY DAMAGES WHATSOEVER, INCLUDING
+ * SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES, INCLUDING LOSS OF USE, DATA,
+ * OR PROFITS, EVEN IF ADVISED OF THE POSSIBILITY THEREOF, AND REGARDLESS OF
+ * WHETHER IN AN ACTION IN CONTRACT, TORT OR NEGLIGENCE, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+/*
+ * atom cache for LBX
+ *
+ * real close to standard atom code, but with a slight twist.
+ * LBX doesn't want to invent the Atom associated with a string,
+ * but insert it itself. only LbxMakeAtom() ends up being modified.
+ *
+ * the end result is a (probably) sparse array of atoms.
+ *
+ * when a client does a GetAtomName(), we use NameForAtom()
+ * - if it works, great, return the value.
+ * - if its doesn't, send it on to the server, and when the answer
+ * comes back, call LbxMakeAtom()
+ *
+ * when a client does InternAtom(), LbxMakeAtom() is called.
+ * if its already there (or only-if-exists is true) we return
+ * the appropriate value. if not, we send it on to the server,
+ * and call LbxMakeAtom() with the answer.
+ */
+
+
+#include "misc.h"
+#include "util.h"
+#include "wire.h"
+#include "atomcache.h"
+
+static int
+Hash(string, len)
+ char *string;
+ int len;
+{
+ int h;
+
+ h = 0;
+ while (len--)
+ h = (h << 3) ^ *string++;
+ if (h < 0)
+ return -h;
+ return h;
+}
+
+static Bool
+ResizeHashTable(server)
+ XServerPtr server;
+{
+ int newHashSize;
+ int newHashMask;
+ AtomListPtr *newHashTable;
+ int i;
+ int h;
+ int newRehash;
+ int r;
+
+ if (server->hashSize == 0)
+ newHashSize = 1024;
+ else
+ newHashSize = server->hashSize * 2;
+ newHashTable = (AtomListPtr *) xalloc(newHashSize * sizeof(AtomListPtr));
+ if (!newHashTable)
+ return FALSE;
+ bzero((char *) newHashTable, newHashSize * sizeof(AtomListPtr));
+ newHashMask = newHashSize - 1;
+ newRehash = (newHashMask - 2);
+ for (i = 0; i < server->hashSize; i++) {
+ if (server->hashTable[i]) {
+ h = (server->hashTable[i]->hash) & newHashMask;
+ if (newHashTable[h]) {
+ r = server->hashTable[i]->hash % newRehash | 1;
+ do {
+ h += r;
+ if (h >= newHashSize)
+ h -= newHashSize;
+ } while (newHashTable[h]);
+ }
+ newHashTable[h] = server->hashTable[i];
+ }
+ }
+ xfree(server->hashTable);
+ server->hashTable = newHashTable;
+ server->hashSize = newHashSize;
+ server->hashMask = newHashMask;
+ server->rehash = newRehash;
+ return TRUE;
+}
+
+static Bool
+ResizeReverseMap(server)
+ XServerPtr server;
+{
+ if (server->reverseMapSize == 0)
+ server->reverseMapSize = 1000;
+ else
+ server->reverseMapSize *= 2;
+
+ server->reverseMap = (AtomListPtr *) xrealloc(server->reverseMap,
+ server->reverseMapSize * sizeof(AtomListPtr));
+ bzero((char *)server->reverseMap,
+ (server->reverseMapSize * sizeof(AtomListPtr)));
+
+ if (!server->reverseMap)
+ return FALSE;
+
+ return TRUE;
+}
+
+Atom
+LbxMakeAtom(server, string, len, atom, makeit)
+ XServerPtr server;
+ char *string;
+ Atom atom;
+ unsigned len;
+ int makeit;
+{
+ AtomListPtr a;
+ int hash;
+ int h;
+ int r;
+
+ hash = Hash(string, len);
+ if (server->hashTable) {
+ h = hash & server->hashMask;
+ if (server->hashTable[h]) {
+ if (server->hashTable[h]->hash == hash &&
+ server->hashTable[h]->len == len &&
+ !strncmp(server->hashTable[h]->name, string, len)) {
+ return server->hashTable[h]->atom;
+ }
+ r = (hash % server->rehash) | 1;
+ for (;;) {
+ h += r;
+ if (h >= server->hashSize)
+ h -= server->hashSize;
+ if (!server->hashTable[h])
+ break;
+ if (server->hashTable[h]->hash == hash &&
+ server->hashTable[h]->len == len &&
+ !strncmp(server->hashTable[h]->name, string, len)) {
+ return server->hashTable[h]->atom;
+ }
+ }
+ }
+ }
+ if (!makeit)
+ return None;
+ a = (AtomListPtr) xalloc(sizeof(AtomListRec) + len + 1);
+ a->name = (char *) (a + 1);
+ a->len = len;
+ strncpy(a->name, string, len);
+ a->name[len] = '\0';
+ a->atom = atom;
+ if (atom > server->lastAtom)
+ server->lastAtom = atom;
+ a->hash = hash;
+ if (server->hashUsed >= server->hashSize / 2) {
+ ResizeHashTable(server);
+ h = hash & server->hashMask;
+ if (server->hashTable[h]) {
+ r = (hash % server->rehash) | 1;
+ do {
+ h += r;
+ if (h >= server->hashSize)
+ h -= server->hashSize;
+ } while (server->hashTable[h]);
+ }
+ }
+ server->hashTable[h] = a;
+ server->hashUsed++;
+ a->flags = 0;
+ for (r = 0; r < server->atom_control_count; r++) {
+ if (a->len == server->atom_control[r].len &&
+ !strncmp(a->name, server->atom_control[r].name, a->len)) {
+ a->flags = server->atom_control[r].flags;
+ break;
+ }
+ }
+ if (server->reverseMapSize <= a->atom)
+ ResizeReverseMap(server);
+ server->reverseMap[a->atom] = a;
+ return a->atom;
+}
+
+char *
+NameForAtom(server, atom)
+ XServerPtr server;
+ Atom atom;
+{
+ if (atom != None && atom <= server->lastAtom && server->reverseMap[atom])
+ return server->reverseMap[atom]->name;
+ return 0;
+}
+
+unsigned
+FlagsForAtom(server, atom)
+ XServerPtr server;
+ Atom atom;
+{
+ if (atom != None && atom <= server->lastAtom && server->reverseMap[atom])
+ return server->reverseMap[atom]->flags;
+ return 0;
+}
+
+void
+FreeAtoms()
+{
+ int i;
+
+ for (i=0; i < lbxMaxServers; i++) {
+ if (servers[i]) {
+ if (servers[i]->reverseMap) {
+ for (i = 0; i <= servers[i]->lastAtom; i++)
+ xfree(servers[i]->reverseMap[i]);
+ xfree(servers[i]->reverseMap);
+ }
+ xfree(servers[i]->hashTable);
+ servers[i]->reverseMapSize = 0;
+ servers[i]->reverseMap = NULL;
+ servers[i]->hashTable = NULL;
+ servers[i]->lastAtom = 0;
+ servers[i]->hashSize = 0;
+ servers[i]->hashUsed = 0;
+ }
+ }
+}
diff --git a/di/cache.c b/di/cache.c
new file mode 100644
index 0000000..9cbf7d8
--- /dev/null
+++ b/di/cache.c
@@ -0,0 +1,353 @@
+/* $Xorg: cache.c,v 1.5 2001/02/09 02:05:31 xorgcvs Exp $ */
+/*
+Copyright 1994, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+ * Copyright 1990, 1991 Network Computing Devices;
+ * Portions Copyright 1987 by Digital Equipment Corporation
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the names of Network Computing Devices,
+ * or Digital not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Network Computing Devices, or Digital
+ * make no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * NETWORK COMPUTING DEVICES, AND DIGITAL DISCLAIM ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS, IN NO EVENT SHALL NETWORK COMPUTING DEVICES, OR DIGITAL BE
+ * LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+#include "misc.h"
+#include "util.h"
+#include "cache.h"
+#include "wire.h"
+
+#define INITBUCKETS 64
+#define INITHASHSIZE 6
+#define MAXHASHSIZE 11
+
+
+#define ENTRYOFFSET 22
+#define CACHE_ENTRY_MASK 0x3FFFFF
+#define CACHE_ENTRY_BITS(id) ((id) & 0x1fc00000)
+#define CACHE_ID(id) ((int)(CACHE_ENTRY_BITS(id) >> ENTRYOFFSET))
+
+typedef struct _cache_entry {
+ pointer data;
+ unsigned long timestamp;
+ CacheID id;
+ unsigned long size;
+ CacheFree free_func;
+ ClientPtr client; /* for a server's serverClient */
+ struct _cache_entry *next;
+} CacheEntryRec, *CacheEntryPtr;
+
+typedef struct _cache {
+ Cache id;
+ CacheEntryPtr *entries;
+ int elements;
+ int buckets;
+ int hashsize;
+ CacheID nextid;
+ unsigned long maxsize;
+ unsigned long cursize;
+} CacheRec;
+
+
+/*-
+ * Notes on cache implementation
+ *
+ * This is basically the X11 resource code, with some modifications
+ * to handle aging.
+ *
+ * Its currently optimized for lookup & store. Flushing old stuff
+ * is a lot slower than it should probably be, but there's tradeoffs
+ * in tuning.
+ */
+
+Cache
+CacheInit(server, maxsize)
+ XServerPtr server;
+ unsigned long maxsize;
+{
+ Cache id;
+ CachePtr cache;
+
+ cache = (CachePtr) xalloc(sizeof(CacheRec));
+ if (!cache)
+ return (Cache) 0;
+ cache->entries = (CacheEntryPtr *)
+ xalloc(INITBUCKETS * sizeof(CacheEntryPtr));
+ if (!cache->entries) {
+ xfree(cache);
+ return (Cache) 0;
+ }
+ bzero((char *) cache->entries, (INITBUCKETS * sizeof(CacheEntryPtr)));
+ id = (Cache) ++server->num_caches;
+ server->caches[id] = cache;
+ cache->elements = 0;
+ cache->buckets = INITBUCKETS;
+ cache->hashsize = INITHASHSIZE;
+ cache->maxsize = maxsize;
+ cache->cursize = 0;
+ cache->nextid = id << ENTRYOFFSET;
+ cache->id = id;
+ return id;
+}
+
+void
+CacheFreeCache(server, cid)
+ XServerPtr server;
+ Cache cid;
+{
+ CachePtr cache = server->caches[cid];
+ int i;
+ CacheEntryPtr cp;
+
+ for (i = 0; i < cache->buckets; i++) {
+ while ((cp = cache->entries[i])) {
+ cache->entries[i] = cp->next;
+ (*cp->free_func) (cp->id, cp->client, cp->data, CacheWasReset);
+ xfree(cp);
+ }
+ }
+ server->caches[cid] = NULL;
+ server->num_caches = 0;
+ server->seed = 0;
+
+ xfree(cache->entries);
+ xfree(cache);
+}
+
+static int
+hash(server, cid, id)
+ XServerPtr server;
+ Cache cid;
+ CacheID id;
+{
+ CachePtr cache = server->caches[cid];
+
+ switch (cache->hashsize) {
+#if INITHASHSIZE < 6
+ case 2:
+ return ((int) (0x03 & (id ^ (id >> 2) ^ (id >> 8))));
+ case 3:
+ return ((int) (0x07 & (id ^ (id >> 3) ^ (id >> 9))));
+ case 4:
+ return ((int) (0x0F & (id ^ (id >> 4) ^ (id >> 10))));
+ case 5:
+ return ((int) (0x01F & (id ^ (id >> 5) ^ (id >> 11))));
+#endif
+ case 6:
+ return ((int) (0x03F & (id ^ (id >> 6) ^ (id >> 12))));
+ case 7:
+ return ((int) (0x07F & (id ^ (id >> 7) ^ (id >> 13))));
+ case 8:
+ return ((int) (0x0FF & (id ^ (id >> 8) ^ (id >> 16))));
+ case 9:
+ return ((int) (0x1FF & (id ^ (id >> 9))));
+ case 10:
+ return ((int) (0x3FF & (id ^ (id >> 10))));
+ case 11:
+ return ((int) (0x7FF & (id ^ (id >> 11))));
+ }
+ return -1;
+}
+
+static void
+rebuild_cache(server, cache)
+ XServerPtr server;
+ CachePtr cache;
+{
+ int j;
+ CacheEntryPtr cp, next, **tails, *entries, **tptr, *cptr;
+
+ j = cache->buckets << 1;
+ tails = (CacheEntryPtr **) ALLOCATE_LOCAL(j * sizeof(CacheEntryPtr *));
+ if (!tails)
+ return;
+ entries = (CacheEntryPtr *) xalloc(j * sizeof(CacheEntryPtr));
+ if (!entries) {
+ DEALLOCATE_LOCAL(tails);
+ return;
+ }
+ for (cptr = entries, tptr = tails; --j >= 0; cptr++, tptr++) {
+ *cptr = NULL;
+ *tptr = cptr;
+ }
+ cache->hashsize++;
+ for (j = cache->buckets, cptr = cache->entries; --j >= 0; cptr++) {
+ for (cp = *cptr; cp; cp = next) {
+ next = cp->next;
+ cp->next = NULL;
+ tptr = &tails[hash(server, cache->id, cp->id)];
+ **tptr = cp;
+ *tptr = &cp->next;
+ }
+ }
+ DEALLOCATE_LOCAL(tails);
+ cache->buckets <<= 1;
+ xfree(cache->entries);
+ cache->entries = entries;
+}
+
+static void
+flush_cache(cache, needed)
+ CachePtr cache;
+ unsigned long needed;
+{
+ CacheEntryPtr cp, *prev, oldest, *oldprev;
+ int i;
+
+ while ((cache->cursize + needed) > cache->maxsize) {
+ oldest = NULL;
+ /* find oldest */
+ for (i = 0; i < cache->buckets; i++) {
+ for (prev = &cache->entries[i]; (cp = *prev); prev = &cp->next) {
+ if (!oldest || (cp->timestamp < oldest->timestamp)) {
+ oldest = cp;
+ oldprev = prev;
+ }
+ }
+ }
+ if (!oldest)
+ break;
+ /* clobber it */
+ cache->elements--;
+ cache->cursize -= oldest->size;
+ *oldprev = oldest->next;
+ (*oldest->free_func) (oldest->id, oldest->client, oldest->data, CacheEntryOld);
+ xfree(oldest);
+ }
+}
+
+Bool
+CacheTrimNeeded(server, cid)
+ XServerPtr server;
+ Cache cid;
+{
+ CachePtr cache = server->caches[cid];
+
+ return cache->cursize > cache->maxsize;
+}
+
+void
+CacheTrim(server, cid)
+ XServerPtr server;
+ Cache cid;
+{
+ flush_cache(server->caches[cid], 0);
+}
+
+Bool
+CacheStoreMemory(server, cid, id, data, size, free_func, can_flush)
+ XServerPtr server;
+ Cache cid;
+ CacheID id;
+ pointer data;
+ unsigned long size;
+ CacheFree free_func;
+ Bool can_flush;
+{
+ CacheEntryPtr cp, *head;
+ CachePtr cache = server->caches[cid];
+
+ if (can_flush && (size > cache->maxsize)) /* beyond cache limits */
+ return FALSE;
+ cp = (CacheEntryPtr) xalloc(sizeof(CacheEntryRec));
+ if (!cp)
+ return FALSE;
+ if (can_flush && ((cache->cursize + size) > cache->maxsize))
+ flush_cache(cache, size);
+ if ((cache->elements >= (cache->buckets << 2)) &&
+ (cache->hashsize < MAXHASHSIZE))
+ rebuild_cache(server, cache);
+ head = &cache->entries[hash(server, cid, id)];
+ cp->next = *head;
+ cp->id = id;
+ cp->timestamp = ++server->seed;
+ cp->free_func = free_func;
+ cp->size = size;
+ cp->data = data;
+ cp->client = server->serverClient;
+ cache->cursize += size;
+ cache->elements++;
+ *head = cp;
+ return TRUE;
+}
+
+pointer
+CacheFetchMemory(server, cid, id, update)
+ XServerPtr server;
+ Cache cid;
+ CacheID id;
+ Bool update;
+{
+ CachePtr cache = server->caches[cid];
+ CacheEntryPtr cp,
+ *head;
+
+ head = &cache->entries[hash(server, cid, id)];
+ for (cp = *head; cp; cp = cp->next) {
+ if (cp->id == id) {
+ if (update)
+ cp->timestamp = ++server->seed;
+ return cp->data;
+ }
+ }
+ return NULL;
+}
+
+void
+CacheFreeMemory(server, cacheid, cid, notify)
+ XServerPtr server;
+ Cache cacheid;
+ CacheID cid;
+ Bool notify;
+{
+ CachePtr cache = server->caches[cacheid];
+ CacheEntryPtr cp, *prev;
+
+ for (prev = &cache->entries[hash(server, cacheid, cid)];
+ (cp = *prev);
+ prev = &cp->next) {
+ if (cp->id == cid) {
+ *prev = cp->next;
+ cache->elements--;
+ cache->cursize -= cp->size;
+ if (notify)
+ (*cp->free_func)(cid, cp->client, cp->data, CacheEntryFreed);
+ xfree(cp);
+ break;
+ }
+ }
+}
diff --git a/di/cmap.c b/di/cmap.c
new file mode 100644
index 0000000..e717c52
--- /dev/null
+++ b/di/cmap.c
@@ -0,0 +1,1772 @@
+/* $Xorg: cmap.c,v 1.5 2001/02/09 02:05:31 xorgcvs Exp $ */
+
+/*
+Copyright 1996, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from The Open Group.
+*/
+
+/*
+ * Copyright 1994 Network Computing Devices, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name Network Computing Devices, Inc. not be
+ * used in advertising or publicity pertaining to distribution of this
+ * software without specific, written prior permission.
+ *
+ * THIS SOFTWARE IS PROVIDED `AS-IS'. NETWORK COMPUTING DEVICES, INC.,
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT
+ * LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, OR NONINFRINGEMENT. IN NO EVENT SHALL NETWORK
+ * COMPUTING DEVICES, INC., BE LIABLE FOR ANY DAMAGES WHATSOEVER, INCLUDING
+ * SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES, INCLUDING LOSS OF USE, DATA,
+ * OR PROFITS, EVEN IF ADVISED OF THE POSSIBILITY THEREOF, AND REGARDLESS OF
+ * WHETHER IN AN ACTION IN CONTRACT, TORT OR NEGLIGENCE, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include <stdio.h>
+#include "assert.h"
+#include "misc.h"
+#include "lbx.h"
+#include "atomcache.h"
+#include "util.h"
+#include "tags.h"
+#include "colormap.h"
+#include "resource.h"
+#include "wire.h"
+#include "swap.h"
+#include "reqtype.h"
+#include "lbxext.h"
+
+static void LocalAllocColor ();
+static void FoundPixel ();
+static Bool grab_cmap_reply();
+static Bool alloc_named_color_reply();
+static Bool alloc_color_cells_reply();
+static Bool alloc_color_planes_reply();
+static Bool lookup_color_reply();
+
+/* ------------------------------------------------------------------------- */
+
+/*
+ * ResolveColor scales down an rgb to the specified number of bits.
+ */
+
+void
+ResolveColor (pVisual, red, green, blue)
+ LbxVisualPtr pVisual;
+ CARD16 *red, *green, *blue;
+{
+ int shift = 16 - pVisual->bitsPerRGB;
+ unsigned lim = (1 << pVisual->bitsPerRGB) - 1;
+ unsigned limr, limg, limb;
+
+ switch (pVisual->class) {
+ case PseudoColor:
+ case DirectColor:
+ case StaticColor:
+ /* rescale to rgb bits */
+ *red = ((*red >> shift) * 65535) / lim;
+ *green = ((*green >> shift) * 65535) / lim;
+ *blue = ((*blue >> shift) * 65535) / lim;
+ break;
+ case GrayScale:
+ /* rescale to gray then rgb bits */
+ *red = (30L * *red + 59L * *green + 11L * *blue) / 100;
+ *blue = *green = *red = ((*red >> shift) * 65535) / lim;
+ break;
+ case StaticGray:
+ limg = pVisual->colormapEntries - 1;
+ /* rescale to gray then [0..limg] then [0..65535] then rgb bits */
+ *red = (30L * *red + 59L * *green + 11L * *blue) / 100;
+ *red = ((((*red * (limg + 1))) >> 16) * 65535) / limg;
+ *blue = *green = *red = ((*red >> shift) * 65535) / lim;
+ break;
+ case TrueColor:
+ limr = NUMRED(pVisual) - 1;
+ limg = NUMGREEN(pVisual) - 1;
+ limb = NUMBLUE(pVisual) - 1;
+ /* rescale to [0..limN] then [0..65535] then rgb bits */
+ *red = ((((((*red * (limr + 1)) >> 16) *
+ 65535) / limr) >> shift) * 65535) / lim;
+ *green = ((((((*green * (limg + 1)) >> 16) *
+ 65535) / limg) >> shift) * 65535) / lim;
+ *blue = ((((((*blue * (limb + 1)) >> 16) *
+ 65535) / limb) >> shift) * 65535) / lim;
+ break;
+ }
+}
+
+void (* LbxResolveColor)(
+#if NeedNestedPrototypes
+ LbxVisualPtr /* pVisual */,
+ CARD16* /* red */,
+ CARD16* /* green */,
+ CARD16* /* blue */
+#endif
+) = ResolveColor;
+
+static Pixel
+find_cell(pent, num, rgb, channel)
+ Entry *pent;
+ int num;
+ CARD32 rgb;
+ int channel;
+{
+ Pixel pixel, freep;
+
+ freep = ~((Pixel)0);
+ for (pixel = 0; pixel < num; pixel++, pent++) {
+ if (pent->status == PIXEL_SHARED) {
+ switch (channel) {
+ case DoRed:
+ if (pent->red == rgb)
+ return pixel;
+ break;
+ case DoGreen:
+ if (pent->green == rgb)
+ return pixel;
+ break;
+ case DoBlue:
+ if (pent->blue == rgb)
+ return pixel;
+ break;
+ }
+ }
+ if (pent->status == PIXEL_FREE && freep == ~((Pixel)0))
+ freep = pixel;
+ }
+ return freep;
+}
+
+/*
+ * Find a free pixel in the colormap.
+ */
+
+Pixel
+FindFreePixel (pmap, red, green, blue)
+ ColormapPtr pmap;
+ CARD32 red, green, blue;
+{
+ Entry *pent;
+ Pixel pixel, p;
+
+ if (pmap->pVisual->class != DirectColor) {
+ for (pixel = 0, pent = pmap->red;
+ pixel < pmap->pVisual->colormapEntries;
+ pixel++, pent++)
+ {
+ if (pent->status == PIXEL_FREE)
+ return pixel;
+ }
+ return ~((Pixel)0);
+ }
+ p = find_cell(pmap->red, NUMRED(pmap->pVisual), red, DoRed);
+ if (p == ~((Pixel)0))
+ return p;
+ pixel = p << pmap->pVisual->offsetRed;
+ p = find_cell(pmap->green, NUMGREEN(pmap->pVisual), green, DoGreen);
+ if (p == ~((Pixel)0))
+ return p;
+ pixel |= p << pmap->pVisual->offsetGreen;
+ p = find_cell(pmap->blue, NUMBLUE(pmap->pVisual), blue, DoBlue);
+ if (p == ~((Pixel)0))
+ return p;
+ pixel |= p << pmap->pVisual->offsetBlue;
+ return pixel;
+}
+
+Pixel (* LbxFindFreePixel)(
+#if NeedNestedPrototypes
+ ColormapPtr /* pmap */,
+ CARD32 /* red */,
+ CARD32 /* green */,
+ CARD32 /* blue */
+#endif
+) = FindFreePixel;
+
+typedef unsigned short BigNumUpper;
+typedef unsigned long BigNumLower;
+
+#define BIGNUMLOWERBITS 24
+#define BIGNUMUPPERBITS 16
+#define BIGNUMLOWER (1 << BIGNUMLOWERBITS)
+#define BIGNUMUPPER (1 << BIGNUMUPPERBITS)
+#define UPPERPART(i) ((i) >> BIGNUMLOWERBITS)
+#define LOWERPART(i) ((i) & (BIGNUMLOWER - 1))
+
+typedef struct _bignum {
+ BigNumUpper upper;
+ BigNumLower lower;
+} BigNumRec, *BigNumPtr;
+
+#define BigNumGreater(x,y) ((x)->upper > (y)->upper ||\
+ (x)->upper == (y)->upper && (x)->lower > (y)->lower)
+
+#define UnsignedToBigNum(u,r) (((r)->upper = UPPERPART(u)), \
+ ((r)->lower = LOWERPART(u)))
+
+#define MaxBigNum(r) (((r)->upper = BIGNUMUPPER-1), \
+ ((r)->lower = BIGNUMLOWER-1))
+
+static void
+BigNumAdd (x, y, r)
+ BigNumPtr x, y, r;
+{
+ BigNumLower lower, carry = 0;
+
+ lower = x->lower + y->lower;
+ if (lower >= BIGNUMLOWER) {
+ lower -= BIGNUMLOWER;
+ carry = 1;
+ }
+ r->lower = lower;
+ r->upper = x->upper + y->upper + carry;
+}
+
+Entry *
+FindBestPixel(pmap, red, green, blue, channels)
+ ColormapPtr pmap;
+ CARD32 red,
+ green,
+ blue;
+ int channels;
+{
+ Entry *pent;
+ int num;
+ Entry *final;
+ Pixel pixel;
+ long dr, dg, db;
+ unsigned long sq;
+ BigNumRec minval, sum, temp;
+
+ switch(channels)
+ {
+ case DoRed:
+ pent = pmap->red;
+ num = NUMRED(pmap->pVisual);
+ break;
+ case DoGreen:
+ pent = pmap->green;
+ num = NUMGREEN(pmap->pVisual);
+ break;
+ case DoBlue:
+ pent = pmap->blue;
+ num = NUMBLUE(pmap->pVisual);
+ break;
+ default:
+ pent = pmap->red;
+ num = pmap->pVisual->colormapEntries;
+ break;
+ }
+ final = pent;
+ MaxBigNum(&minval);
+ /* look for the minimal difference */
+ for (pixel = 0; pixel < num; pent++, pixel++)
+ {
+ dr = dg = db = 0;
+ switch(channels) {
+ case DoRed:
+ dr = pent->red - red;
+ break;
+ case DoGreen:
+ dg = pent->green - green;
+ break;
+ case DoBlue:
+ db = pent->blue - blue;
+ break;
+ default:
+ dr = pent->red - red;
+ dg = pent->green - green;
+ db = pent->blue - blue;
+ break;
+ }
+ sq = dr * dr;
+ UnsignedToBigNum (sq, &sum);
+ sq = dg * dg;
+ UnsignedToBigNum (sq, &temp);
+ BigNumAdd (&sum, &temp, &sum);
+ sq = db * db;
+ UnsignedToBigNum (sq, &temp);
+ BigNumAdd (&sum, &temp, &sum);
+ if (BigNumGreater (&minval, &sum))
+ {
+ final = pent;
+ minval = sum;
+ }
+ }
+ return final;
+}
+
+Entry * (* LbxFindBestPixel)(
+#if NeedNestedPrototypes
+ ColormapPtr /* pmap */,
+ CARD32 /* red */,
+ CARD32 /* green */,
+ CARD32 /* blue */,
+ int /* channels */
+#endif
+) = FindBestPixel;
+
+
+/* ------------------------------------------------------------------------- */
+
+#define PIX_IN(ptr,is2,dst) \
+ if (is2) { \
+ dst = *ptr++ << 8; dst |= *ptr++; \
+ } else \
+ dst = *ptr++
+
+#define RGB_IN(ptr,is2,lim,dst) \
+ if (is2) { \
+ dst = *ptr++ << 8; dst |= *ptr++; \
+ } else \
+ dst = (*ptr++ * 65535) / lim
+
+static CARD8 *
+DecodeChannel(pmap, pent, flags, channels, data)
+ ColormapPtr pmap;
+ Entry *pent;
+ CARD8 flags;
+ CARD8 channels;
+ CARD8 *data;
+{
+ Bool px2;
+ Bool rgb2;
+ CARD16 pixel1, pixel2;
+ int i;
+ int lim;
+ CARD8 code;
+
+ px2 = (flags & LBX_2BYTE_PIXELS) != 0;
+ rgb2 = (flags & LBX_RGB_BITS_MASK) > 7;
+ lim = (1 << ((flags & LBX_RGB_BITS_MASK) + 1)) - 1;
+ /*
+ * All pixels other than the ones specified in the GrabCmap reply
+ * are implied to be free. Mark all the cells free now, and then
+ * mark the cells specified in the GrabCmap reply either:
+ *
+ * PIXEL_PRIVATE - a read/write cell - proxy can't do local alloc
+ * in this cell. We don't care about the contents.
+ * PIXEL_SHARED - a read only cell that can be shared.
+ */
+
+ for (i = 0; i < pmap->pVisual->colormapEntries; i++)
+ {
+ if ((pent[i].status == PIXEL_SHARED && pent[i].refcnt == 0) ||
+ (pent[i].status == PIXEL_PRIVATE && pent[i].server_ref))
+ pent[i].status = PIXEL_FREE;
+ }
+
+ while ((code = *data++))
+ {
+ if (code == LBX_PIXEL_PRIVATE)
+ {
+ PIX_IN(data, px2, pixel1);
+
+ pent[pixel1].pixel = pixel1;
+ if (pent[pixel1].status != PIXEL_PRIVATE)
+ pent[pixel1].server_ref = 1;
+ pent[pixel1].status = PIXEL_PRIVATE;
+
+#ifdef COLOR_DEBUG
+ fprintf (stderr, "Got PIXEL_PRIVATE, pixel = %d\n", pixel1);
+#endif
+ }
+ else if (code == LBX_PIXEL_RANGE_PRIVATE)
+ {
+ PIX_IN(data, px2, pixel1);
+ PIX_IN(data, px2, pixel2);
+
+ for (i = pixel1; i <= pixel2; i++)
+ {
+ pent[i].pixel = i;
+ if (pent[i].status != PIXEL_PRIVATE)
+ pent[i].server_ref = 1;
+ pent[i].status = PIXEL_PRIVATE;
+ }
+
+#ifdef COLOR_DEBUG
+ fprintf (stderr, "Got PIXEL_RANGE_PRIVATE, pixels = %d...%d\n",
+ pixel1, pixel2);
+#endif
+ }
+ else if (code == LBX_PIXEL_SHARED)
+ {
+ PIX_IN(data, px2, pixel1);
+
+ pent[pixel1].pixel = pixel1;
+ if (pent[pixel1].status != PIXEL_SHARED)
+ pent[pixel1].refcnt = 0;
+ pent[pixel1].status = PIXEL_SHARED;
+ pent[pixel1].server_ref = 1;
+ if (channels & DoRed) {
+ RGB_IN(data, rgb2, lim, pent[pixel1].red);
+ }
+ if (channels & DoGreen) {
+ RGB_IN(data, rgb2, lim, pent[pixel1].green);
+ }
+ if (channels & DoBlue) {
+ RGB_IN(data, rgb2, lim, pent[pixel1].blue);
+ }
+
+#ifdef COLOR_DEBUG
+ fprintf (stderr,
+ "Got PIXEL_SHARED, pixel = %d, rgb = (%d,%d,%d)\n",
+ pixel1, pent[pixel1].red, pent[pixel1].green,
+ pent[pixel1].blue);
+#endif
+ }
+ else if (code == LBX_PIXEL_RANGE_SHARED)
+ {
+ PIX_IN(data, px2, pixel1);
+ PIX_IN(data, px2, pixel2);
+
+#ifdef COLOR_DEBUG
+ fprintf (stderr, "Got PIXEL_RANGE_SHARED, pixels = %d...%d\n",
+ pixel1, pixel2);
+#endif
+
+ for (i = pixel1; i <= pixel2; i++)
+ {
+ pent[i].pixel = i;
+ if (pent[i].status != PIXEL_SHARED)
+ pent[i].refcnt = 0;
+ pent[i].status = PIXEL_SHARED;
+ pent[i].server_ref = 1;
+ if (channels & DoRed) {
+ RGB_IN(data, rgb2, lim, pent[i].red);
+ }
+ if (channels & DoGreen) {
+ RGB_IN(data, rgb2, lim, pent[i].green);
+ }
+ if (channels & DoBlue) {
+ RGB_IN(data, rgb2, lim, pent[i].blue);
+ }
+
+#ifdef COLOR_DEBUG
+ fprintf (stderr, " pixel = %d, rgb = (%d,%d,%d)\n",
+ i, pent[i].red, pent[i].green, pent[i].blue);
+#endif
+ }
+ }
+ else
+ break;
+ }
+ return data;
+}
+
+static void
+GotColormapGrab (pmap, flags, data)
+ ColormapPtr pmap;
+ CARD8 flags;
+ CARD8 *data;
+{
+
+ pmap->grab_status = CMAP_GRABBED;
+
+ if (flags & LBX_SMART_GRAB)
+ {
+ /*
+ * We have a SMART GRAB : since this proxy last ungrabbed the
+ * colormap, no color cell was alloc'd by an entity other than
+ * this proxy (this includes other proxies as well as clients
+ * directly connected to the X server without a proxy).
+ *
+ * We want to optimize this special case because a proxy may give
+ * up a grab because it got a request that it could not handle
+ * (e.g. AllocNamedColor or LookupColor). When it asks back for
+ * the grab, there is no need for the server to send the colormap
+ * state, because the proxy is already up to date on the state of
+ * the colormap.
+ *
+ * In order for this to work, the following assumptions are made
+ * about the proxy:
+ *
+ * - the proxy is kept up to date on all cell allocations made on its
+ * behalf resulting from the following requests: AllocNamedColor,
+ * AllocColorCells, AllocColorPlanes
+ * - the proxy is kept up to date on all cells freed by any client
+ * via the LbxFreeCell event.
+ */
+
+ return;
+ }
+
+ if ((pmap->pVisual->class | DynamicClass) != DirectColor)
+ DecodeChannel(pmap, pmap->red, flags, DoRed|DoGreen|DoBlue, data);
+ else {
+ data = DecodeChannel(pmap, pmap->red, flags, DoRed, data);
+ data = DecodeChannel(pmap, pmap->green, flags, DoGreen, data);
+ DecodeChannel(pmap, pmap->blue, flags, DoBlue, data);
+ }
+}
+
+static void
+GrabCmap (client, pmap, red, green, blue, alloc_named, xred, xgreen, xblue)
+ ClientPtr client;
+ ColormapPtr pmap;
+ CARD16 red, green, blue;
+ Bool alloc_named;
+ CARD16 xred, xgreen, xblue;
+{
+ xLbxGrabCmapReq req;
+ ReplyStuffPtr nr;
+
+#ifdef COLOR_DEBUG
+ fprintf (stderr, "LbxGrabCmapReq: cmap = 0x%x, seq = 0x%x\n",
+ pmap->id, LBXSequenceNumber(client));
+ fprintf (stderr, "suspending %s (%d, %d, %d)\n",
+ alloc_named ? "AllocNamedColor" : "AllocColor",
+ red, green, blue);
+#endif
+
+ nr = NewReply(client, client->server->lbxReq, X_LbxGrabCmap,
+ grab_cmap_reply);
+ if (nr)
+ {
+ --nr->sequenceNumber;
+ nr->request_info.lbxgrabcmap.pmap = pmap;
+ nr->request_info.lbxgrabcmap.alloc_named = alloc_named;
+ nr->request_info.lbxgrabcmap.vred = red;
+ nr->request_info.lbxgrabcmap.vgreen = green;
+ nr->request_info.lbxgrabcmap.vblue = blue;
+ nr->request_info.lbxgrabcmap.xred = xred;
+ nr->request_info.lbxgrabcmap.xgreen = xgreen;
+ nr->request_info.lbxgrabcmap.xblue = xblue;
+ }
+
+ req.reqType = client->server->lbxReq;
+ req.lbxReqType = X_LbxGrabCmap;
+ req.length = sz_xLbxGrabCmapReq >> 2;
+ req.cmap = pmap->id;
+
+ if (client->swapped)
+ SwapGrabCmap (&req);
+
+ WriteReqToServer (client, sz_xLbxGrabCmapReq, (char *) &req, TRUE);
+
+ pmap->grab_status = CMAP_GRAB_REQUESTED;
+}
+
+static Bool
+grab_cmap_reply(client, nr, data)
+ ClientPtr client;
+ ReplyStuffPtr nr;
+ char *data;
+{
+ xLbxGrabCmapReply *reply;
+ Entry *pent;
+
+ reply = (xLbxGrabCmapReply *) data;
+
+#ifdef COLOR_DEBUG
+ fprintf (stderr, "LbxGrabCmapReply: cmap = 0x%x, seq = 0x%x, ",
+ nr->request_info.lbxgrabcmap.pmap->id, reply->sequenceNumber);
+ fprintf (stderr, "flags = %x\n", reply->flags);
+ fprintf (stderr, "resuming %s (%d, %d, %d)\n",
+ nr->request_info.lbxgrabcmap.alloc_named ?
+ "AllocNamedColor" : "AllocColor",
+ nr->request_info.lbxgrabcmap.vred,
+ nr->request_info.lbxgrabcmap.vgreen,
+ nr->request_info.lbxgrabcmap.vblue);
+#endif
+
+ GotColormapGrab (nr->request_info.lbxgrabcmap.pmap, reply->flags,
+ (CARD8 *) reply + sz_xLbxGrabCmapReplyHdr);
+
+ /*
+ * We suspended an AllocColor request so we could grab the colormap.
+ * Now that the colormap is grabbed we resume handling the AllocColor.
+ * We first check to see if the color is already allocated.
+ */
+
+ FindPixel (client,
+ nr->request_info.lbxgrabcmap.pmap,
+ nr->request_info.lbxgrabcmap.vred,
+ nr->request_info.lbxgrabcmap.vgreen,
+ nr->request_info.lbxgrabcmap.vblue,
+ &pent);
+
+ if (pent)
+ {
+ /*
+ * We found the pixel in the proxy's colormap. We can
+ * immediately short circuit this AllocColor.
+ */
+
+ FoundPixel (client, TRUE, nr->request_info.lbxgrabcmap.pmap, pent,
+ nr->request_info.lbxgrabcmap.alloc_named,
+ nr->request_info.lbxgrabcmap.xred,
+ nr->request_info.lbxgrabcmap.xgreen,
+ nr->request_info.lbxgrabcmap.xblue);
+ }
+ else
+ {
+ /*
+ * We didn't find the pixel, but we just grabbed the color map,
+ * so we can handle the color allocation locally now, then do
+ * the short circuit.
+ */
+
+ LocalAllocColor (client, TRUE,
+ nr->request_info.lbxgrabcmap.pmap,
+ nr->request_info.lbxgrabcmap.vred,
+ nr->request_info.lbxgrabcmap.vgreen,
+ nr->request_info.lbxgrabcmap.vblue,
+ nr->request_info.lbxgrabcmap.alloc_named,
+ nr->request_info.lbxgrabcmap.xred,
+ nr->request_info.lbxgrabcmap.xgreen,
+ nr->request_info.lbxgrabcmap.xblue);
+ }
+
+ return TRUE;
+}
+
+
+/*
+ * Release the colormap currently grabbed by the proxy.
+ */
+
+void
+ReleaseCmap (client, pmap)
+ ClientPtr client;
+ ColormapPtr pmap;
+{
+ xLbxReleaseCmapReq req;
+
+ pmap->grab_status = CMAP_NOT_GRABBED;
+
+ req.reqType = client->server->lbxReq;
+ req.lbxReqType = X_LbxReleaseCmap;
+ req.length = sz_xLbxReleaseCmapReq >> 2;
+ req.cmap = pmap->id;
+
+ /* write the request on the proxy control connection */
+
+ WriteReqToServer (client->server->serverClient,
+ sz_xLbxReleaseCmapReq,
+ (char *) &req,
+ FALSE);
+}
+
+/* ------------------------------------------------------------------------- */
+
+static void
+DoAllocColorReply (client, in_reply, red, green, blue, pixel)
+ ClientPtr client;
+ Bool in_reply;
+ CARD16 red, green, blue;
+ Pixel pixel;
+{
+ /*
+ * Prepare the AllocColor reply for the client.
+ */
+
+ xAllocColorReply reply;
+
+ reply.type = X_Reply;
+ reply.length = 0;
+ reply.sequenceNumber = LBXSequenceNumber(client);
+
+ reply.red = red;
+ reply.green = green;
+ reply.blue = blue;
+ reply.pixel = pixel;
+
+ if (client->swapped)
+ SwapAllocColorReply (&reply);
+
+ if (LBXCacheSafe (client))
+ {
+ /*
+ * We can write the AllocColor reply now.
+ */
+
+ if (!in_reply)
+ FinishLBXRequest(client, REQ_REPLACE);
+
+ WriteToClient (client, sizeof (xAllocColorReply), &reply);
+
+#ifdef LBX_STATS
+ ac_good++;
+#endif
+ }
+ else
+ {
+ /*
+ * We can't write the AllocColor reply now, we must first sync.
+ */
+
+ if (!LBXCanDelayReply(client))
+ SendLbxSync (client);
+ if (!in_reply)
+ FinishLBXRequest(client, REQ_REPLACELATE);
+
+ /*
+ * Save the AllocColor reply. We will write it when the
+ * LbxSync reply comes back.
+ */
+
+ SaveReplyData (client, (xReply *) & reply, 0, NULL);
+ }
+}
+
+static void
+DoAllocNamedColorReply (client, in_reply, red, green, blue, pixel,
+ xred, xgreen, xblue)
+ ClientPtr client;
+ Bool in_reply;
+ CARD16 red, green, blue;
+ Pixel pixel;
+ CARD16 xred, xgreen, xblue;
+{
+ /*
+ * Prepare the AllocNamedColor reply for the client.
+ */
+
+ xAllocNamedColorReply reply;
+
+ reply.type = X_Reply;
+ reply.length = 0;
+ reply.sequenceNumber = LBXSequenceNumber(client);
+
+ reply.exactRed = xred;
+ reply.exactGreen = xgreen;
+ reply.exactBlue = xblue;
+ reply.screenRed = red;
+ reply.screenGreen = green;
+ reply.screenBlue = blue;
+ reply.pixel = pixel;
+
+ if (client->swapped)
+ SwapAllocNamedColorReply (&reply);
+
+ if (LBXCacheSafe (client))
+ {
+ /*
+ * We can write the AllocColor reply now.
+ */
+
+ if (!in_reply)
+ FinishLBXRequest(client, REQ_REPLACE);
+
+ WriteToClient (client, sizeof (xAllocNamedColorReply), &reply);
+
+#ifdef LBX_STATS
+ anc_good++;
+#endif
+ }
+ else
+ {
+ /*
+ * We can't write the AllocColor reply now, we must first sync.
+ */
+
+ if (!LBXCanDelayReply(client))
+ SendLbxSync (client);
+ if (!in_reply)
+ FinishLBXRequest(client, REQ_REPLACELATE);
+
+ /*
+ * We can't write the AllocNamedColor reply now, we must first
+ * sync. You might ask why we didn't just send the AllocNamedColor
+ * request to the server? The answer is that if the colormap is
+ * grabbed, we don't want to send the AllocNamedColor to the server
+ * because that would force the proxy to give up control over the
+ * colormap. So the proxy generates the reply on its own, but must
+ * force a round trip sync before the reply is written.
+ */
+
+ SaveReplyData (client, (xReply *) & reply, 0, NULL);
+
+#ifdef LBX_STATS
+ anc_miss++;
+#endif
+ }
+}
+
+/*
+ * LocalAllocColor is called when the specified color is not already
+ * allocated in the colormap, and the proxy has the colormap grabbed.
+ * The proxy handles the AllocColor locally, and tells the server
+ * what allocation it made.
+ *
+ * (red, green, blue) are actual rgb values, not requested ones -
+ * they have already been put through ResolveColor.
+ */
+
+static void
+LocalAllocColor (client, in_reply, pmap, red, green, blue, alloc_named,
+ xred, xgreen, xblue)
+ ClientPtr client;
+ Bool in_reply;
+ ColormapPtr pmap;
+ CARD16 red, green, blue;
+ Bool alloc_named;
+ CARD16 xred, xgreen, xblue;
+{
+ Pixel pixel;
+
+ /*
+ * First find a free cell.
+ */
+
+ pixel = (*LbxFindFreePixel) (pmap, red, green, blue);
+
+ if (pixel == ~((Pixel)0))
+ {
+#ifdef COLOR_DEBUG
+ fprintf(stderr, "alloc failed: (%d, %d, %d)\n", red, green, blue);
+#endif
+ if (in_reply)
+ WriteError(client,
+ alloc_named ? X_AllocNamedColor : X_AllocColor,
+ 0, pmap->id, BadAlloc);
+ else
+ SendErrorToClient(client,
+ alloc_named ? X_AllocNamedColor : X_AllocColor,
+ 0, pmap->id, BadAlloc);
+ return;
+ }
+
+#ifdef COLOR_DEBUG
+ if (LBXCacheSafe (client))
+ fprintf (stderr,
+ "X %s: short circuiting (allocating color locally):\n",
+ alloc_named ? "AllocNamedColor" : "AllocColor");
+ else
+ fprintf (stderr,
+ "X %s: allocating color locally, but need Sync:\n",
+ alloc_named ? "AllocNamedColor" : "AllocColor");
+
+ fprintf (stderr,
+ " seq = 0x%x, cmap = 0x%x, pixel = %d, rgb = (%d,%d,%d)\n",
+ LBXSequenceNumber(client), pmap->id, pixel, red, green, blue);
+#endif
+
+ /*
+ * Now handle the X AllocColor reply to the client.
+ */
+
+ if (alloc_named)
+ DoAllocNamedColorReply (client, in_reply, red, green, blue, pixel,
+ xred, xgreen, xblue);
+ else
+ DoAllocColorReply (client, in_reply, red, green, blue, pixel);
+
+ /*
+ * Store the rgb in the cell.
+ */
+
+ StorePixel (client, pmap, red, green, blue, pixel, FALSE);
+}
+
+
+static void
+FoundPixel (client, in_reply, pmap, pent, alloc_named, xred, xgreen, xblue)
+ ClientPtr client;
+ Bool in_reply;
+ ColormapPtr pmap;
+ Entry *pent;
+ Bool alloc_named;
+ CARD16 xred, xgreen, xblue;
+{
+#ifdef COLOR_DEBUG
+ if (LBXCacheSafe (client))
+ fprintf (stderr,
+ "X %s: short circuiting (color already exists):\n",
+ alloc_named ? "AllocNamedColor" : "AllocColor");
+ else
+ {
+ fprintf (stderr,
+ "X %s: color already exists locally, but need Sync:\n",
+ alloc_named ? "AllocNamedColor" : "AllocColor");
+ }
+
+ fprintf (stderr,
+ " seq = 0x%x, cmap = 0x%x, pixel = %d, rgb = (%d,%d,%d)\n",
+ LBXSequenceNumber(client), pmap->id, pent->pixel,
+ pent->red, pent->green, pent->blue);
+#endif
+
+ /*
+ * Now handle the X AllocColor reply to the client.
+ */
+
+ if (alloc_named)
+ DoAllocNamedColorReply (client, in_reply,
+ pent->red, pent->green, pent->blue,
+ pent->pixel, xred, xgreen, xblue);
+ else
+ DoAllocColorReply (client, in_reply,
+ pent->red, pent->green, pent->blue, pent->pixel);
+
+ /*
+ * We found a match. Increment our ref count and tell the
+ * server to bump up its own ref count.
+ */
+
+ IncrementPixel (client, pmap, pent, FALSE);
+}
+
+
+/* ------------------------------------------------------------------------- */
+
+int
+ProcLBXCreateColormap(client)
+ ClientPtr client;
+{
+ REQUEST(xCreateColormapReq);
+ Colormap cmap;
+ VisualID vis;
+ char n;
+
+ /* AllocAll are read/write, so ignore */
+ if (stuff->alloc) {
+ cmap = stuff->mid;
+ vis = stuff->visual;
+ if (client->swapped) {
+ swapl(&cmap, n);
+ swapl(&vis, n);
+ }
+ CreateColormap(client, cmap, vis);
+ }
+
+ return ProcStandardRequest(client);
+}
+
+static ColormapPtr
+create_colormap(cmap, visual)
+ Colormap cmap;
+ VisualID visual;
+{
+ ColormapPtr pmap;
+ LbxVisualPtr pvis;
+ int tsize, csize;
+ Pixel **pptr;
+
+ pvis = GetVisual(visual);
+ csize = pvis->colormapEntries;
+ tsize = (csize * sizeof(Entry)) + (MAXCLIENTS * sizeof(Pixel *)) +
+ (MAXCLIENTS * sizeof(int));
+ if ((pvis->class | DynamicClass) == DirectColor)
+ tsize *= 3;
+ tsize += sizeof(ColormapRec);
+ pmap = (ColormapPtr) xalloc(tsize);
+ if (!pmap)
+ return pmap;
+ bzero((char *) pmap, tsize);
+ pmap->id = cmap;
+ pmap->pVisual = pvis;
+ pmap->grab_status = CMAP_NOT_GRABBED;
+ pmap->red = (Entry *) ((char *) pmap + sizeof(ColormapRec));
+ pmap->clientPixelsRed = (Pixel **)
+ ((char *) pmap->red + (csize * sizeof(Entry)));
+ pmap->numPixelsRed = (int *) ((char *) pmap->clientPixelsRed +
+ (MAXCLIENTS * sizeof(Pixel *)));
+ bzero((char *) pmap->red, (csize * sizeof(Entry)));
+ bzero((char *) pmap->numPixelsRed, (MAXCLIENTS * sizeof(int)));
+ for (pptr = &pmap->clientPixelsRed[MAXCLIENTS];
+ --pptr >= pmap->clientPixelsRed; )
+ *pptr = (Pixel *) NULL;
+ if ((pvis->class | DynamicClass) != DirectColor) {
+ pmap->green = NULL;
+ pmap->numPixelsGreen = NULL;
+ pmap->clientPixelsGreen = NULL;
+ pmap->blue = NULL;
+ pmap->numPixelsBlue = NULL;
+ pmap->clientPixelsBlue = NULL;
+ return pmap;
+ }
+ pmap->green = (Entry *) ((char *) pmap->numPixelsRed +
+ (MAXCLIENTS * sizeof(int)));
+ pmap->clientPixelsGreen = (Pixel **)
+ ((char *) pmap->green + (csize * sizeof(Entry)));
+ pmap->numPixelsGreen = (int *) ((char *) pmap->clientPixelsGreen +
+ (MAXCLIENTS * sizeof(Pixel *)));
+ bzero((char *) pmap->green, (csize * sizeof(Entry)));
+ bzero((char *) pmap->numPixelsGreen, (MAXCLIENTS * sizeof(int)));
+ for (pptr = &pmap->clientPixelsGreen[MAXCLIENTS];
+ --pptr >= pmap->clientPixelsGreen; )
+ *pptr = (Pixel *) NULL;
+ pmap->blue = (Entry *) ((char *) pmap->numPixelsGreen +
+ (MAXCLIENTS * sizeof(int)));
+ pmap->clientPixelsBlue = (Pixel **)
+ ((char *) pmap->blue + (csize * sizeof(Entry)));
+ pmap->numPixelsBlue = (int *) ((char *) pmap->clientPixelsBlue +
+ (MAXCLIENTS * sizeof(Pixel *)));
+ bzero((char *) pmap->blue, (csize * sizeof(Entry)));
+ bzero((char *) pmap->numPixelsBlue, (MAXCLIENTS * sizeof(int)));
+ for (pptr = &pmap->clientPixelsBlue[MAXCLIENTS];
+ --pptr >= pmap->clientPixelsBlue; )
+ *pptr = (Pixel *) NULL;
+ return pmap;
+}
+
+/* ARGSUSED */
+Bool
+CreateColormap(client, cmap, visual)
+ ClientPtr client;
+ Colormap cmap;
+ VisualID visual;
+{
+ ColormapPtr pmap;
+
+ pmap = create_colormap(cmap, visual);
+ if (!pmap)
+ return FALSE;
+ return AddResource(client, cmap, RT_COLORMAP, (pointer) pmap);
+}
+
+/* ------------------------------------------------------------------------- */
+
+
+int
+ProcLBXFreeColormap(client)
+ ClientPtr client;
+{
+ REQUEST(xResourceReq);
+ Colormap cmap;
+ char n;
+
+ cmap = stuff->id;
+ if (client->swapped) {
+ swapl(&cmap, n);
+ }
+ FreeColormap(client, cmap);
+
+ return ProcStandardRequest(client);
+}
+
+/* ARGSUSED */
+Bool
+FreeColormap(client, cmap)
+ ClientPtr client;
+ Colormap cmap;
+{
+ ColormapPtr pmap;
+
+ pmap = (ColormapPtr) LookupIDByType(client, cmap, RT_COLORMAP);
+ if (!pmap)
+ return FALSE;
+ FreeResource(client, cmap, RT_NONE);
+ return TRUE;
+}
+
+/* ------------------------------------------------------------------------- */
+
+/*
+ * cop out: don't try to track the new colormap
+ */
+int
+ProcLBXCopyColormapAndFree(client)
+ ClientPtr client;
+{
+ REQUEST(xCopyColormapAndFreeReq);
+ Colormap srcmap;
+ ColormapPtr pmap;
+ char n;
+
+ srcmap = stuff->srcCmap;
+ if (client->swapped) {
+ swapl(&srcmap, n);
+ }
+ pmap = (ColormapPtr) LookupIDByType(client, srcmap, RT_COLORMAP);
+ if (pmap)
+ FreeAllClientPixels(pmap, client->index);
+
+ return ProcStandardRequest(client);
+}
+
+/* ------------------------------------------------------------------------- */
+
+int
+ProcLBXFreeColors(client)
+ ClientPtr client;
+{
+ REQUEST(xFreeColorsReq);
+ int num;
+ Pixel *pixels;
+ CARD32 mask;
+ Colormap cmap;
+ Bool freepix = FALSE;
+ int n;
+ CARD16 len;
+ ColormapPtr pmap;
+
+ mask = stuff->planeMask;
+ cmap = stuff->cmap;
+ len = stuff->length;
+
+ if (client->swapped) {
+ swapl(&cmap, n);
+ swapl(&mask, n);
+ swaps(&len, n);
+ }
+ pmap = (ColormapPtr) LookupIDByType(client, cmap, RT_COLORMAP);
+ if (!pmap)
+ return ProcStandardRequest(client);
+
+ num = ((len << 2) - sizeof(xFreeColorsReq)) >> 2;
+
+ if (client->swapped) {
+ pixels = (Pixel *) ALLOCATE_LOCAL(num * sizeof(Pixel));
+ if (pixels) {
+ memcpy((char *) pixels, (char *) &stuff[1], (num * sizeof(Pixel)));
+ SwapLongs((CARD32 *) pixels, num);
+ }
+ freepix = TRUE;
+ } else
+ pixels = (Pixel *) &stuff[1];
+
+#ifdef COLOR_DEBUG
+ fprintf(stderr, "freeing on cmap 0x%x mask: %d pixels:", cmap, mask);
+ for (n = 0; n < num; n++)
+ fprintf(stderr, " %d", pixels[n]);
+ fprintf(stderr, "\n");
+#endif
+ FreePixels(client, pmap, num, pixels, mask);
+
+ if (freepix)
+ DEALLOCATE_LOCAL(pixels);
+
+ return ProcStandardRequest(client);
+}
+
+/* ------------------------------------------------------------------------- */
+
+int
+ProcLBXAllocColor(client)
+ ClientPtr client;
+{
+ REQUEST(xAllocColorReq);
+ Entry *pent;
+ Colormap cmap;
+ ColormapPtr pmap;
+ CARD16 red, green, blue;
+ char n;
+
+ cmap = stuff->cmap;
+
+ if (client->swapped)
+ swapl(&cmap, n);
+
+ pmap = (ColormapPtr) LookupIDByType (client, cmap, RT_COLORMAP);
+
+ if (!pmap)
+ return ProcStandardRequest(client);
+
+ red = stuff->red;
+ green = stuff->green;
+ blue = stuff->blue;
+
+ if (client->swapped)
+ {
+ swaps(&red, n);
+ swaps(&green, n);
+ swaps(&blue, n);
+ }
+
+
+ /*
+ * Resolve the color (requested rgb -> actual rgb)
+ */
+
+ (*LbxResolveColor)(pmap->pVisual, &red, &green, &blue);
+
+
+ /*
+ * Search for the pixel in the proxy's colormap.
+ */
+
+ FindPixel (client, pmap, red, green, blue, &pent);
+
+ if (pent && (pent->refcnt || pmap->grab_status == CMAP_GRABBED))
+ {
+ /*
+ * We found the pixel in the proxy's colormap. We can
+ * short circuit this AllocColor.
+ */
+
+ FoundPixel (client, FALSE, pmap, pent, FALSE, 0, 0, 0);
+ }
+ else if (pmap->grab_status == CMAP_GRABBED)
+ {
+ /*
+ * The color map is already grabbed by the proxy, so we
+ * can handle the AllocColor locally now.
+ */
+
+ LocalAllocColor(client, FALSE, pmap, red, green, blue, FALSE, 0, 0, 0);
+ }
+ else
+ {
+ /*
+ * The proxy must first grab the color map. Then it can
+ * handle the AllocColor.
+ */
+
+ FinishLBXRequest(client, REQ_REPLACELATE);
+
+ GrabCmap(client, pmap, red, green, blue, FALSE, 0, 0, 0);
+ }
+ return Success;
+}
+
+/* ------------------------------------------------------------------------- */
+
+int
+ProcLBXAllocNamedColor(client)
+ ClientPtr client;
+{
+ REQUEST(xAllocNamedColorReq);
+ Entry *pent;
+ RGBEntryPtr rgbe;
+ ReplyStuffPtr nr;
+ CARD16 nbytes;
+ Colormap cmap;
+ ColormapPtr pmap;
+ char n;
+
+ cmap = stuff->cmap;
+ nbytes = stuff->nbytes;
+
+ if (client->swapped) {
+ swapl(&cmap, n);
+ swaps(&nbytes, n);
+ }
+
+ pmap = (ColormapPtr) LookupIDByType (client, cmap, RT_COLORMAP);
+
+ if (nbytes > MAX_COLORNAME_LENGTH || !pmap)
+ return ProcStandardRequest(client);
+
+ pent = NULL;
+ rgbe = FindColorName(client->server, (char *) &stuff[1], nbytes,
+ pmap->pVisual);
+ if (rgbe) {
+#ifdef COLOR_DEBUG
+ fprintf(stderr, "looking for %.*s = (%d,%d,%d)\n", nbytes,
+ (char *)&stuff[1], rgbe->vred, rgbe->vgreen, rgbe->vblue);
+#endif
+ FindPixel (client, pmap, rgbe->vred, rgbe->vgreen, rgbe->vblue, &pent);
+ }
+ if (pent && (pent->refcnt || pmap->grab_status == CMAP_GRABBED)) {
+ FoundPixel (client, FALSE, pmap, pent, TRUE,
+ rgbe->xred, rgbe->xgreen, rgbe->xblue);
+ } else if (rgbe) {
+ if (pmap->grab_status == CMAP_GRABBED) {
+ /*
+ * The color map is already grabbed by the proxy, so we
+ * can handle the AllocNamedColor locally now.
+ */
+
+ LocalAllocColor (client, FALSE, pmap,
+ rgbe->vred, rgbe->vgreen, rgbe->vblue,
+ TRUE,
+ rgbe->xred, rgbe->xgreen, rgbe->xblue);
+ } else {
+ FinishLBXRequest(client, REQ_REPLACELATE);
+ GrabCmap(client, pmap,
+ rgbe->vred, rgbe->vgreen, rgbe->vblue,
+ TRUE, rgbe->xred, rgbe->xgreen, rgbe->xblue);
+ }
+ } else {
+
+ /*
+ * We can't short circuit the AllocNamedColor request.
+ * The proxy will need control over the colormap to handle
+ * this request, so rather than wait for the server to ask
+ * the proxy to release the colormap, we release it now.
+ */
+
+ if (pmap->grab_status == CMAP_GRABBED &&
+ (pmap->pVisual->class & DynamicClass))
+ ReleaseCmap (client, pmap);
+
+
+ /*
+ * We need to catch the AllocNamedColor reply so we can cache
+ * the results for future short circuiting.
+ */
+
+ nr = NewReply(client, X_AllocNamedColor, 0, alloc_named_color_reply);
+ if (!nr)
+ return ProcStandardRequest(client);
+ nr->request_info.xallocnamedcolor.pmap = pmap;
+ strncpy(nr->request_info.xallocnamedcolor.name, (char *) &stuff[1],
+ nbytes);
+ nr->request_info.xallocnamedcolor.namelen = nbytes;
+
+#ifdef COLOR_DEBUG
+ fprintf (stderr, "X AllocNamedColor: could not short circuit\n");
+ fprintf (stderr, " seq = 0x%x, cmap = 0x%x\n",
+ LBXSequenceNumber(client), cmap);
+#endif
+
+#ifdef LBX_STATS
+ anc_miss++;
+#endif
+ return ProcStandardRequest(client);
+ }
+ return Success;
+}
+
+static Bool
+alloc_named_color_reply(client, nr, data)
+ ClientPtr client;
+ ReplyStuffPtr nr;
+ char *data;
+{
+ xAllocNamedColorReply *reply;
+ Pixel pixel;
+ char n;
+ RGBEntryRec rgbe;
+
+ reply = (xAllocNamedColorReply *) data;
+
+ rgbe.xred = reply->exactRed;
+ rgbe.xgreen = reply->exactGreen;
+ rgbe.xblue = reply->exactBlue;
+ rgbe.vred = reply->screenRed;
+ rgbe.vgreen = reply->screenGreen;
+ rgbe.vblue = reply->screenBlue;
+ pixel = reply->pixel;
+
+ if (client->swapped) {
+ swapl(&pixel, n);
+ swaps(&rgbe.xred, n);
+ swaps(&rgbe.xgreen, n);
+ swaps(&rgbe.xblue, n);
+ swaps(&rgbe.vred, n);
+ swaps(&rgbe.vgreen, n);
+ swaps(&rgbe.vblue, n);
+ }
+
+#ifdef COLOR_DEBUG
+ fprintf (stderr,
+ "X AllocNamedColorReply: caching results\n");
+ fprintf (stderr, "pixel = %d, rgb = (%d,%d,%d)\n",
+ pixel, rgbe.vred, rgbe.vgreen, rgbe.vblue);
+#endif
+
+ AddColorName(client->server,
+ nr->request_info.xallocnamedcolor.name,
+ nr->request_info.xallocnamedcolor.namelen,
+ &rgbe);
+
+ return StorePixel(client, nr->request_info.xallocnamedcolor.pmap,
+ rgbe.vred, rgbe.vgreen, rgbe.vblue, pixel, TRUE);
+}
+
+/* ------------------------------------------------------------------------- */
+
+int
+ProcLBXAllocColorCells(client)
+ ClientPtr client;
+{
+ REQUEST(xAllocColorCellsReq);
+ ReplyStuffPtr nr;
+ Colormap cmap;
+ ColormapPtr pmap;
+ char n;
+
+ cmap = stuff->cmap;
+ if (client->swapped)
+ swapl(&cmap, n);
+
+ pmap = (ColormapPtr) LookupIDByType (client, cmap, RT_COLORMAP);
+
+ if (!pmap)
+ return ProcStandardRequest(client);
+ if (!(pmap->pVisual->class & DynamicClass))
+ return BadAlloc;
+
+ /*
+ * We don't short circuit AllocColorCells requests.
+ * The server will need control over the colormap to handle
+ * this request, so rather than wait for the server to ask
+ * the proxy to release the colormap, we release it now.
+ */
+
+ if (pmap->grab_status == CMAP_GRABBED)
+ ReleaseCmap (client, pmap);
+
+
+ /*
+ * The proxy needs to keep track of all read/write cells allocated
+ * for its own clients. By doing this, we can optimize the special
+ * case of GrabCmapReply with smartGrab = TRUE. This means
+ * that the proxy asked back for a grab that it temporarily gave up
+ * to the server, and no other client or proxy did a color allocation
+ * in the colormap.
+ */
+
+ nr = NewReply(client, X_AllocColorCells, 0, alloc_color_cells_reply);
+
+ if (nr)
+ nr->request_info.xalloccolorcells.pmap = pmap;
+
+ return ProcStandardRequest(client);
+}
+
+static Bool
+alloc_color_cells_reply(client, nr, data)
+ ClientPtr client;
+ ReplyStuffPtr nr;
+ char *data;
+{
+ xAllocColorCellsReply *reply;
+ CARD16 nPixels, nMasks;
+ CARD32 *pixels, *masks;
+ ColormapPtr pmap;
+ int i, j, k;
+ char n;
+
+ reply = (xAllocColorCellsReply *) data;
+
+ pmap = nr->request_info.xalloccolorcells.pmap;
+
+#ifdef COLOR_DEBUG
+ fprintf (stderr, "AllocColorCells on cmap 0x%x:",
+ nr->request_info.xalloccolorcells.pmap->id);
+#endif
+
+ nPixels = reply->nPixels;
+ nMasks = reply->nMasks;
+
+ if (client->swapped)
+ {
+ swaps(&nPixels, n);
+ swaps(&nMasks, n);
+
+ pixels = (CARD32 *) xalloc (nPixels * sizeof (CARD32));
+ masks = (CARD32 *) xalloc (nMasks * sizeof (CARD32));
+
+ memcpy (pixels, (char *) (reply + 1), nPixels * sizeof (CARD32));
+ memcpy (masks, ((char *) (reply + 1)) + nPixels * sizeof (CARD32),
+ nMasks * sizeof (CARD32));
+
+ for (i = 0; i < nPixels; i++)
+ swapl (&pixels[i], n);
+ for (i = 0; i < nMasks; i++)
+ swapl (&masks[i], n);
+ }
+ else
+ {
+ pixels = (CARD32 *) (reply + 1);
+ masks = pixels + nPixels;
+ }
+
+ for (i = 0; i < nPixels; i++)
+ for (j = 0; j < (1 << nMasks); j++)
+ {
+ CARD32 pixel, plane_mask = 0;
+ int bits = j;
+
+ for (k = 0; k < nMasks; k++)
+ {
+ if (bits & 1)
+ plane_mask |= masks[k];
+ bits >>= 1;
+ }
+
+ pixel = pixels[i] | plane_mask;
+
+ AllocCell(client, pmap, pixel);
+
+#ifdef COLOR_DEBUG
+ fprintf (stderr, " %d", pixel);
+#endif
+ }
+
+#ifdef COLOR_DEBUG
+ fprintf (stderr, "\n");
+#endif
+ if (client->swapped)
+ {
+ xfree (pixels);
+ xfree (masks);
+ }
+
+ return TRUE;
+}
+
+/* ------------------------------------------------------------------------- */
+
+int
+ProcLBXAllocColorPlanes(client)
+ ClientPtr client;
+{
+ REQUEST(xAllocColorPlanesReq);
+ ReplyStuffPtr nr;
+ Colormap cmap;
+ ColormapPtr pmap;
+ char n;
+
+ cmap = stuff->cmap;
+ if (client->swapped)
+ swapl(&cmap, n);
+
+ pmap = (ColormapPtr) LookupIDByType (client, cmap, RT_COLORMAP);
+
+ if (!pmap)
+ return ProcStandardRequest(client);
+ if (!(pmap->pVisual->class & DynamicClass))
+ return BadAlloc;
+
+ /*
+ * We don't short circuit AllocColorPlanes requests.
+ * The server will need control over the colormap to handle
+ * this request, so rather than wait for the server to ask
+ * the proxy to release the colormap, we release it now.
+ */
+
+ if (pmap->grab_status == CMAP_GRABBED)
+ ReleaseCmap (client, pmap);
+
+
+ /*
+ * The proxy needs to keep track of all read/write cells allocated
+ * for its own clients. By doing this, we can optimize the special
+ * case of GrabCmapReply with smartGrab = TRUE. This means
+ * that the proxy asked back for a grab that it temporarily gave up
+ * to the server, and no other client or proxy did a color allocation
+ * in the colormap.
+ */
+
+ nr = NewReply(client, X_AllocColorPlanes, 0, alloc_color_planes_reply);
+
+ if (nr)
+ nr->request_info.xalloccolorplanes.pmap = pmap;
+
+ return ProcStandardRequest(client);
+}
+
+static Bool
+alloc_color_planes_reply(client, nr, data)
+ ClientPtr client;
+ ReplyStuffPtr nr;
+ char *data;
+{
+ xAllocColorPlanesReply *reply;
+ CARD32 redMask, greenMask, blueMask, mask;
+ CARD16 nPixels;
+ CARD32 *pixels;
+ ColormapPtr pmap;
+ int i;
+ char n;
+
+ reply = (xAllocColorPlanesReply *) data;
+
+ pmap = nr->request_info.xalloccolorplanes.pmap;
+
+ nPixels = reply->nPixels;
+ redMask = reply->redMask;
+ greenMask = reply->greenMask;
+ blueMask = reply->blueMask;
+
+ if (client->swapped)
+ {
+ swaps(&nPixels, n);
+ swapl(&redMask, n);
+ swapl(&greenMask, n);
+ swapl(&blueMask, n);
+
+ pixels = (CARD32 *) xalloc (nPixels * sizeof (CARD32));
+
+ memcpy (pixels, (char *) (reply + 1), nPixels * sizeof (CARD32));
+
+ for (i = 0; i < nPixels; i++)
+ swapl (&pixels[i], n);
+
+ }
+ else
+ {
+ pixels = (CARD32 *) (reply + 1);
+ }
+
+#ifdef COLOR_DEBUG
+ fprintf (stderr, "AllocColorPlanes on cmap 0x%x:",
+ nr->request_info.xalloccolorplanes.pmap->id);
+#endif
+
+ mask = redMask | greenMask | blueMask;
+
+ for (i = 0; i < nPixels; i++)
+ {
+ Pixel pixel, x = 0;
+
+ do
+ {
+ x = (x + ~mask + 1) & mask;
+
+ pixel = x | pixels[i];
+
+ AllocCell(client, pmap, pixel);
+
+#ifdef COLOR_DEBUG
+ fprintf(stderr, " %d", pixel);
+#endif
+ } while (x);
+ }
+
+#ifdef COLOR_DEBUG
+ fprintf(stderr, "\n");
+#endif
+ if (client->swapped)
+ {
+ xfree (pixels);
+ }
+
+ return TRUE;
+}
+
+/* ------------------------------------------------------------------------- */
+
+int
+ProcLBXLookupColor(client)
+ ClientPtr client;
+{
+ REQUEST(xLookupColorReq);
+ xLookupColorReply reply;
+ ReplyStuffPtr nr;
+ RGBEntryPtr rgbe;
+ int len;
+ char n;
+ Colormap cmap;
+ ColormapPtr pmap;
+
+ len = stuff->nbytes;
+ cmap = stuff->cmap;
+
+ if (client->swapped) {
+ swapl(&cmap, n);
+ swaps(&len, n);
+ }
+
+ pmap = (ColormapPtr) LookupIDByType (client, cmap, RT_COLORMAP);
+
+ if (len > MAX_COLORNAME_LENGTH || !pmap)
+ return ProcStandardRequest(client);
+
+ rgbe = FindColorName(client->server, (char *) &stuff[1], len,
+ pmap->pVisual);
+
+ if (rgbe) { /* found the value */
+ reply.type = X_Reply;
+ reply.length = 0;
+ reply.sequenceNumber = LBXSequenceNumber(client);
+
+ reply.exactRed = rgbe->xred;
+ reply.exactBlue = rgbe->xblue;
+ reply.exactGreen = rgbe->xgreen;
+
+ reply.screenRed = rgbe->vred;
+ reply.screenBlue = rgbe->vblue;
+ reply.screenGreen = rgbe->vgreen;
+
+#ifdef COLOR_DEBUG
+ if (LBXCacheSafe (client))
+ fprintf(stderr, "X LookupColor: short circuiting:\n");
+ else
+ fprintf(stderr,
+ "X LookupColor: short circuiting, but need Sync:\n");
+ fprintf (stderr, " seq = 0x%x, name = %.*s\n",
+ LBXSequenceNumber(client), len, (char *)&stuff[1]);
+#endif
+
+ if (client->swapped)
+ SwapLookupColorReply(&reply);
+ if (LBXCacheSafe(client)) {
+ FinishLBXRequest(client, REQ_YANK);
+ WriteToClient(client, sizeof(xLookupColorReply), &reply);
+ } else {
+ if (!LBXCanDelayReply(client))
+ SendLbxSync(client);
+ FinishLBXRequest(client, REQ_YANKLATE);
+ SaveReplyData(client, (xReply *) & reply, 0, NULL);
+ }
+
+#ifdef LBX_STATS
+ luc_good++;
+#endif
+
+ return Success;
+ } else {
+ nr = NewReply(client, X_LookupColor, 0, lookup_color_reply);
+ if (!nr)
+ return ProcStandardRequest(client);
+ strncpy(nr->request_info.xlookupcolor.name,
+ (char *) &stuff[1], len);
+ nr->request_info.xlookupcolor.namelen = len;
+ nr->request_info.xlookupcolor.visual = pmap->pVisual->id;
+
+#ifdef LBX_STATS
+ luc_miss++;
+#endif
+ return ProcStandardRequest(client);
+ }
+}
+
+
+static Bool
+lookup_color_reply(client, nr, data)
+ ClientPtr client;
+ ReplyStuffPtr nr;
+ char *data;
+{
+ xLookupColorReply *reply;
+ RGBEntryRec rgbe;
+ char n;
+
+ reply = (xLookupColorReply *) data;
+
+ rgbe.xred = reply->exactRed;
+ rgbe.xblue = reply->exactBlue;
+ rgbe.xgreen = reply->exactGreen;
+ rgbe.vred = reply->screenRed;
+ rgbe.vgreen = reply->screenGreen;
+ rgbe.vblue = reply->screenBlue;
+
+ rgbe.visual = nr->request_info.xlookupcolor.visual;
+ if (client->swapped) {
+ swaps(&rgbe.xred, n);
+ swaps(&rgbe.xgreen, n);
+ swaps(&rgbe.xblue, n);
+ swaps(&rgbe.vred, n);
+ swaps(&rgbe.vgreen, n);
+ swaps(&rgbe.vblue, n);
+ }
+ AddColorName(client->server,
+ nr->request_info.xlookupcolor.name,
+ nr->request_info.xlookupcolor.namelen,
+ &rgbe);
+ return TRUE;
+}
diff --git a/di/cmaputil.c b/di/cmaputil.c
new file mode 100644
index 0000000..ddec241
--- /dev/null
+++ b/di/cmaputil.c
@@ -0,0 +1,981 @@
+/* $Xorg: cmaputil.c,v 1.5 2001/02/09 02:05:31 xorgcvs Exp $ */
+
+/*
+Copyright 1996, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from The Open Group.
+*/
+
+/*
+ * Copyright 1994 Network Computing Devices, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name Network Computing Devices, Inc. not be
+ * used in advertising or publicity pertaining to distribution of this
+ * software without specific, written prior permission.
+ *
+ * THIS SOFTWARE IS PROVIDED `AS-IS'. NETWORK COMPUTING DEVICES, INC.,
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT
+ * LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, OR NONINFRINGEMENT. IN NO EVENT SHALL NETWORK
+ * COMPUTING DEVICES, INC., BE LIABLE FOR ANY DAMAGES WHATSOEVER, INCLUDING
+ * SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES, INCLUDING LOSS OF USE, DATA,
+ * OR PROFITS, EVEN IF ADVISED OF THE POSSIBILITY THEREOF, AND REGARDLESS OF
+ * WHETHER IN AN ACTION IN CONTRACT, TORT OR NEGLIGENCE, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include <stdio.h>
+#include "misc.h"
+#include "lbx.h"
+#include "assert.h"
+#include "colormap.h"
+#include "util.h"
+#include "resource.h"
+#include "wire.h"
+#define XK_LATIN1
+#include "keysymdef.h"
+
+typedef struct {
+ Colormap mid;
+} colorResource;
+
+
+static int num_visuals = 0;
+
+LbxVisualPtr *visuals;
+
+
+int
+CreateVisual(depth, vis)
+ int depth;
+ xVisualType *vis;
+{
+ LbxVisualPtr pvis;
+
+ pvis = (LbxVisualPtr) xalloc(sizeof(LbxVisualRec));
+ if (!pvis)
+ return 0;
+ pvis->id = vis->visualID;
+ pvis->class = vis->class;
+ pvis->depth = depth;
+ pvis->bitsPerRGB = vis->bitsPerRGB;
+ pvis->colormapEntries = vis->colormapEntries;
+ pvis->redMask = vis->redMask;
+ pvis->greenMask = vis->greenMask;
+ pvis->blueMask = vis->blueMask;
+ if ((pvis->class | DynamicClass) == DirectColor) {
+ pvis->offsetRed = 0;
+ while (pvis->redMask && !((pvis->redMask >> pvis->offsetRed) & 1))
+ pvis->offsetRed++;
+ pvis->offsetGreen = 0;
+ while (pvis->greenMask && !((pvis->greenMask >> pvis->offsetGreen) & 1))
+ pvis->offsetGreen++;
+ pvis->offsetBlue = 0;
+ while (pvis->blueMask && !((pvis->blueMask >> pvis->offsetBlue) & 1))
+ pvis->offsetBlue++;
+ }
+ visuals = (LbxVisualPtr *) xrealloc(visuals,
+ (num_visuals + 1) * sizeof(LbxVisualPtr));
+ if (!visuals) {
+ xfree(pvis);
+ return 0;
+ }
+ visuals[num_visuals++] = pvis;
+
+ return 1;
+}
+
+LbxVisualPtr
+GetVisual(vid)
+ VisualID vid;
+{
+ LbxVisualPtr pvis;
+ int i;
+
+ for (i = 0; i < num_visuals; i++) {
+ pvis = visuals[i];
+ if (pvis->id == vid)
+ return pvis;
+ }
+ assert(0);
+ return (LbxVisualPtr) 0;
+}
+
+
+/*
+ * ISO Latin-1 case conversion routine
+ *
+ * this routine always null-terminates the result, so
+ * beware of too-small buffers
+ */
+
+void
+CopyISOLatin1Lowered(dest, source, length)
+ register unsigned char *dest, *source;
+ int length;
+{
+ register int i;
+
+ for (i = 0; i < length; i++, source++, dest++)
+ {
+ if ((*source >= XK_A) && (*source <= XK_Z))
+ *dest = *source + (XK_a - XK_A);
+ else if ((*source >= XK_Agrave) && (*source <= XK_Odiaeresis))
+ *dest = *source + (XK_agrave - XK_Agrave);
+ else if ((*source >= XK_Ooblique) && (*source <= XK_Thorn))
+ *dest = *source + (XK_oslash - XK_Ooblique);
+ else
+ *dest = *source;
+ }
+ *dest = '\0';
+}
+
+
+/*
+ * colormap cache code
+ *
+ * handles RGB database and AllocColor
+ *
+ */
+
+
+/*
+ * The dbm routines are a porting hassle. This implementation will do
+ * the same thing by reading the rgb.txt file directly, which is much
+ * more portable.
+ */
+
+#define HASHSIZE 511
+
+typedef struct _dbEntry * dbEntryPtr;
+typedef struct _dbEntry {
+ dbEntryPtr link;
+ unsigned short red;
+ unsigned short green;
+ unsigned short blue;
+ char name[1]; /* some compilers complain if [0] */
+} dbEntry;
+
+
+static dbEntryPtr hashTab[HASHSIZE];
+
+static dbEntryPtr
+lookup(name, len, create)
+ char *name;
+ int len;
+ Bool create;
+{
+ unsigned int h = 0, g;
+ dbEntryPtr entry, *prev;
+ char *str = name;
+
+ if (!(name = (char*)ALLOCATE_LOCAL(len +1))) return NULL;
+ CopyISOLatin1Lowered((unsigned char *)name, (unsigned char *)str, len);
+ name[len] = '\0';
+
+ for(str = name; *str; str++) {
+ h = (h << 4) + *str;
+ if ((g = h) & 0xf0000000) h ^= (g >> 24);
+ h &= g;
+ }
+ h %= HASHSIZE;
+
+ if (( entry = hashTab[h] ))
+ {
+ for( ; entry; prev = (dbEntryPtr*)entry, entry = entry->link )
+ if (! strcmp(name, entry->name) ) break;
+ }
+ else
+ prev = &(hashTab[h]);
+
+ if (!entry && create && (entry = (dbEntryPtr)xalloc(sizeof(dbEntry) +len)))
+ {
+ *prev = entry;
+ entry->link = NULL;
+ strcpy( entry->name, name );
+ }
+
+ DEALLOCATE_LOCAL(name);
+
+ return entry;
+}
+
+extern char *rgbPath;
+
+static Bool have_rgb_db = FALSE;
+
+Bool
+InitColors()
+{
+ FILE *rgb;
+ char *path;
+ char line[BUFSIZ];
+ char name[BUFSIZ];
+ int red, green, blue, lineno = 0;
+ dbEntryPtr entry;
+
+ if (!rgbPath)
+ return TRUE;
+ if (!have_rgb_db)
+ {
+ path = (char*)ALLOCATE_LOCAL(strlen(rgbPath) +5);
+ strcpy(path, rgbPath);
+ strcat(path, ".txt");
+
+ if (!(rgb = fopen(path, "r")))
+ {
+ ErrorF( "Couldn't open RGB_DB '%s'\n", rgbPath );
+ DEALLOCATE_LOCAL(path);
+ return FALSE;
+ }
+
+ while(fgets(line, sizeof(line), rgb))
+ {
+ lineno++;
+ if (sscanf(line,"%d %d %d %[^\n]\n", &red, &green, &blue, name) == 4)
+ {
+ if (red >= 0 && red <= 0xff &&
+ green >= 0 && green <= 0xff &&
+ blue >= 0 && blue <= 0xff)
+ {
+ if ((entry = lookup(name, strlen(name), TRUE)))
+ {
+ entry->red = (red * 65535) / 255;
+ entry->green = (green * 65535) / 255;
+ entry->blue = (blue * 65535) / 255;
+ }
+ }
+ else
+ ErrorF("Value for \"%s\" out of range: %s:%d\n",
+ name, path, lineno);
+ }
+ else if (*line && *line != '#' && *line != '!')
+ ErrorF("Syntax Error: %s:%d\n", path, lineno);
+ }
+
+ fclose(rgb);
+ DEALLOCATE_LOCAL(path);
+
+ have_rgb_db = TRUE;
+ }
+
+ return TRUE;
+}
+
+
+
+static Bool
+OsLookupColor(name, len, pred, pgreen, pblue)
+ char *name;
+ unsigned len;
+ unsigned short *pred, *pgreen, *pblue;
+
+{
+ dbEntryPtr entry;
+
+ if ((entry = lookup(name, len, FALSE)))
+ {
+ *pred = entry->red;
+ *pgreen = entry->green;
+ *pblue = entry->blue;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/*
+ * colorname cache
+ */
+
+
+static int
+Hash(name, len)
+ char *name;
+ int len;
+{
+ int hash = 0;
+
+ while (len--)
+ hash = (hash << 1) ^ *name++;
+ if (hash < 0)
+ hash = -hash;
+ return hash;
+}
+
+RGBEntryPtr
+FindColorName(server, name, len, pVisual)
+ XServerPtr server;
+ char *name;
+ int len;
+ LbxVisualPtr pVisual;
+{
+ RGBCacheEntryPtr ce;
+ int hash;
+ char cname[BUFSIZ];
+
+ if (have_rgb_db &&
+ OsLookupColor(name, len,
+ &server->rgb_buf.xred,
+ &server->rgb_buf.xgreen,
+ &server->rgb_buf.xblue)) {
+
+ server->rgb_buf.vred = server->rgb_buf.xred;
+ server->rgb_buf.vgreen = server->rgb_buf.xgreen;
+ server->rgb_buf.vblue = server->rgb_buf.xblue;
+
+ (*LbxResolveColor)(pVisual,
+ &server->rgb_buf.vred,
+ &server->rgb_buf.vgreen,
+ &server->rgb_buf.vblue);
+
+ return &server->rgb_buf;
+ }
+
+ CopyISOLatin1Lowered((unsigned char *)cname, (unsigned char *)name, len);
+ hash = Hash(cname, len) % NBUCKETS;
+
+ ce = server->rgb_cache[hash];
+
+ while (ce) {
+ if ((ce->color.visual == pVisual->id) &&
+ (ce->color.namelen == len) &&
+ !strncmp(ce->color.name, cname, len)) {
+ return &ce->color;
+ }
+ ce = ce->next;
+ }
+ return (RGBEntryPtr) NULL;
+}
+
+Bool
+AddColorName(server, name, len, rgbe)
+ XServerPtr server;
+ char *name;
+ int len;
+ RGBEntryRec *rgbe;
+{
+ RGBCacheEntryPtr new;
+ int hash;
+
+ hash = Hash(name, len) % NBUCKETS;
+
+ new = (RGBCacheEntryPtr) xalloc(sizeof(RGBCacheEntryRec));
+ if (!new)
+ return FALSE;
+ new->next = server->rgb_cache[hash];
+ server->rgb_cache[hash] = new;
+ new->color = *rgbe;
+ new->color.name = (char *)xalloc(len + 1);
+ CopyISOLatin1Lowered((unsigned char *)new->color.name,
+ (unsigned char *)name, len);
+ new->color.namelen = len;
+ return TRUE;
+}
+
+
+void
+FreeColors()
+{
+ RGBCacheEntryPtr ce,
+ nce;
+ int i, j;
+
+ for (i = 0; i < lbxMaxServers; i++) {
+ if (servers[i]) {
+ for (j = 0; j < NBUCKETS; j++) {
+ for (ce = servers[i]->rgb_cache[j]; ce; ce = nce) {
+ nce = ce->next;
+ xfree(ce->color.name);
+ xfree(ce);
+ }
+ servers[i]->rgb_cache[j] = NULL;
+ }
+ }
+ }
+}
+
+
+
+/* ARGSUSED */
+int
+DestroyColormap(client, value, id)
+ ClientPtr client;
+ pointer value;
+ XID id;
+{
+ ColormapPtr pmap = (ColormapPtr)value;
+ xfree(pmap->blue);
+ xfree(pmap->green);
+ xfree(pmap);
+ return Success;
+}
+
+/* ------------------------------------------------------------------------- */
+
+static int
+find_matching_pixel(pent, num, channels, red, green, blue, pe)
+ Entry *pent;
+ int num;
+ int channels;
+ CARD32 red,
+ green,
+ blue;
+ Entry **pe;
+{
+ int i;
+
+ /* OK if only server has it allocated, because even if a
+ * FreeCell is in transit for it, only we can realloc it */
+ for (i = 0; i < num; pent++, i++) {
+ if (pent->status == PIXEL_SHARED) {
+ switch (channels) {
+ case DoRed:
+ if (pent->red == red)
+ {
+ *pe = pent;
+ return 1;
+ }
+ break;
+ case DoGreen:
+ if (pent->green == green)
+ {
+ *pe = pent;
+ return 1;
+ }
+ break;
+ case DoBlue:
+ if (pent->blue == blue)
+ {
+ *pe = pent;
+ return 1;
+ }
+ break;
+ default:
+ if (pent->red == red &&
+ pent->green == green &&
+ pent->blue == blue)
+ {
+ *pe = pent;
+ return 1;
+ }
+ }
+ }
+ }
+ *pe = NULL;
+ return 0;
+}
+
+/* ARGSUSED */
+int
+FindPixel(client, pmap, red, green, blue, pent)
+ ClientPtr client;
+ ColormapPtr pmap;
+ CARD32 red,
+ green,
+ blue;
+ Entry **pent;
+{
+ Entry *p;
+
+ switch (pmap->pVisual->class) {
+ case PseudoColor:
+ case GrayScale:
+ return find_matching_pixel(pmap->red, pmap->pVisual->colormapEntries,
+ DoRed|DoGreen|DoBlue,
+ red, green, blue, pent);
+ case StaticGray:
+ case StaticColor:
+ if (pmap->grab_status != CMAP_GRABBED)
+ break;
+ *pent = (*LbxFindBestPixel)(pmap, red, green, blue,
+ DoRed|DoGreen|DoBlue);
+ return 1;
+ case TrueColor:
+ if (pmap->grab_status != CMAP_GRABBED)
+ break;
+ p = (*LbxFindBestPixel)(pmap, red, green, blue, DoRed);
+ client->server->rgb_ent.pixel = p->pixel << pmap->pVisual->offsetRed;
+ client->server->rgb_ent.red = p->red;
+ client->server->rgb_ent.refcnt = p->refcnt;
+ p = (*LbxFindBestPixel)(pmap, red, green, blue, DoGreen);
+ client->server->rgb_ent.pixel |= p->pixel << pmap->pVisual->offsetGreen;
+ client->server->rgb_ent.green = p->green;
+ if (!p->refcnt)
+ client->server->rgb_ent.refcnt = 0;
+ p = (*LbxFindBestPixel)(pmap, red, green, blue, DoBlue);
+ client->server->rgb_ent.pixel |= p->pixel << pmap->pVisual->offsetBlue;
+ client->server->rgb_ent.blue = p->blue;
+ if (!p->refcnt)
+ client->server->rgb_ent.refcnt = 0;
+ *pent = &client->server->rgb_ent;
+ return 1;
+ case DirectColor:
+ if (!find_matching_pixel(pmap->red, NUMRED(pmap->pVisual),
+ DoRed, red, green, blue, &p))
+ break;
+ client->server->rgb_ent.pixel = p->pixel << pmap->pVisual->offsetRed;
+ client->server->rgb_ent.red = p->red;
+ client->server->rgb_ent.refcnt = p->refcnt;
+ if (!find_matching_pixel(pmap->green, NUMGREEN(pmap->pVisual),
+ DoGreen, red, green, blue, &p))
+ break;
+ client->server->rgb_ent.pixel |= p->pixel << pmap->pVisual->offsetGreen;
+ client->server->rgb_ent.green = p->green;
+ if (!p->refcnt)
+ client->server->rgb_ent.refcnt = 0;
+ if (!find_matching_pixel(pmap->blue, NUMBLUE(pmap->pVisual),
+ DoBlue, red, green, blue, &p))
+ break;
+ client->server->rgb_ent.pixel |= p->pixel << pmap->pVisual->offsetBlue;
+ client->server->rgb_ent.blue = p->blue;
+ if (!p->refcnt)
+ client->server->rgb_ent.refcnt = 0;
+ *pent = &client->server->rgb_ent;
+ return 1;
+ }
+ *pent = NULL;
+ return 0;
+}
+
+static int
+AddPixel(pclient, pmap, pixel)
+ ClientPtr pclient;
+ ColormapPtr pmap;
+ Pixel pixel;
+{
+ colorResource *pcr;
+ int npix;
+ Pixel *ppix;
+ int client = pclient->index;
+
+ if ((pmap->pVisual->class | DynamicClass) != DirectColor) {
+ npix = pmap->numPixelsRed[client];
+ ppix = (Pixel *) xrealloc(pmap->clientPixelsRed[client],
+ (npix + 1) * sizeof(Pixel));
+ if (!ppix)
+ return 0;
+ ppix[npix] = pixel;
+ pmap->clientPixelsRed[client] = ppix;
+ pmap->numPixelsRed[client]++;
+ } else {
+ npix = pmap->numPixelsRed[client];
+ ppix = (Pixel *) xrealloc(pmap->clientPixelsRed[client],
+ (npix + 1) * sizeof(Pixel));
+ if (!ppix)
+ return 0;
+ ppix[npix] = REDPART(pmap->pVisual, pixel);
+ pmap->clientPixelsRed[client] = ppix;
+ pmap->numPixelsRed[client]++;
+ npix = pmap->numPixelsGreen[client];
+ ppix = (Pixel *) xrealloc(pmap->clientPixelsGreen[client],
+ (npix + 1) * sizeof(Pixel));
+ if (!ppix)
+ return 0;
+ ppix[npix] = GREENPART(pmap->pVisual, pixel);
+ pmap->clientPixelsGreen[client] = ppix;
+ pmap->numPixelsGreen[client]++;
+ npix = pmap->numPixelsBlue[client];
+ ppix = (Pixel *) xrealloc(pmap->clientPixelsBlue[client],
+ (npix + 1) * sizeof(Pixel));
+ if (!ppix)
+ return 0;
+ ppix[npix] = BLUEPART(pmap->pVisual, pixel);
+ pmap->clientPixelsBlue[client] = ppix;
+ pmap->numPixelsBlue[client]++;
+ }
+ if ((pclient->index != client) &&
+ (pmap->numPixelsRed[client] == 1)) {
+ pcr = (colorResource *) xalloc(sizeof(colorResource));
+ if (!pcr)
+ return 0;
+ pcr->mid = pmap->id;
+ AddResource(pclient, FakeClientID(client), RT_CMAPENTRY, (pointer) pcr);
+ }
+ return 1;
+}
+
+int
+IncrementPixel(pclient, pmap, pent, from_server)
+ ClientPtr pclient;
+ ColormapPtr pmap;
+ Entry *pent;
+ Bool from_server;
+{
+
+ if (!AddPixel(pclient, pmap, pent->pixel))
+ return 0;
+
+ /* we have to AllocColor if refcnt is 0, even if server_ref is 1,
+ * because the server might have a FreeCell for it in flight */
+ if (!from_server) {
+ if (!pent->refcnt && (pmap->pVisual->class & DynamicClass))
+ SendAllocColor(pclient, pmap->id, pent->pixel,
+ pent->red, pent->green, pent->blue);
+ else
+ SendIncrementPixel(pclient, pmap->id, pent->pixel);
+ }
+ if ((pmap->pVisual->class | DynamicClass) != DirectColor)
+ pent->refcnt++;
+ else {
+ pmap->red[REDPART(pmap->pVisual, pent->pixel)].refcnt++;
+ pmap->green[GREENPART(pmap->pVisual, pent->pixel)].refcnt++;
+ pmap->blue[BLUEPART(pmap->pVisual, pent->pixel)].refcnt++;
+ }
+ return 1;
+}
+
+int
+AllocCell(client, pmap, pixel)
+ ClientPtr client;
+ ColormapPtr pmap;
+ Pixel pixel;
+{
+ Entry *pent;
+ Pixel p;
+
+ if (!AddPixel(client, pmap, pixel))
+ return 0;
+ switch (pmap->pVisual->class) {
+ case PseudoColor:
+ case GrayScale:
+ pent = &pmap->red[pixel];
+ pent->pixel = pixel;
+ pent->status = PIXEL_PRIVATE;
+ pent->server_ref = 0;
+ return 1;
+ case DirectColor:
+ p = REDPART(pmap->pVisual, pixel);
+ pent = &pmap->red[p];
+ pent->pixel = p;
+ pent->status = PIXEL_PRIVATE;
+ pent->server_ref = 0;
+ p = GREENPART(pmap->pVisual, pixel);
+ pent = &pmap->green[p];
+ pent->pixel = p;
+ pent->status = PIXEL_PRIVATE;
+ pent->server_ref = 0;
+ p = BLUEPART(pmap->pVisual, pixel);
+ pent = &pmap->blue[p];
+ pent->pixel = p;
+ pent->status = PIXEL_PRIVATE;
+ pent->server_ref = 0;
+ return 1;
+ default:
+ fprintf(stderr, "storing pixel in class %d colormap\n",
+ pmap->pVisual->class);
+ break;
+ }
+ return 0;
+}
+
+int
+StorePixel (client, pmap, red, green, blue, pixel, from_server)
+ ClientPtr client;
+ ColormapPtr pmap;
+ CARD32 red,
+ green,
+ blue;
+ Pixel pixel;
+ Bool from_server;
+{
+ Entry *pent;
+ Pixel p;
+
+ switch (pmap->pVisual->class) {
+ case PseudoColor:
+ case GrayScale:
+ pent = pmap->red;
+ pent[pixel].red = red;
+ pent[pixel].green = green;
+ pent[pixel].blue = blue;
+ pent[pixel].pixel = pixel;
+ if (pent[pixel].status != PIXEL_SHARED)
+ pent[pixel].refcnt = 0;
+ pent[pixel].status = PIXEL_SHARED;
+ pent[pixel].server_ref = 1;
+ IncrementPixel(client, pmap, &pent[pixel], from_server);
+ return 1;
+ case DirectColor:
+ client->server->rgb_ent.refcnt = 1;
+ p = REDPART(pmap->pVisual, pixel);
+ pent = pmap->red;
+ pent[p].red = red;
+ pent[p].pixel = p;
+ if (pent[p].status != PIXEL_SHARED)
+ client->server->rgb_ent.refcnt = pent[p].refcnt = 0;
+ pent[p].status = PIXEL_SHARED;
+ pent[p].server_ref = 1;
+ p = GREENPART(pmap->pVisual, pixel);
+ pent = pmap->green;
+ pent[p].green = green;
+ pent[p].pixel = p;
+ if (pent[p].status != PIXEL_SHARED)
+ client->server->rgb_ent.refcnt = pent[p].refcnt = 0;
+ pent[p].status = PIXEL_SHARED;
+ pent[p].server_ref = 1;
+ p = BLUEPART(pmap->pVisual, pixel);
+ pent = pmap->blue;
+ pent[p].blue = blue;
+ pent[p].pixel = p;
+ if (pent[p].status != PIXEL_SHARED)
+ client->server->rgb_ent.refcnt = pent[p].refcnt = 0;
+ pent[p].status = PIXEL_SHARED;
+ pent[p].server_ref = 1;
+ client->server->rgb_ent.pixel = pixel;
+ client->server->rgb_ent.red = red;
+ client->server->rgb_ent.green = green;
+ client->server->rgb_ent.blue = blue;
+ IncrementPixel(client, pmap, &client->server->rgb_ent, from_server);
+ return 0;
+ default:
+ fprintf(stderr, "storing pixel in class %d colormap\n",
+ pmap->pVisual->class);
+ break;
+ }
+ return 0;
+}
+
+/* ARGSUSED */
+static void
+FreeCell(pent, pixel)
+ Entry *pent;
+ Pixel pixel;
+{
+ pent = &pent[pixel];
+ if (pent->status == PIXEL_PRIVATE) {
+ if (!pent->server_ref)
+ pent->status = PIXEL_FREE;
+ } else if (pent->status == PIXEL_SHARED) {
+ if (pent->refcnt > 0)
+ pent->refcnt--;
+ if (!pent->refcnt && !pent->server_ref)
+ pent->status = PIXEL_FREE;
+ }
+}
+
+static void
+FreeServerCell(pent, pixel)
+ Entry *pent;
+ Pixel pixel;
+{
+ pent = &pent[pixel];
+ if (pent->status == PIXEL_PRIVATE && pent->server_ref)
+ pent->status = PIXEL_FREE;
+ else if (pent->status == PIXEL_SHARED) {
+ if (!pent->refcnt)
+ pent->status = PIXEL_FREE;
+ else
+ pent->server_ref = 0;
+ }
+}
+
+void
+GotServerFreeCellsEvent(pmap, pixel_start, pixel_end)
+ ColormapPtr pmap;
+ Pixel pixel_start;
+ Pixel pixel_end;
+{
+ Pixel pixel;
+
+ if ((pmap->pVisual->class | DynamicClass) != DirectColor)
+ for (pixel = pixel_start; pixel <= pixel_end; pixel++) {
+ FreeServerCell(pmap->red, pixel);
+ }
+ else
+ for (pixel = pixel_start; pixel <= pixel_end; pixel++) {
+ FreeServerCell(pmap->red, REDPART(pmap->pVisual, pixel));
+ FreeServerCell(pmap->green, GREENPART(pmap->pVisual, pixel));
+ FreeServerCell(pmap->blue, BLUEPART(pmap->pVisual, pixel));
+ }
+}
+
+void
+FreeAllClientPixels(pmap, client)
+ ColormapPtr pmap;
+ int client;
+{
+ Pixel *ppix, *ppst;
+ int n;
+
+ ppst = pmap->clientPixelsRed[client];
+ for (ppix = ppst, n = pmap->numPixelsRed[client]; --n >= 0; ppix++)
+ FreeCell(pmap->red, *ppix);
+ xfree(ppst);
+ pmap->clientPixelsRed[client] = (Pixel *) NULL;
+ pmap->numPixelsRed[client] = 0;
+ if ((pmap->pVisual->class | DynamicClass) == DirectColor) {
+ ppst = pmap->clientPixelsGreen[client];
+ for (ppix = ppst, n = pmap->numPixelsGreen[client]; --n >= 0; ppix++)
+ FreeCell(pmap->green, *ppix);
+ xfree(ppst);
+ pmap->clientPixelsGreen[client] = (Pixel *) NULL;
+ pmap->numPixelsGreen[client] = 0;
+ ppst = pmap->clientPixelsBlue[client];
+ for (ppix = ppst, n = pmap->numPixelsBlue[client]; --n >= 0; ppix++)
+ FreeCell(pmap->blue, *ppix);
+ xfree(ppst);
+ pmap->clientPixelsBlue[client] = (Pixel *) NULL;
+ pmap->numPixelsBlue[client] = 0;
+ }
+}
+
+/* ARGSUSED */
+int
+FreeClientPixels(client, value, id)
+ ClientPtr client;
+ pointer value;
+ XID id;
+{
+ colorResource *pcr = (colorResource *)value;
+ ColormapPtr pmap;
+
+ pmap = (ColormapPtr) LookupIDByType(client, pcr->mid, RT_COLORMAP);
+
+ if (pmap)
+ FreeAllClientPixels(pmap, client->index);
+ xfree(pcr);
+ return Success;
+}
+
+#define GetNextBitsOrBreak(bits, mask, base) \
+ if((bits) == (mask)) \
+ break; \
+ (bits) += (base); \
+ while((bits) & ~(mask)) \
+ (bits) += ((bits) & ~(mask))
+
+static void
+FreeCells(client, pmap, num, pixels, mask, channels)
+ ClientPtr client;
+ ColormapPtr pmap;
+ int num;
+ Pixel *pixels;
+ Pixel mask;
+ int channels;
+{
+ Pixel pix, base, bits, cmask;
+ int i, zapped, npix, npixnew, offset;
+ Pixel *cptr, *pptr, *ppixClient, **ppixp;
+ int *npixp;
+ Entry *pent;
+ int idx;
+
+ idx = client->index;
+ switch (channels) {
+ case DoRed:
+ ppixp = &pmap->clientPixelsRed[idx];
+ npixp = &pmap->numPixelsRed[idx];
+ cmask = pmap->pVisual->redMask;
+ offset = pmap->pVisual->offsetRed;
+ pent = pmap->red;
+ break;
+ case DoGreen:
+ ppixp = &pmap->clientPixelsGreen[idx];
+ npixp = &pmap->numPixelsGreen[idx];
+ cmask = pmap->pVisual->greenMask;
+ offset = pmap->pVisual->offsetGreen;
+ pent = pmap->green;
+ break;
+ case DoBlue:
+ ppixp = &pmap->clientPixelsBlue[idx];
+ npixp = &pmap->numPixelsBlue[idx];
+ cmask = pmap->pVisual->blueMask;
+ offset = pmap->pVisual->offsetBlue;
+ pent = pmap->blue;
+ break;
+ default:
+ ppixp = &pmap->clientPixelsRed[idx];
+ npixp = &pmap->numPixelsRed[idx];
+ cmask = ~((Pixel)0);
+ offset = 0;
+ pent = pmap->red;
+ break;
+ }
+ mask &= cmask;
+ zapped = 0;
+ bits = 0;
+ base = lowbit(mask);
+ while (1)
+ {
+ for (i = 0; i < num; i++) {
+ pix = (pixels[i] & cmask) >> offset;
+ for (cptr = *ppixp, npix = *npixp;
+ --npix >= 0 && *cptr != pix;
+ cptr++)
+ ;
+ if (npix >= 0) {
+ FreeCell(pent, pix);
+ *cptr = ~((Pixel)0);
+ zapped++;
+ }
+ }
+ GetNextBitsOrBreak(bits, mask, base);
+ }
+ if (zapped) {
+ npixnew = *npixp - zapped;
+ if (npixnew) {
+ pptr = cptr = *ppixp;
+ for (npix = 0; npix < npixnew; cptr++) {
+ if (*cptr != ~((Pixel)0)) {
+ *pptr++ = *cptr;
+ npix++;
+ }
+ }
+ ppixClient = *ppixp;
+ pptr = (Pixel *) xrealloc(ppixClient, npixnew * sizeof(Pixel));
+ if (pptr)
+ ppixClient = pptr;
+ *npixp = npixnew;
+ *ppixp = ppixClient;
+ } else {
+ *npixp = 0;
+ xfree(*ppixp);
+ *ppixp = NULL;
+ }
+ }
+}
+
+int
+FreePixels(client, pmap, num, pixels, mask)
+ ClientPtr client;
+ ColormapPtr pmap;
+ int num;
+ Pixel *pixels;
+ Pixel mask;
+{
+
+ if ((pmap->pVisual->class | DynamicClass) != DirectColor)
+ FreeCells(client, pmap, num, pixels, mask, DoRed|DoGreen|DoBlue);
+ else {
+ FreeCells(client, pmap, num, pixels, mask, DoRed);
+ FreeCells(client, pmap, num, pixels, mask, DoGreen);
+ FreeCells(client, pmap, num, pixels, mask, DoBlue);
+ }
+ return 1;
+}
diff --git a/di/dispatch.c b/di/dispatch.c
new file mode 100644
index 0000000..b7907e5
--- /dev/null
+++ b/di/dispatch.c
@@ -0,0 +1,638 @@
+/* $Xorg: dispatch.c,v 1.3 2000/08/17 19:53:55 cpqbld Exp $ */
+/*
+ * Copyright 1992 Network Computing Devices
+ * Copyright 1996 X Consortium, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of NCD. not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. NCD. makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * NCD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL NCD.
+ * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include <stdio.h>
+#include "assert.h"
+#include "lbx.h"
+#include "wire.h"
+#include "swap.h"
+#include "lbxext.h"
+#include "util.h"
+#include "resource.h"
+#include "pm.h"
+
+extern int (* InitialVector[3]) ();
+
+static void KillAllClients(
+#if NeedFunctionPrototypes
+ void
+#endif
+);
+
+static void
+HandleLargeRequest(
+#if NeedFunctionPrototypes
+ void
+#endif
+);
+
+int nextFreeClientID; /* always MIN free client ID */
+int nClients; /* number active clients */
+char *display_name = 0;
+char dispatchException = 0;
+char isItTimeToYield;
+Bool lbxUseLbx = TRUE;
+Bool lbxCompressImages = TRUE;
+Bool lbxDoAtomShortCircuiting = TRUE;
+Bool lbxDoLbxGfx = TRUE;
+
+extern Bool lbxWinAttr;
+extern Bool lbxDoCmapGrabbing;
+extern char *atomsFile;
+
+#define MAJOROP ((xReq *)client->requestBuffer)->reqType
+#define MINOROP ((xReq *)client->requestBuffer)->data
+
+int
+Dispatch ()
+{
+ register int *clientReady; /* array of request ready clients */
+ register int result;
+ register ClientPtr client;
+ register int nready;
+
+ nextFreeClientID = 2;
+ nClients = 0;
+
+ clientReady = (int *) xalloc(sizeof(int) * MaxClients);
+ if (!clientReady)
+ FatalError("couldn't create client ready array");
+
+ while (!dispatchException)
+ {
+ if (numLargeRequestsInQueue == 0) {
+ /*
+ * There are no pending large requests, so do blocking read.
+ */
+
+ nready = WaitForSomething(clientReady, FALSE /* block */);
+
+ } else {
+ /*
+ * If there is no input from any clients (the only way we can
+ * check this is by polling rather than blocking), handle a
+ * large request.
+ */
+
+ nready = WaitForSomething(clientReady, TRUE /* poll */);
+
+ if (!nready && numLargeRequestsInQueue)
+ HandleLargeRequest ();
+ }
+
+ /*****************
+ * Handle events in round robin fashion, doing input between
+ * each round
+ *****************/
+
+ while (!dispatchException && (--nready >= 0))
+ {
+ client = clients[clientReady[nready]];
+ if (! client)
+ {
+ /* KillClient can cause this to happen */
+ continue;
+ }
+ isItTimeToYield = FALSE;
+
+ while (!isItTimeToYield)
+ {
+ /* now, finally, deal with client requests */
+
+ result = ReadRequestFromClient(client);
+ if (result <= 0)
+ {
+ if (result < 0)
+ CloseDownClient(client);
+ break;
+ }
+
+ client->sequence++;
+#ifdef DEBUG
+ if (client->requestLogIndex == MAX_REQUEST_LOG)
+ client->requestLogIndex = 0;
+ client->requestLog[client->requestLogIndex] = MAJOROP;
+ client->requestLogIndex++;
+#endif
+ client->sequenceNumber++;
+ result = (* client->requestVector[MAJOROP])(client);
+
+ if (result != Success)
+ {
+ if (client->noClientException != Success)
+ CloseDownClient(client);
+ else
+ SendErrorToClient(client, MAJOROP, MINOROP,
+ client->errorValue, result);
+ break;
+ }
+ }
+ if (result >= 0 && client != client->server->serverClient)
+ client->server->prev_exec = client;
+ FlushAllOutput();
+ }
+ }
+ KillAllClients();
+ LbxCleanupSession();
+ xfree (clientReady);
+ dispatchException &= ~DE_RESET;
+ return (dispatchException & DE_TERMINATE);
+}
+
+void
+SendErrorToClient(client, majorCode, minorCode, resId, errorCode)
+ ClientPtr client;
+ unsigned int majorCode;
+ unsigned int minorCode;
+ XID resId;
+ int errorCode;
+{
+ xError rep;
+ int n;
+
+ rep.type = X_Error;
+ rep.sequenceNumber = LBXSequenceNumber(client);
+ rep.errorCode = errorCode;
+ rep.majorCode = majorCode;
+ rep.minorCode = minorCode;
+ rep.resourceID = resId;
+
+ if (client->swapped) {
+ swaps(&rep.sequenceNumber, n);
+ swaps(&rep.minorCode, n);
+ swaps(&rep.resourceID, n);
+ }
+
+ if (LBXCacheSafe(client)) {
+ FinishLBXRequest(client, REQ_YANK);
+ WriteToClient(client, sizeof(rep), (char *)&rep);
+ } else {
+ if (!LBXCanDelayReply(client))
+ SendLbxSync(client);
+ FinishLBXRequest(client, REQ_YANKLATE);
+ SaveReplyData(client, (xReply *) &rep, 0, NULL);
+ }
+}
+
+/************************
+ * int NextAvailableClient(ospriv)
+ *
+ * OS dependent portion can't assign client id's because of CloseDownModes.
+ * Returns NULL if there are no free clients.
+ *************************/
+
+ClientPtr
+NextAvailableClient(ospriv, connect_fd)
+ pointer ospriv;
+ int connect_fd;
+{
+ register int i;
+ register ClientPtr client;
+ xReq data;
+ static int been_there;
+
+ if (!been_there) {
+ nextFreeClientID = 1; /* The first client is serverClient */
+ been_there++;
+ }
+ i = nextFreeClientID;
+ if (i == MAXCLIENTS)
+ return (ClientPtr)NULL;
+ clients[i] = client = (ClientPtr)xcalloc(sizeof(ClientRec));
+ if (!client)
+ return (ClientPtr)NULL;
+ client->index = i;
+ client->closeDownMode = DestroyAll;
+ client->awaitingSetup = TRUE;
+ client->saveSet = (pointer *)NULL;
+ client->noClientException = Success;
+ client->public.requestLength = StandardRequestLength;
+ client->requestVector = InitialVector;
+ client->osPrivate = ospriv;
+ client->big_requests = TRUE;
+
+ /*
+ * Use the fd the client connected on as a search key to find the
+ * associated display for this client
+ */
+ if (connect_fd != -1)
+ {
+ int j, k, found = 0;
+ for (j=0; j < lbxMaxServers; j++)
+ {
+ if (servers[j])
+ {
+ for (k=0; k < MAXTRANSPORTS; k++)
+ if (servers[j]->listen_fds[k] == connect_fd)
+ {
+ found = 1;
+ break;
+ }
+ }
+ if (found)
+ break;
+ }
+ if (!found) {
+ fprintf (stderr, "Cannot determine a client's transport connection\n");
+ return (ClientPtr) NULL;
+ }
+ client->server = servers[j];
+ }
+
+ if (client->server && !InitClientResources(client))
+ {
+ xfree(client);
+ return (ClientPtr)NULL;
+ }
+
+ if (i == currentMaxClients)
+ currentMaxClients++;
+ while ((nextFreeClientID < MAXCLIENTS) && clients[nextFreeClientID])
+ nextFreeClientID++;
+ if (client->server)
+ {
+ data.reqType = 1;
+ data.length = (sz_xReq + sz_xConnClientPrefix) >> 2;
+ if (!InsertFakeRequest(client, (char *)&data, sz_xReq))
+ {
+ xfree (client);
+ return (ClientPtr) NULL;
+ }
+ }
+ return(client);
+}
+
+int
+ProcInitialConnection(client)
+ register ClientPtr client;
+{
+ REQUEST(xReq);
+ register xConnClientPrefix *prefix;
+ int whichbyte = 1;
+
+ prefix = (xConnClientPrefix *)((char *)stuff + sz_xReq);
+ if ((prefix->byteOrder != 'l') && (prefix->byteOrder != 'B'))
+ return (client->noClientException = -1);
+ if (((*(char *) &whichbyte) && (prefix->byteOrder == 'B')) ||
+ (!(*(char *) &whichbyte) && (prefix->byteOrder == 'l')))
+ {
+ client->swapped = TRUE;
+ SwapConnClientPrefix(prefix);
+ }
+ stuff->reqType = 2;
+ stuff->length += ((prefix->nbytesAuthProto + 3) >> 2) +
+ ((prefix->nbytesAuthString + 3) >> 2);
+ if (client->swapped) {
+ swaps(&stuff->length, whichbyte);
+ }
+ ResetCurrentRequest(client);
+ return (client->noClientException);
+}
+
+int
+ProcEstablishConnection(client)
+ register ClientPtr client;
+{
+ register xConnClientPrefix *prefix;
+ register int i;
+ int len;
+
+ REQUEST(xReq);
+
+ prefix = (xConnClientPrefix *) ((char *) stuff + sz_xReq);
+
+ nClients++;
+ client->requestVector = client->server->requestVector;
+ client->sequence = 0;
+ client->sequenceNumber = 0;
+ client->largeRequest = NULL;
+
+ /* wait for X server to kill client */
+ client->closeDownMode = RetainPermanent;
+
+ /*
+ * NewClient outputs the LbxNewClient request header - have to follow it
+ * up with the setup connection info.
+ */
+ /* length is still swapped */
+ if (client->swapped) {
+ swaps(&stuff->length, i);
+ /* put data back to the way server will expect it */
+ SwapConnClientPrefix((xConnClientPrefix *) prefix);
+ }
+ len = (stuff->length << 2) - sz_xReq;
+ if (!NewClient(client, len))
+ return (client->noClientException = -1);
+
+ WriteToServer(client->server->serverClient, len, (char *) prefix,
+ TRUE, FALSE);
+
+ /*
+ * Can't allow any requests to be passed on to the server until the
+ * connection setup reply has been received.
+ */
+ IgnoreClient(client);
+
+ return (client->noClientException);
+}
+
+/**********************
+ * CloseDownClient
+ *
+ * Client can either mark his resources destroy or retain. If retained and
+ * then killed again, the client is really destroyed.
+ *********************/
+
+Bool resetAfterLastClient = FALSE;
+Bool terminateAfterLastClient = FALSE;
+
+void
+CloseDownClient(client)
+ register ClientPtr client;
+{
+ if (!client->clientGone)
+ {
+ CloseClient (client);
+
+
+ /* X server is telling us this client is dead */
+ if (client->closeDownMode == DestroyAll)
+ {
+ client->clientGone = TRUE; /* so events aren't sent to client */
+ FreeClientResources(client);
+ CloseDownConnection(client);
+ if (ClientIsAsleep (client))
+ ClientSignal (client);
+ if (client->index < nextFreeClientID)
+ nextFreeClientID = client->index;
+ clients[client->index] = NullClient;
+ if ((client->requestVector != InitialVector) &&
+ (client->server && client->server->serverClient != client) &&
+ (--nClients == 0))
+ {
+ if (resetAfterLastClient)
+ dispatchException |= DE_RESET;
+ else if (terminateAfterLastClient)
+ dispatchException |= DE_TERMINATE;
+ }
+ xfree(client);
+ }
+ else
+ {
+ client->clientGone = TRUE;
+ CloseDownConnection(client);
+ --nClients;
+ }
+ }
+ else
+ {
+ /* really kill resources this time */
+ FreeClientResources(client);
+ if (ClientIsAsleep (client))
+ ClientSignal (client);
+ if (client->index < nextFreeClientID)
+ nextFreeClientID = client->index;
+ clients[client->index] = NullClient;
+ xfree(client);
+ if (nClients == 0)
+ {
+ if (resetAfterLastClient)
+ dispatchException |= DE_RESET;
+ else if (terminateAfterLastClient)
+ dispatchException |= DE_TERMINATE;
+ }
+ }
+
+ while (!clients[currentMaxClients-1])
+ currentMaxClients--;
+}
+
+static void
+KillAllClients()
+{
+ int i;
+ for (i=1; i<currentMaxClients; i++)
+ {
+ if (clients[i])
+ {
+ clients[i]->closeDownMode = DestroyAll;
+ CloseDownClient(clients[i]);
+ }
+ }
+}
+
+extern void (*ZeroPadReqVector[128]) ();
+
+int
+ProcStandardRequest (client)
+ ClientPtr client;
+{
+ REQUEST(xReq);
+ void (*zeroPadProc)();
+ extern int lbxZeroPad;
+
+ if (lbxZeroPad &&
+ (MAJOROP < 128) && (zeroPadProc = ZeroPadReqVector[MAJOROP]))
+ (*zeroPadProc) ((void *) stuff);
+ FinishLBXRequest(client, REQ_PASSTHROUGH);
+ WriteReqToServer(client, client->req_len << 2, (char *) stuff, TRUE);
+ return Success;
+}
+
+/* ARGSUSED */
+int
+ProcBadRequest (client)
+ ClientPtr client;
+{
+ return BadRequest;
+}
+
+/*
+ * Turn off optional features. Some features, like tags, will be turned
+ * off after option negotiation.
+ */
+
+void
+AdjustProcVector()
+{
+ int i;
+
+ /*
+ * to turn off all LBX request reencodings, set all proc vectors to
+ * ProcStandardRequest
+ */
+ if (!lbxUseLbx) {
+ for (i = 1; i < 256; i++) {
+ ProcVector[i] = ProcStandardRequest;
+ }
+ }
+
+ if (!atomsFile)
+ ProcVector[X_ChangeWindowAttributes] = ProcStandardRequest;
+
+ if (!lbxCompressImages) {
+ ProcVector[X_PutImage] = ProcStandardRequest;
+ ProcVector[X_GetImage] = ProcStandardRequest;
+ }
+
+ if (!lbxDoAtomShortCircuiting) {
+ ProcVector[X_InternAtom] = ProcStandardRequest;
+ ProcVector[X_GetAtomName] = ProcStandardRequest;
+ }
+
+ if (!lbxDoCmapGrabbing)
+ {
+ ProcVector[X_CreateColormap] = ProcStandardRequest;
+ ProcVector[X_FreeColormap] = ProcStandardRequest;
+ ProcVector[X_CopyColormapAndFree] = ProcStandardRequest;
+ ProcVector[X_AllocColor] = ProcStandardRequest;
+ ProcVector[X_AllocNamedColor] = ProcStandardRequest;
+ ProcVector[X_AllocColorCells] = ProcStandardRequest;
+ ProcVector[X_AllocColorPlanes] = ProcStandardRequest;
+ ProcVector[X_FreeColors] = ProcStandardRequest;
+ ProcVector[X_LookupColor] = ProcStandardRequest;
+ }
+
+ if (!lbxDoLbxGfx) {
+ ProcVector[X_CopyArea] = ProcStandardRequest;
+ ProcVector[X_CopyPlane] = ProcStandardRequest;
+ ProcVector[X_PolyPoint] = ProcStandardRequest;
+ ProcVector[X_PolyLine] = ProcStandardRequest;
+ ProcVector[X_PolySegment] = ProcStandardRequest;
+ ProcVector[X_PolyRectangle] = ProcStandardRequest;
+ ProcVector[X_PolyArc] = ProcStandardRequest;
+ ProcVector[X_FillPoly] = ProcStandardRequest;
+ ProcVector[X_PolyFillRectangle] = ProcStandardRequest;
+ ProcVector[X_PolyFillArc] = ProcStandardRequest;
+ ProcVector[X_PolyText8] = ProcStandardRequest;
+ ProcVector[X_PolyText16] = ProcStandardRequest;
+ ProcVector[X_ImageText8] = ProcStandardRequest;
+ ProcVector[X_ImageText16] = ProcStandardRequest;
+ }
+
+ if (!lbxWinAttr)
+ {
+ ProcVector[X_GetWindowAttributes] = ProcStandardRequest;
+ ProcVector[X_GetGeometry] = ProcStandardRequest;
+ }
+}
+
+
+static void
+HandleLargeRequest ()
+
+{
+ LbxLargeRequestRec *largeRequest = largeRequestQueue[0];
+ ClientPtr client = largeRequest->client;
+ int bytesLeft, chunkSize;
+
+ /*
+ * Process the first large request on the queue. If this is the first
+ * chunk of a large request, send an LbxBeginLargeRequest message.
+ */
+
+ if (largeRequest->bytesWritten == 0) {
+ xLbxBeginLargeRequestReq beginReq;
+ int n;
+
+ beginReq.reqType = client->server->lbxReq;
+ beginReq.lbxReqType = X_LbxBeginLargeRequest;
+ beginReq.length = 2;
+ beginReq.largeReqLength = largeRequest->totalBytes >> 2;
+ if (client->swapped) {
+ swapl(&beginReq.largeReqLength, n);
+ }
+ _write_to_server (client,
+ largeRequest->compressed,
+ sizeof (beginReq), (char *) &beginReq,
+ FALSE, TRUE);
+ }
+
+ /*
+ * Send a chunk of the large request using the LbxLargeRequestData message.
+ */
+
+ bytesLeft = largeRequest->totalBytes - largeRequest->bytesWritten;
+
+ if (bytesLeft > LBX_LARGE_REQUEST_CHUNK_SIZE)
+ chunkSize = LBX_LARGE_REQUEST_CHUNK_SIZE;
+ else
+ chunkSize = bytesLeft;
+
+ if (chunkSize > 0) {
+ xLbxLargeRequestDataReq dataReq;
+
+ dataReq.reqType = client->server->lbxReq;
+ dataReq.lbxReqType = X_LbxLargeRequestData;
+ dataReq.length = 1 + (chunkSize >> 2);
+
+ _write_to_server (client,
+ largeRequest->compressed,
+ sizeof (dataReq), (char *) &dataReq,
+ FALSE, TRUE);
+
+ _write_to_server (client,
+ largeRequest->compressed,
+ chunkSize,
+ largeRequest->buf + largeRequest->bytesWritten,
+ FALSE, FALSE);
+
+ largeRequest->bytesWritten += chunkSize;
+ }
+
+ if (numLargeRequestsInQueue > 1) {
+ /*
+ * Move this large request to the end of the queue - this way
+ * we can process large requests from other clients too.
+ */
+
+ memmove((char *)&largeRequestQueue[0], (char *)&largeRequestQueue[1],
+ (numLargeRequestsInQueue - 1) * sizeof(LbxLargeRequestRec *));
+ largeRequestQueue[numLargeRequestsInQueue - 1] = largeRequest;
+ }
+
+ /*
+ * See if the whole request has been sent. If yes, send an
+ * LbxEndLargeRequest and re-enable input for this client.
+ */
+
+ if (largeRequest->bytesWritten == largeRequest->totalBytes) {
+ xLbxEndLargeRequestReq endReq;
+
+ endReq.reqType = client->server->lbxReq;
+ endReq.lbxReqType = X_LbxEndLargeRequest;
+ endReq.length = 1;
+
+ _write_to_server (client,
+ largeRequest->compressed,
+ sizeof (endReq), (char *) &endReq,
+ FALSE, TRUE);
+
+ xfree ((char *) largeRequest);
+ client->largeRequest = NULL;
+ numLargeRequestsInQueue--;
+
+ AttendClient (client);
+ }
+}
diff --git a/di/extensions.c b/di/extensions.c
new file mode 100644
index 0000000..a26edb4
--- /dev/null
+++ b/di/extensions.c
@@ -0,0 +1,319 @@
+/* $Xorg: extensions.c,v 1.5 2001/02/09 02:05:31 xorgcvs Exp $ */
+/*
+
+Copyright 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+*/
+/*
+ * Copyright 1994 Network Computing Devices, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name Network Computing Devices, Inc. not be
+ * used in advertising or publicity pertaining to distribution of this
+ * software without specific, written prior permission.
+ *
+ * THIS SOFTWARE IS PROVIDED `AS-IS'. NETWORK COMPUTING DEVICES, INC.,
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT
+ * LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, OR NONINFRINGEMENT. IN NO EVENT SHALL NETWORK
+ * COMPUTING DEVICES, INC., BE LIABLE FOR ANY DAMAGES WHATSOEVER, INCLUDING
+ * SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES, INCLUDING LOSS OF USE, DATA,
+ * OR PROFITS, EVEN IF ADVISED OF THE POSSIBILITY THEREOF, AND REGARDLESS OF
+ * WHETHER IN AN ACTION IN CONTRACT, TORT OR NEGLIGENCE, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+/* tracks server extensions */
+
+#include "lbx.h"
+#include "assert.h"
+#include "wire.h"
+#include "lbxext.h"
+#include "reqtype.h"
+#include "swap.h"
+
+typedef struct _extinfo {
+ int nlen;
+ char *name;
+ int idx;
+ int opcode;
+ int event;
+ int error;
+ CARD8 *rep_mask,
+ *ev_mask;
+ int num_reqs;
+ ExtensionInfoPtr next;
+} ExtensionInfoRec;
+
+static Bool
+AddExtension(server, name, reply, rep_mask, ev_mask)
+ XServerPtr server;
+ char *name;
+ xLbxQueryExtensionReplyPtr reply;
+ CARD8 *rep_mask,
+ *ev_mask;
+{
+ ExtensionInfoPtr eip = NULL;
+ int req_mask_len;
+
+ for (eip = server->extensions; eip; eip = eip->next) {
+ if (!strcmp(eip->name, name))
+ return TRUE;
+ }
+ eip = (ExtensionInfoPtr) xalloc(sizeof(ExtensionInfoRec));
+ if (!eip)
+ return FALSE;
+ eip->nlen = strlen(name);
+ eip->name = (char *) xalloc(eip->nlen + 1);
+ if (!eip->name) {
+ xfree(eip);
+ return FALSE;
+ }
+ strcpy(eip->name, name);
+ req_mask_len = (reply->numReqs + 7) >> 3;
+ eip->rep_mask = (CARD8 *) xalloc(req_mask_len);
+ eip->ev_mask = (CARD8 *) xalloc(req_mask_len);
+ if (req_mask_len && (!eip->rep_mask || !eip->ev_mask)) {
+ xfree(eip->rep_mask);
+ xfree(eip->ev_mask);
+ xfree(eip->name);
+ xfree(eip);
+ return FALSE;
+ }
+ if (reply->numReqs) {
+ memcpy((char *) eip->rep_mask, (char *) rep_mask, req_mask_len);
+ memcpy((char *) eip->ev_mask, (char *) ev_mask, req_mask_len);
+ }
+ eip->num_reqs = reply->numReqs;
+ eip->opcode = reply->major_opcode;
+ eip->event = reply->first_event;
+ eip->error = reply->first_error;
+ eip->next = server->extensions;
+ server->extensions = eip;
+ return TRUE;
+}
+
+void
+DeleteExtensions(server)
+ XServerPtr server;
+{
+ ExtensionInfoPtr eip;
+
+ while ((eip = server->extensions)) {
+ server->extensions = eip->next;
+ xfree(eip->name);
+ xfree(eip->rep_mask);
+ xfree(eip->ev_mask);
+ xfree(eip);
+ }
+}
+
+/*ARGSUSED*/
+void
+HandleExtensionError(client, err, nr)
+ ClientPtr client;
+ xError *err;
+ ReplyStuffPtr nr;
+{
+}
+
+/*ARGSUSED*/
+void
+HandleExtensionEvent(client, ev)
+ ClientPtr client;
+ xEvent *ev;
+{
+}
+
+static Bool
+check_mask(mask, minorop)
+ CARD8 *mask;
+ int minorop;
+{
+ if (mask[minorop >> 3] & (1 << (minorop & 7)))
+ return REQ_TYPE_YES;
+ else
+ return REQ_TYPE_NO;
+}
+
+Bool
+CheckExtensionForEvents(client, req)
+ ClientPtr client;
+ xReq *req;
+{
+ int opcode = req->reqType;
+ int minorop = req->data;
+ ExtensionInfoPtr eip;
+
+ for (eip = client->server->extensions; eip; eip = eip->next) {
+ if (eip->opcode == opcode) {
+ if (!eip->ev_mask || !eip->num_reqs)
+ return TRUE; /* assume worst */
+ return check_mask(eip->ev_mask, minorop);
+ }
+ }
+ /* assume the worst */
+ return TRUE;
+}
+
+Bool
+CheckExtensionForReplies(client, req)
+ ClientPtr client;
+ xReq *req;
+{
+ int opcode = req->reqType;
+ int minorop = req->data;
+ ExtensionInfoPtr eip;
+
+ for (eip = client->server->extensions; eip; eip = eip->next) {
+ if (eip->opcode == opcode) {
+ if (!eip->rep_mask || !eip->num_reqs)
+ return REQ_TYPE_MAYBE; /* assume worst */
+ return check_mask(eip->rep_mask, minorop);
+ }
+ }
+ /* assume the worst */
+ return REQ_TYPE_MAYBE;
+}
+
+static Bool
+HandleLbxQueryExtensionReply(client, nr, data)
+ ClientPtr client;
+ ReplyStuffPtr nr;
+ char *data;
+{
+ xLbxQueryExtensionReply *reply;
+ xQueryExtensionReply crep;
+ char *ename;
+ CARD8 *rep_mask = NULL,
+ *ev_mask = NULL;
+
+ reply = (xLbxQueryExtensionReply *) data;
+
+ ename = nr->request_info.lbxqueryextension.name;
+
+ if (reply->length) {
+ rep_mask = (CARD8 *) &reply[1];
+ ev_mask = rep_mask + ((((reply->numReqs + 7) >> 3) + 3) & ~3);
+ }
+ if (reply->present)
+ AddExtension(client->server, ename, reply, rep_mask, ev_mask);
+ xfree(ename);
+
+ /* and finally tell client about it */
+ crep.type = X_Reply;
+ crep.length = 0;
+ crep.sequenceNumber = reply->sequenceNumber;
+ crep.present = reply->present;
+ crep.major_opcode = reply->major_opcode;
+ crep.first_event = reply->first_event;
+ crep.first_error = reply->first_error;
+ if (client->swapped)
+ SwapQueryExtensionReply(&crep);
+ WriteToClient(client, sizeof(xQueryExtensionReply), (char *) &crep);
+
+ return TRUE;
+}
+
+static int
+QueryExtensionReply(client, present, opcode, event, error)
+ ClientPtr client;
+ Bool present;
+ int opcode, event, error;
+{
+ xQueryExtensionReply reply;
+
+ reply.type = X_Reply;
+ reply.length = 0;
+ reply.sequenceNumber = LBXSequenceNumber(client);
+ reply.present = present;
+ reply.major_opcode = opcode;
+ reply.first_event = event;
+ reply.first_error = error;
+ if (client->swapped)
+ SwapQueryExtensionReply(&reply);
+ if (LBXCacheSafe(client)) {
+ FinishLBXRequest(client, REQ_YANK);
+ WriteToClient(client, sizeof(xQueryExtensionReply), (char *)&reply);
+ } else { /* store for later */
+ if (!LBXCanDelayReply(client))
+ SendLbxSync(client);
+ FinishLBXRequest(client, REQ_YANKLATE);
+ SaveReplyData(client, (xReply *) &reply, 0, NULL);
+ }
+ return Success;
+}
+
+int
+ProcLBXQueryExtension(client)
+ ClientPtr client;
+{
+ REQUEST(xQueryExtensionReq);
+ char n;
+ char *ename;
+ xLbxQueryExtensionReq req;
+ CARD16 nlen;
+ ReplyStuffPtr nr;
+ ExtensionInfoPtr eip;
+
+ nlen = stuff->nbytes;
+ if (client->swapped) {
+ swaps(&nlen, n);
+ }
+ if (nlen == (sizeof(LBXNAME) - 1) &&
+ !strncmp((char *)&stuff[1], LBXNAME, nlen))
+ return QueryExtensionReply(client, FALSE, 0, 0, 0);
+ for (eip = client->server->extensions; eip; eip = eip->next) {
+ if (nlen == eip->nlen && !strncmp((char *)&stuff[1], eip->name, nlen))
+ return QueryExtensionReply(client, TRUE, eip->opcode,
+ eip->event, eip->error);
+ }
+ ename = (char *) xalloc(nlen + 1);
+ if (!ename)
+ return BadAlloc;
+ memcpy(ename, (char *) &stuff[1], nlen);
+ ename[nlen] = '\0';
+
+ req.reqType = client->server->lbxReq;
+ req.lbxReqType = X_LbxQueryExtension;
+ req.length = 2 + ((nlen + 3) >> 2);
+ req.nbytes = nlen;
+ if (client->swapped)
+ SwapQueryExtension(&req);
+ nr = NewReply(client, client->server->lbxReq, X_LbxQueryExtension,
+ HandleLbxQueryExtensionReply);
+ if (!nr) {
+ xfree(ename);
+ return ProcStandardRequest(client);
+ }
+ nr->request_info.lbxqueryextension.name = ename;
+ FinishLBXRequest(client, REQ_PASSTHROUGH);
+ WriteToServer(client, sizeof(req), (char *) &req, TRUE, TRUE);
+ WriteToServer(client, nlen, ename, FALSE, TRUE);
+
+ return Success;
+}
diff --git a/di/gfx.c b/di/gfx.c
new file mode 100644
index 0000000..885fe5c
--- /dev/null
+++ b/di/gfx.c
@@ -0,0 +1,1258 @@
+/* $Xorg: gfx.c,v 1.4 2001/02/09 02:05:31 xorgcvs Exp $ */
+/*
+
+Copyright 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+*/
+/*
+ * Copyright 1994 Network Computing Devices, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name Network Computing Devices, Inc. not be
+ * used in advertising or publicity pertaining to distribution of this
+ * software without specific, written prior permission.
+ *
+ * THIS SOFTWARE IS PROVIDED `AS-IS'. NETWORK COMPUTING DEVICES, INC.,
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT
+ * LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, OR NONINFRINGEMENT. IN NO EVENT SHALL NETWORK
+ * COMPUTING DEVICES, INC., BE LIABLE FOR ANY DAMAGES WHATSOEVER, INCLUDING
+ * SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES, INCLUDING LOSS OF USE, DATA,
+ * OR PROFITS, EVEN IF ADVISED OF THE POSSIBILITY THEREOF, AND REGARDLESS OF
+ * WHETHER IN AN ACTION IN CONTRACT, TORT OR NEGLIGENCE, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+/*
+ * graphics acceleration
+ */
+
+#include <stdio.h>
+#include "assert.h"
+#include "misc.h"
+#include "lbx.h"
+#include "util.h"
+#include "resource.h"
+#include "wire.h"
+#include "lbximage.h"
+#include "proxyopts.h"
+#include "swap.h"
+
+static Bool GetLbxImageReply();
+
+static int pad[4] = {0, 3, 2, 1};
+
+/*
+ * Routines for re-encoding line, rectangle and arc requests
+ */
+
+#define REENCODE_PSHORT(val, out) \
+ if ((val) >= 0 && (val) < 0xf0) \
+ *(out)++ = (val); \
+ else if ((val) >= 0xef0 || (val) < (short)0xfe00) \
+ return 0; \
+ else if ((val) < 0) { \
+ *(out)++ = 0xf0 | (((val) + 0x1000) >> 8); \
+ *(out)++ = (val) + 0x1000; \
+ } else { \
+ *(out)++ = 0xf0 | (((val) - 0xf0) >> 8); \
+ *(out)++ = (val) - 0xf0; \
+ }
+
+
+#define REENCODE_SHORT(val, out) \
+ if ((val) >= (short)0xff90 && (val) < 0x80) \
+ *(out)++ = (val); \
+ else if ((val) >= (short)0x0880 || (val) < (short)0xf790) \
+ return 0; \
+ else if ((val) < 0) { \
+ *(out)++ = 0x80 | ((((val) + 0x70) >> 8) & 0x0f); \
+ *(out)++ = (val) + 0x70; \
+ } else { \
+ *(out)++ = 0x80 | ((((val) - 0x80) >> 8) & 0x0f); \
+ *(out)++ = (val) - 0x80; \
+ }
+
+#define REENCODE_USHORT(val, out) \
+ if ((val) < 0xf0) \
+ *(out)++ = (val); \
+ else if ((unsigned short)(val) >= 0x10f0) \
+ return 0; \
+ else { \
+ *(out)++ = 0xf0 | (((val) - 0xf0) >> 8); \
+ *(out)++ = (val) - 0xf0; \
+ }
+
+#define REENCODE_ANGLE(val, out) \
+ if ((val) > (360 << 6) || (val) < -(360 << 6)) \
+ return 0; \
+ else if ((val) >= 0 && (val) <= (95 << 6) && !((val) % (5 << 6))) \
+ *(out)++ = 0x5a + ((val) / (5 << 6)); \
+ else if ((val) >= (105 << 6) && !((val) % (15 << 6))) \
+ *(out)++ = 0x67 + ((val) / (15 << 6)); \
+ else if ((val) >= -(100 << 6) && (val) <= -(5 << 6) && \
+ !((val) % (5 << 6))) \
+ *(out)++ = 0xa6 + ((val) / (5 << 6)); \
+ else if ((val) <= -(105 << 6) && !((val) % (15 << 6))) \
+ *(out)++ = 0x98 + ((val) / (15 << 6)); \
+ else { \
+ *(out)++ = (val) >> 8; \
+ *(out)++ = (val); \
+ }
+
+#define COPY_AND_SWAPS(oval, ival) \
+ { \
+ register int n; \
+ (oval) = (ival); \
+ if (client->swapped) \
+ swaps(&(oval), n); \
+ }
+
+#define SWAP_REENCODE_PSHORT(ival, out) { \
+ register int _n; \
+ short _val; \
+ _val = (ival); \
+ if (client->swapped) swaps (&_val, _n); \
+ REENCODE_PSHORT(_val, out); \
+}
+
+#define SWAP_REENCODE_SHORT(ival, out) { \
+ register int _n; \
+ short _val; \
+ _val = (ival); \
+ if (client->swapped) swaps (&_val, _n); \
+ REENCODE_SHORT(_val, out); \
+}
+
+#define SWAP_REENCODE_USHORT(ival, out) { \
+ register int _n; \
+ unsigned short _val; \
+ _val = (ival); \
+ if (client->swapped) swaps (&_val, _n); \
+ REENCODE_USHORT(_val, out); \
+}
+
+int gfx_gc_hit;
+int gfx_gc_miss;
+int gfx_draw_hit;
+int gfx_draw_miss;
+int gfx_total;
+
+static void
+push(cache, xid)
+ XID cache[GFX_CACHE_SIZE];
+ XID xid;
+{
+ memmove(cache + 1, cache, (GFX_CACHE_SIZE - 1) * sizeof(cache[0]));
+ cache[0] = xid;
+}
+
+static void
+use(cache, i)
+ XID cache[GFX_CACHE_SIZE];
+ int i;
+{
+ XID tmp;
+
+ if (i == 0)
+ return;
+ tmp = cache[i];
+ memmove(cache + 1, cache, i * sizeof(cache[0]));
+ cache[0] = tmp;
+}
+
+static int
+match(cache, xid)
+ XID cache[GFX_CACHE_SIZE];
+ XID xid;
+{
+ int j;
+
+ for (j = 0; j < GFX_CACHE_SIZE; j++)
+ if (cache[j] == xid)
+ return j;
+ return GFXCacheNone;
+}
+
+#define GFX_REQ_PAD 8
+
+#define GFX_SRC_DST_REQ_PAD 12
+
+#define GFX_CACHE_DECLARE int _dcache, _gcache; \
+ Drawable _drawable; \
+ GContext _gcontext
+
+#define GFX_SRC_DST_CACHE_DECLARE int _srcDcache, _dstDcache, _gcache; \
+ Drawable _srcDrawable, _dstDrawable; \
+ GContext _gcontext
+
+#define GFX_SETUP_DRAWABLE_AND_GC(after) {\
+ _drawable = stuff->drawable; \
+ _gcontext = stuff->gc; \
+ if (client->swapped) { \
+ register int _n; \
+ swapl(&_drawable, _n); \
+ swapl(&_gcontext, _n); \
+ } \
+ _dcache = match (LBXDrawableCache(client), _drawable); \
+ if (_dcache == GFXCacheNone) \
+ { \
+ memcpy (after, &stuff->drawable, 4); \
+ after += 4; \
+ } \
+ _gcache = match (LBXGContextCache(client), _gcontext); \
+ if (_gcache == GFXCacheNone) \
+ { \
+ memcpy (after, &stuff->gc, 4); \
+ after += 4; \
+ } \
+}
+
+#define GFX_SETUP_SRC_DST_DRAWABLE_AND_GC(after) {\
+ Drawable tmpDrawableCache[GFX_CACHE_SIZE]; \
+ memcpy (tmpDrawableCache, LBXDrawableCache(client), sizeof (LBXDrawableCache(client))); \
+ _srcDrawable = stuff->srcDrawable; \
+ _dstDrawable = stuff->dstDrawable; \
+ _gcontext = stuff->gc; \
+ if (client->swapped) { \
+ register int _n; \
+ swapl (&_srcDrawable, _n); \
+ swapl (&_dstDrawable, _n); \
+ swapl (&_gcontext, _n); \
+ } \
+ _srcDcache = match (LBXDrawableCache(client), _srcDrawable); \
+ if (_srcDcache == GFXCacheNone) \
+ { \
+ memcpy (after, &stuff->srcDrawable, 4); \
+ after += 4; \
+ push (tmpDrawableCache, _srcDrawable); \
+ } else \
+ use (tmpDrawableCache, _srcDcache); \
+ _dstDcache = match (tmpDrawableCache, _dstDrawable); \
+ if (_dstDcache == GFXCacheNone) \
+ { \
+ memcpy (after, &stuff->dstDrawable, 4); \
+ after += 4; \
+ } \
+ _gcache = match (LBXGContextCache(client), _gcontext); \
+ if (_gcache == GFXCacheNone) \
+ { \
+ memcpy (after, &stuff->gc, 4); \
+ after += 4; \
+ } \
+}
+
+#define GFX_SET_DRAWABLE_AND_GC {\
+ if (_dcache == GFXCacheNone) { \
+ gfx_draw_miss++; \
+ push (LBXDrawableCache(client), _drawable); \
+ } else { \
+ gfx_draw_hit++; \
+ use (LBXDrawableCache(client), _dcache); \
+ } \
+ if (_gcache == GFXCacheNone) { \
+ gfx_gc_miss++; \
+ push (LBXGContextCache(client), _gcontext);\
+ } else { \
+ gfx_gc_hit++; \
+ use (LBXGContextCache(client), _gcache); \
+ } \
+ newreq->cacheEnts = GFXCacheEnts (_dcache, _gcache); \
+ gfx_total++; \
+}
+#define GFX_SET_SRC_DST_DRAWABLE_AND_GC {\
+ if (_srcDcache == GFXCacheNone) { \
+ gfx_draw_miss++; \
+ push (LBXDrawableCache(client), _srcDrawable); \
+ } else { \
+ gfx_draw_hit++; \
+ use (LBXDrawableCache(client), _srcDcache); \
+ } \
+ newreq->srcCache = GFXCacheEnts (_srcDcache, 0); \
+ if (_dstDcache == GFXCacheNone) { \
+ gfx_draw_miss++; \
+ push (LBXDrawableCache(client), _dstDrawable); \
+ } else { \
+ gfx_draw_hit++; \
+ use (LBXDrawableCache(client), _dstDcache); \
+ } \
+ if (_gcache == GFXCacheNone) { \
+ gfx_gc_miss++; \
+ push (LBXGContextCache(client), _gcontext);\
+ } else { \
+ gfx_gc_hit++; \
+ use (LBXGContextCache(client), _gcache); \
+ } \
+ newreq->cacheEnts = GFXCacheEnts (_dstDcache, _gcache); \
+ gfx_total++; \
+}
+
+static int
+reencode_poly(client, lbxreq, reencode_rtn)
+ ClientPtr client;
+ CARD8 lbxreq;
+ int (*reencode_rtn) ();
+{
+ REQUEST(xPolyPointReq);
+ XServerPtr server = client->server;
+ int len = client->req_len << 2;
+ int space;
+ xLbxPolyPointReq *newreq = NULL;
+ char *after;
+ int bytes;
+
+ GFX_CACHE_DECLARE;
+
+ space = len - sz_xPolyPointReq + sz_xLbxPolyPointReq + GFX_REQ_PAD + 3;
+ newreq = (xLbxPolyPointReq *) xalloc(space);
+ if (newreq == NULL)
+ goto bail;
+ after = ((char *) newreq) + sz_xLbxPolyPointReq;
+ GFX_SETUP_DRAWABLE_AND_GC(after);
+ bytes = (*reencode_rtn) (client, (short *) &stuff[1],
+ (char *) after,
+ (len - sz_xPolyPointReq) >> 2);
+ if (bytes == 0)
+ goto bail;
+ FinishLBXRequest(client, REQ_PASSTHROUGH);
+ newreq->reqType = server->lbxReq;
+ newreq->lbxReqType = lbxreq;
+ GFX_SET_DRAWABLE_AND_GC;
+ len = after - ((char *) newreq) + bytes;
+ newreq->padBytes = pad[len & 3];
+ bzero(((char *) newreq) + len, newreq->padBytes);
+ len += newreq->padBytes;
+ newreq->length = len >> 2;
+ WriteReqToServer(client, len, (char *) newreq, TRUE);
+ xfree(newreq);
+ return Success;
+bail:
+ if (newreq)
+ xfree(newreq);
+ return ProcStandardRequest(client);
+
+}
+
+
+/* ARGSUSED */
+static int
+reencode_points_origin(client, in, out, count)
+ ClientPtr client;
+ register short *in;
+ register char *out;
+ int count;
+{
+ register short diff;
+ int i;
+ short inval;
+ short last_x = 0;
+ short last_y = 0;
+ char *start_out = out;
+
+ for (i = 0; i < count; i++, in += 2) {
+ COPY_AND_SWAPS(inval, in[0]);
+ diff = inval - last_x;
+ last_x = inval;
+ REENCODE_SHORT(diff, out);
+ COPY_AND_SWAPS(inval, in[1]);
+ diff = inval - last_y;
+ last_y = inval;
+ REENCODE_SHORT(diff, out);
+ }
+ return out - start_out;
+}
+
+/* ARGSUSED */
+static int
+reencode_points_previous(client, in, out, count)
+ ClientPtr client;
+ register short *in;
+ register char *out;
+ int count;
+{
+ int i;
+ short inval;
+ char *start_out = out;
+
+ for (i = 0; i < count; i++, in += 2) {
+ COPY_AND_SWAPS(inval, in[0]);
+ REENCODE_SHORT(inval, out);
+ COPY_AND_SWAPS(inval, in[1]);
+ REENCODE_SHORT(inval, out);
+ }
+ return out - start_out;
+}
+
+/* ARGSUSED */
+static int
+reencode_segment(client, in, out, count)
+ ClientPtr client;
+ register short *in;
+ register char *out;
+ int count;
+{
+ register short diff;
+ int i;
+ short inval;
+ short last_x = 0;
+ short last_y = 0;
+ char *start_out = out;
+
+ count >>= 1;
+ for (i = 0; i < count; i++, in += 4) {
+ /* reencode (x1, y1) */
+ COPY_AND_SWAPS(inval, in[0]);
+ diff = inval - last_x;
+ last_x = inval;
+ REENCODE_SHORT(diff, out);
+ COPY_AND_SWAPS(inval, in[1]);
+ diff = inval - last_y;
+ last_y = inval;
+ REENCODE_SHORT(diff, out);
+
+ /* reencode (x2, y2) */
+ COPY_AND_SWAPS(inval, in[2]);
+ diff = inval - last_x;
+ REENCODE_SHORT(diff, out);
+ COPY_AND_SWAPS(inval, in[3]);
+ diff = inval - last_y;
+ REENCODE_SHORT(diff, out);
+ }
+ return out - start_out;
+}
+
+/* ARGSUSED */
+static int
+reencode_rectangle(client, in, out, count)
+ ClientPtr client;
+ register short *in;
+ register char *out;
+ int count;
+{
+ register short diff;
+ int i;
+ short inval;
+ short last_x = 0;
+ short last_y = 0;
+ char *start_out = out;
+
+ count >>= 1;
+ for (i = 0; i < count; i++, in += 4) {
+ /* reencode (x, y) origin */
+ COPY_AND_SWAPS(inval, in[0]);
+ diff = inval - last_x;
+ last_x = inval;
+ REENCODE_SHORT(diff, out);
+ COPY_AND_SWAPS(inval, in[1]);
+ diff = inval - last_y;
+ last_y = inval;
+ REENCODE_SHORT(diff, out);
+
+ /* reencode (width, height) */
+ COPY_AND_SWAPS(inval, in[2]);
+ REENCODE_USHORT(inval, out);
+ COPY_AND_SWAPS(inval, in[3]);
+ REENCODE_USHORT(inval, out);
+ }
+ return out - start_out;
+}
+
+/* ARGSUSED */
+static int
+reencode_arc(client, in, out, count)
+ ClientPtr client;
+ register short *in;
+ register char *out;
+ int count;
+{
+ register short diff;
+ int i;
+ short inval;
+ short last_x = 0;
+ short last_y = 0;
+ char *start_out = out;
+
+ count = count / 3;
+ for (i = 0; i < count; i++, in += 6) {
+ /* reencode (x, y) origin */
+ COPY_AND_SWAPS(inval, in[0]);
+ diff = inval - last_x;
+ last_x = inval;
+ REENCODE_SHORT(diff, out);
+ COPY_AND_SWAPS(inval, in[1]);
+ diff = inval - last_y;
+ last_y = inval;
+ REENCODE_SHORT(diff, out);
+
+ /* reencode (width, height) */
+ COPY_AND_SWAPS(inval, in[2]);
+ REENCODE_USHORT(inval, out);
+ COPY_AND_SWAPS(inval, in[3]);
+ REENCODE_USHORT(inval, out);
+
+ /* reencode (angle1, angle2) */
+ COPY_AND_SWAPS(inval, in[4]);
+ REENCODE_ANGLE(inval, out);
+ COPY_AND_SWAPS(inval, in[5]);
+ REENCODE_ANGLE(inval, out);
+ }
+ return out - start_out;
+}
+
+int
+ProcLBXPolyPoint(client)
+ ClientPtr client;
+{
+ REQUEST(xPolyPointReq);
+ int (*reencode_rtn) ();
+
+ reencode_rtn = (stuff->coordMode) ? reencode_points_previous :
+ reencode_points_origin;
+ return reencode_poly(client, X_LbxPolyPoint, reencode_rtn);
+}
+
+int
+ProcLBXPolyLine(client)
+ ClientPtr client;
+{
+ REQUEST(xPolyLineReq);
+ int (*reencode_rtn) ();
+
+ reencode_rtn = (stuff->coordMode) ? reencode_points_previous :
+ reencode_points_origin;
+ return reencode_poly(client, X_LbxPolyLine, reencode_rtn);
+}
+
+int
+ProcLBXPolySegment(client)
+ ClientPtr client;
+{
+ return reencode_poly(client, X_LbxPolySegment, reencode_segment);
+}
+
+int
+ProcLBXPolyRectangle(client)
+ ClientPtr client;
+{
+ return reencode_poly(client, X_LbxPolyRectangle, reencode_rectangle);
+}
+
+int
+ProcLBXPolyArc(client)
+ ClientPtr client;
+{
+ return reencode_poly(client, X_LbxPolyArc, reencode_arc);
+}
+
+int
+ProcLBXFillPoly(client)
+ ClientPtr client;
+{
+ REQUEST(xFillPolyReq);
+ XServerPtr server = client->server;
+ int len = client->req_len << 2;
+ xLbxFillPolyReq *newreq = NULL;
+ char *after;
+ int bytes;
+ int space;
+ int (*reencode_rtn) ();
+
+ GFX_CACHE_DECLARE;
+
+ reencode_rtn = (stuff->coordMode) ? reencode_points_previous :
+ reencode_points_origin;
+
+ space = len - sz_xFillPolyReq + sz_xLbxPolyPointReq + GFX_REQ_PAD + 3;
+ newreq = (xLbxFillPolyReq *) xalloc(space);
+ if (newreq == NULL)
+ goto bail;
+ after = ((char *) newreq) + sz_xLbxFillPolyReq;
+ GFX_SETUP_DRAWABLE_AND_GC(after);
+ bytes = (*reencode_rtn) (client, (short *) &stuff[1], after,
+ (len - sz_xFillPolyReq) >> 2);
+ if (bytes == 0)
+ goto bail;
+
+ FinishLBXRequest(client, REQ_PASSTHROUGH);
+ newreq->reqType = server->lbxReq;
+ newreq->lbxReqType = X_LbxFillPoly;
+ newreq->shape = stuff->shape;
+ GFX_SET_DRAWABLE_AND_GC;
+ len = after - ((char *) newreq) + bytes;
+ newreq->padBytes = pad[len & 3];
+ bzero(((char *) newreq) + len, newreq->padBytes);
+ len += newreq->padBytes;
+ newreq->length = len >> 2;
+ WriteReqToServer(client, len, (char *) newreq, TRUE);
+ xfree(newreq);
+ return Success;
+bail:
+ if (newreq)
+ xfree(newreq);
+ return ProcStandardRequest(client);
+}
+
+int
+ProcLBXPolyFillRectangle(client)
+ ClientPtr client;
+{
+ return reencode_poly(client, X_LbxPolyFillRectangle, reencode_rectangle);
+}
+
+int
+ProcLBXPolyFillArc(client)
+ ClientPtr client;
+{
+ return reencode_poly(client, X_LbxPolyFillArc, reencode_arc);
+}
+
+static int
+reencode_copy(client, in, out)
+ ClientPtr client;
+ register xCopyAreaReq *in;
+ register char *out;
+{
+ char *start_out = out;
+
+ SWAP_REENCODE_PSHORT(in->srcX, out);
+ SWAP_REENCODE_PSHORT(in->srcY, out);
+ SWAP_REENCODE_PSHORT(in->dstX, out);
+ SWAP_REENCODE_PSHORT(in->dstY, out);
+ SWAP_REENCODE_USHORT(in->width, out);
+ SWAP_REENCODE_USHORT(in->height, out);
+ return out - start_out;
+}
+
+int
+ProcLBXCopyArea(client)
+ ClientPtr client;
+{
+ REQUEST(xCopyAreaReq);
+ XServerPtr server = client->server;
+ int len;
+ xLbxCopyAreaReq *newreq = NULL;
+ unsigned long space[(SIZEOF(xLbxCopyAreaReq) + GFX_SRC_DST_REQ_PAD + 7 * sizeof(unsigned long) - 1) / sizeof(unsigned long)];
+ char *after;
+ int extra;
+ int bytes;
+
+ GFX_SRC_DST_CACHE_DECLARE;
+
+ newreq = (xLbxCopyAreaReq *) space;
+ after = ((char *) newreq) + sz_xLbxCopyAreaReq;
+ GFX_SETUP_SRC_DST_DRAWABLE_AND_GC(after);
+ bytes = reencode_copy(client, stuff, after);
+ if (bytes == 0)
+ goto bail;
+ FinishLBXRequest(client, REQ_PASSTHROUGH);
+ newreq->reqType = server->lbxReq;
+ newreq->lbxReqType = X_LbxCopyArea;
+ GFX_SET_SRC_DST_DRAWABLE_AND_GC;
+ len = ((after + bytes) - ((char *) newreq));
+ extra = pad[len & 3];
+ bzero(((char *) newreq) + len, extra);
+ len += extra;
+ newreq->length = len >> 2;
+ WriteReqToServer(client, len, (char *) newreq, TRUE);
+ return Success;
+bail:
+ return ProcStandardRequest(client);
+}
+
+int
+ProcLBXCopyPlane(client)
+ ClientPtr client;
+{
+ REQUEST(xCopyPlaneReq);
+ XServerPtr server = client->server;
+ int len;
+ xLbxCopyPlaneReq *newreq = NULL;
+ unsigned long space[(SIZEOF(xLbxCopyPlaneReq) + GFX_SRC_DST_REQ_PAD + 7 * sizeof(unsigned long) - 1) / sizeof(unsigned long)];
+ char *after;
+ int bytes;
+ int extra;
+
+ GFX_SRC_DST_CACHE_DECLARE;
+
+ newreq = (xLbxCopyPlaneReq *) space;
+ after = ((char *) newreq) + sz_xLbxCopyPlaneReq;
+ GFX_SETUP_SRC_DST_DRAWABLE_AND_GC(after);
+ bytes = reencode_copy(client, (xCopyAreaReq *)stuff, after);
+ if (bytes == 0)
+ goto bail;
+ FinishLBXRequest(client, REQ_PASSTHROUGH);
+ newreq->reqType = server->lbxReq;
+ newreq->bitPlane = stuff->bitPlane;
+ newreq->lbxReqType = X_LbxCopyPlane;
+ GFX_SET_SRC_DST_DRAWABLE_AND_GC;
+ len = ((after + bytes) - ((char *) newreq));
+ extra = pad[len & 3];
+ bzero(((char *) newreq) + len, extra);
+ len += extra;
+ newreq->length = len >> 2;
+ WriteReqToServer(client, len, (char *) newreq, TRUE);
+ return Success;
+bail:
+ return ProcStandardRequest(client);
+}
+
+static int
+reencode_text_pos(client, in, out)
+ ClientPtr client;
+ xPolyTextReq *in;
+ char *out;
+{
+ char *start_out;
+
+ start_out = out;
+ SWAP_REENCODE_PSHORT(in->x, out);
+ SWAP_REENCODE_PSHORT(in->y, out);
+ return out - start_out;
+}
+
+int
+ProcLBXPolyText(client)
+ ClientPtr client;
+{
+ REQUEST(xPolyTextReq);
+ XServerPtr server = client->server;
+ int len = client->req_len << 2;
+ xLbxPolyTextReq *newreq = NULL;
+ int space;
+ char *after;
+ int bytes;
+ int extra;
+
+ GFX_CACHE_DECLARE;
+
+ space = len - sz_xPolyTextReq + sz_xLbxPolyTextReq + GFX_REQ_PAD + 4 + 3;
+ newreq = (xLbxPolyTextReq *) xalloc(space);
+ if (newreq == NULL)
+ goto bail;
+ after = ((char *) newreq) + sz_xLbxPolyTextReq;
+ GFX_SETUP_DRAWABLE_AND_GC(after);
+ /* Reencode the text position */
+ bytes = reencode_text_pos(client, stuff, after);
+ if (bytes == 0)
+ goto bail;
+ /* copy the text elements */
+ memcpy(after + bytes, (char *) &stuff[1], len - sz_xPolyTextReq);
+ bytes += len - sz_xPolyTextReq;
+ FinishLBXRequest(client, REQ_PASSTHROUGH);
+ newreq->reqType = server->lbxReq;
+ newreq->lbxReqType = stuff->reqType == X_PolyText8 ? X_LbxPolyText8 : X_LbxPolyText16;
+ GFX_SET_DRAWABLE_AND_GC;
+ len = ((after + bytes) - ((char *) newreq));
+ extra = pad[len & 3];
+ bzero(((char *) newreq) + len, extra);
+ len += extra;
+ newreq->length = len >> 2;
+ WriteReqToServer(client, len, (char *) newreq, TRUE);
+ xfree(newreq);
+ return Success;
+bail:
+ if (newreq)
+ xfree(newreq);
+ return ProcStandardRequest(client);
+}
+
+int
+ProcLBXImageText(client)
+ ClientPtr client;
+{
+ REQUEST(xImageTextReq);
+ XServerPtr server = client->server;
+ int len = client->req_len << 2;
+ xLbxImageTextReq *newreq = NULL;
+ int space;
+ char *after;
+ int bytes;
+ int extra;
+
+ GFX_CACHE_DECLARE;
+
+ space = len - sz_xImageTextReq + sz_xLbxImageTextReq + GFX_REQ_PAD + 4 + 3;
+ newreq = (xLbxImageTextReq *) xalloc(space);
+ if (newreq == NULL)
+ goto bail;
+ after = ((char *) newreq) + sz_xLbxImageTextReq;
+ GFX_SETUP_DRAWABLE_AND_GC(after);
+ /* Reencode the text position */
+ bytes = reencode_text_pos(client, (xPolyTextReq *) stuff, after);
+ if (bytes == 0)
+ goto bail;
+ /* copy the text elements */
+ memcpy(after + bytes, (char *) &stuff[1], len - sz_xImageTextReq);
+ bytes += len - sz_xImageTextReq;
+ FinishLBXRequest(client, REQ_PASSTHROUGH);
+ newreq->reqType = server->lbxReq;
+ newreq->lbxReqType = stuff->reqType == X_ImageText8 ? X_LbxImageText8 : X_LbxImageText16;
+ newreq->nChars = stuff->nChars;
+ GFX_SET_DRAWABLE_AND_GC;
+ len = ((after + bytes) - ((char *) newreq));
+ extra = pad[len & 3];
+ bzero(((char *) newreq) + len, extra);
+ len += extra;
+ newreq->length = len >> 2;
+ WriteReqToServer(client, len, (char *) newreq, TRUE);
+ xfree(newreq);
+ return Success;
+bail:
+ if (newreq)
+ xfree(newreq);
+ return ProcStandardRequest(client);
+}
+
+static void
+SwapXPutImage(req)
+ xPutImageReq *req;
+{
+ char n;
+
+ swaps(&req->width, n);
+ swaps(&req->height, n);
+ swaps(&req->dstX, n);
+ swaps(&req->dstY, n);
+}
+
+static char *
+reencode_putimage(stuff, newreq)
+ xPutImageReq *stuff;
+ xLbxPutImageReq *newreq;
+{
+ char *out;
+
+ if (stuff->format > ZPixmap || stuff->leftPad > 31 ||
+ !stuff->depth || stuff->depth > 32 ||
+ (stuff->format == ZPixmap && stuff->leftPad != 0))
+ return 0;
+
+ out = (char *)newreq + sz_xLbxPutImageReq;
+ if (!stuff->leftPad && stuff->depth <= 8)
+ newreq->bitPacked = 0x80 | (stuff->format << 5) |
+ ((stuff->depth - 1) << 2);
+ else {
+ newreq->bitPacked = ((stuff->depth - 1) << 2);
+ *out++ = (stuff->format << 5) | stuff->leftPad;
+ }
+ REENCODE_USHORT(stuff->width, out);
+ REENCODE_USHORT(stuff->height, out);
+ REENCODE_PSHORT(stuff->dstX, out);
+ REENCODE_PSHORT(stuff->dstY, out);
+
+ return out;
+}
+
+#define MaxPutImageSz sz_xLbxPutImageReq + 1 + 2 + 2 + 2 + 2 + GFX_REQ_PAD
+
+int
+ProcLBXPutImage(client)
+ ClientPtr client;
+{
+ REQUEST(xPutImageReq);
+ XServerPtr server = client->server;
+ unsigned long space[(MaxPutImageSz + sizeof(unsigned long) - 1) / sizeof(unsigned long)];
+ xLbxPutImageReq *newreq;
+ char *data = NULL;
+ char *out;
+ int len,
+ reqlen,
+ method,
+ compBytes,
+ status;
+#ifdef LBX_STATS
+ float percentCompression;
+ char *methodName;
+#endif
+ LbxBitmapCompMethod *bcompMethod;
+ LbxPixmapCompMethod *pcompMethod;
+ GFX_CACHE_DECLARE;
+
+ status = LBX_IMAGE_COMPRESS_SUCCESS;
+ if (stuff->format != ZPixmap ||
+ (stuff->depth == 1 && LBXZBitsPerPixel1(client) == 1))
+ {
+ bcompMethod = LbxFindPreferredBitmapCompMethod (client->server);
+ if (!bcompMethod)
+ status = LBX_IMAGE_COMPRESS_NO_SUPPORT;
+ } else {
+ pcompMethod = LbxFindPreferredPixmapCompMethod (client->server,
+ (int) stuff->format, (int) stuff->depth);
+ if (!pcompMethod)
+ status = LBX_IMAGE_COMPRESS_NO_SUPPORT;
+ }
+
+ if (status == LBX_IMAGE_COMPRESS_NO_SUPPORT &&
+ client->req_len >= 64 + (sz_xPutImageReq >> 2))
+ return ProcStandardRequest(client);
+
+ if (client->swapped)
+ SwapXPutImage(stuff);
+
+ newreq = (xLbxPutImageReq *)space;
+ newreq->reqType = server->lbxReq;
+ newreq->lbxReqType = X_LbxPutImage;
+ out = reencode_putimage(stuff, newreq);
+
+ if (!out) {
+ SwapXPutImage(stuff);
+ return ProcStandardRequest(client);
+ }
+
+ GFX_SETUP_DRAWABLE_AND_GC(out);
+
+ reqlen = out - (char *)space;
+ len = client->req_len << 2;
+
+ data = (char *) xalloc(len);
+ if (!data || status == LBX_IMAGE_COMPRESS_NO_SUPPORT)
+ {
+ if (!data)
+ status = LBX_IMAGE_COMPRESS_BAD_MALLOC;
+ }
+ else if (stuff->format != ZPixmap ||
+ (stuff->depth == 1 && LBXZBitsPerPixel1(client) == 1))
+ {
+ int ppl, bpl, nbytes;
+
+ if (!bcompMethod->inited)
+ {
+ if (bcompMethod->compInit)
+ (*bcompMethod->compInit)();
+ bcompMethod->inited = 1;
+ }
+
+ ppl = stuff->width + stuff->leftPad;
+ if (LBXBitmapBitOrder(client) != LBXImageByteOrder(client))
+ ppl = ((ppl + LBXBitmapScanlineUnit(client) - 1) &
+ ~LBXBitmapScanlineUnit(client));
+ bpl = (((ppl + LBXBitmapScanlinePad(client) - 1) /
+ LBXBitmapScanlinePad(client)) *
+ (LBXBitmapScanlinePad(client) >> 3));
+ nbytes = bpl * stuff->height;
+ if (stuff->format == XYPixmap)
+ nbytes *= stuff->depth;
+ status = (*bcompMethod->compFunc) (
+ (unsigned char *) &stuff[1],
+ (unsigned char *) data + reqlen,
+ len - reqlen,
+ nbytes,
+ ppl,
+ bpl,
+ LBXBitmapBitOrder(client) == LSBFirst,
+ &compBytes);
+
+ method = bcompMethod->methodOpCode;
+#ifdef LBX_STATS
+ methodName = bcompMethod->methodName;
+#endif
+ }
+ else
+ {
+ if (!pcompMethod->inited)
+ {
+ if (pcompMethod->compInit)
+ (*pcompMethod->compInit)();
+ pcompMethod->inited = 1;
+ }
+
+ status = (*pcompMethod->compFunc) (
+ (char *) &stuff[1],
+ (char *) data + reqlen,
+ len - reqlen,
+ (int) stuff->format,
+ (int) stuff->depth,
+ (int) stuff->height,
+ (int) (len - sz_xPutImageReq) / stuff->height,
+ &compBytes);
+
+ method = pcompMethod->methodOpCode;
+#ifdef LBX_STATS
+ methodName = pcompMethod->methodName;
+#endif
+ }
+
+#ifdef LBX_STATS
+ fprintf(stderr, "PutImage (xid=%x, w=%d, h=%d, x=%d, y=%d): ",
+ stuff->drawable, stuff->width, stuff->height,
+ stuff->dstX, stuff->dstY);
+#endif
+
+ if (status != LBX_IMAGE_COMPRESS_SUCCESS)
+ {
+#ifdef LBX_STATS
+ fprintf(stderr, "image not compressed - ");
+
+ if (status == LBX_IMAGE_COMPRESS_NO_SUPPORT)
+ fprintf(stderr, "no support for compressing this image\n");
+ else if (status == LBX_IMAGE_COMPRESS_NOT_WORTH_IT)
+ fprintf(stderr, "not worth it\n");
+ else if (status == LBX_IMAGE_COMPRESS_BAD_MALLOC)
+ fprintf(stderr, "bad malloc\n");
+#endif
+
+ if (!data || len >= 256 || reqlen > sz_xPutImageReq) {
+ if (data)
+ xfree(data);
+
+ if (client->swapped) /* Swap it back */
+ SwapXPutImage(stuff);
+
+ return ProcStandardRequest(client);
+ }
+ method = 0;
+ compBytes = len - sz_xPutImageReq;
+ memcpy(data + reqlen, (char *) &stuff[1], compBytes);
+ }
+
+ GFX_SET_DRAWABLE_AND_GC;
+
+ newreq->compressionMethod = method;
+
+ len = reqlen + compBytes;
+ newreq->bitPacked |= pad[len & 3];
+ len += pad[len & 3];
+ newreq->length = len >> 2;
+ memcpy(data, (char *)newreq, reqlen);
+
+ FinishLBXRequest(client, REQ_PASSTHROUGH);
+
+#ifdef LBX_STATS
+ percentCompression = 100.0 * (1.0 -
+ ((float) (compBytes + pad[compBytes & 3]) /
+ (float) ((client->req_len << 2) - sz_xPutImageReq)));
+
+ fprintf(stderr, "%f percent compression (%s)\n",
+ percentCompression, methodName);
+#endif
+
+ /*
+ * If the compressed image is greater that 25% of the original
+ * image, or is small enough to fit into the delta cache, then
+ * run the PutImage request through the regular stream
+ * compressor. Otherwise, just write the compressed image.
+ */
+
+ if (newreq->length > (client->req_len >> 2) ||
+ DELTA_CACHEABLE(&server->outdeltas, len))
+ WriteReqToServer(client, len, data, TRUE);
+ else
+ WriteToServerUncompressed(client, len, data, TRUE);
+
+ xfree(data);
+ return Success;
+}
+
+
+int
+ProcLBXGetImage(client)
+ ClientPtr client;
+{
+ REQUEST(xGetImageReq);
+ ReplyStuffPtr nr;
+
+ nr = NewReply(client, client->server->lbxReq, X_LbxGetImage,
+ GetLbxImageReply);
+
+ if (!nr)
+ return ProcStandardRequest(client);
+
+ if (client->swapped) {
+ char n;
+
+ swapl(&stuff->drawable, n);
+ swaps(&stuff->x, n);
+ swaps(&stuff->y, n);
+ swaps(&stuff->width, n);
+ swaps(&stuff->height, n);
+ swapl(&stuff->planeMask, n);
+ }
+ nr->request_info.lbxgetimage.width = stuff->width;
+ nr->request_info.lbxgetimage.height = stuff->height;
+ nr->request_info.lbxgetimage.format = stuff->format;
+
+#ifdef LBX_STATS
+ nr->request_info.lbxgetimage.drawable = stuff->drawable;
+ nr->request_info.lbxgetimage.x = stuff->x;
+ nr->request_info.lbxgetimage.y = stuff->y;
+#endif
+
+ FinishLBXRequest(client, REQ_PASSTHROUGH);
+ SendGetImage(client, stuff->drawable, stuff->x, stuff->y,
+ stuff->width, stuff->height, stuff->planeMask,
+ stuff->format);
+ return Success;
+}
+
+static Bool
+GetLbxImageReply(client, nr, data)
+ ClientPtr client;
+ ReplyStuffPtr nr;
+ char *data;
+{
+ xLbxGetImageReply *rep;
+ xGetImageReply reply;
+ pointer imageData;
+ int freeIt = 1;
+#ifdef LBX_STATS
+ char *methodName;
+#endif
+
+ rep = (xLbxGetImageReply *) data;
+
+ if (client->swapped) {
+ char n;
+
+ swapl(&rep->xLength, n);
+ swapl(&rep->visual, n);
+ }
+ /* +1 is because fillspan in DecodeFaxG42D seems to go 1 byte too far,
+ * and I don't want to mess with that code */
+ if ((imageData = (pointer) xalloc((rep->xLength << 2) + 1)) == NULL)
+ return FALSE;
+
+ if (rep->compressionMethod == LbxImageCompressNone)
+ {
+ xfree((char *) imageData);
+ imageData = (pointer) &rep[1];
+ freeIt = 0;
+ }
+ else if (nr->request_info.lbxgetimage.format != ZPixmap ||
+ (rep->depth == 1 && LBXZBitsPerPixel1(client) == 1))
+ {
+ LbxBitmapCompMethod *compMethod;
+
+ compMethod = LbxLookupBitmapCompMethod (client->server,
+ rep->compressionMethod);
+
+ if (!compMethod)
+ {
+ xfree((char *) imageData);
+ return FALSE;
+ }
+ else
+ {
+ int ppl, bpl, nbytes;
+
+ if (!compMethod->inited)
+ {
+ if (compMethod->compInit)
+ (*compMethod->compInit)();
+ compMethod->inited = 1;
+ }
+
+ ppl = nr->request_info.lbxgetimage.width;
+ if (LBXBitmapBitOrder(client) != LBXImageByteOrder(client))
+ ppl = ((ppl + LBXBitmapScanlineUnit(client) - 1) &
+ ~LBXBitmapScanlineUnit(client));
+ bpl = (((ppl + LBXBitmapScanlinePad(client) - 1) /
+ LBXBitmapScanlinePad(client)) *
+ (LBXBitmapScanlinePad(client) >> 3));
+ nbytes = bpl * nr->request_info.lbxgetimage.height;
+ if (nr->request_info.lbxgetimage.format == XYPixmap)
+ nbytes *= rep->depth;
+
+ (*compMethod->decompFunc) (
+ (unsigned char *) &rep[1],
+ (unsigned char *) imageData,
+ nbytes,
+ ppl,
+ bpl,
+ LBXBitmapBitOrder(client) == LSBFirst);
+
+#ifdef LBX_STATS
+ methodName = compMethod->methodName;
+#endif
+ }
+ }
+ else
+ {
+ LbxPixmapCompMethod *compMethod;
+
+ compMethod = LbxLookupPixmapCompMethod (client->server,
+ rep->compressionMethod);
+
+ if (!compMethod)
+ {
+ xfree((char *) imageData);
+ return FALSE;
+ }
+ else
+ {
+ if (!compMethod->inited)
+ {
+ if (compMethod->compInit)
+ (*compMethod->compInit)();
+ compMethod->inited = 1;
+ }
+
+ (*compMethod->decompFunc) (
+ (char *) &rep[1],
+ (char *) imageData,
+ (int) nr->request_info.lbxgetimage.height,
+ (rep->xLength << 2) / nr->request_info.lbxgetimage.height);
+
+#ifdef LBX_STATS
+ methodName = compMethod->methodName;
+#endif
+ }
+ }
+
+ reply.type = X_Reply;
+ reply.depth = rep->depth;
+ reply.sequenceNumber = rep->sequenceNumber;
+ reply.length = rep->xLength;
+ reply.visual = rep->visual;
+
+ if (client->swapped)
+ SwapGetImageReply(&reply);
+
+#ifdef LBX_STATS
+ fprintf (stderr, "GetImage (xid=%x, w=%d, h=%d, x=%d, y=%d): ",
+ nr->request_info.lbxgetimage.drawable,
+ nr->request_info.lbxgetimage.width,
+ nr->request_info.lbxgetimage.height,
+ nr->request_info.lbxgetimage.x,
+ nr->request_info.lbxgetimage.y);
+ if (rep->compressionMethod == LbxImageCompressNone) {
+ fprintf(stderr, "image not compressed\n");
+ } else {
+ float percentCompression = 100.0 * (1.0 -
+ ((float) rep->lbxLength / (float) rep->xLength));
+
+ fprintf(stderr, "%f percent compression (%s)\n",
+ percentCompression, methodName);
+ }
+#endif
+
+ WriteToClient(client, sizeof(xGetImageReply), &reply);
+ WriteToClient(client, rep->xLength << 2, imageData);
+
+ if (freeIt)
+ xfree((char *) imageData);
+
+ return TRUE;
+}
diff --git a/di/globals.c b/di/globals.c
new file mode 100644
index 0000000..51843bb
--- /dev/null
+++ b/di/globals.c
@@ -0,0 +1,56 @@
+/* $Xorg: globals.c,v 1.4 2001/02/09 02:05:31 xorgcvs Exp $ */
+/************************************************************
+
+Copyright 1987, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+
+Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+********************************************************/
+
+#include "misc.h"
+#include "lbx.h"
+
+ClientPtr *clients;
+int currentMaxClients; /* current size of clients array */
+
+LbxLargeRequestRec *largeRequestQueue[LARGE_REQUEST_QUEUE_LEN];
+int numLargeRequestsInQueue = 0;
diff --git a/di/init.c b/di/init.c
new file mode 100644
index 0000000..25ab189
--- /dev/null
+++ b/di/init.c
@@ -0,0 +1,270 @@
+/* $Xorg: init.c,v 1.4 2001/02/09 02:05:31 xorgcvs Exp $ */
+/*
+
+Copyright 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+*/
+/*
+ * Copyright 1992 Network Computing Devices
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of NCD. not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. NCD. makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * NCD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL NCD.
+ * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+/*
+ * This file is used for anything that needs to dip into Xlib structures
+ */
+
+/* lbxproxy source files are compiled with -D_XSERVER64 on 64 bit machines.
+ * For the most part, this is appropriate. However, for this file it
+ * is not, because we make Xlib calls here.
+ */
+#undef _XSERVER64
+#include "wire.h"
+#include "util.h"
+#include <X11/Xlibint.h>
+#include <X11/Xutil.h>
+#include <stdio.h>
+
+/* Hook up to an X server and set up a multiplexing LBX encoded connection */
+struct _XDisplay*
+DisplayOpen (dpy_name, requestp, eventp, errorp, sequencep)
+ char *dpy_name;
+ int *requestp, *eventp, *errorp;
+ int *sequencep;
+{
+ Display *dpy;
+ int lbxMajor, lbxMinor;
+ Window win;
+ XTextProperty name;
+ XClassHint class;
+
+ dpy = XOpenDisplay (dpy_name);
+ if (!dpy)
+ return NULL;
+
+ win = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy),
+ -1, -1, 1, 1, 0, 0, 0);
+ class.res_name = "lbxproxy";
+ class.res_class = "LbxProxy";
+ XStringListToTextProperty(&class.res_name, 1, &name);
+ XSetWMProperties(dpy, win, &name, NULL, NULL, 0, NULL, NULL, &class);
+
+ if (!XLbxQueryExtension (dpy, requestp, eventp, errorp)) {
+ ErrorF("X server doesn't have LBX extension\n");
+ XCloseDisplay(dpy);
+ return NULL;
+ }
+ if (!XLbxQueryVersion (dpy, &lbxMajor, &lbxMinor)) {
+ ErrorF("LBX extension query failed\n");
+ XCloseDisplay(dpy);
+ return NULL;
+ }
+ if (lbxMajor != LBX_MAJOR_VERSION || lbxMinor != LBX_MINOR_VERSION)
+ ErrorF("LBX version numbers don't match (proxy %d.%d, server %d.%d), good luck!\n", LBX_MAJOR_VERSION, LBX_MINOR_VERSION, lbxMajor, lbxMinor);
+ *sequencep = NextRequest (dpy) - 1;
+ return dpy;
+}
+
+int DisplayConnectionNumber (dpy)
+ struct _XDisplay* dpy;
+{
+ return ConnectionNumber (dpy);
+}
+
+void DisplayGetConnSetup (dpy, cs, cs_len, change_type, changes, change_len)
+ struct _XDisplay* dpy;
+ xConnSetup** cs;
+ int* cs_len;
+ int change_type;
+ CARD32* changes;
+ int change_len;
+{
+ char* datap;
+ xConnSetup setup;
+ int olen;
+ int i, s, d, v;
+ static int padlength[4] = {0, 3, 2, 1};
+ XPixmapFormatValues* pixmap_formats;
+ int npixmap_formats;
+ int min_keycode, max_keycode;
+ xWindowRoot root;
+ Screen* scrnp;
+ int numScreens;
+ int numVideoScreens;
+ int scrlist[16]; /* are there servers with more than 16 screens? */
+ int scrldex;
+
+ if (change_type == 2) {
+ numScreens = change_len - 6;
+ numVideoScreens = 1;
+ } else
+ numScreens = numVideoScreens = ScreenCount(dpy);
+
+ pixmap_formats = XListPixmapFormats (dpy, &npixmap_formats);
+ XDisplayKeycodes (dpy, &min_keycode, &max_keycode);
+
+ setup.release = VendorRelease(dpy);
+ setup.ridBase = dpy->resource_base;
+ setup.ridMask = dpy->resource_mask;
+ setup.motionBufferSize = XDisplayMotionBufferSize (dpy);
+ setup.nbytesVendor = strlen (ServerVendor (dpy));
+ setup.maxRequestSize = XMaxRequestSize (dpy);
+ setup.numRoots = ScreenCount(dpy);
+ setup.numFormats = npixmap_formats;
+ setup.imageByteOrder = ImageByteOrder(dpy);
+ setup.bitmapBitOrder = BitmapBitOrder(dpy);
+ setup.bitmapScanlineUnit = BitmapUnit(dpy);
+ setup.bitmapScanlinePad = BitmapPad(dpy);
+ setup.minKeyCode = min_keycode;
+ setup.maxKeyCode = max_keycode;
+
+ olen = sizeof (xConnSetup) + ((setup.nbytesVendor + 3) & ~3) +
+ (setup.numFormats * sizeof (xPixmapFormat));
+
+ scrldex = 0;
+ if (change_type != 2) {
+ olen += (setup.numRoots * sizeof (xWindowRoot));
+
+ for (s = 0; s < numScreens; s++) {
+ scrlist[scrldex++] = s;
+ for (d = 0; d < ScreenOfDisplay(dpy,s)->ndepths; d++) {
+ olen += sizeof (xDepth) +
+ sizeof (xVisualType) * ScreenOfDisplay(dpy,s)->depths[d].nvisuals;
+ }
+ }
+ } else {
+ olen += ((1 + numScreens - numVideoScreens) * sizeof (xWindowRoot));
+
+ /* find the one video screen that matches the appgroup's */
+ for (s = 0; s < numScreens; s++)
+ if (RootWindow (dpy, s) == (Window) changes[1])
+ break;
+ scrlist[scrldex++] = s;
+ for (d = 0; d < ScreenOfDisplay(dpy,s)->ndepths; d++) {
+ olen += sizeof (xDepth) +
+ sizeof (xVisualType) * ScreenOfDisplay(dpy,s)->depths[d].nvisuals;
+ }
+ /* and any print screens */
+ for (s = numVideoScreens; s < numScreens; s++) {
+ scrlist[scrldex++] = s;
+ for (d = 0; d < ScreenOfDisplay(dpy,s)->ndepths; d++) {
+ olen += sizeof (xDepth) +
+ sizeof (xVisualType) * ScreenOfDisplay(dpy,s)->depths[d].nvisuals;
+ }
+ }
+ }
+
+ datap = (char*) xalloc (olen);
+ if (datap == NULL) {
+ Xfree (pixmap_formats);
+ *cs = NULL;
+ *cs_len = 0;
+ return;
+ }
+
+ *cs = (xConnSetup*) datap;
+ *cs_len = olen;
+ memmove (datap, &setup, sizeof (xConnSetup));
+ datap += sizeof (xConnSetup);
+ memmove (datap, ServerVendor(dpy), setup.nbytesVendor);
+ datap += setup.nbytesVendor;
+ i = padlength[setup.nbytesVendor & 3];
+ while (--i >= 0)
+ *datap++ = 0;
+
+ for (i = 0; i < npixmap_formats; i++) {
+ xPixmapFormat pf;
+
+ pf.depth = pixmap_formats[i].depth;
+ pf.bitsPerPixel = pixmap_formats[i].bits_per_pixel;
+ pf.scanLinePad = pixmap_formats[i].scanline_pad;
+ memmove (datap, &pf, sizeof (xPixmapFormat));
+ datap += sizeof (xPixmapFormat);
+ }
+
+ for (s = 0; s < scrldex; s++) {
+ xDepth dep;
+ Depth* depthp;
+
+ scrnp = ScreenOfDisplay(dpy,scrlist[s]);
+ root.windowId = scrnp->root;
+ root.defaultColormap = scrnp->cmap;
+ root.whitePixel = scrnp->white_pixel;
+ root.blackPixel = scrnp->black_pixel;
+ root.currentInputMask = scrnp->root_input_mask;
+ root.pixWidth = scrnp->width;
+ root.pixHeight = scrnp->height;
+ root.mmWidth = scrnp->mwidth;
+ root.mmHeight = scrnp->mheight;
+ root.minInstalledMaps = scrnp->min_maps;
+ root.maxInstalledMaps = scrnp->max_maps;
+ root.rootVisualID = scrnp->root_visual->visualid;
+ root.backingStore = scrnp->backing_store;
+ root.saveUnders = scrnp->save_unders;
+ root.rootDepth = scrnp->root_depth;
+ root.nDepths = scrnp->ndepths;
+ memmove (datap, &root, sizeof (xWindowRoot));
+ datap += sizeof (xWindowRoot);
+
+ for (d = 0; d < scrnp->ndepths; d++) {
+ xVisualType vis;
+ Visual* visp;
+
+ depthp = &scrnp->depths[d];
+ dep.depth = depthp->depth;
+ dep.nVisuals = depthp->nvisuals;
+ memmove (datap, &dep, sizeof (xDepth));
+ datap += sizeof (xDepth);
+
+ for (v = 0; v < depthp->nvisuals; v++) {
+ visp = &depthp->visuals[v];
+ vis.visualID = visp->visualid;
+ vis.class = visp->class;
+ vis.bitsPerRGB = visp->bits_per_rgb;
+ vis.colormapEntries = visp->map_entries;
+ vis.redMask = visp->red_mask;
+ vis.greenMask = visp->green_mask;
+ vis.blueMask = visp->blue_mask;
+ memmove (datap, &vis, sizeof (xVisualType));
+ datap += sizeof (xVisualType);
+ }
+ }
+ }
+ Xfree (pixmap_formats);
+}
diff --git a/di/lbxfuncs.c b/di/lbxfuncs.c
new file mode 100644
index 0000000..402ab60
--- /dev/null
+++ b/di/lbxfuncs.c
@@ -0,0 +1,1450 @@
+/* $Xorg: lbxfuncs.c,v 1.3 2000/08/17 19:53:55 cpqbld Exp $ */
+/*
+ * Copyright 1994 Network Computing Devices, Inc.
+ * Copyright 1996 X Consortium, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name Network Computing Devices, Inc. not be
+ * used in advertising or publicity pertaining to distribution of this
+ * software without specific, written prior permission.
+ *
+ * THIS SOFTWARE IS PROVIDED `AS-IS'. NETWORK COMPUTING DEVICES, INC.,
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT
+ * LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, OR NONINFRINGEMENT. IN NO EVENT SHALL NETWORK
+ * COMPUTING DEVICES, INC., BE LIABLE FOR ANY DAMAGES WHATSOEVER, INCLUDING
+ * SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES, INCLUDING LOSS OF USE, DATA,
+ * OR PROFITS, EVEN IF ADVISED OF THE POSSIBILITY THEREOF, AND REGARDLESS OF
+ * WHETHER IN AN ACTION IN CONTRACT, TORT OR NEGLIGENCE, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+/*
+ * top level LBX request & reply handling
+ */
+
+/*
+ * requests copy out interesting stuff and then swap so original data
+ * is left alone as much as possible. note that the length field
+ * is *not* swapped
+ *
+ * replied data is copied yet again before swapping because the data
+ * may be stored as a tag result and we don't want to change that.
+ */
+
+
+#include <stdio.h>
+#include "assert.h"
+#include "lbx.h"
+#include "atomcache.h"
+#include "util.h"
+#include "init.h"
+#include "tags.h"
+#include "resource.h"
+#include "wire.h"
+#include "swap.h"
+#include "reqtype.h"
+#include "lbxext.h"
+#include "proxyopts.h"
+
+#ifdef DEBUG
+extern int lbxDebug;
+#endif
+
+static Bool intern_atom_reply();
+static Bool get_atom_name_reply();
+static Bool get_mod_map_reply();
+static Bool get_key_map_reply();
+static Bool sync_reply();
+static Bool get_queryfont_reply();
+static Bool GetWinAttrAndGeomReply();
+
+#define reply_length(cp,rep) ((rep)->type==X_Reply ? \
+ 32 + (HostUnswapLong((cp),(rep)->length) << 2) \
+ : 32)
+
+char protocolMode = PROTOCOL_FULL;
+
+/* ARGSUSED */
+static void
+get_connection_info(client, cs, cs_len, change_type, changes, changes_len)
+ ClientPtr client;
+ xConnSetup *cs;
+ int cs_len;
+ int change_type;
+ CARD32 *changes;
+ int changes_len;
+{
+ xWindowRoot *root;
+ xDepth *depth;
+ xVisualType *vis;
+ char *dp = (char *) cs;
+ int i,
+ j,
+ k;
+ static int pad[4] = {0, 3, 2, 1};
+
+ if (!changes)
+ return;
+
+ cs->ridBase = changes[0];
+ dp += sizeof(xConnSetup);
+ /* skip vendor string & pixmap formats */
+ dp += cs->nbytesVendor + pad[cs->nbytesVendor & 3];
+ for (i = 0; i < cs->numFormats; i++) {
+ if (((xPixmapFormat *)dp)->depth == 1)
+ client->ZbitsPerPixel1 = ((xPixmapFormat *)dp)->bitsPerPixel;
+ dp += sizeof(xPixmapFormat);
+ }
+ /* process screens */
+ root = (xWindowRoot *) dp;
+ if (change_type == 2) {
+ if (changes[2])
+ root->rootVisualID = (VisualID) changes[2];
+ if (changes[3]) {
+ root->defaultColormap = (Colormap) changes[3];
+ root->whitePixel = changes[4];
+ root->blackPixel = changes[5];
+ }
+ }
+ client->rootWindow = root->windowId;
+ for (i = 0; i < cs->numRoots; i++) {
+ if (change_type != 2) {
+ root->currentInputMask = changes[i + 1];
+ } else {
+ root->currentInputMask = changes[i + 6];
+ }
+ dp += sizeof(xWindowRoot);
+ for (j = 0; j < root->nDepths; j++) {
+ depth = (xDepth *) dp;
+ dp += sizeof(xDepth);
+ for (k = 0; k < depth->nVisuals; k++) {
+ vis = (xVisualType *) dp;
+ CreateVisual(depth->depth, vis);
+ dp += (sizeof(xVisualType));
+ vis = (xVisualType *) dp;
+ }
+ }
+ if (!LookupIDByType(client, root->defaultColormap, RT_COLORMAP))
+ CreateColormap(client,
+ root->defaultColormap, root->rootVisualID);
+ }
+}
+
+static void
+send_setup_reply(client, success, majorVer, minorVer, cs, cs_len)
+ ClientPtr client;
+ Bool success;
+ int majorVer, minorVer;
+ char *cs;
+ int cs_len;
+{
+ xConnSetupPrefix reply;
+
+ reply.success = success;
+ if (!success) {
+ reply.lengthReason = strlen(cs);
+ cs_len = reply.lengthReason + 3;
+ }
+ reply.majorVersion = majorVer;
+ reply.minorVersion = minorVer;
+ reply.length = cs_len >> 2;
+
+ if (client->swapped)
+ WriteSConnSetupPrefix(client, &reply);
+ else
+ (void)WriteToClient(client, sizeof(xConnSetupPrefix), (char *) &reply);
+ if (success && client->swapped)
+ WriteSConnectionInfo(client, (unsigned long)(reply.length << 2), cs);
+ else
+ (void)WriteToClient(client, (int)(reply.length << 2), cs);
+}
+
+static void
+finish_setup_reply(client, cs, cs_len, change_type, changes, changes_len, majorVer, minorVer)
+ ClientPtr client;
+ xConnSetup *cs;
+ int cs_len;
+ int change_type;
+ CARD32* changes;
+ int changes_len;
+ int majorVer,
+ minorVer;
+{
+ get_connection_info(client, cs, cs_len, change_type, changes, changes_len);
+ client->minKeyCode = cs->minKeyCode;
+ client->maxKeyCode = cs->maxKeyCode;
+ client->imageByteOrder = cs->imageByteOrder;
+ client->bitmapBitOrder = cs->bitmapBitOrder;
+ client->bitmapScanlineUnit = cs->bitmapScanlineUnit;
+ client->bitmapScanlinePad = cs->bitmapScanlinePad;
+ client->ridBase = cs->ridBase;
+ client->ridMask = cs->ridMask;
+ FinishInitClientResources (client, cs->ridBase, cs->ridMask);
+ send_setup_reply(client, TRUE, majorVer, minorVer, cs, cs_len);
+}
+
+/*
+ * ConnectionSetup data can come from three places: 1) a fully qualified
+ * connection-setup in the reply, 2) from the tag store, and 3) built
+ * from the Display* returned by the call the proxy made to XOpenDisplay.
+ */
+
+static void
+get_setup_reply(client, data, len)
+ ClientPtr client;
+ char *data;
+ int len;
+{
+ register xLbxConnSetupPrefix *rep;
+ TagData td;
+ xConnSetup *tag_data;
+ Bool free_td = FALSE;
+ CARD32* changes = NULL;
+ int changes_len = 0;
+
+ rep = (xLbxConnSetupPrefix *) data;
+ if (client->swapped) {
+ data = (char *)ALLOCATE_LOCAL(len);
+ memcpy(data, (char *)rep, len);
+ rep = (xLbxConnSetupPrefix *) data;
+ SwapLbxConnSetupPrefix(rep);
+ }
+ switch (rep->changeType) {
+ default:
+ case 0: /* full ConnectionSetup, possibly with tag */
+#ifdef LBX_STATS
+ getsetup_full++;
+#endif
+ tag_data = (xConnSetup *) &rep[1];
+ if (rep->tag != 0) {
+ if (!TagStoreData(client->server, client->server->global_cache,
+ rep->tag, rep->length,
+ LbxTagTypeConnInfo, tag_data)) {
+ /* tell server we lost it */
+ SendInvalidateTag(client, rep->tag);
+ }
+ }
+ len = rep->length << 2;
+ break;
+
+ case 1: /* LbxNormalDeltas */
+ case 2: /* LbxEmbeddedAppGroup */
+ changes = (CARD32*) &rep[1];
+ changes_len = rep->length - 1;
+ if (client->swapped)
+ SwapLongs(changes, changes_len);
+
+ if (rep->tag != 0) {
+ td = TagGetTag(client->server, client->server->global_cache,
+ rep->tag);
+ if (!td) {
+ fprintf(stderr, "no data for setup tag 0x%x\n", rep->tag);
+ send_setup_reply(client, FALSE, 0, 0, "bad tag data from server", 0);
+ if (client->swapped)
+ DEALLOCATE_LOCAL(data);
+ return;
+ }
+#ifdef LBX_STATS
+ getsetup_tag++;
+ tag_bytes_unsent += td->size - len;
+#endif
+ tag_data = td->tdata;
+ len = td->size;
+ } else {
+ DisplayGetConnSetup (client->server->dpy, &tag_data, &len,
+ rep->changeType, changes, changes_len);
+ free_td = TRUE;
+ }
+ break;
+
+ }
+ finish_setup_reply(client, tag_data, len,
+ rep->changeType, changes, changes_len,
+ (int) rep->majorVersion, (int) rep->minorVersion);
+ if (free_td) xfree (tag_data);
+ if (client->swapped)
+ DEALLOCATE_LOCAL(data);
+}
+
+int
+ProcLBXInternAtom(client)
+ ClientPtr client;
+{
+ REQUEST(xInternAtomReq);
+ char *s;
+ Atom atom,
+ a = None;
+ xInternAtomReply reply;
+ ReplyStuffPtr nr;
+ char n;
+ CARD16 nbytes;
+
+ nbytes = stuff->nbytes;
+ if (client->swapped) {
+ swaps(&nbytes, n);
+ }
+ if (nbytes > MAX_ATOM_LENGTH)
+ return ProcStandardRequest(client);
+
+ s = (char *)stuff + sizeof(xInternAtomReq);
+
+ atom = LbxMakeAtom(client->server, s, nbytes, a, FALSE);
+ if (atom != None) {
+ reply.type = X_Reply;
+ reply.length = 0;
+ reply.sequenceNumber = LBXSequenceNumber(client);
+ reply.atom = atom;
+ if (client->swapped)
+ SwapInternAtomReply(&reply);
+ if (LBXCacheSafe(client)) {
+ FinishLBXRequest(client, REQ_YANK);
+ WriteToClient(client, sizeof(xInternAtomReply), &reply);
+ } else { /* store for later */
+ if (!LBXCanDelayReply(client))
+ SendLbxSync(client);
+ FinishLBXRequest(client, REQ_YANKLATE);
+ SaveReplyData(client, (xReply *) & reply, 0, NULL);
+ }
+
+#ifdef LBX_STATS
+ intern_good++;
+#endif
+
+ return Success;
+ } else if (nbytes < MAX_ATOM_LENGTH) {
+ nr = NewReply(client, X_InternAtom, 0, intern_atom_reply);
+ if (!nr)
+ return ProcStandardRequest(client);
+ strncpy(nr->request_info.xintern.str, s, nbytes);
+ nr->request_info.xintern.str[nbytes] = '\0';
+ nr->request_info.xintern.len = nbytes;
+
+#ifdef LBX_STATS
+ intern_miss++;
+#endif
+
+ return ProcStandardRequest(client);
+ }
+}
+
+static Bool
+intern_atom_reply(client, nr, data)
+ ClientPtr client;
+ ReplyStuffPtr nr;
+ char *data;
+{
+ Atom atom;
+ char *str;
+ xInternAtomReply *reply;
+ int len;
+ char n;
+
+ reply = (xInternAtomReply *) data;
+
+ str = nr->request_info.xintern.str;
+ len = nr->request_info.xintern.len;
+
+ atom = reply->atom;
+ if (client->swapped) {
+ swapl(&atom, n);
+ }
+ if (atom != None)
+ /* make sure it gets stuffed in the DB */
+ (void) LbxMakeAtom(client->server, str, len, atom, TRUE);
+ return TRUE;
+}
+
+int
+ProcLBXGetAtomName(client)
+ ClientPtr client;
+{
+ REQUEST(xResourceReq);
+ char *str;
+ xGetAtomNameReply reply;
+ int len;
+ ReplyStuffPtr nr;
+ char n;
+ Atom id;
+
+ id = stuff->id;
+ if (client->swapped) {
+ swapl(&id, n);
+ }
+ str = NameForAtom(client->server, id);
+
+ if (str) { /* found the value */
+ len = strlen(str);
+ reply.type = X_Reply;
+ reply.length = (len + 3) >> 2;
+ reply.sequenceNumber = LBXSequenceNumber(client);
+ reply.nameLength = len;
+ if (client->swapped)
+ SwapGetAtomNameReply(&reply);
+ if (LBXCacheSafe(client)) {
+ FinishLBXRequest(client, REQ_YANK);
+ WriteToClient(client, sizeof(xGetAtomNameReply), &reply);
+ WriteToClient(client, len, str);
+ } else {
+ if (!LBXCanDelayReply(client))
+ SendLbxSync(client);
+ FinishLBXRequest(client, REQ_YANKLATE);
+ SaveReplyData(client, (xReply *) & reply, len, str);
+ }
+
+#ifdef LBX_STATS
+ getatom_good++;
+#endif
+
+ return Success;
+ } else {
+ nr = NewReply(client, X_GetAtomName, 0, get_atom_name_reply);
+ if (!nr)
+ return ProcStandardRequest(client);
+ nr->request_info.xgetatom.atom = id;
+
+#ifdef LBX_STATS
+ getatom_miss++;
+#endif
+
+ return ProcStandardRequest(client);
+ }
+}
+
+static Bool
+get_atom_name_reply(client, nr, data)
+ ClientPtr client;
+ ReplyStuffPtr nr;
+ char *data;
+{
+ Atom atom;
+ char *s;
+ xGetAtomNameReply *reply;
+ CARD16 len;
+ char n;
+
+ reply = (xGetAtomNameReply *) data;
+
+ len = reply->nameLength;
+
+ if (client->swapped) {
+ swaps(&len, n);
+ }
+
+ if (len > MAX_ATOM_LENGTH)
+ return FALSE;
+
+ s = data + sizeof(xGetAtomNameReply);
+
+ atom = nr->request_info.xgetatom.atom;
+ /* make sure it gets stuffed in the DB */
+ if (atom)
+ (void) LbxMakeAtom(client->server, s, (unsigned) len, atom, TRUE);
+ return TRUE;
+}
+
+/*
+ * Send an LbxSync request to the server. After the SyncReply comes
+ * back, the proxy will flush any replies it saved for the client.
+ */
+
+void
+SendLbxSync (client)
+ ClientPtr client;
+{
+ xLbxSyncReq req;
+ ReplyStuffPtr nr;
+
+#ifdef SEQ_DEBUG
+ fprintf(stderr, "sending LbxSync, seq 0x%x\n", LBXSequenceNumber(client) - 1);
+#endif
+
+ ForceSequenceUpdate(client);
+ nr = NewReply(client, client->server->lbxReq, X_LbxSync, sync_reply);
+ --nr->sequenceNumber; /* executed BEFORE the real request */
+ req.reqType = client->server->lbxReq;
+ req.lbxReqType = X_LbxSync;
+ req.length = sz_xLbxSyncReq >> 2;
+
+ WriteReqToServer (client, sz_xLbxSyncReq, (char *) &req, TRUE);
+}
+
+/* ARGSUSED */
+static Bool
+sync_reply(client, nr, data)
+ ClientPtr client;
+ ReplyStuffPtr nr;
+ char *data;
+{
+ /* do nothing; just here to catch and discard the reply */
+ return TRUE;
+}
+
+void
+WriteError(client, majorCode, minorCode, resId, errorCode)
+ ClientPtr client;
+ unsigned int majorCode;
+ unsigned int minorCode;
+ XID resId;
+ int errorCode;
+{
+ xError rep;
+ int n;
+
+ rep.type = X_Error;
+ rep.sequenceNumber = LBXSequenceNumber(client);
+ rep.errorCode = errorCode;
+ rep.majorCode = majorCode;
+ rep.minorCode = minorCode;
+ rep.resourceID = resId;
+
+ if (client->swapped) {
+ swaps(&rep.sequenceNumber, n);
+ swaps(&rep.minorCode, n);
+ swaps(&rep.resourceID, n);
+ }
+
+ WriteToClient(client, sizeof(rep), (char *)&rep);
+}
+
+int
+ProcLBXGetModifierMapping(client)
+ ClientPtr client;
+{
+ ReplyStuffPtr nr;
+
+ nr = NewReply(client, client->server->lbxReq, X_LbxGetModifierMapping,
+ get_mod_map_reply);
+ if (!nr)
+ return ProcStandardRequest(client);
+
+ FinishLBXRequest(client, REQ_PASSTHROUGH);
+ SendGetModifierMapping(client);
+ return Success;
+}
+
+/*ARGSUSED*/
+static Bool
+get_mod_map_reply(client, nr, data)
+ ClientPtr client;
+ ReplyStuffPtr nr;
+ char *data;
+{
+ xLbxGetModifierMappingReply *rep;
+ int len;
+ pointer tag_data;
+ CARD32 tag;
+ char n;
+ xGetModifierMappingReply reply;
+
+ rep = (xLbxGetModifierMappingReply *) data;
+
+ tag = rep->tag;
+ if (client->swapped) {
+ swapl(&tag, n);
+ }
+ len = rep->keyspermod << 3;
+ if (rep->tag) {
+ if (rep->length) { /* first time, set tag */
+
+#ifdef LBX_STATS
+ getmodmap_full++;
+#endif
+
+ tag_data = (pointer) &rep[1];
+ if (!TagStoreData(client->server, client->server->global_cache,
+ tag, len,
+ LbxTagTypeModmap, tag_data)) {
+ /* tell server we lost it */
+ SendInvalidateTag(client, tag);
+ }
+ } else {
+ tag_data = TagGetData(client->server, client->server->global_cache,
+ tag);
+ if (!tag_data) {
+ fprintf(stderr, "no data for mod map tag 0x%x\n", tag);
+ WriteError(client, X_GetModifierMapping, 0, 0, BadAlloc);
+ return TRUE;
+ }
+
+#ifdef LBX_STATS
+ getmodmap_tag++;
+ tag_bytes_unsent += (rep->keyspermod << 3);
+#endif
+ }
+ } else {
+
+#ifdef LBX_STATS
+ getmodmap_full++;
+#endif
+
+ /* server didn't send us a tag for some reason -- just pass on data */
+ tag_data = (pointer) &rep[1];
+ }
+
+ reply.type = X_Reply;
+ reply.numKeyPerModifier = rep->keyspermod;
+ reply.sequenceNumber = rep->sequenceNumber;
+ reply.length = len >> 2;
+ if (client->swapped)
+ SwapModmapReply(&reply);
+ WriteToClient(client, sizeof(xGetModifierMappingReply), &reply);
+ WriteToClient(client, len, tag_data);
+
+ return TRUE;
+}
+
+int
+ProcLBXGetKeyboardMapping(client)
+ ClientPtr client;
+{
+ REQUEST(xGetKeyboardMappingReq);
+ ReplyStuffPtr nr;
+
+ nr = NewReply(client, client->server->lbxReq, X_LbxGetKeyboardMapping,
+ get_key_map_reply);
+ if (!nr)
+ return ProcStandardRequest(client);
+ nr->request_info.lbxgetkeymap.count = stuff->count;
+ nr->request_info.lbxgetkeymap.first = stuff->firstKeyCode;
+
+
+ FinishLBXRequest(client, REQ_PASSTHROUGH);
+ SendGetKeyboardMapping(client);
+ return Success;
+}
+
+/*
+ * always ask for the whole map from server, and send requested subset to
+ * client
+ */
+
+static Bool
+get_key_map_reply(client, nr, data)
+ ClientPtr client;
+ ReplyStuffPtr nr;
+ char *data;
+{
+ xLbxGetKeyboardMappingReply *rep;
+ int len;
+ pointer tag_data;
+ CARD32 tag;
+ char n;
+ xGetKeyboardMappingReply reply;
+ char *sdata;
+
+ rep = (xLbxGetKeyboardMappingReply *) data;
+
+ tag = rep->tag;
+ if (client->swapped) {
+ swapl(&tag, n);
+ }
+ if (tag) {
+ if (rep->length) { /* first time, set tag */
+
+#ifdef LBX_STATS
+ getkeymap_full++;
+#endif
+
+ tag_data = (pointer) &rep[1];
+ len = rep->keysperkeycode *
+ (LBXMaxKeyCode(client) - LBXMinKeyCode(client) + 1) * 4;
+ /* data always swapped, because reswapped when written */
+ if (client->swapped)
+ SwapLongs((CARD32 *) tag_data, len / 4);
+ if (!TagStoreData(client->server, client->server->global_cache,
+ tag, len,
+ LbxTagTypeKeymap, tag_data)) {
+ /* tell server we lost it */
+ SendInvalidateTag(client, tag);
+ }
+ } else {
+ tag_data = TagGetData(client->server,
+ client->server->global_cache, tag);
+ if (!tag_data) {
+ fprintf(stderr, "no data for key map tag 0x%x\n", tag);
+ WriteError(client, X_GetKeyboardMapping, 0, 0, BadAlloc);
+ return TRUE;
+ }
+
+#ifdef LBX_STATS
+ getkeymap_tag++;
+ tag_bytes_unsent += (rep->keysperkeycode *
+ (LBXMaxKeyCode(client) - LBXMinKeyCode(client) + 1) * 4);
+#endif
+ }
+ } else {
+
+#ifdef LBX_STATS
+ getkeymap_full++;
+#endif
+
+ /* server didn't send us a tag for some reason -- just pass on data */
+ tag_data = (pointer) &rep[1];
+ /* data always swapped, because reswapped when written */
+ if (client->swapped) {
+ len = rep->keysperkeycode *
+ (LBXMaxKeyCode(client) - LBXMinKeyCode(client) + 1) * 4;
+ SwapLongs((CARD32 *) tag_data, len / 4);
+ }
+ }
+
+ len = (rep->keysperkeycode * nr->request_info.lbxgetkeymap.count) << 2;
+
+ reply.type = X_Reply;
+ reply.keySymsPerKeyCode = rep->keysperkeycode;
+ reply.sequenceNumber = rep->sequenceNumber;
+ reply.length = len >> 2;
+
+ tag_data = (char *)tag_data + (rep->keysperkeycode *
+ (nr->request_info.lbxgetkeymap.first -
+ LBXMinKeyCode(client)));
+ if (client->swapped) {
+ SwapKeymapReply(&reply);
+ /* have to copy data because we could be handed the tag storage */
+ sdata = (char *) ALLOCATE_LOCAL(len);
+ if (sdata) {
+ memcpy(sdata, tag_data, len);
+ SwapLongs((CARD32 *) sdata, len / 4);
+ }
+ } else
+ sdata = tag_data;
+ WriteToClient(client, sizeof(xGetKeyboardMappingReply), &reply);
+ WriteToClient(client, len, sdata);
+ if (sdata != tag_data)
+ DEALLOCATE_LOCAL(sdata);
+
+ return TRUE;
+}
+
+int
+ProcLBXQueryFont(client)
+ ClientPtr client;
+{
+ REQUEST(xResourceReq);
+ ReplyStuffPtr nr;
+ Font fid;
+ char n;
+
+ fid = stuff->id;
+ if (client->swapped) {
+ swapl(&fid, n);
+ }
+ nr = NewReply(client, client->server->lbxReq, X_LbxQueryFont,
+ get_queryfont_reply);
+ if (!nr)
+ return ProcStandardRequest(client);
+
+ FinishLBXRequest(client, REQ_PASSTHROUGH);
+ SendQueryFont(client, fid);
+ return Success;
+}
+
+static INT16
+unpack_val(val, mask, sft, bts)
+ CARD32 val;
+ CARD32 mask;
+ int sft,
+ bts;
+{
+ CARD16 utmp;
+ INT16 sval;
+
+ /* get the proper value */
+ utmp = (val & mask) >> sft;
+ /* push the sign bit to the right spot */
+ utmp <<= (16 - bts);
+ /* cast it so sign bit takes effect */
+ sval = (INT16) utmp;
+ /* shift back down */
+ sval >>= (16 - bts);
+
+ return sval;
+}
+
+/*ARGSUSED*/
+static int
+UnsquishFontInfo(compression, fdata, dlen, qfr)
+ int compression;
+ xLbxFontInfo *fdata;
+ int dlen;
+ pointer *qfr;
+{
+ int len,
+ hlen,
+ junklen = sizeof(BYTE) * 2 + sizeof(CARD16) + sizeof(CARD32);
+ char *t;
+ int nchars;
+ int i;
+ xCharInfo *maxb;
+ xQueryFontReply *new;
+ xLbxCharInfo *lci;
+ xCharInfo *ci;
+ CARD16 attrs;
+
+ maxb = &fdata->maxBounds;
+
+ nchars = fdata->nCharInfos;
+ hlen = sizeof(xQueryFontReply) + fdata->nFontProps * sizeof(xFontProp);
+ len = hlen + nchars * sizeof(xCharInfo);
+
+ new = (xQueryFontReply *) xalloc(len);
+ *qfr = (pointer) new;
+
+ if (!new) /* XXX bad stuff... */
+ return 0;
+
+ /* copy the header & props parts */
+ t = (char *) new;
+ t += junklen;
+ if (compression) {
+ memcpy((char *) t, (char *) fdata, hlen - junklen);
+ } else {
+ memcpy((char *) t, (char *) fdata, len - junklen);
+ return len;
+ }
+
+ attrs = maxb->attributes;
+
+ t = (char *) fdata;
+ t += hlen - junklen;
+ lci = (xLbxCharInfo *) t;
+
+ t = (char *) new;
+ t += hlen;
+ ci = (xCharInfo *) t;
+
+ /* now expand the chars */
+ for (i = 0; i < nchars; i++, lci++, ci++) {
+ if (lci->metrics == 0) {
+ /* empty char */
+ ci->characterWidth = ci->leftSideBearing = ci->rightSideBearing =
+ ci->ascent = ci->descent = ci->attributes = 0;
+ } else {
+ ci->characterWidth =
+ unpack_val(lci->metrics, LBX_WIDTH_MASK,
+ LBX_WIDTH_SHIFT, LBX_WIDTH_BITS);
+ ci->leftSideBearing = unpack_val(lci->metrics, LBX_LEFT_MASK,
+ LBX_LEFT_SHIFT, LBX_LEFT_BITS);
+ ci->rightSideBearing = unpack_val(lci->metrics, LBX_RIGHT_MASK,
+ LBX_RIGHT_SHIFT, LBX_RIGHT_BITS);
+ ci->ascent = unpack_val(lci->metrics, LBX_ASCENT_MASK,
+ LBX_ASCENT_SHIFT, LBX_ASCENT_BITS);
+ ci->descent = unpack_val(lci->metrics, LBX_DESCENT_MASK,
+ LBX_DESCENT_SHIFT, LBX_DESCENT_BITS);
+ ci->attributes = attrs;
+ }
+ }
+
+ return len;
+}
+
+/*ARGSUSED*/
+static Bool
+get_queryfont_reply(client, nr, data)
+ ClientPtr client;
+ ReplyStuffPtr nr;
+ char *data;
+{
+ xLbxQueryFontReply *rep;
+ int len,
+ sqlen;
+ pointer tag_data,
+ sqtag_data;
+ TagData td;
+ CARD32 tag;
+ char n;
+ xQueryFontReply *reply;
+
+ rep = (xLbxQueryFontReply *) data;
+
+ tag = rep->tag;
+ if (client->swapped) {
+ swapl(&tag, n);
+ }
+ if (tag) {
+ if (rep->length) { /* first time, set tag */
+
+#ifdef LBX_STATS
+ queryfont_full++;
+#endif
+
+ sqtag_data = (pointer) &rep[1];
+ sqlen = rep->length << 2;
+ if (client->swapped)
+ LbxSwapFontInfo(sqtag_data, rep->compression);
+
+ /*
+ * store squished version of data
+ */
+ if (!TagStoreData(client->server, client->server->global_cache,
+ tag, sqlen,
+ LbxTagTypeFont, sqtag_data)) {
+ /* tell server we lost it */
+ SendInvalidateTag(client, tag);
+ }
+ len = UnsquishFontInfo(rep->compression, sqtag_data, sqlen,
+ &tag_data);
+ } else {
+ td = TagGetTag(client->server, client->server->global_cache, tag);
+ if (!td) {
+ fprintf(stderr, "no data for font tag 0x%x\n", tag);
+ WriteError(client, X_QueryFont, 0, 0, BadAlloc);
+ return TRUE;
+ }
+ sqlen = td->size;
+ sqtag_data = td->tdata;
+ len = UnsquishFontInfo(rep->compression, sqtag_data, sqlen,
+ &tag_data);
+
+#ifdef LBX_STATS
+ queryfont_tag++;
+ tag_bytes_unsent += len;
+#endif
+ }
+ } else {
+
+#ifdef LBX_STATS
+ queryfont_full++;
+#endif
+
+ /* server didn't send us a tag for some reason -- just pass on data */
+ sqtag_data = (pointer) &rep[1];
+ if (client->swapped)
+ LbxSwapFontInfo(sqtag_data, FALSE);
+ sqlen = rep->length << 2;
+ len = UnsquishFontInfo(rep->compression, sqtag_data, sqlen, &tag_data);
+ }
+
+ reply = (xQueryFontReply *) ALLOCATE_LOCAL(len);
+ if (reply) {
+ memcpy((char *) reply, (char *) tag_data, len);
+ /* patch up certain fields */
+ reply->type = X_Reply;
+ reply->sequenceNumber = rep->sequenceNumber;
+ reply->length = (len - sizeof(xGenericReply)) >> 2;
+
+ len -= sizeof(xQueryFontReply);
+ if (client->swapped)
+ SwapFont(reply, TRUE);
+ WriteToClient(client, sizeof(xQueryFontReply), reply);
+ WriteToClient(client, len, reply + 1);
+ DEALLOCATE_LOCAL(reply);
+ }
+
+ xfree(tag_data); /* free unsquished version */
+
+ return TRUE;
+}
+
+
+int
+ProcLBXGetWindowAttributes(client)
+ ClientPtr client;
+{
+ REQUEST(xResourceReq);
+ xLbxGetWinAttrAndGeomReq newreq;
+ XServerPtr server = client->server;
+ ReplyStuffPtr nr;
+
+ /*
+ * GetWindowAttributes is always followed by GetGeometry.
+ * At this point, if lbxproxy requests the window attributes
+ * *AND* the geometry in one request, we are guaranteed to be
+ * able to short circuit the GetGeometry that follows.
+ */
+
+ nr = NewReply(client, client->server->lbxReq, X_LbxGetWinAttrAndGeom,
+ GetWinAttrAndGeomReply);
+
+ if (!nr)
+ return ProcStandardRequest(client);
+
+ /*
+ * R6 Xlib will not wait for the GetWindowAttributes reply before
+ * sending the GetGeometry. As a result, when lbxproxy gets the
+ * GetGeometry we must defer short circuting until lbxproxy receives
+ * the LbxGetWinAttrAndGeomReply.
+ */
+
+ nr->request_info.lbxWinGeom.got_geom_request = FALSE;
+ nr->request_info.lbxWinGeom.got_geom_reply = FALSE;
+
+
+ FinishLBXRequest(client, REQ_PASSTHROUGH);
+
+ newreq.reqType = server->lbxReq;
+ newreq.lbxReqType = X_LbxGetWinAttrAndGeom;
+ newreq.length = sz_xLbxGetWinAttrAndGeomReq >> 2;
+ newreq.id = stuff->id;
+
+ WriteReqToServer (client, sz_xLbxGetWinAttrAndGeomReq, (char *) &newreq, TRUE);
+ return Success;
+}
+
+
+static Bool
+GetWinAttrAndGeomReply (client, nr, data)
+ ClientPtr client;
+ ReplyStuffPtr nr;
+ char *data;
+{
+ xLbxGetWinAttrAndGeomReply *lbxrep;
+ xGetWindowAttributesReply reply;
+ char n;
+
+ /*
+ * We got the window attributes and geometry. Write the
+ * WindowAttributes reply now.
+ */
+
+ lbxrep = (xLbxGetWinAttrAndGeomReply *) data;
+
+ reply.type = X_Reply;
+ reply.sequenceNumber = lbxrep->sequenceNumber;
+ reply.length = (sizeof(xGetWindowAttributesReply) -
+ sizeof(xGenericReply)) >> 2;
+ reply.backingStore = lbxrep->backingStore;
+ reply.visualID = lbxrep->visualID;
+#if defined(__cplusplus) || defined(c_plusplus)
+ reply.c_class = lbxrep->c_class;
+#else
+ reply.class = lbxrep->class;
+#endif
+ reply.bitGravity = lbxrep->bitGravity;
+ reply.winGravity = lbxrep->winGravity;
+ reply.backingBitPlanes = lbxrep->backingBitPlanes;
+ reply.backingPixel = lbxrep->backingPixel;
+ reply.saveUnder = lbxrep->saveUnder;
+ reply.mapInstalled = lbxrep->mapInstalled;
+ reply.mapState = lbxrep->mapState;
+ reply.override = lbxrep->override;
+ reply.colormap = lbxrep->colormap;
+ reply.allEventMasks = lbxrep->allEventMasks;
+ reply.yourEventMask = lbxrep->yourEventMask;
+ reply.doNotPropagateMask = lbxrep->doNotPropagateMask;
+
+ if (client->swapped) {
+ swaps (&reply.sequenceNumber, n);
+ swapl (&reply.length, n);
+ }
+
+ WriteToClient(client, sizeof(xGetWindowAttributesReply), &reply);
+
+ if (nr->request_info.lbxWinGeom.got_geom_request)
+ {
+ /*
+ * We can write the GetGeometry reply now too.
+ */
+
+ xGetGeometryReply geomReply;
+
+ geomReply.type = X_Reply;
+ geomReply.sequenceNumber = lbxrep->sequenceNumber + 1;
+ geomReply.length = 0;
+ geomReply.depth = lbxrep->depth;
+ geomReply.root = lbxrep->root;
+ geomReply.x = lbxrep->x;
+ geomReply.y = lbxrep->y;
+ geomReply.width = lbxrep->width;
+ geomReply.height = lbxrep->height;
+ geomReply.borderWidth = lbxrep->borderWidth;
+
+ if (client->swapped) {
+ swaps (&geomReply.sequenceNumber, n);
+ }
+
+ WriteToClient(client, sizeof(xGetGeometryReply), &geomReply);
+
+ LBXLastResponse(client) = lbxrep->sequenceNumber + 1;
+
+ return TRUE; /* remove matching reply record */
+ }
+ else
+ {
+ /*
+ * We didn't get the GetGeometry request yet, so we
+ * stash away the geometry.
+ */
+
+ nr->request_info.lbxWinGeom.got_geom_reply = TRUE;
+ nr->request_info.lbxWinGeom.depth = lbxrep->depth;
+ nr->request_info.lbxWinGeom.root = lbxrep->root;
+ nr->request_info.lbxWinGeom.x = lbxrep->x;
+ nr->request_info.lbxWinGeom.y = lbxrep->y;
+ nr->request_info.lbxWinGeom.width = lbxrep->width;
+ nr->request_info.lbxWinGeom.height = lbxrep->height;
+ nr->request_info.lbxWinGeom.borderWidth = lbxrep->borderWidth;
+
+ return FALSE; /* don't remove matching reply record */
+ }
+}
+
+
+int
+ProcLBXGetGeometry(client)
+ ClientPtr client;
+{
+ REQUEST(xResourceReq);
+ xGetGeometryReply reply;
+ ReplyStuffPtr nr;
+ char n;
+
+ /*
+ * If the previous request was GetWindowAttributes, then lbxproxy
+ * requested the window attributes *AND* the geometry in one request.
+ * That means we can short circuit this GetGeometry!
+ */
+
+ nr = GetMatchingReply (client, LBXSequenceNumber(client) - 1, FALSE);
+
+ if (!nr || nr->major != client->server->lbxReq ||
+ nr->minor != X_LbxGetWinAttrAndGeom)
+ {
+ /*
+ * This GetGeometry was not preceded by a GetWindowAttributes,
+ * so we can't short circuit. Send the normal GetGeometry request.
+ */
+
+ return ProcStandardRequest(client);
+ }
+
+ if (nr->request_info.lbxWinGeom.got_geom_reply)
+ {
+ /*
+ * We already have the geom information, so we
+ * can write the reply now.
+ */
+
+ reply.type = X_Reply;
+ reply.sequenceNumber = LBXSequenceNumber(client);
+ reply.length = 0;
+ reply.depth = nr->request_info.lbxWinGeom.depth;
+ reply.root = nr->request_info.lbxWinGeom.root;
+ reply.x = nr->request_info.lbxWinGeom.x;
+ reply.y = nr->request_info.lbxWinGeom.y;
+ reply.width = nr->request_info.lbxWinGeom.width;
+ reply.height = nr->request_info.lbxWinGeom.height;
+ reply.borderWidth = nr->request_info.lbxWinGeom.borderWidth;
+
+ if (client->swapped) {
+ swaps (&reply.sequenceNumber, n);
+ }
+
+ FinishLBXRequest(client, REQ_YANK);
+ WriteToClient(client, sizeof(xGetGeometryReply), &reply);
+ RemoveReply (client, nr);
+ }
+ else
+ {
+ /*
+ * We must wait for the geom information before
+ * writing the GetGeometry reply.
+ */
+
+ nr->request_info.lbxWinGeom.got_geom_request = TRUE;
+
+ FinishLBXRequest(client, REQ_YANKLATE);
+ }
+ return Success;
+}
+
+/* We're just looking for signs of the window manager here */
+int
+ProcLBXChangeWindowAttributes(client)
+ ClientPtr client;
+{
+ REQUEST(xChangeWindowAttributesReq);
+ Window win;
+ CARD32 mask;
+ char n;
+
+ win = stuff->window;
+ mask = stuff->valueMask;
+ if (client->swapped) {
+ swapl(&win, n);
+ swapl(&mask, n);
+ }
+ if (mask == CWEventMask && win == LBXRootWindow(client)) {
+ mask = *(CARD32 *)&stuff[1];
+ if (client->swapped) {
+ swapl(&mask, n);
+ }
+ if (mask & SubstructureRedirectMask)
+ client->server->wm_running = TRUE;
+ }
+ return ProcStandardRequest(client);
+}
+
+void
+FinishLBXRequest(client, yank)
+ ClientPtr client;
+ int yank;
+{
+ REQUEST(xReq);
+ char n;
+
+ if (yank != REQ_PASSTHROUGH) {
+ LBXLastForReply(client) = LBXSequenceNumber(client);
+ LBXLastForResponse(client) = LBXSequenceNumber(client);
+ if (yank == REQ_YANK || yank == REQ_REPLACE)
+ LBXLastResponse(client) = LBXSequenceNumber(client);
+ } else {
+ switch (GeneratesReplies(client, stuff)) {
+ case REQ_TYPE_YES:
+ LBXLastForReply(client) = LBXSequenceNumber(client);
+ LBXLastForResponse(client) = LBXSequenceNumber(client);
+ break;
+ case REQ_TYPE_MAYBE:
+ LBXLastForResponse(client) = LBXSequenceNumber(client);
+ break;
+ case REQ_TYPE_NO:
+ if (protocolMode != PROTOCOL_POOR &&
+ GeneratesEvents(client, stuff))
+ LBXLastForResponse(client) = LBXSequenceNumber(client);
+ break;
+ }
+ }
+ switch (protocolMode) {
+ case PROTOCOL_FULL:
+ LBXCacheSafe(client) = (LBXSequenceNumber(client) ==
+ LBXLastResponse(client));
+ LBXCanDelayReply(client) = (LBXSequenceNumber(client) ==
+ LBXLastForReply(client));
+ break;
+ default:
+ LBXCacheSafe(client) = (LBXLastForResponse(client) <=
+ LBXLastResponse(client));
+ LBXCanDelayReply(client) = (LBXLastForResponse(client) <=
+ LBXLastForReply(client));
+ break;
+ }
+#ifdef SEQ_DEBUG
+ fprintf(stderr,
+ "finished req %d, seq 0x%x, yank %d cache %d delay %d reply 0x%x response 0x%x\n",
+ stuff->reqType, LBXSequenceNumber(client), yank,
+ LBXCacheSafe(client), LBXCanDelayReply(client),
+ LBXLastForReply(client), LBXLastForResponse(client));
+#endif
+
+ if (yank == REQ_YANK || yank == REQ_YANKLATE) {
+ LBXSequenceLost(client)++;
+ LBXYanked(client)++;
+ DBG(DBG_CLIENT, (stderr, "short-circuited client %d req %d\n",
+ client->index, stuff->reqType));
+ }
+ /* make sure server's sequence number is accurate */
+ if (yank != REQ_YANK && yank != REQ_YANKLATE && LBXSequenceLost(client))
+ BumpSequence(client);
+
+ /* put request length in proxy byte order */
+ if (client->swapped) {
+ swaps(&stuff->length, n);
+ }
+}
+
+/*
+ * need to rewrite error codes for requests we've replaced.
+ *
+ * QueryFont regularly hits this in normal operation
+ */
+static int
+patchup_error(client, err, nr)
+ ClientPtr client;
+ xError *err;
+ ReplyStuffPtr nr;
+{
+ int retval = 1;
+ CARD16 minor_code;
+ char n;
+
+ minor_code = err->minorCode;
+ if (client->swapped) {
+ swaps(&minor_code, n);
+ }
+ switch (minor_code) {
+ case X_LbxGetModifierMapping:
+ minor_code = X_GetModifierMapping;
+ break;
+ case X_LbxGetKeyboardMapping:
+ minor_code = X_GetKeyboardMapping;
+ break;
+ case X_LbxGetProperty:
+ minor_code = X_GetProperty;
+ break;
+ case X_LbxQueryFont:
+ minor_code = X_QueryFont;
+ break;
+ case X_LbxGetWinAttrAndGeom:
+ minor_code = X_GetWindowAttributes;
+ if (nr->request_info.lbxWinGeom.got_geom_request) {
+ err->majorCode = minor_code;
+ err->minorCode = 0;
+ if (client->swapped) {
+ swaps(&err->sequenceNumber, n);
+ }
+ WriteToClient (client, sizeof(xError), (char *)err);
+ if (client->swapped) {
+ swaps(&err->sequenceNumber, n);
+ }
+ err->sequenceNumber++;
+ LBXLastResponse(client) = err->sequenceNumber;
+ minor_code = X_GetGeometry;
+ }
+ break;
+ default:
+ retval = 0; /* error caused by some LBX req that shouldn't
+ * have an error, so eat it */
+ break;
+ }
+ err->majorCode = minor_code; /* err->majorCode is CARD8, don't swap */
+ err->minorCode = 0;
+ return retval;
+}
+
+static Bool
+error_matches(client, nr, err)
+ ClientPtr client;
+ ReplyStuffPtr nr;
+ xError *err;
+{
+ CARD16 mc;
+ char n;
+
+ mc = err->minorCode;
+ if (client->swapped) {
+ swaps(&mc, n);
+ }
+ return (err->majorCode == nr->major && mc == nr->minor);
+}
+
+/*
+ * returns TRUE if data (possibly modified) is to be sent on to client,
+ * FALSE if data is replaced
+ */
+static Bool
+HandleReply(client, data, len)
+ ClientPtr client;
+ char *data;
+ int len;
+{
+ xGenericReply *reply;
+ xError *err;
+ ReplyStuffPtr nr;
+ Bool ret = TRUE;
+ char n;
+
+ reply = (xGenericReply *) data;
+
+ if (client->awaitingSetup) {
+ xConnSetupPrefix *prefix = (xConnSetupPrefix *) reply;
+
+ AttendClient(client);
+ if (prefix->success) {
+ get_setup_reply(client, (char *) reply, len);
+ return FALSE;
+ }
+ return TRUE;
+ }
+ if (client->swapped && reply->type != KeymapNotify) {
+ swaps(&reply->sequenceNumber, n);
+ }
+
+ if (reply->type != KeymapNotify &&
+ reply->sequenceNumber < LBXLastResponse(client)) {
+ /* spontaneous events, and events in PROTOCOL_POOR mode,
+ * may have sequence numbers that are earlier
+ * than short-circuited replies and errors */
+ if (reply->type > X_Reply)
+ reply->sequenceNumber = LBXLastResponse(client);
+ }
+
+ if (reply->type != KeymapNotify &&
+ reply->sequenceNumber > LBXSequenceNumber(client))
+ {
+#ifdef SEQ_DEBUG
+ fprintf(stderr, "lbxproxy: reply seq #0x%x > internal seq 0x%x\n",
+ reply->sequenceNumber, LBXSequenceNumber(client));
+#endif
+ reply->sequenceNumber = LBXSequenceNumber(client);
+ }
+
+ if (reply->type != X_Reply) { /* event or error */
+ /* clear out pending replies that resulted in errors */
+ if (reply->type == X_Error) {
+ LBXLastResponse(client) = reply->sequenceNumber;
+ err = (xError *) reply;
+ nr = GetMatchingReply(client, reply->sequenceNumber, TRUE);
+ if (nr && error_matches(client, nr, err)) {
+ if (err->majorCode == client->server->lbxReq) {
+ int eret;
+
+ if ((eret = patchup_error(client, err, nr)) < 0) {
+ CloseDownClient(client);
+ return FALSE;
+ } else if (eret == 0) {
+ /* error for proxy -- eat it */
+ ret = FALSE;
+ }
+ } else {
+ /* error in core X or other extension */
+ HandleExtensionError(client, err, nr);
+ }
+ }
+ if (nr)
+ RemoveReply(client, nr);
+ } else if (reply->type >= 64)
+ HandleExtensionEvent(client, (xEvent *)reply);
+ if (client->swapped && reply->type != KeymapNotify) {
+ swaps(&reply->sequenceNumber, n);
+ }
+ return ret;
+ }
+
+ LBXLastResponse(client) = reply->sequenceNumber;
+
+ nr = GetMatchingReply(client, reply->sequenceNumber, TRUE);
+ if (nr) {
+ if (nr->major == client->server->lbxReq)
+ ret = FALSE;
+ if ((*nr->reply_func)(client, nr, (char *)reply))
+ RemoveReply(client, nr);
+ }
+
+ if (client->swapped) { /* put seq & length back */
+ swaps(&reply->sequenceNumber, n);
+ swapl(&reply->length, n);
+ }
+ return ret;
+}
+
+void
+DoLBXReply(client, data, len)
+ ClientPtr client;
+ char *data;
+ int len;
+{
+ if (HandleReply(client, data, len))
+ WriteToClient (client, len, data);
+
+ FlushDelayedReplies (client);
+
+ switch (protocolMode) {
+ case PROTOCOL_FULL:
+ LBXCacheSafe(client) = (LBXSequenceNumber(client) ==
+ LBXLastResponse(client));
+ break;
+ default:
+ LBXCacheSafe(client) = (LBXLastForResponse(client) <=
+ LBXLastResponse(client));
+ break;
+ }
+#ifdef SEQ_DEBUG
+ fprintf(stderr, "finished reply 0x%x, cache %d\n",
+ ((xGenericReply *)data)->sequenceNumber, LBXCacheSafe(client));
+#endif
+}
diff --git a/di/lbxutil.c b/di/lbxutil.c
new file mode 100644
index 0000000..6612201
--- /dev/null
+++ b/di/lbxutil.c
@@ -0,0 +1,507 @@
+/* $Xorg: lbxutil.c,v 1.4 2000/08/17 19:53:55 cpqbld Exp $ */
+/*
+ * Copyright 1994 Network Computing Devices, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name Network Computing Devices, Inc. not be
+ * used in advertising or publicity pertaining to distribution of this
+ * software without specific, written prior permission.
+ *
+ * THIS SOFTWARE IS PROVIDED `AS-IS'. NETWORK COMPUTING DEVICES, INC.,
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT
+ * LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, OR NONINFRINGEMENT. IN NO EVENT SHALL NETWORK
+ * COMPUTING DEVICES, INC., BE LIABLE FOR ANY DAMAGES WHATSOEVER, INCLUDING
+ * SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES, INCLUDING LOSS OF USE, DATA,
+ * OR PROFITS, EVEN IF ADVISED OF THE POSSIBILITY THEREOF, AND REGARDLESS OF
+ * WHETHER IN AN ACTION IN CONTRACT, TORT OR NEGLIGENCE, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+/*
+ * utility routines for LBX requests
+ */
+
+
+#include <stdio.h>
+#include "misc.h"
+#include "assert.h"
+#include "lbx.h"
+#include "util.h"
+#include "tags.h"
+#include "resource.h"
+#include "wire.h"
+#include "swap.h"
+#include "colormap.h"
+
+Bool compStats = FALSE; /* report stream compression statistics */
+
+#ifdef DEBUG
+extern int lbxDebug;
+#endif
+
+extern int lbxMaxMotionEvents;
+
+ReplyStuffPtr
+NewReply(client, major, minor, reply_func)
+ ClientPtr client;
+ int major;
+ int minor;
+ ReplyFunc reply_func;
+{
+ ReplyStuffPtr new,
+ *end;
+
+ new = (ReplyStuffPtr) xalloc(sizeof(ReplyStuffRec));
+ if (!new)
+ return new;
+ new->sequenceNumber = LBXSequenceNumber(client);
+ new->major = major;
+ new->minor = minor;
+ new->reply_func = reply_func;
+ new->next = NULL;
+ end = &LBXReplyList(client);
+ while (*end)
+ end = &(*end)->next;
+ *end = new;
+ return new;
+}
+
+void
+RemoveReply(client, rp)
+ ClientPtr client;
+ ReplyStuffPtr rp;
+{
+ ReplyStuffPtr cur, *prev;
+
+ prev = &LBXReplyList(client);
+
+ while ((cur = *prev) != rp)
+ prev = &cur->next;
+ *prev = cur->next;
+ if (cur->major == client->server->lbxReq) {
+ if (CacheTrimNeeded(client->server, client->server->global_cache) &&
+ !AnyTagBearingReplies(client->server, client->server->global_cache))
+ CacheTrim(client->server, client->server->global_cache);
+ if (CacheTrimNeeded(client->server, client->server->prop_cache) &&
+ !AnyTagBearingReplies(client->server, client->server->prop_cache))
+ CacheTrim(client->server, client->server->prop_cache);
+ }
+ xfree(cur);
+}
+
+ReplyStuffPtr
+GetMatchingReply(client, seqno, flush_older)
+ ClientPtr client;
+ int seqno;
+ Bool flush_older;
+{
+ ReplyStuffPtr t, old;
+
+ seqno &= 0xffff;
+ for (t = LBXReplyList(client); t; t = t->next) {
+ if ((t->sequenceNumber & 0xffff) == seqno)
+ break;
+ }
+#ifdef SEQ_DEBUG
+ if (t)
+ fprintf(stderr, "matched reply for seq 0x%x\n", seqno);
+ else
+ fprintf(stderr, "no reply for seq 0x%x\n", seqno);
+#endif
+ if (t && flush_older) {
+ while ((old = LBXReplyList(client)) != t) {
+ fprintf(stderr,
+ "unclaimed reply: maj %d min %d seq 0x%x curseq 0x%x\n",
+ old->major, old->minor, old->sequenceNumber, seqno);
+ LBXReplyList(client) = old->next;
+ xfree(old);
+ }
+ }
+ return t;
+}
+
+Bool
+AnyReplies(client)
+ ClientPtr client;
+{
+ return (LBXReplyList(client) != NULL);
+}
+
+Bool
+AnyTagBearingReplies(server, cache)
+ XServerPtr server;
+ Cache cache;
+{
+ int i;
+ int lbxreq;
+ ReplyStuffPtr t;
+ Bool found = FALSE;
+
+ /* assume this is called while a reply is being processed, so need two */
+ for (i = 1; i < currentMaxClients; i++)
+ {
+ if (!clients[i])
+ continue;
+ lbxreq = clients[i]->server->lbxReq;
+ for (t = LBXReplyList(clients[i]); t; t = t->next) {
+ if (t->major == lbxreq) {
+ switch (t->minor) {
+ case X_LbxGetModifierMapping:
+ case X_LbxGetKeyboardMapping:
+ case X_LbxQueryFont:
+ if (cache == server->global_cache) {
+ if (found)
+ return TRUE;
+ found = TRUE;
+ }
+ break;
+ case X_LbxGetProperty:
+ if (cache == server->prop_cache) {
+ if (found)
+ return TRUE;
+ found = TRUE;
+ }
+ break;
+ }
+ }
+ }
+ }
+ return FALSE;
+}
+
+/*
+ * this is used for stashing short-circuited replies for later.
+ * it currently assumes that all of them will be 32 bytes for the reply
+ * plus some amount of extra data
+ */
+
+Bool
+SaveReplyData(client, rep, len, data)
+ ClientPtr client;
+ xReply *rep;
+ int len;
+ pointer data;
+{
+ ReplyDataPtr new, *end;
+
+ new = (ReplyDataPtr) xalloc(sizeof(ReplyDataRec));
+ if (!new)
+ return FALSE;
+ if (len) {
+ new->data = (pointer) xalloc(len);
+ if (!new->data) {
+ xfree(new);
+ return FALSE;
+ } else {
+ memcpy((char *) new->data, (char *) data, len);
+ }
+ }
+ new->reply = *rep;
+ new->dlen = len;
+ new->delay_seq_no = LBXSequenceNumber(client);
+ new->next = NULL;
+
+ end = &LBXReplyData(client);
+ while (*end)
+ end = &(*end)->next;
+ *end = new;
+#ifdef SEQ_DEBUG
+ fprintf(stderr, "saving reply seq 0x%x\n", LBXSequenceNumber(client));
+#endif
+ return TRUE;
+}
+
+Bool
+FlushDelayedReplies(client)
+ ClientPtr client;
+{
+ ReplyDataPtr *prev, cur;
+
+#ifdef SEQ_DEBUG
+ fprintf(stderr, "flushing replies seq 0x%x:", LBXLastResponse(client));
+#endif
+ for (prev = &LBXReplyData(client); (cur = *prev); ) {
+#ifdef SEQ_DEBUG
+ fprintf(stderr, " 0x%x", cur->delay_seq_no);
+#endif
+ if ((cur->delay_seq_no & 0xffff) == LBXLastResponse(client) + 1) {
+ WriteToClient(client, sizeof(xReply), (char *) &cur->reply);
+ if (cur->dlen)
+ WriteToClient(client, cur->dlen, (char *) cur->data);
+ LBXLastResponse(client) = cur->delay_seq_no;
+ *prev = cur->next;
+ xfree(cur);
+ }
+ else
+ prev = &cur->next;
+ }
+#ifdef SEQ_DEBUG
+ fprintf(stderr, "\n");
+#endif
+ return TRUE;
+}
+
+void
+BumpSequence(client)
+ ClientPtr client;
+{
+ DBG(DBG_CLIENT, (stderr, "bumping client %d sequence by %d to %d\n",
+ client->index, LBXSequenceLost(client), LBXSequenceNumber(client)));
+ ModifySequence(client, LBXSequenceLost(client));
+ LBXSequenceLost(client) = 0;
+}
+
+void
+ForceSequenceUpdate(client)
+ ClientPtr client;
+{
+ if (LBXSequenceLost(client)) {
+ BumpSequence(client);
+ }
+}
+
+void
+LbxFreeTag(server, tag, tagtype)
+ XServerPtr server;
+ XID tag;
+ int tagtype;
+
+{
+ Cache tag_cache;
+
+ switch (tagtype) {
+ case LbxTagTypeProperty:
+ tag_cache = server->prop_cache;
+ break;
+ case LbxTagTypeFont:
+ case LbxTagTypeModmap:
+ case LbxTagTypeKeymap:
+ case LbxTagTypeConnInfo:
+ tag_cache = server->global_cache;
+ break;
+ default:
+ fprintf(stderr,
+ "unknown type in InvalidateTag request: tag 0x%x type %d\n",
+ tag, tagtype);
+ return;
+ }
+ TagFreeData(server, tag_cache, tag, TRUE);
+}
+
+void
+LbxSendTagData(client, tag, tagtype)
+ ClientPtr client;
+ XID tag;
+ int tagtype;
+{
+ TagData td;
+ unsigned long len;
+ pointer tdata;
+ PropertyTagDataPtr ptdp;
+
+ if (tagtype == LbxTagTypeProperty && (td = TagGetTag(client->server,
+ client->server->prop_cache, tag))) {
+ ptdp = (PropertyTagDataPtr) td->tdata;
+ tdata = ptdp->data;
+ len = ptdp->length;
+ } else {
+ fprintf(stderr, "invalid SendTagData request: tag 0x%x type %d\n",
+ tag, tagtype);
+ len = 0;
+ tdata = NULL;
+ }
+ SendTagData(client, tag, len, tdata);
+}
+
+extern unsigned long stream_out_compressed;
+extern unsigned long stream_out_uncompressed;
+extern unsigned long stream_out_plain;
+extern unsigned long stream_in_compressed;
+extern unsigned long stream_in_uncompressed;
+extern unsigned long stream_in_plain;
+extern unsigned long raw_stream_out;
+extern unsigned long raw_stream_in;
+
+void
+DumpCompressionStats()
+{
+ if (raw_stream_out && stream_out_plain) {
+ fprintf(stderr, "Requests: normal = %d, reencoded = %d",
+ raw_stream_out, stream_out_plain);
+ stream_out_compressed += stream_out_uncompressed;
+ if (stream_out_compressed)
+ fprintf(stderr, ", compressed = %d", stream_out_compressed);
+ else
+ stream_out_compressed = stream_out_plain;
+ fprintf(stderr, "\n %.2f:1 overall reduction ratio\n",
+ (float)raw_stream_out / (float)stream_out_compressed);
+ }
+ if (raw_stream_in && stream_in_plain) {
+ fprintf(stderr, "Responses: normal = %d, reencoded = %d",
+ raw_stream_in, stream_in_plain);
+ stream_in_compressed += stream_in_uncompressed;
+ if (stream_in_compressed)
+ fprintf(stderr, ", compressed = %d", stream_in_compressed);
+ else
+ stream_in_compressed = stream_in_plain;
+ fprintf(stderr, "\n %.2f:1 overall reduction ratio\n",
+ (float)raw_stream_in / (float)stream_in_compressed);
+ }
+}
+
+void
+ZeroCompressionStats()
+{
+ stream_out_compressed = 0;
+ stream_out_uncompressed = 0;
+ stream_out_plain = 0;
+ stream_in_compressed = 0;
+ stream_in_uncompressed = 0;
+ stream_in_plain = 0;
+ raw_stream_out = 0;
+ raw_stream_in = 0;
+}
+
+
+
+#ifdef LBX_STATS
+int intern_good,
+ intern_miss;
+int getatom_good,
+ getatom_miss;
+int luc_good,
+ luc_miss;
+int ac_good,
+ ac_miss;
+int anc_good,
+ anc_miss;
+
+int getmodmap_tag, /* tag only */
+ getmodmap_full;
+int getkeymap_tag, /* tag only */
+ getkeymap_full;
+int queryfont_tag, /* tag only */
+ queryfont_full;
+int getsetup_tag, /* tag only */
+ getsetup_full;
+
+int getprop_tag,
+ getprop_full;
+
+
+int tag_bytes_unsent; /* approx data kept off wire by tags */
+
+int delta_out_total;
+int delta_out_attempts;
+int delta_out_hits;
+int delta_in_total;
+int delta_in_attempts;
+int delta_in_hits;
+
+extern int gfx_gc_hit;
+extern int gfx_gc_miss;
+extern int gfx_draw_hit;
+extern int gfx_draw_miss;
+extern int gfx_total;
+
+void
+DumpOtherStats()
+{
+ fprintf(stderr, "Short-circuit stats\n");
+ fprintf(stderr, "InternAtom cache hits %d misses %d\n", intern_good, intern_miss);
+ fprintf(stderr, "GetAtomName cache hits %d misses %d\n", getatom_good, getatom_miss);
+ fprintf(stderr, "LookupColor cache hits %d misses %d\n", luc_good, luc_miss);
+ fprintf(stderr, "AllocColor cache hits %d misses %d\n", ac_good, ac_miss);
+ fprintf(stderr, "AllocNamedColor cache hits %d misses %d\n", anc_good, anc_miss);
+
+ fprintf(stderr, "Tag stats\n");
+ fprintf(stderr, "GetModifierMapping used tag %d, full data %d\n", getmodmap_tag, getmodmap_full);
+ fprintf(stderr, "GetKeyboardMapping used tag %d, full data %d\n", getkeymap_tag, getkeymap_full);
+ fprintf(stderr, "QueryFont used tag %d, full data %d\n", queryfont_tag, queryfont_full);
+ fprintf(stderr, "GetProperty used tag %d, full data %d\n", getprop_tag, getprop_full);
+ fprintf(stderr, "ConnectionSetup used tag %d, full data %d\n", getsetup_tag, getsetup_full);
+
+ fprintf(stderr, "Approx bytes kept off wire by tags %d\n", tag_bytes_unsent);
+
+ fprintf(stderr, "Delta Compressor stats\n");
+ fprintf(stderr, "Sent: total msgs = %d, cacheable = %d, cache hits = %d\n",
+ delta_out_total, delta_out_attempts, delta_out_hits);
+ fprintf(stderr, "Received: total = %d, cacheable = %d, cache hits = %d\n",
+ delta_in_total, delta_in_attempts, delta_in_hits);
+
+ fprintf(stderr, "GFX Cache stats\n");
+ fprintf(stderr, "Reencoded = %d\n", gfx_total);
+#define percent(s,t) ((t) ? ((s) * 100) / (t) : 0)
+
+#define ratios(h,m) (h), percent (h, (h)+(m)), (m), percent (m, (h) + (m))
+ fprintf(stderr, "Draw hit = %d (%d%%) miss = %d (%d%%) GC hit = %d (%d%%) miss = %d (%d%%)\n",
+ ratios (gfx_draw_hit, gfx_draw_miss),
+ ratios (gfx_gc_hit, gfx_gc_miss));
+#define savings(h,m) (((h) + (m)) * 4) - ((h) + (m) * 5)
+ fprintf(stderr, "Total bytes saved = %d Draw = %d GC = %d\n",
+ savings (gfx_gc_hit + gfx_draw_hit, gfx_gc_miss + gfx_draw_miss),
+ savings (gfx_draw_hit, gfx_draw_miss),
+ savings (gfx_gc_hit, gfx_gc_miss));
+}
+
+void
+ZeroOtherStats()
+{
+ intern_good = intern_miss = 0;
+ getatom_good = getatom_miss = 0;
+ luc_good = luc_miss = 0;
+ ac_good = ac_miss = 0;
+ anc_good = anc_miss = 0;
+
+ getmodmap_tag = 0;
+ getmodmap_full = 0;
+ getkeymap_tag = 0;
+ getkeymap_full = 0;
+ getprop_tag = 0;
+ getprop_full = 0;
+ getsetup_tag = 0;
+ getsetup_full = 0;
+
+ delta_out_total = delta_out_attempts = delta_out_hits = 0;
+ delta_in_total = delta_in_attempts = delta_in_hits = 0;
+
+ gfx_gc_hit = 0;
+ gfx_gc_miss = 0;
+ gfx_draw_hit = 0;
+ gfx_draw_miss = 0;
+ gfx_total = 0;
+}
+
+#endif
+
+void
+SendInitLBXPackets(server)
+ XServerPtr server;
+{
+
+ ZeroCompressionStats();
+#ifdef LBX_STATS
+ ZeroOtherStats();
+#endif
+
+ AllowMotion(server->serverClient, lbxMaxMotionEvents);
+}
+
+void
+LbxCleanupSession()
+{
+ if (compStats)
+ {
+ DumpCompressionStats();
+ ZeroCompressionStats();
+ }
+
+#ifdef LBX_STATS
+ DumpOtherStats();
+ ZeroOtherStats();
+#endif
+}
diff --git a/di/main.c b/di/main.c
new file mode 100644
index 0000000..acba869
--- /dev/null
+++ b/di/main.c
@@ -0,0 +1,181 @@
+/* $Xorg: main.c,v 1.5 2001/02/09 02:05:31 xorgcvs Exp $ */
+/*
+
+Copyright 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+*/
+/*
+ * Copyright 1992 Network Computing Devices
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of NCD. not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. NCD. makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * NCD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL NCD.
+ * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include "lbx.h"
+#include "wire.h"
+#include "atomcache.h"
+#include "colormap.h"
+#include "tags.h"
+#include "lbxext.h"
+#include "os.h"
+#include "resource.h"
+#include "pm.h"
+#include "misc.h"
+
+int LbxWhoAmI = 0; /*
+ * for lbx zlib library to know who we are
+ * server = 1
+ * proxy = 0
+ */
+
+#define DEFAULT_MAXSERVERS 20
+
+XServerPtr *servers;
+
+char *display;
+
+int lbxMaxServers = DEFAULT_MAXSERVERS;
+
+static void InitializeGlobals ();
+
+int
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ display = "63";
+
+ ProcessCommandLine (argc, argv);
+
+ AdjustProcVector();
+
+ InitializeGlobals ();
+
+ proxyMngr = CheckForProxyManager ();
+ CreateWellKnownSockets ();
+ if (proxyMngr)
+ {
+ ConnectToProxyManager ();
+ ListenToProxyManager ();
+ }
+
+ while (1)
+ {
+ OsInit ();
+ InitColors ();
+ InitDeleteFuncs();
+
+ if (!proxyMngr && !ConnectToServer (display_name))
+ {
+ /*
+ * If no display name was given on the command line, the
+ * DISPLAY variable is used.
+ */
+ if(!display_name)
+ display_name = getenv("DISPLAY");
+
+ if(display_name) {
+ FatalError("could not connect to display '%s'", display_name);
+ } else {
+ FatalError("no display specified");
+ }
+ }
+
+ if (!InitClientResources(clients[0]))
+ FatalError("couldn't init server resources");
+ FinishInitClientResources(clients[0], 0, 0x3ffff);
+
+ if (Dispatch () != 0)
+ break;
+
+ FreeAllResources();
+ FreeAtoms();
+ FreeColors();
+ FreeTags();
+ }
+ exit (0);
+}
+
+/*
+ * Initalize those global variables that are needed to connect
+ * to a display server.
+ */
+static void
+InitializeGlobals ()
+{
+ int i;
+ ClientPtr tmp;
+
+ clients = (ClientPtr *)xalloc(MAXCLIENTS * sizeof(ClientPtr));
+ if (!clients)
+ FatalError("couldn't create client array");
+ for (i=1; i < MAXCLIENTS; i++)
+ clients[i] = NullClient;
+
+ servers = (XServerPtr *)xalloc(lbxMaxServers * sizeof (XServerPtr));
+ if (!servers)
+ FatalError("couldn't create servers array");
+ for (i=0; i < lbxMaxServers; i++)
+ servers[i] = (XServerPtr) NULL;
+
+ tmp = (ClientPtr)xcalloc(sizeof(ClientRec));
+ if (!tmp)
+ FatalError("couldn't create server client");
+
+ tmp->sequence = 0;
+ tmp->closeDownMode = RetainPermanent;
+ tmp->clientGone = FALSE;
+ tmp->server = servers[0];
+ tmp->index = 0;
+ tmp->noClientException = Success;
+ tmp->awaitingSetup = FALSE;
+ tmp->swapped = FALSE;
+ tmp->big_requests = FALSE;
+
+ clients[0] = tmp;
+
+ currentMaxClients = 1;
+}
+
+
+/* ARGSUSED */
+void
+MarkClientException (client)
+ ClientPtr client;
+{
+}
diff --git a/di/options.c b/di/options.c
new file mode 100644
index 0000000..5d9cd6c
--- /dev/null
+++ b/di/options.c
@@ -0,0 +1,808 @@
+/* $Xorg: options.c,v 1.4 2001/02/09 02:05:31 xorgcvs Exp $ */
+/*
+
+Copyright 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+*/
+/*
+ * Copyright 1994 Network Computing Devices, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name Network Computing Devices, Inc. not be
+ * used in advertising or publicity pertaining to distribution of this
+ * software without specific, written prior permission.
+ *
+ * THIS SOFTWARE IS PROVIDED `AS-IS'. NETWORK COMPUTING DEVICES, INC.,
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT
+ * LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, OR NONINFRINGEMENT. IN NO EVENT SHALL NETWORK
+ * COMPUTING DEVICES, INC., BE LIABLE FOR ANY DAMAGES WHATSOEVER, INCLUDING
+ * SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES, INCLUDING LOSS OF USE, DATA,
+ * OR PROFITS, EVEN IF ADVISED OF THE POSSIBILITY THEREOF, AND REGARDLESS OF
+ * WHETHER IN AN ACTION IN CONTRACT, TORT OR NEGLIGENCE, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include <stdio.h>
+#include "X.h"
+#include "misc.h"
+#include "XLbx.h"
+#include "lbxopts.h"
+#include "proxyopts.h"
+#include "lbximage.h"
+#include "util.h"
+#include "colormap.h"
+#ifndef NO_ZLIB
+#include "lbxzlib.h"
+#endif /* NO_ZLIB */
+#include "wire.h"
+
+static int LbxDeltaReply();
+static int LbxProxyDeltaReq();
+static int LbxServerDeltaReq();
+static int LbxStreamCompReq();
+static int LbxBitmapCompReq();
+static int LbxPixmapCompReq();
+static int LbxSquishReq();
+static int LbxUseTagsReq();
+static int LbxCmapAllReq();
+
+static int LbxProxyDeltaReply();
+static int LbxServerDeltaReply();
+static int LbxStreamCompReply();
+static int LbxBitmapCompReply();
+static int LbxPixmapCompReply();
+static int LbxSquishReply();
+static int LbxUseTagsReply();
+static int LbxCmapAllReply();
+
+static int OptZlibReq();
+static int OptZlibReply();
+
+#define OPT_INDEX_STREAM_COMP 2
+
+/*
+ * Local variables that get set when the command line options
+ * are parsed.
+ */
+static Bool called_LbxNoComp;
+static Bool called_LbxNoDelta;
+
+
+static void
+InitializeOptionsList (server, idx, optcode, negotiate, req, reply)
+ XServerPtr server;
+ int idx;
+ CARD8 optcode;
+ Bool negotiate;
+ int (*req)();
+ int (*reply)();
+{
+ server->LbxOptions[idx].optcode = optcode;
+ server->LbxOptions[idx].negotiate = negotiate;
+ server->LbxOptions[idx].req = req;
+ server->LbxOptions[idx].reply = reply;
+}
+
+static void
+InitializeDeltaOptions (server)
+ XServerPtr server;
+{
+ server->proxyDeltaOpt.minN = 0;
+ server->proxyDeltaOpt.maxN = 0xff;
+ server->proxyDeltaOpt.prefN = LBX_OPT_DELTA_NCACHE_DFLT;
+ server->proxyDeltaOpt.minMaxMsgLen = LBX_OPT_DELTA_MSGLEN_MIN >> 2;
+ server->proxyDeltaOpt.maxMaxMsgLen = 0xff;
+ server->proxyDeltaOpt.prefMaxMsgLen = LBX_OPT_DELTA_MSGLEN_DFLT >> 2;
+
+ server->serverDeltaOpt.minN = 0;
+ server->serverDeltaOpt.maxN = 0xff;
+ server->serverDeltaOpt.prefN = LBX_OPT_DELTA_NCACHE_DFLT;
+ server->serverDeltaOpt.minMaxMsgLen = LBX_OPT_DELTA_MSGLEN_MIN >> 2;
+ server->serverDeltaOpt.maxMaxMsgLen = 0xff;
+ server->serverDeltaOpt.prefMaxMsgLen = LBX_OPT_DELTA_MSGLEN_DFLT >> 2;
+}
+
+static void
+InitializeStreamComp (server)
+ XServerPtr server;
+{
+ server->LbxStreamComp[0].typelen = ZLIB_STRCOMP_OPT_LEN;
+ server->LbxStreamComp[0].type = ZLIB_STRCOMP_OPT;
+ server->LbxStreamComp[0].req = OptZlibReq;
+ server->LbxStreamComp[0].reply = OptZlibReply;
+}
+
+static void
+InitializeBitmapCompMethod (server)
+ XServerPtr server;
+{
+ /* compression method name */
+ server->LbxBitmapCompMethods[0].methodName = "XC-FaxG42D";
+
+ /* inited */
+ server->LbxBitmapCompMethods[0].inited = 0;
+
+ /* method opcode - to be filled on reply */
+ server->LbxBitmapCompMethods[0].methodOpCode= -1;
+
+ /* init function */
+ server->LbxBitmapCompMethods[0].compInit = NULL;
+
+ /* encode function */
+ server->LbxBitmapCompMethods[0].compFunc = LbxImageEncodeFaxG42D;
+
+ /* decode function */
+ server->LbxBitmapCompMethods[0].decompFunc = LbxImageDecodeFaxG42D;
+}
+
+/*ARGSUSED*/
+static void
+InitializePixmapCompMethod (server)
+ XServerPtr server;
+{
+ /*
+ * Currently, we don't support any pixmap compression algorithms
+ * because regular stream compression does much better than PackBits.
+ * If we want to plug in a better pixmap image compression algorithm,
+ * it would go here.
+ */
+
+#define NUM_PIXMAP_METHODS 0
+
+}
+
+static void
+InitializeCmpaAllMethods (server)
+ XServerPtr server;
+{
+ /* colormap allocation method name */
+ server->LbxCmapAllMethods[0].methodName = "XC-CMAP";
+
+ /* rgb resolver */
+ server->LbxCmapAllMethods[0].resolver = ResolveColor;
+
+ /* allocator */
+ server->LbxCmapAllMethods[0].findfree = FindFreePixel;
+
+ /* matcher */
+ server->LbxCmapAllMethods[0].findbest = FindBestPixel;
+}
+
+void
+LbxOptInit(server)
+ XServerPtr server;
+{
+ bzero((char *)&server->lbxNegOpt, sizeof(LbxNegOptsRec));
+
+ server->lbxNegOpt.proxyDeltaN = LBX_OPT_DELTA_NCACHE_DFLT;
+ server->lbxNegOpt.proxyDeltaMaxLen = LBX_OPT_DELTA_MSGLEN_DFLT;
+ server->lbxNegOpt.serverDeltaN = LBX_OPT_DELTA_NCACHE_DFLT;
+ server->lbxNegOpt.serverDeltaMaxLen = LBX_OPT_DELTA_MSGLEN_DFLT;
+ server->lbxNegOpt.numBitmapCompMethods = 0;
+ server->lbxNegOpt.bitmapCompMethods = NULL;
+ server->lbxNegOpt.numPixmapCompMethods = 0;
+ server->lbxNegOpt.pixmapCompMethods = NULL;
+ server->lbxNegOpt.squish = TRUE;
+ server->lbxNegOpt.useTags = TRUE;
+
+ /*
+ * Fill in the server's LbxOptions array.
+ */
+ InitializeOptionsList (server, 0, LBX_OPT_DELTA_PROXY, TRUE,
+ LbxProxyDeltaReq, LbxProxyDeltaReply);
+ InitializeOptionsList (server, 1, LBX_OPT_DELTA_SERVER, TRUE,
+ LbxServerDeltaReq, LbxServerDeltaReply);
+ InitializeOptionsList (server, 2, LBX_OPT_STREAM_COMP, TRUE,
+ LbxStreamCompReq, LbxStreamCompReply);
+ InitializeOptionsList (server, 3, LBX_OPT_BITMAP_COMP, TRUE,
+ LbxBitmapCompReq, LbxBitmapCompReply);
+ InitializeOptionsList (server, 4, LBX_OPT_PIXMAP_COMP, TRUE,
+ LbxPixmapCompReq, LbxPixmapCompReply);
+ InitializeOptionsList (server, 5, LBX_OPT_MSG_COMP, TRUE,
+ LbxSquishReq, LbxSquishReply);
+ InitializeOptionsList (server, 6, LBX_OPT_USE_TAGS, TRUE,
+ LbxUseTagsReq, LbxUseTagsReply);
+ InitializeOptionsList (server, 7, LBX_OPT_CMAP_ALL, TRUE,
+ LbxCmapAllReq, LbxCmapAllReply);
+
+ InitializeDeltaOptions (server);
+
+ InitializeStreamComp (server);
+
+ InitializeBitmapCompMethod (server);
+
+ InitializePixmapCompMethod (server);
+
+ InitializeCmpaAllMethods (server);
+
+ /*
+ * Now update this server's LbxOptions that were set when
+ * command line was parsed.
+ */
+ if (called_LbxNoComp)
+ server->LbxOptions[OPT_INDEX_STREAM_COMP].negotiate = FALSE;
+ if (called_LbxNoDelta) {
+ server->proxyDeltaOpt.prefN = 0;
+ server->serverDeltaOpt.prefN = 0;
+ }
+}
+
+int
+LbxOptBuildReq(server, buf)
+ XServerPtr server;
+ register char *buf;
+{
+ int i;
+ char *bufstart = buf;
+ char *pnopts = buf++;
+
+ server->optcount = 0;
+
+ for (i = 0; i < (sizeof(server->LbxOptions) / sizeof (LbxOptionsListRec));
+ i++) {
+ int reqlen;
+
+ if (server->LbxOptions[i].negotiate) {
+ reqlen = (*server->LbxOptions[i].req) (server,
+ buf + LBX_OPT_SMALLHDR_LEN);
+ *buf++ = server->LbxOptions[i].optcode;
+ *buf++ = LBX_OPT_SMALLHDR_LEN + reqlen;
+ buf += reqlen;
+ server->optlist[server->optcount++] = i;
+ }
+ }
+
+ *pnopts = server->optcount;
+ return (buf - bufstart);
+}
+
+int
+LbxOptParseReply(server, nopts, preply, replylen)
+ XServerPtr server;
+ int nopts;
+ unsigned char *preply;
+ int replylen;
+{
+ int i;
+
+ for (i = 0; i < nopts; i++) {
+ int len;
+ int hdrlen;
+ int result;
+ int optindex = *preply;
+
+ if (optindex >= server->optcount)
+ return -1;
+ LBX_OPT_DECODE_LEN(preply + 1, len, hdrlen);
+ if (len < ++hdrlen || len > replylen) {
+#ifdef OPTDEBUG
+ fprintf(stderr, "bad length, len = %d, hdrlen = %d, optlen = %d\n",
+ len, hdrlen, replylen);
+#endif
+ return -1;
+ }
+
+ result = (*server->LbxOptions[server->optlist[optindex]].reply) (server,
+ preply + hdrlen, len - hdrlen);
+ if (result < 0)
+ return -1;
+
+ preply += len;
+ replylen -= len;
+ }
+ return 0;
+}
+
+void
+LbxNoDelta()
+{
+ /*
+ * All we can do now is to flag that this was called
+ * since the associated server structure may not be
+ * initialized.
+ */
+ called_LbxNoDelta = TRUE;
+}
+
+static int
+LbxProxyDeltaReq(server, buf)
+ XServerPtr server;
+ unsigned char *buf;
+{
+ memcpy(buf, (char *)&server->proxyDeltaOpt, sizeof(LbxDeltaOptionsRec));
+ return LBX_OPT_DELTA_REQLEN;
+}
+
+static int
+LbxServerDeltaReq(server, buf)
+ XServerPtr server;
+ unsigned char *buf;
+{
+ memcpy(buf, (char *)&server->serverDeltaOpt, sizeof(LbxDeltaOptionsRec));
+ return LBX_OPT_DELTA_REQLEN;
+}
+
+static int
+LbxProxyDeltaReply(server, preply, replylen)
+ XServerPtr server;
+ unsigned char *preply;
+ int replylen;
+{
+ return LbxDeltaReply(preply,
+ replylen,
+ &server->lbxNegOpt.proxyDeltaN,
+ &server->lbxNegOpt.proxyDeltaMaxLen);
+}
+
+static int
+LbxServerDeltaReply(server, preply, replylen)
+ XServerPtr server;
+ unsigned char *preply;
+ int replylen;
+{
+ return LbxDeltaReply(preply,
+ replylen,
+ &server->lbxNegOpt.serverDeltaN,
+ &server->lbxNegOpt.serverDeltaMaxLen);
+}
+
+static int
+LbxDeltaReply(preply, replylen, pn, pmaxlen)
+ unsigned char *preply;
+ int replylen;
+ short *pn;
+ short *pmaxlen;
+{
+ if (replylen < 2)
+ return -1;
+ *pn = *preply++;
+ *pmaxlen = *preply;
+ if ((*pmaxlen <<= 2) == 0)
+ *pn = 0;
+ else if (*pmaxlen < 32) {
+#ifdef DEBUG
+ printf("bad delta max msg length %d\n", *pmaxlen);
+#endif
+ return -1;
+ }
+ return 0;
+}
+
+
+void
+LbxNoComp()
+{
+ /*
+ * All we can do now is to flag that this was called
+ * since the associated server structure may not be
+ * initialized.
+ */
+ called_LbxNoComp = TRUE;
+}
+
+static int
+LbxStreamCompReq(server, buf)
+ XServerPtr server;
+ unsigned char *buf;
+{
+ int i;
+ int reqlen;
+ int LBX_N_STRCOMP;
+
+ LBX_N_STRCOMP = sizeof (server->LbxStreamComp) /
+ sizeof (LbxStreamCompRec);
+
+ *buf++ = LBX_N_STRCOMP;
+ reqlen = 1;
+
+ for (i = 0; i < LBX_N_STRCOMP; i++) {
+ int optdatalen;
+ int typelen = server->LbxStreamComp[i].typelen;
+
+ *buf++ = typelen;
+ memcpy(buf, server->LbxStreamComp[i].type, typelen);
+ buf += typelen;
+ reqlen += 1 + typelen;
+
+ optdatalen = (*server->LbxStreamComp[i].req) (server, buf + 1);
+ *buf = optdatalen + 1;
+ buf += optdatalen + 1;
+ reqlen += optdatalen + 1;
+ }
+
+ return reqlen;
+}
+
+static int
+LbxStreamCompReply(server, preply, replylen)
+ XServerPtr server;
+ unsigned char *preply;
+ int replylen;
+{
+ int optindex;
+ int LBX_N_STRCOMP;
+
+ LBX_N_STRCOMP = sizeof(server->LbxStreamComp) /
+ sizeof (LbxStreamCompRec);
+
+ if (replylen < 1 || (optindex = *preply) >= LBX_N_STRCOMP)
+ return -1;
+ return (*server->LbxStreamComp[optindex].reply) (server,
+ preply + 1,
+ replylen - 1);
+
+}
+
+extern int zlevel;
+
+/*ARGSUSED*/
+static int
+OptZlibReq(server, buf)
+ XServerPtr server;
+ unsigned char *buf;
+{
+ *buf++ = 1; /* len */
+ *buf = zlevel;
+ return (2);
+}
+
+extern LbxStreamCompHandle ZlibInit();
+extern int ZlibStuffInput(), ZlibInputAvail(), ZlibFlush(),
+ ZlibRead(), ZlibWriteV();
+extern void ZlibCompressOn(), ZlibCompressOff(), ZlibFree();
+
+/*ARGSUSED*/
+static int
+OptZlibReply(server, preply, replylen)
+ XServerPtr server;
+ unsigned char *preply;
+ int replylen;
+{
+ server->lbxNegOpt.streamOpts.streamCompInit = ZlibInit;
+ server->lbxNegOpt.streamOpts.streamCompArg = (pointer) zlevel;
+ server->lbxNegOpt.streamOpts.streamCompStuffInput = ZlibStuffInput;
+ server->lbxNegOpt.streamOpts.streamCompInputAvail = ZlibInputAvail;
+ server->lbxNegOpt.streamOpts.streamCompFlush = ZlibFlush;
+ server->lbxNegOpt.streamOpts.streamCompRead = ZlibRead;
+ server->lbxNegOpt.streamOpts.streamCompWriteV = ZlibWriteV;
+ server->lbxNegOpt.streamOpts.streamCompOn = ZlibCompressOn;
+ server->lbxNegOpt.streamOpts.streamCompOff = ZlibCompressOff;
+ server->lbxNegOpt.streamOpts.streamCompFreeHandle = ZlibFree;
+
+ return 0;
+}
+
+Bool lbxDoSquishing = TRUE;
+
+/*ARGSUSED*/
+static int
+LbxSquishReq(server, buf)
+ XServerPtr server;
+ unsigned char *buf;
+{
+ *buf = lbxDoSquishing;
+ return 1;
+}
+
+static int
+LbxSquishReply(server, preply, replylen)
+ XServerPtr server;
+ unsigned char *preply;
+ int replylen;
+{
+ if (replylen < 1)
+ return -1;
+ server->lbxNegOpt.squish = *preply;
+ return 0;
+}
+
+
+Bool lbxUseTags = TRUE;
+
+/*ARGSUSED*/
+static int
+LbxUseTagsReq(server, buf)
+ XServerPtr server;
+ unsigned char *buf;
+{
+ *buf = lbxUseTags;
+ return 1;
+}
+
+
+static int
+LbxUseTagsReply(server, preply, replylen)
+ XServerPtr server;
+ unsigned char *preply;
+ int replylen;
+{
+ if (replylen < 1)
+ return -1;
+ server->lbxNegOpt.useTags = *preply;
+ return 0;
+}
+
+
+/*
+ * Option negotiation for image compression
+ */
+
+static int
+LbxBitmapCompReq (server, buf)
+ XServerPtr server;
+ unsigned char *buf;
+{
+ unsigned char *bufStart = buf;
+ int i;
+ int NUM_BITMAP_METHODS;
+
+ NUM_BITMAP_METHODS = sizeof(server->LbxBitmapCompMethods) /
+ sizeof (LbxBitmapCompMethod);
+
+ *buf++ = NUM_BITMAP_METHODS;
+
+ for (i = 0; i < NUM_BITMAP_METHODS; i++)
+ {
+ int len = strlen (server->LbxBitmapCompMethods[i].methodName);
+ *buf++ = len;
+ memcpy (buf, server->LbxBitmapCompMethods[i].methodName, len);
+ buf += len;
+ }
+
+ return (buf - bufStart);
+}
+
+/*ARGSUSED*/
+static int
+LbxBitmapCompReply (server, preply, replylen)
+ XServerPtr server;
+ unsigned char *preply;
+ int replylen;
+{
+ int count = *preply++;
+ int i;
+
+ server->lbxNegOpt.numBitmapCompMethods = count;
+
+ if (count > 0)
+ {
+ server->lbxNegOpt.bitmapCompMethods = (char *) xalloc (count);
+ if (server->lbxNegOpt.bitmapCompMethods == NULL)
+ {
+ server->lbxNegOpt.numBitmapCompMethods = 0;
+ return -1;
+ }
+ }
+
+ for (i = 0; i < count; i++)
+ {
+ int index = *preply++;
+ server->lbxNegOpt.bitmapCompMethods[i] = index;
+ server->LbxBitmapCompMethods[index].methodOpCode = *preply++;
+ }
+
+ return 0;
+}
+
+
+static int
+LbxPixmapCompReq (server, buf)
+ XServerPtr server;
+ unsigned char *buf;
+{
+ unsigned char *bufStart = buf;
+ int i, j;
+
+ *buf++ = NUM_PIXMAP_METHODS;
+
+ for (i = 0; i < NUM_PIXMAP_METHODS; i++)
+ {
+ int len = strlen (server->LbxPixmapCompMethods[i].methodName);
+ *buf++ = len;
+ memcpy (buf, server->LbxPixmapCompMethods[i].methodName, len);
+ buf += len;
+ *buf++ = server->LbxPixmapCompMethods[i].formatMask;
+ *buf++ = server->LbxPixmapCompMethods[i].depthCount;
+ for (j = 0; j < server->LbxPixmapCompMethods[i].depthCount; j++)
+ *buf++ = server->LbxPixmapCompMethods[i].depths[j];
+ }
+
+ return (buf - bufStart);
+}
+
+/*ARGSUSED*/
+static int
+LbxPixmapCompReply (server, preply, replylen)
+ XServerPtr server;
+ unsigned char *preply;
+ int replylen;
+{
+ int count = *preply++;
+ int i, j;
+
+ server->lbxNegOpt.numPixmapCompMethods = count;
+
+ if (count > 0)
+ {
+ server->lbxNegOpt.pixmapCompMethods = (char *) xalloc (count);
+ if (server->lbxNegOpt.pixmapCompMethods == NULL)
+ {
+ server->lbxNegOpt.numPixmapCompMethods = 0;
+ return -1;
+ }
+ }
+
+ for (i = 0; i < count; i++)
+ {
+ int index = *preply++;
+ server->lbxNegOpt.pixmapCompMethods[i] = index;
+ server->LbxPixmapCompMethods[index].methodOpCode = *preply++;
+ server->LbxPixmapCompMethods[index].formatMask = *preply++;
+ server->LbxPixmapCompMethods[index].depthCount = *preply++;
+ for (j = 0; j < server->LbxPixmapCompMethods[index].depthCount; j++)
+ server->LbxPixmapCompMethods[index].depths[j] = *preply++;
+ }
+
+ return 0;
+}
+
+
+LbxBitmapCompMethod *
+LbxLookupBitmapCompMethod (server, methodOpCode)
+ XServerPtr server;
+ int methodOpCode;
+
+{
+ int i;
+
+ for (i = 0; i < server->lbxNegOpt.numBitmapCompMethods; i++)
+ {
+ LbxBitmapCompMethod *method;
+
+ method = &server->LbxBitmapCompMethods[server->lbxNegOpt.bitmapCompMethods[i]];
+
+ if (method->methodOpCode == methodOpCode)
+ return (method);
+ }
+
+ return (NULL);
+}
+
+
+LbxPixmapCompMethod *
+LbxLookupPixmapCompMethod (server, methodOpCode)
+ XServerPtr server;
+ int methodOpCode;
+
+{
+ int i;
+
+ for (i = 0; i < server->lbxNegOpt.numPixmapCompMethods; i++)
+ {
+ LbxPixmapCompMethod *method;
+
+ method = &server->LbxPixmapCompMethods[server->lbxNegOpt.pixmapCompMethods[i]];
+
+ if (method->methodOpCode == methodOpCode)
+ return (method);
+ }
+
+ return (NULL);
+}
+
+
+LbxBitmapCompMethod *
+LbxFindPreferredBitmapCompMethod (server)
+ XServerPtr server;
+
+{
+ if (server->lbxNegOpt.numBitmapCompMethods == 0)
+ return NULL;
+ else
+ return (&server->LbxBitmapCompMethods[server->lbxNegOpt.bitmapCompMethods[0]]);
+}
+
+
+LbxPixmapCompMethod *
+LbxFindPreferredPixmapCompMethod (server, format, depth)
+ XServerPtr server;
+ int format;
+ int depth;
+
+{
+ if (server->lbxNegOpt.numPixmapCompMethods == 0)
+ return NULL;
+ else
+ {
+ LbxPixmapCompMethod *method;
+ int i, j;
+
+ for (i = 0; i < server->lbxNegOpt.numPixmapCompMethods; i++)
+ {
+ method = &server->LbxPixmapCompMethods[server->lbxNegOpt.pixmapCompMethods[i]];
+
+ if ((method->formatMask & (1 << format)))
+ {
+ for (j = 0; j < method->depthCount; j++)
+ if (depth == method->depths[j])
+ return method;
+ }
+ }
+
+ return NULL;
+ }
+}
+
+/*
+ * Colormap methods
+ */
+static int
+LbxCmapAllReq (server, buf)
+ XServerPtr server;
+ unsigned char *buf;
+{
+ unsigned char *bufStart = buf;
+ int i;
+ int NUM_CMAP_METHODS;
+
+ NUM_CMAP_METHODS = sizeof (server->LbxCmapAllMethods) /
+ sizeof (LbxCmapAllMethod);
+
+ *buf++ = NUM_CMAP_METHODS;
+
+ for (i = 0; i < NUM_CMAP_METHODS; i++)
+ {
+ int len = strlen (server->LbxCmapAllMethods[i].methodName);
+ *buf++ = len;
+ memcpy (buf, server->LbxCmapAllMethods[i].methodName, len);
+ buf += len;
+ }
+
+ return (buf - bufStart);
+}
+
+static int
+LbxCmapAllReply(server, preply, replylen)
+ XServerPtr server;
+ unsigned char *preply;
+ int replylen;
+{
+ int NUM_CMAP_METHODS;
+
+ NUM_CMAP_METHODS = sizeof (server->LbxCmapAllMethods) /
+ sizeof (LbxCmapAllMethod);
+
+ if (replylen < 1)
+ return -1;
+ if (*preply < NUM_CMAP_METHODS) {
+ LbxResolveColor = server->LbxCmapAllMethods[*preply].resolver;
+ LbxFindFreePixel = server->LbxCmapAllMethods[*preply].findfree;
+ LbxFindBestPixel = server->LbxCmapAllMethods[*preply].findbest;
+ }
+ return 0;
+}
diff --git a/di/pm.c b/di/pm.c
new file mode 100644
index 0000000..c6e145f
--- /dev/null
+++ b/di/pm.c
@@ -0,0 +1,491 @@
+/* $Xorg: pm.c,v 1.5 2001/02/09 02:05:31 xorgcvs Exp $ */
+
+/*
+Copyright 1996, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from The Open Group.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <X11/Xmd.h>
+#include <X11/ICE/ICElib.h>
+#include <X11/ICE/ICEmsg.h>
+#include <X11/ICE/ICEproto.h>
+#include <X11/PM/PM.h>
+#include <X11/PM/PMproto.h>
+
+/*
+ * Because ICElib.h had a #define for Bool and because misc.h
+ * has a typedef for Bool, _BOOL_ALREADY_DEFINED_ is defined so
+ * that misc.h does not cause a conflict for Bool.
+ */
+#define _BOOL_ALREADY_DEFINED_
+#include "wire.h"
+#include "pmP.h"
+#include "pm.h"
+
+extern char *display_name;
+
+/*
+ * Local constants
+ */
+#define ERROR_STRING_SIZE 256
+
+/*
+ * Static definitions
+ */
+static void PMprocessMessages ();
+static Status _ConnectToProxyManager ();
+
+static int PMopcode;
+static int PMversionCount = 1;
+static IcePoVersionRec PMversions[] =
+ {{PM_MAJOR_VERSION, PM_MINOR_VERSION, PMprocessMessages}};
+static int gotFirstGetProxyAddr = 0;
+
+/*
+ * Public variables
+ */
+IceConn PM_iceConn;
+int proxy_manager_fd = -1;
+Bool proxyMngr;
+
+/*
+ * The following comment and ICE I/O error handler code were taken
+ * from the X Session Manager. What's good enough for the XSM
+ * is good enough for the LBX proxy ...
+ *
+ * The real way to handle IO errors is to check the return status
+ * of IceProcessMessages. xsm properly does this.
+ *
+ * Unfortunately, a design flaw exists in the ICE library in which
+ * a default IO error handler is invoked if no IO error handler is
+ * installed. This default handler exits. We must avoid this.
+ *
+ * To get around this problem, we install an IO error handler that
+ * does a little magic. Since a previous IO handler might have been
+ * installed, when we install our IO error handler, we do a little
+ * trick to get both the previous IO error handler and the default
+ * IO error handler. When our IO error handler is called, if the
+ * previous handler is not the default handler, we call it. This
+ * way, everyone's IO error handler gets called except the stupid
+ * default one which does an exit!
+ *
+ */
+static IceIOErrorHandler prev_handler;
+
+static void
+MyIoErrorHandler (ice_conn)
+ IceConn ice_conn;
+{
+ if (prev_handler)
+ (*prev_handler) (ice_conn);
+ fprintf (stderr, "Received an ICE I/O error from the Proxy Manager\n");
+
+ proxy_manager_fd = -1;
+}
+
+static void
+InstallIOErrorHandler ()
+{
+ IceIOErrorHandler default_handler;
+
+ prev_handler = IceSetIOErrorHandler (NULL);
+ default_handler = IceSetIOErrorHandler (MyIoErrorHandler);
+ if (prev_handler == default_handler)
+ prev_handler = NULL;
+}
+
+
+Bool
+CheckForProxyManager ()
+{
+ if (getenv ("PROXY_MANAGER"))
+ return 1;
+ else
+ return 0;
+}
+
+void
+ConnectToProxyManager ()
+{
+ char *proxyManagerAddr;
+ char errorString[ERROR_STRING_SIZE];
+
+ proxyManagerAddr = (char *) getenv ("PROXY_MANAGER");
+
+ if (proxyManagerAddr)
+ {
+ InstallIOErrorHandler ();
+
+ if (!_ConnectToProxyManager (proxyManagerAddr, errorString))
+ {
+ fprintf (stderr, "%s\n", errorString);
+ exit (1);
+ }
+ }
+}
+
+
+static Status
+_ConnectToProxyManager (pmAddr, errorString)
+ char *pmAddr;
+ char *errorString;
+{
+ IceProtocolSetupStatus setupstat;
+ char *vendor = NULL;
+ char *release = NULL;
+ pmStartProxyMsg *pMsg;
+ char *pData;
+ int len;
+ int majorVersion, minorVersion;
+ char iceError[ERROR_STRING_SIZE];
+
+ /*
+ * Register support for PROXY_MANAGEMENT.
+ */
+ if ((PMopcode = IceRegisterForProtocolSetup (
+ PM_PROTOCOL_NAME,
+ "The Open Group, Inc.", "1.0",
+ PMversionCount, PMversions,
+ 0, /* authcount */
+ NULL, /* authnames */
+ NULL, /* authprocs */
+ NULL /* IceIOErrorProc */ )) < 0)
+ {
+ strcpy (errorString,
+ "Could not register PROXY_MANAGEMENT protocol with ICE");
+ return 0;
+ }
+
+
+ if ((PM_iceConn = IceOpenConnection (
+ pmAddr, NULL, 0, 0, sizeof(iceError), iceError)) == NULL)
+ {
+ sprintf (errorString,
+ "Could not open ICE connection to proxy manager: %s", iceError);
+ return 0;
+ }
+
+ setupstat = IceProtocolSetup (PM_iceConn, PMopcode, NULL,
+ False /* mustAuthenticate */,
+ &majorVersion, &minorVersion,
+ &vendor, &release, ERROR_STRING_SIZE, errorString);
+
+ if (setupstat != IceProtocolSetupSuccess)
+ {
+ IceCloseConnection (PM_iceConn);
+ sprintf (errorString,
+ "Could not initialize proxy management protocol: %s",
+ iceError);
+ return 0;
+ }
+
+
+ /*
+ * Now send the StartProxy message.
+ */
+
+ len = STRING_BYTES ("LBX");
+
+ IceGetHeaderExtra (PM_iceConn, PMopcode, PM_StartProxy,
+ SIZEOF (pmStartProxyMsg), WORD64COUNT (len),
+ pmStartProxyMsg, pMsg, pData);
+
+ STORE_STRING (pData, "LBX");
+
+ IceFlush (PM_iceConn);
+
+ while (!gotFirstGetProxyAddr)
+ {
+ /* wait for a GetProxyAddr request before continuing... */
+ int status = IceProcessMessages( PM_iceConn, NULL, NULL );
+ if (status == IceProcessMessagesIOError)
+ {
+ fprintf( stderr, "IO error occured connecting to proxy manager");
+ return FALSE;
+ }
+ }
+
+ proxy_manager_fd = IceConnectionNumber (PM_iceConn);
+
+ ListenToProxyManager();
+
+ return 1;
+}
+
+
+void
+SendGetProxyAddrReply (
+ IceConn requestor_iceConn,
+ int status,
+ char *addr,
+ char *error)
+
+{
+ int len = STRING_BYTES (addr) + STRING_BYTES (error);
+ pmGetProxyAddrReplyMsg *pReply;
+ char *pData;
+
+ IceGetHeaderExtra (requestor_iceConn,
+ PMopcode, PM_GetProxyAddrReply,
+ SIZEOF (pmGetProxyAddrReplyMsg), WORD64COUNT (len),
+ pmGetProxyAddrReplyMsg, pReply, pData);
+
+ pReply->status = status;
+
+ STORE_STRING (pData, addr);
+ STORE_STRING (pData, error);
+
+ IceFlush (requestor_iceConn);
+}
+
+
+static int
+casecmp (str1, str2)
+ char *str1, *str2;
+{
+ char buf1[512],buf2[512];
+ char c, *s;
+ register int n;
+
+ for (n=0, s = buf1; (c = *str1++); n++) {
+ if (isupper(c))
+ c = tolower(c);
+ if (n>510)
+ break;
+ *s++ = c;
+ }
+ *s = '\0';
+ for (n=0, s = buf2; (c = *str2++); n++) {
+ if (isupper(c))
+ c = tolower(c);
+ if (n>510)
+ break;
+ *s++ = c;
+ }
+ *s = '\0';
+ return (strcmp(buf1, buf2));
+}
+
+
+/* ARGSUSED */
+static void
+PMprocessMessages (iceConn, clientData, opcode, length,
+ swap, replyWait, replyReadyRet)
+ IceConn iceConn;
+ IcePointer clientData;
+ int opcode;
+ unsigned long length;
+ Bool swap;
+ IceReplyWaitInfo *replyWait;
+ Bool *replyReadyRet;
+{
+ switch (opcode)
+ {
+ case PM_GetProxyAddr:
+ {
+ pmGetProxyAddrMsg *pMsg;
+ char *pData, *pStart;
+ char *serviceName = NULL, *serverAddress = NULL;
+ char *hostAddress = NULL, *startOptions = NULL;
+ char *authName = NULL, *authData = NULL;
+ int authLen;
+ char * colon;
+ char * tmpAddress = NULL;
+
+ CHECK_AT_LEAST_SIZE (iceConn, PMopcode, opcode,
+ length, SIZEOF (pmGetProxyAddrMsg), IceFatalToProtocol);
+
+ IceReadCompleteMessage (iceConn, SIZEOF (pmGetProxyAddrMsg),
+ pmGetProxyAddrMsg, pMsg, pStart);
+
+ if (!IceValidIO (iceConn))
+ {
+ IceDisposeCompleteMessage (iceConn, pStart);
+ return;
+ }
+
+ authLen = swap ? lswaps (pMsg->authLen) : pMsg->authLen;
+
+ pData = pStart;
+
+ SKIP_STRING (pData, swap); /* proxy-service */
+ SKIP_STRING (pData, swap); /* server-address */
+ SKIP_STRING (pData, swap); /* host-address */
+ SKIP_STRING (pData, swap); /* start-options */
+ if (authLen > 0)
+ {
+ SKIP_STRING (pData, swap); /* auth-name */
+ pData += (authLen + PAD64 (authLen)); /* auth-data */
+ }
+
+ CHECK_COMPLETE_SIZE (iceConn, PMopcode, opcode,
+ length, pData - pStart + SIZEOF (pmGetProxyAddrMsg),
+ pStart, IceFatalToProtocol);
+
+ pData = pStart;
+
+ EXTRACT_STRING (pData, swap, serviceName);
+ EXTRACT_STRING (pData, swap, serverAddress);
+ EXTRACT_STRING (pData, swap, hostAddress);
+ EXTRACT_STRING (pData, swap, startOptions);
+ if (authLen > 0)
+ {
+ EXTRACT_STRING (pData, swap, authName);
+ authData = (char *) malloc (authLen);
+ memcpy (authData, pData, authLen);
+ }
+
+ /*
+ * Convert the display name (serverAddress) into a FQDN
+ * to consolidate servers. So that for example, requests
+ * for displays foo:0, foo.bar:0 and foo.bar.com:0 will
+ * be set to the same server.
+ *
+ * If gethostbyname fails, try to connect anyhow because
+ * the display name could be something like :0, local:0
+ * or unix:0.
+ */
+ colon = strchr (serverAddress, ':');
+ if (colon)
+ {
+ struct hostent *hostent;
+
+ *colon = '\0';
+ hostent = gethostbyname (serverAddress);
+ *colon = ':';
+
+ if (hostent && hostent->h_name) {
+ tmpAddress = (char *) malloc (strlen (hostent->h_name) +
+ strlen (colon) + 1);
+ (void) sprintf (tmpAddress, "%s%s", hostent->h_name, colon);
+ serverAddress = tmpAddress;
+ }
+ }
+ display_name = serverAddress;
+
+ if (casecmp (serviceName, "LBX") != 0)
+ {
+ SendGetProxyAddrReply (iceConn, PM_Unable,
+ NULL, "Incorrect proxy service, should be LBX");
+ }
+ else
+ {
+ if (!gotFirstGetProxyAddr)
+ {
+ gotFirstGetProxyAddr = 1;
+ if (authLen > 0)
+ XSetAuthorization (authName, strlen (authName),
+ authData, authLen);
+ /*
+ * Connect to this server and send a GetProxyAddrReply msg.
+ */
+ if (!ConnectToServer (display_name)) {
+ char msg [100];
+
+ (void) sprintf (msg,
+ "could not connect to '%s'",
+ display_name);
+ FatalError(msg);
+ }
+ }
+ else
+ {
+ /*
+ * First check to see if a server for this serverAddress
+ * already exists.
+ */
+ int i;
+ int found = 0;
+
+ for (i=0; i < lbxMaxServers; i++)
+ {
+ if (servers[i] && servers[i]->display_name &&
+ casecmp (serverAddress, servers[i]->display_name) == 0)
+ {
+ SendGetProxyAddrReply (iceConn,
+ PM_Success,
+ servers[i]->proxy_name,
+ NULL);
+ found = 1;
+ break;
+ }
+ }
+ if (!found)
+ {
+ /*
+ * Go ahead and try to connect to the new server. If
+ * there is an error, the connection code will send
+ * a GetProxyAddrReply message.
+ */
+ if (authLen > 0)
+ XSetAuthorization (authName, strlen (authName),
+ authData, authLen);
+
+ (void) ConnectToServer (display_name);
+ }
+ }
+ }
+
+ IceDisposeCompleteMessage (iceConn, pStart);
+
+ if (serviceName)
+ free (serviceName);
+ if (hostAddress)
+ free (hostAddress);
+ if (startOptions)
+ free (startOptions);
+ if (authName)
+ free (authName);
+ if (authData)
+ free (authData);
+ if (tmpAddress)
+ free (tmpAddress);
+
+ break;
+ }
+
+ default:
+ {
+ _IceErrorBadMinor (iceConn, PMopcode, opcode, IceCanContinue);
+ _IceReadSkip (iceConn, length << 3);
+ break;
+ }
+ }
+}
+
+void
+HandleProxyManagerConnection ()
+{
+ /*
+ * If an IO error occurs, the IO error handler will output
+ * an error message.
+ */
+ (void) IceProcessMessages (PM_iceConn, NULL, NULL);
+}
diff --git a/di/props.c b/di/props.c
new file mode 100644
index 0000000..84dfc9d
--- /dev/null
+++ b/di/props.c
@@ -0,0 +1,410 @@
+/* $Xorg: props.c,v 1.4 2001/02/09 02:05:32 xorgcvs Exp $ */
+/*
+
+Copyright 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+*/
+/*
+ * Copyright 1994 Network Computing Devices, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name Network Computing Devices, Inc. not be
+ * used in advertising or publicity pertaining to distribution of this
+ * software without specific, written prior permission.
+ *
+ * THIS SOFTWARE IS PROVIDED `AS-IS'. NETWORK COMPUTING DEVICES, INC.,
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT
+ * LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, OR NONINFRINGEMENT. IN NO EVENT SHALL NETWORK
+ * COMPUTING DEVICES, INC., BE LIABLE FOR ANY DAMAGES WHATSOEVER, INCLUDING
+ * SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES, INCLUDING LOSS OF USE, DATA,
+ * OR PROFITS, EVEN IF ADVISED OF THE POSSIBILITY THEREOF, AND REGARDLESS OF
+ * WHETHER IN AN ACTION IN CONTRACT, TORT OR NEGLIGENCE, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+/*
+ * property handling
+ */
+
+
+#include <stdio.h>
+#include "misc.h"
+#include "assert.h"
+#include "lbx.h"
+#include "util.h"
+#include "tags.h"
+#include "resource.h"
+#include "wire.h"
+#include "swap.h"
+#include "proxyopts.h"
+#include "atomcache.h"
+
+static Bool GetLbxChangePropertyReply();
+static Bool GetLbxGetPropertyReply();
+
+/*
+ * wrapper for tags
+ *
+ * since this stuff has pointers, have to package it for
+ * tag cache
+ */
+static Bool
+propTagStoreData(server, tid, dlen, swapit, ptdp)
+ XServerPtr server;
+ XID tid;
+ unsigned long dlen;
+ Bool swapit;
+ PropertyTagDataPtr ptdp;
+{
+ PropertyTagDataPtr new;
+
+ new = (PropertyTagDataPtr) xalloc(dlen + sizeof(PropertyTagDataRec));
+ if (!new)
+ return FALSE;
+ *new = *ptdp;
+ new->data = (pointer) (new + 1);
+ memcpy((char *) new->data, (char *) ptdp->data, dlen);
+ /* save data in proxy format */
+ if (swapit) {
+ switch (new->format) {
+ case 32:
+ SwapLongs((CARD32 *) new->data, dlen >> 2);
+ break;
+ case 16:
+ SwapShorts((short *) new->data, dlen >> 1);
+ break;
+ }
+ }
+ return TagStoreDataNC(server, server->prop_cache, tid,
+ (dlen + sizeof(PropertyTagDataRec)),
+ LbxTagTypeProperty, new);
+}
+
+/*
+ * lots of brains need to live here. this decides whether or not
+ * to use an LbxChangeProperty
+ *
+ * some possible heuristics:
+ *
+ * - don't rewrite if it's small -- roundtrip swamps bandwidth
+ * - don't rewrite if it's a WM property and the WM isn't sharing
+ * the proxy
+ * - don't rewrite if the prop is on a non-root window owned by
+ * a non-proxy client
+ *
+ * - do rewrite if it's a prop on one of the client's windows
+ * - do rewrite if it's a Selection property (hope is that
+ * receiver is also using proxy)
+ */
+/*ARGSUSED*/
+static Bool
+rewrite_change_prop(client, win, property, type, format, mode, nUnits)
+ ClientPtr client;
+ Window win;
+ Atom property;
+ Atom type;
+ int format;
+ int mode;
+ unsigned long nUnits;
+{
+ unsigned flags;
+
+ /* if tags are turned off, don't try */
+ if (!client || !client->server)
+ return FALSE;
+ if (!client->server->lbxNegOpt.useTags)
+ return FALSE;
+ /* we aren't nearly clever enough to know what data we have */
+ if (mode != PropModeReplace)
+ return FALSE;
+ if ((nUnits * (format >> 3)) < min_keep_prop_size)
+ return FALSE;
+ flags = FlagsForAtom(client->server, property);
+ if (flags & AtomNoCacheFlag)
+ return FALSE;
+ if ((flags & AtomWMCacheFlag) && !client->server->wm_running)
+ return FALSE;
+ return TRUE;
+}
+
+int
+ProcLBXChangeProperty(client)
+ ClientPtr client;
+{
+ REQUEST(xChangePropertyReq);
+ ReplyStuffPtr nr;
+ int size;
+ pointer datacopy;
+ char n;
+ Atom type, property;
+ Window win;
+ CARD32 nUnits;
+
+ win = stuff->window;
+ property = stuff->property;
+ type = stuff->type;
+ nUnits = stuff->nUnits;
+
+ if (client->swapped) {
+ swapl(&win, n);
+ swapl(&property, n);
+ swapl(&type, n);
+ swapl(&nUnits, n);
+ }
+
+ /* we may want to leave it as X_ChangeProperty */
+ if (!rewrite_change_prop(client, win, property, type,
+ stuff->format, stuff->mode, nUnits))
+ return ProcStandardRequest(client);
+
+ size = nUnits * (stuff->format >> 3);
+ datacopy = (pointer) xalloc(size);
+ if (!datacopy)
+ return ProcStandardRequest(client);
+ memcpy((char *) datacopy, (char *) &stuff[1], size);
+
+ nr = NewReply(client, client->server->lbxReq, X_LbxChangeProperty,
+ GetLbxChangePropertyReply);
+ if (!nr) {
+ xfree(datacopy);
+ return ProcStandardRequest(client);
+ }
+ nr->request_info.lbxchangeprop.ptd.length = size;
+ nr->request_info.lbxchangeprop.ptd.type = type;
+ nr->request_info.lbxchangeprop.ptd.format = stuff->format;
+ nr->request_info.lbxchangeprop.ptd.data = datacopy;
+
+ FinishLBXRequest(client, REQ_REPLACELATE);
+ SendChangeProperty(client, win, property, type,
+ stuff->format, stuff->mode, nUnits);
+ return Success;
+}
+
+static Bool
+GetLbxChangePropertyReply(client, nr, data)
+ ClientPtr client;
+ ReplyStuffPtr nr;
+ char *data;
+{
+ xLbxChangePropertyReply *rep;
+ PropertyTagDataPtr ptdp;
+ char n;
+ CARD32 tag;
+
+ rep = (xLbxChangePropertyReply *) data;
+ tag = rep->tag;
+ if (client->swapped) {
+ swapl(&tag, n);
+ }
+
+ ptdp = &nr->request_info.lbxchangeprop.ptd;
+ if (tag) {
+ if (!propTagStoreData(client->server, tag, (unsigned long)ptdp->length,
+ client->swapped, ptdp)) {
+ if (client->swapped) {
+ switch (ptdp->format) {
+ case 32:
+ SwapLongs((CARD32 *) ptdp->data, ptdp->length >> 2);
+ break;
+ case 16:
+ SwapShorts((short *) ptdp->data, ptdp->length >> 1);
+ break;
+ }
+ }
+ SendTagData(client, tag, ptdp->length, ptdp->data);
+ SendInvalidateTag(client, tag);
+ WriteError(client, X_ChangeProperty, 0, 0, BadAlloc);
+ }
+ }
+ xfree(ptdp->data); /* propStore gets its own copy */
+ return TRUE;
+}
+
+int
+ProcLBXGetProperty(client)
+ ClientPtr client;
+{
+ REQUEST(xGetPropertyReq);
+ ReplyStuffPtr nr;
+
+ nr = NewReply(client, client->server->lbxReq, X_LbxGetProperty,
+ GetLbxGetPropertyReply);
+ if (!nr)
+ return ProcStandardRequest(client);
+
+ if (client->swapped) {
+ char n;
+
+ swapl(&stuff->window, n);
+ swapl(&stuff->property, n);
+ swapl(&stuff->type, n);
+ swapl(&stuff->longOffset, n);
+ swapl(&stuff->longLength, n);
+ }
+ nr->request_info.lbxgetprop.offset = stuff->longOffset;
+ nr->request_info.lbxgetprop.length = stuff->longLength;
+
+ FinishLBXRequest(client, REQ_PASSTHROUGH);
+
+ SendGetProperty(client, stuff->window, stuff->property, stuff->type,
+ stuff->delete, stuff->longOffset, stuff->longLength);
+ return Success;
+}
+
+static Bool
+GetLbxGetPropertyReply(client, nr, data)
+ ClientPtr client;
+ ReplyStuffPtr nr;
+ char *data;
+{
+ xLbxGetPropertyReply *rep;
+ unsigned long len;
+ PropertyTagDataRec ptd;
+ PropertyTagDataPtr ptdp;
+ pointer pdata = NULL;
+ char *sdata;
+ char n;
+ xGetPropertyReply reply;
+ CARD32 tag, nItems, type, bytesAfter;
+
+ rep = (xLbxGetPropertyReply *) data;
+
+ tag = rep->tag;
+ nItems = rep->nItems;
+ type = rep->propertyType;
+ bytesAfter = rep->bytesAfter;
+ if (client->swapped) {
+ swapl(&tag, n);
+ swapl(&nItems, n);
+ swapl(&type, n);
+ swapl(&bytesAfter, n);
+ }
+ ptd.type = type;
+ ptd.format = rep->format;
+ ptd.data = NULL;
+ len = rep->length << 2;
+ if (len)
+ ptd.length = nItems * (rep->format >> 3);
+ else
+ ptd.length = 0;
+ ptdp = &ptd;
+
+ if (tag) {
+ if (len) { /* first time, set tag */
+
+#ifdef LBX_STATS
+ getprop_full++;
+#endif
+
+ ptd.data = (pointer) &rep[1];
+ if (!propTagStoreData(client->server, tag, len, client->swapped,
+ &ptd)) {
+ /* tell server we lost it */
+ SendInvalidateTag(client, tag);
+ }
+ } else {
+
+ ptdp = (PropertyTagDataPtr) TagGetData(client->server,
+ client->server->prop_cache, tag);
+
+ if (!ptdp) {
+ fprintf(stderr, "no data for property tag 0x%x\n", tag);
+ WriteError(client, X_GetProperty, 0, 0, BadAlloc);
+ return TRUE;
+ }
+ if (client->swapped && rep->format != 8) {
+ /*
+ * Make a copy, because we will need to swap the property data
+ * and we don't want to alter the tag database.
+ */
+ pdata = (pointer) ALLOCATE_LOCAL(ptdp->length);
+ memcpy((char *) pdata, (char *) ptdp->data, ptdp->length);
+ switch (rep->format) {
+ case 32:
+ SwapLongs((CARD32 *) pdata, ptdp->length >> 2);
+ break;
+ case 16:
+ SwapShorts((short *) pdata, ptdp->length >> 1);
+ break;
+ }
+ }
+
+#ifdef LBX_STATS
+ getprop_tag++;
+ tag_bytes_unsent += ptdp->length;
+#endif
+
+ }
+ } else if (len) {
+
+#ifdef LBX_STATS
+ getprop_full++;
+#endif
+
+ /*
+ * server didn't send us a tag -- either can't store it or no prop
+ * data
+ */
+ ptd.data = (pointer) &rep[1];
+ }
+
+ if (pdata)
+ sdata = pdata;
+ else
+ sdata = ptdp->data;
+ if (rep->tag) {
+ len = ptdp->length;
+ reply.bytesAfter = bytesAfter;
+ } else {
+ len = ptdp->length - (nr->request_info.lbxgetprop.offset << 2);
+ len = min(len, nr->request_info.lbxgetprop.length << 2);
+ reply.bytesAfter = (ptdp->length -
+ (len + (nr->request_info.lbxgetprop.offset << 2)));
+ sdata = sdata + (nr->request_info.lbxgetprop.offset << 2);
+ }
+
+ reply.type = X_Reply;
+ reply.sequenceNumber = rep->sequenceNumber;
+ reply.format = ptdp->format;
+ reply.length = (len + 3) >> 2;
+ reply.propertyType = ptdp->type;
+ if (len)
+ reply.nItems = len / (ptdp->format >> 3);
+ else
+ reply.nItems = 0;
+
+ if (client->swapped)
+ SwapGetPropertyReply(&reply);
+ WriteToClient(client, sizeof(xGetPropertyReply), (char *) &reply);
+ if (len)
+ WriteToClient(client, len, sdata);
+
+ if (pdata)
+ DEALLOCATE_LOCAL(pdata);
+
+ return TRUE;
+}
diff --git a/di/reqtype.c b/di/reqtype.c
new file mode 100644
index 0000000..b6a779c
--- /dev/null
+++ b/di/reqtype.c
@@ -0,0 +1,312 @@
+/* $Xorg: reqtype.c,v 1.3 2000/08/17 19:53:56 cpqbld Exp $ */
+/*
+ * Copyright 1994 Network Computing Devices, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name Network Computing Devices, Inc. not be
+ * used in advertising or publicity pertaining to distribution of this
+ * software without specific, written prior permission.
+ *
+ * THIS SOFTWARE IS PROVIDED `AS-IS'. NETWORK COMPUTING DEVICES, INC.,
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT
+ * LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, OR NONINFRINGEMENT. IN NO EVENT SHALL NETWORK
+ * COMPUTING DEVICES, INC., BE LIABLE FOR ANY DAMAGES WHATSOEVER, INCLUDING
+ * SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES, INCLUDING LOSS OF USE, DATA,
+ * OR PROFITS, EVEN IF ADVISED OF THE POSSIBILITY THEREOF, AND REGARDLESS OF
+ * WHETHER IN AN ACTION IN CONTRACT, TORT OR NEGLIGENCE, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+/* decides what tupe of request it is */
+#include "misc.h"
+#include "os.h" /* in server/include */
+#include "reqtype.h"
+#include "lbxext.h"
+
+static char cause_replies[] = {
+ FALSE, /* BadRequest */
+ FALSE, /* CreateWindow */
+ FALSE, /* ChangeWindowAttributes */
+ TRUE, /* GetWindowAttributes */
+ FALSE, /* DestroyWindow */
+ FALSE, /* DestroySubwindows */
+ FALSE, /* ChangeSaveSet */
+ FALSE, /* ReparentWindow */
+ FALSE, /* MapWindow */
+ FALSE, /* MapSubwindows */
+ FALSE, /* UnmapWindow */
+ FALSE, /* UnmapSubwindows */
+ FALSE, /* ConfigureWindow */
+ FALSE, /* CirculateWindow */
+ TRUE, /* GetGeometry */
+ TRUE, /* QueryTree */
+ TRUE, /* InternAtom */
+ TRUE, /* GetAtomName */
+ FALSE, /* ChangeProperty */
+ FALSE, /* DeleteProperty */
+ TRUE, /* GetProperty */
+ TRUE, /* ListProperties */
+ FALSE, /* SetSelectionOwner */
+ TRUE, /* GetSelectionOwner */
+ FALSE, /* ConvertSelection */
+ FALSE, /* SendEvent */
+ TRUE, /* GrabPointer */
+ FALSE, /* UngrabPointer */
+ FALSE, /* GrabButton */
+ FALSE, /* UngrabButton */
+ FALSE, /* ChangeActivePointerGrab */
+ TRUE, /* GrabKeyboard */
+ FALSE, /* UngrabKeyboard */
+ FALSE, /* GrabKey */
+ FALSE, /* UngrabKey */
+ FALSE, /* AllowEvents */
+ FALSE, /* GrabServer */
+ FALSE, /* UngrabServer */
+ TRUE, /* QueryPointer */
+ TRUE, /* GetMotionEvents */
+ TRUE, /* TranslateCoords */
+ FALSE, /* WarpPointer */
+ FALSE, /* SetInputFocus */
+ TRUE, /* GetInputFocus */
+ TRUE, /* QueryKeymap */
+ FALSE, /* OpenFont */
+ FALSE, /* CloseFont */
+ TRUE, /* QueryFont */
+ TRUE, /* QueryTextExtents */
+ TRUE, /* ListFonts */
+ TRUE, /* ListFontsWithInfo */
+ FALSE, /* SetFontPath */
+ TRUE, /* GetFontPath */
+ FALSE, /* CreatePixmap */
+ FALSE, /* FreePixmap */
+ FALSE, /* CreateGC */
+ FALSE, /* ChangeGC */
+ FALSE, /* CopyGC */
+ FALSE, /* SetDashes */
+ FALSE, /* SetClipRectangles */
+ FALSE, /* FreeGC */
+ FALSE, /* ClearToBackground */
+ FALSE, /* CopyArea */
+ FALSE, /* CopyPlane */
+ FALSE, /* PolyPoint */
+ FALSE, /* PolyLine */
+ FALSE, /* PolySegment */
+ FALSE, /* PolyRectangle */
+ FALSE, /* PolyArc */
+ FALSE, /* FillPoly */
+ FALSE, /* PolyFillRectangle */
+ FALSE, /* PolyFillArc */
+ FALSE, /* PutImage */
+ TRUE, /* GetImage */
+ FALSE, /* PolyText */
+ FALSE, /* PolyText */
+ FALSE, /* ImageText8 */
+ FALSE, /* ImageText16 */
+ FALSE, /* CreateColormap */
+ FALSE, /* FreeColormap */
+ FALSE, /* CopyColormapAndFree */
+ FALSE, /* InstallColormap */
+ FALSE, /* UninstallColormap */
+ TRUE, /* ListInstalledColormaps */
+ TRUE, /* AllocColor */
+ TRUE, /* AllocNamedColor */
+ TRUE, /* AllocColorCells */
+ TRUE, /* AllocColorPlanes */
+ FALSE, /* FreeColors */
+ FALSE, /* StoreColors */
+ FALSE, /* StoreNamedColor */
+ TRUE, /* QueryColors */
+ TRUE, /* LookupColor */
+ FALSE, /* CreateCursor */
+ FALSE, /* CreateGlyphCursor */
+ FALSE, /* FreeCursor */
+ FALSE, /* RecolorCursor */
+ TRUE, /* QueryBestSize */
+ TRUE, /* QueryExtension */
+ TRUE, /* ListExtensions */
+ FALSE, /* ChangeKeyboardMapping */
+ TRUE, /* GetKeyboardMapping */
+ FALSE, /* ChangeKeyboardControl */
+ TRUE, /* GetKeyboardControl */
+ FALSE, /* Bell */
+ FALSE, /* ChangePointerControl */
+ TRUE, /* GetPointerControl */
+ FALSE, /* SetScreenSaver */
+ TRUE, /* GetScreenSaver */
+ FALSE, /* ChangeHosts */
+ TRUE, /* ListHosts */
+ FALSE, /* ChangeAccessControl */
+ FALSE, /* ChangeCloseDownMode */
+ FALSE, /* KillClient */
+ FALSE, /* RotateProperties */
+ FALSE, /* ForceScreenSaver */
+ TRUE, /* SetPointerMapping */
+ TRUE, /* GetPointerMapping */
+ TRUE, /* SetModifierMapping */
+ TRUE, /* GetModifierMapping */
+ FALSE, /* BadRequest */
+ FALSE, /* BadRequest */
+ FALSE, /* BadRequest */
+ FALSE, /* BadRequest */
+ FALSE, /* BadRequest */
+ FALSE, /* BadRequest */
+ FALSE, /* BadRequest */
+ FALSE /* NoOp */
+};
+
+static char cause_events[] = {
+ FALSE, /* BadRequest */
+ TRUE, /* CreateWindow */
+ TRUE, /* ChangeWindowAttributes */
+ FALSE, /* GetWindowAttributes */
+ TRUE, /* DestroyWindow */
+ TRUE, /* DestroySubwindows */
+ FALSE, /* ChangeSaveSet */
+ TRUE, /* ReparentWindow */
+ TRUE, /* MapWindow */
+ TRUE, /* MapSubwindows */
+ TRUE, /* UnmapWindow */
+ TRUE, /* UnmapSubwindows */
+ TRUE, /* ConfigureWindow */
+ TRUE, /* CirculateWindow */
+ FALSE, /* GetGeometry */
+ FALSE, /* QueryTree */
+ FALSE, /* InternAtom */
+ FALSE, /* GetAtomName */
+ TRUE, /* ChangeProperty */
+ TRUE, /* DeleteProperty */
+ TRUE, /* GetProperty */
+ FALSE, /* ListProperties */
+ TRUE, /* SetSelectionOwner */
+ FALSE, /* GetSelectionOwner */
+ TRUE, /* ConvertSelection */
+ TRUE, /* SendEvent */
+ TRUE, /* GrabPointer */
+ TRUE, /* UngrabPointer */
+ FALSE, /* GrabButton */
+ FALSE, /* UngrabButton */
+ FALSE, /* ChangeActivePointerGrab */
+ TRUE, /* GrabKeyboard */
+ TRUE, /* UngrabKeyboard */
+ FALSE, /* GrabKey */
+ FALSE, /* UngrabKey */
+ TRUE, /* AllowEvents */
+ FALSE, /* GrabServer */
+ FALSE, /* UngrabServer */
+ FALSE, /* QueryPointer */
+ FALSE, /* GetMotionEvents */
+ FALSE, /* TranslateCoords */
+ TRUE, /* WarpPointer */
+ TRUE, /* SetInputFocus */
+ FALSE, /* GetInputFocus */
+ FALSE, /* QueryKeymap */
+ FALSE, /* OpenFont */
+ FALSE, /* CloseFont */
+ FALSE, /* QueryFont */
+ FALSE, /* QueryTextExtents */
+ FALSE, /* ListFonts */
+ FALSE, /* ListFontsWithInfo */
+ FALSE, /* SetFontPath */
+ FALSE, /* GetFontPath */
+ FALSE, /* CreatePixmap */
+ FALSE, /* FreePixmap */
+ FALSE, /* CreateGC */
+ FALSE, /* ChangeGC */
+ FALSE, /* CopyGC */
+ FALSE, /* SetDashes */
+ FALSE, /* SetClipRectangles */
+ FALSE, /* FreeGC */
+ TRUE, /* ClearToBackground */
+ TRUE, /* CopyArea */
+ TRUE, /* CopyPlane */
+ FALSE, /* PolyPoint */
+ FALSE, /* PolyLine */
+ FALSE, /* PolySegment */
+ FALSE, /* PolyRectangle */
+ FALSE, /* PolyArc */
+ FALSE, /* FillPoly */
+ FALSE, /* PolyFillRectangle */
+ FALSE, /* PolyFillArc */
+ FALSE, /* PutImage */
+ FALSE, /* GetImage */
+ FALSE, /* PolyText */
+ FALSE, /* PolyText */
+ FALSE, /* ImageText8 */
+ FALSE, /* ImageText16 */
+ FALSE, /* CreateColormap */
+ TRUE, /* FreeColormap */
+ FALSE, /* CopyColormapAndFree */
+ TRUE, /* InstallColormap */
+ TRUE, /* UninstallColormap */
+ FALSE, /* ListInstalledColormaps */
+ FALSE, /* AllocColor */
+ FALSE, /* AllocNamedColor */
+ FALSE, /* AllocColorCells */
+ FALSE, /* AllocColorPlanes */
+ FALSE, /* FreeColors */
+ FALSE, /* StoreColors */
+ FALSE, /* StoreNamedColor */
+ FALSE, /* QueryColors */
+ FALSE, /* LookupColor */
+ FALSE, /* CreateCursor */
+ FALSE, /* CreateGlyphCursor */
+ FALSE, /* FreeCursor */
+ FALSE, /* RecolorCursor */
+ FALSE, /* QueryBestSize */
+ FALSE, /* QueryExtension */
+ FALSE, /* ListExtensions */
+ TRUE, /* ChangeKeyboardMapping */
+ FALSE, /* GetKeyboardMapping */
+ FALSE, /* ChangeKeyboardControl */
+ FALSE, /* GetKeyboardControl */
+ FALSE, /* Bell */
+ FALSE, /* ChangePointerControl */
+ FALSE, /* GetPointerControl */
+ FALSE, /* SetScreenSaver */
+ FALSE, /* GetScreenSaver */
+ FALSE, /* ChangeHosts */
+ FALSE, /* ListHosts */
+ FALSE, /* ChangeAccessControl */
+ FALSE, /* ChangeCloseDownMode */
+ FALSE, /* KillClient */
+ TRUE, /* RotateProperties */
+ FALSE, /* ForceScreenSaver */
+ TRUE, /* SetPointerMapping */
+ FALSE, /* GetPointerMapping */
+ TRUE, /* SetModifierMapping */
+ FALSE, /* GetModifierMapping */
+ FALSE, /* BadRequest */
+ FALSE, /* BadRequest */
+ FALSE, /* BadRequest */
+ FALSE, /* BadRequest */
+ FALSE, /* BadRequest */
+ FALSE, /* BadRequest */
+ FALSE, /* BadRequest */
+ FALSE /* NoOp */
+};
+
+
+Bool
+GeneratesEvents(client, req)
+ ClientPtr client;
+ xReq *req;
+{
+ if (req->reqType > X_NoOperation)
+ return CheckExtensionForEvents(client, req);
+ return cause_events[req->reqType];
+}
+
+int
+GeneratesReplies(client, req)
+ ClientPtr client;
+ xReq *req;
+{
+ if (req->reqType > X_NoOperation)
+ return CheckExtensionForReplies(client, req);
+ return (int) cause_replies[req->reqType];
+}
diff --git a/di/resource.c b/di/resource.c
new file mode 100644
index 0000000..b928230
--- /dev/null
+++ b/di/resource.c
@@ -0,0 +1,480 @@
+/* $Xorg: resource.c,v 1.4 2000/08/17 19:53:56 cpqbld Exp $ */
+/*
+
+Copyright 1987, 1998 The Open Group
+
+All Rights Reserved.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+*/
+
+/************************************************************
+
+Copyright 1988, 1989 Network Computing Devices, Inc. All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+
+Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+********************************************************/
+
+
+#include <stdio.h>
+#include "misc.h"
+#include "os.h"
+#include "resource.h"
+#include "lbx.h"
+#include "colormap.h"
+#include "wire.h"
+
+static void RebuildTable();
+
+#define INITBUCKETS 64
+#define INITHASHSIZE 6
+#define MAXHASHSIZE 11
+
+#define NullResource ((ResourcePtr)NULL)
+
+#define TypeMask (RC_LASTPREDEF - 1)
+
+static DeleteType *DeleteFuncs = (DeleteType *)NULL;
+
+/*
+ * NOTE for LBX Multi Display
+ *
+ * The index field for each client in the global "clients" array
+ * represents that client's position in the "clients" array.
+ *
+ * Each server has its own clientTable array and the client's
+ * index in the "clients" array is identical to the client's
+ * index in its server's clientTable array. This facilitates
+ * the storage and retrieval of a client's resources.
+ */
+
+Bool
+InitDeleteFuncs()
+{
+ if (DeleteFuncs)
+ xfree(DeleteFuncs);
+ DeleteFuncs = (DeleteType *) xalloc((RT_LASTPREDEF + 1) *
+ sizeof(DeleteType));
+ if (!DeleteFuncs)
+ return FALSE;
+ DeleteFuncs[RT_COLORMAP & TypeMask] = DestroyColormap;
+ DeleteFuncs[RT_CMAPENTRY & TypeMask] = FreeClientPixels;
+ return TRUE;
+}
+
+/*****************
+ * InitClientResources
+ * When a new client is created, call this to allocate space
+ * in resource table
+ *****************/
+
+Bool
+InitClientResources(client)
+ ClientPtr client;
+{
+ register int i, j;
+
+ if (!client || !client->server)
+ /*
+ * This can occur during a reset
+ */
+ return TRUE;
+
+ client->server->clientTable[i = client->index].resources =
+ (ResourcePtr *)xalloc(INITBUCKETS*sizeof(ResourcePtr));
+ if (!client->server->clientTable[i].resources)
+ return FALSE;
+
+ client->server->clientTable[i].buckets = INITBUCKETS;
+ client->server->clientTable[i].elements = 0;
+ client->server->clientTable[i].hashsize = INITHASHSIZE;
+
+ for (j=0; j<INITBUCKETS; j++)
+ {
+ client->server->clientTable[i].resources[j] = NullResource;
+ }
+ return TRUE;
+}
+
+void
+FinishInitClientResources(client, ridBase, ridMask)
+ ClientPtr client;
+ XID ridBase, ridMask;
+{
+ client->ridBase = ridBase;
+ client->ridMask = ridMask;
+ client->server->clientTable[client->index].endFakeID =
+ (ridBase | ridMask) + 1;
+ client->server->clientTable[client->index].fakeID = ridBase | PROXY_BIT;
+}
+
+static int
+Hash(client, id)
+ int client;
+ register XID id;
+{
+ id &= clients[client]->ridMask;
+ switch (clients[client]->server->clientTable[client].hashsize)
+ {
+ case 6:
+ return ((int)(0x03F & (id ^ (id>>6) ^ (id>>12))));
+ case 7:
+ return ((int)(0x07F & (id ^ (id>>7) ^ (id>>13))));
+ case 8:
+ return ((int)(0x0FF & (id ^ (id>>8) ^ (id>>16))));
+ case 9:
+ return ((int)(0x1FF & (id ^ (id>>9))));
+ case 10:
+ return ((int)(0x3FF & (id ^ (id>>10))));
+ case 11:
+ return ((int)(0x7FF & (id ^ (id>>11))));
+ }
+ return -1;
+}
+
+static XID
+AvailableID(client, id, maxid, goodid)
+ register int client;
+ register XID id, maxid, goodid;
+{
+ register ResourcePtr res;
+
+ if ((goodid >= id) && (goodid <= maxid))
+ return goodid;
+ for (; id <= maxid; id++)
+ {
+ res = clients[client]->server->clientTable[client].resources[Hash(client, id)];
+ while (res && (res->id != id))
+ res = res->next;
+ if (!res)
+ return id;
+ }
+ return 0;
+}
+
+/*
+ * return the next usable fake client ID.
+ *
+ * normally this is just the next one in line, but if we've used the last
+ * in the range, we need to find a new range of safe IDs to avoid
+ * over-running another client.
+ */
+
+XID
+FakeClientID(client)
+ register int client; /* Index of a client for the global clients
+ * array and the server's clientTable */
+{
+ register XID id, maxid;
+ register ResourcePtr *resp;
+ register ResourcePtr res;
+ register int i;
+ XID goodid = 0;
+
+ id = clients[client]->server->clientTable[client].fakeID++;
+ if (id != clients[client]->server->clientTable[client].endFakeID)
+ return id;
+
+ id = clients[client]->ridBase | PROXY_BIT;
+ maxid = id | clients[client]->ridMask;
+
+ for (resp = clients[client]->server->clientTable[client].resources,
+ i = clients[client]->server->clientTable[client].buckets;
+ --i >= 0;)
+ {
+ for (res = *resp++; res; res = res->next)
+ {
+ if ((res->id < id) || (res->id > maxid))
+ continue;
+ if (((res->id - id) >= (maxid - res->id)) ?
+ (goodid = AvailableID(client, id, res->id - 1, goodid)) :
+ !(goodid = AvailableID(client, res->id + 1, maxid, goodid)))
+ maxid = res->id - 1;
+ else
+ id = res->id + 1;
+ }
+ }
+
+ clients[client]->server->clientTable[client].fakeID = id + 1;
+ clients[client]->server->clientTable[client].endFakeID = maxid + 1;
+
+ return id;
+}
+
+Bool
+AddResource(pclient, id, type, value)
+ ClientPtr pclient;
+ XID id;
+ RESTYPE type;
+ pointer value;
+{
+ int client;
+ register ClientResourceRec *rrec;
+ register ResourcePtr res, *head;
+
+ client = pclient->index;
+
+ rrec = &clients[client]->server->clientTable[client];
+ if (!rrec->buckets)
+ {
+ ErrorF("AddResource(%x, %x, %x), client=%d \n",
+ id, type, (unsigned long)value, client);
+ FatalError("client not in use\n");
+ }
+ if ((rrec->elements >= 4*rrec->buckets) &&
+ (rrec->hashsize < MAXHASHSIZE))
+ RebuildTable(client);
+ head = &rrec->resources[Hash(client, id)];
+ res = (ResourcePtr)xalloc(sizeof(ResourceRec));
+ if (!res)
+ {
+ (*DeleteFuncs[type & TypeMask])(pclient, value, id);
+ return FALSE;
+ }
+ res->next = *head;
+ res->id = id;
+ res->type = type;
+ res->value = value;
+ *head = res;
+ rrec->elements++;
+ return TRUE;
+}
+
+static void
+RebuildTable(client)
+ int client;
+{
+ register int j;
+ register ResourcePtr res, next;
+ ResourcePtr **tails, *resources;
+ register ResourcePtr **tptr, *rptr;
+
+ /*
+ * For now, preserve insertion order, since some ddx layers depend
+ * on resources being free in the opposite order they are added.
+ */
+
+ j = 2 * clients[client]->server->clientTable[client].buckets;
+ tails = (ResourcePtr **)ALLOCATE_LOCAL(j * sizeof(ResourcePtr *));
+ if (!tails)
+ return;
+ resources = (ResourcePtr *)xalloc(j * sizeof(ResourcePtr));
+ if (!resources)
+ {
+ DEALLOCATE_LOCAL(tails);
+ return;
+ }
+ for (rptr = resources, tptr = tails; --j >= 0; rptr++, tptr++)
+ {
+ *rptr = NullResource;
+ *tptr = rptr;
+ }
+ clients[client]->server->clientTable[client].hashsize++;
+ for (j = clients[client]->server->clientTable[client].buckets,
+ rptr = clients[client]->server->clientTable[client].resources;
+ --j >= 0;
+ rptr++)
+ {
+ for (res = *rptr; res; res = next)
+ {
+ next = res->next;
+ res->next = NullResource;
+ tptr = &tails[Hash(client, res->id)];
+ **tptr = res;
+ *tptr = &res->next;
+ }
+ }
+ DEALLOCATE_LOCAL(tails);
+ clients[client]->server->clientTable[client].buckets *= 2;
+ xfree(clients[client]->server->clientTable[client].resources);
+ clients[client]->server->clientTable[client].resources = resources;
+}
+
+void
+FreeResource(client, id, skipDeleteFuncType)
+ ClientPtr client;
+ XID id;
+ RESTYPE skipDeleteFuncType;
+{
+ int cid;
+ register ResourcePtr res;
+ register ResourcePtr *prev, *head;
+ register int *eltptr;
+ int elements;
+ Bool gotOne = FALSE;
+
+ cid = client->index;
+
+ if (clients[cid]->server->clientTable[cid].buckets)
+ {
+ head = &clients[cid]->server->clientTable[cid].resources[Hash(cid, id)];
+ eltptr = &clients[cid]->server->clientTable[cid].elements;
+
+ prev = head;
+ while ((res = *prev))
+ {
+ if (res->id == id)
+ {
+ RESTYPE rtype = res->type;
+ *prev = res->next;
+ elements = --*eltptr;
+ if (rtype != skipDeleteFuncType)
+ (*DeleteFuncs[rtype & TypeMask])(client, res->value, res->id);
+ xfree(res);
+ if (*eltptr != elements)
+ prev = head; /* prev may no longer be valid */
+ gotOne = TRUE;
+ }
+ else
+ prev = &res->next;
+ }
+ }
+ if (!gotOne)
+ FatalError("Freeing resource id=%X which isn't there", id);
+}
+
+void
+FreeClientResources(client)
+ ClientPtr client;
+{
+ register ResourcePtr *resources;
+ register ResourcePtr this;
+ int j;
+
+ /* This routine shouldn't be called with a null client, but just in
+ case ... */
+
+ if (!client)
+ return;
+
+ /*
+ * For a multi-display proxy, must not re-free the clientTable
+ * for a server.
+ */
+ if (!client->server)
+ return;
+
+ resources = client->server->clientTable[client->index].resources;
+ for (j=0; j < client->server->clientTable[client->index].buckets; j++)
+ {
+ /* It may seem silly to update the head of this resource list as
+ we delete the members, since the entire list will be deleted any way,
+ but there are some resource deletion functions "FreeClientPixels" for
+ one which do a LookupID on another resource id (a Colormap id in this
+ case), so the resource list must be kept valid up to the point that
+ it is deleted, so every time we delete a resource, we must update the
+ head, just like in FreeResource. I hope that this doesn't slow down
+ mass deletion appreciably. PRH */
+
+ ResourcePtr *head;
+
+ head = &resources[j];
+
+ for (this = *head; this; this = *head)
+ {
+ RESTYPE rtype = this->type;
+ *head = this->next;
+ (*DeleteFuncs[rtype & TypeMask])(client, this->value, this->id);
+ xfree(this);
+ }
+ }
+ xfree(client->server->clientTable[client->index].resources);
+ client->server->clientTable[client->index].buckets = 0;
+ if (client->server->lastLbxClientIndexLookup == client)
+ client->server->lastLbxClientIndexLookup = NULL;
+}
+
+void
+FreeAllResources()
+{
+ int j;
+
+ for (j = currentMaxClients; --j >= 0; )
+ {
+ if (clients[j]->server->clientTable[j].buckets)
+ FreeClientResources(clients[j]);
+ }
+}
+
+/*
+ * LookupIDByType returns the object with the given id and type, else NULL.
+ */
+pointer
+LookupIDByType(pclient, id, rtype)
+ ClientPtr pclient;
+ XID id;
+ RESTYPE rtype;
+{
+ register ResourcePtr res;
+ int i, j;
+ XServerPtr pserver = pclient->server;
+
+ for (i = 1; i < currentMaxClients; i++) {
+ if (pserver->clientTable[i].buckets) {
+ for (j = 0; j < INITBUCKETS; j++) {
+ if (pserver->clientTable[i].resources[j]) {
+ res = pserver->clientTable[i].resources[Hash(j, id)];
+ for (; res; res = res->next)
+ if ((res->id == id) && (res->type == rtype))
+ return res->value;
+ }
+ }
+ }
+ }
+
+ return (pointer)NULL;
+}
diff --git a/di/swaprep.c b/di/swaprep.c
new file mode 100644
index 0000000..c5fc372
--- /dev/null
+++ b/di/swaprep.c
@@ -0,0 +1,431 @@
+/* $Xorg: swaprep.c,v 1.4 2001/02/09 02:05:32 xorgcvs Exp $ */
+/*
+
+Copyright 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+*/
+/*
+ *
+ * Copyright 1994 Network Computing Devices, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name Network Computing Devices, Inc. not be
+ * used in advertising or publicity pertaining to distribution of this
+ * software without specific, written prior permission.
+ *
+ * THIS SOFTWARE IS PROVIDED `AS-IS'. NETWORK COMPUTING DEVICES, INC.,
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT
+ * LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, OR NONINFRINGEMENT. IN NO EVENT SHALL NETWORK
+ * COMPUTING DEVICES, INC., BE LIABLE FOR ANY DAMAGES WHATSOEVER, INCLUDING
+ * SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES, INCLUDING LOSS OF USE, DATA,
+ * OR PROFITS, EVEN IF ADVISED OF THE POSSIBILITY THEREOF, AND REGARDLESS OF
+ * WHETHER IN AN ACTION IN CONTRACT, TORT OR NEGLIGENCE, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include <stdio.h>
+#include "misc.h"
+#include "assert.h"
+#include "lbx.h"
+#include "swap.h"
+
+void
+SwapConnSetup(pConnSetup, pConnSetupT)
+ xConnSetup *pConnSetup,
+ *pConnSetupT;
+{
+ cpswapl(pConnSetup->release, pConnSetupT->release);
+ cpswapl(pConnSetup->ridBase, pConnSetupT->ridBase);
+ cpswapl(pConnSetup->ridMask, pConnSetupT->ridMask);
+ cpswapl(pConnSetup->motionBufferSize, pConnSetupT->motionBufferSize);
+ cpswaps(pConnSetup->nbytesVendor, pConnSetupT->nbytesVendor);
+ cpswaps(pConnSetup->maxRequestSize, pConnSetupT->maxRequestSize);
+ pConnSetupT->minKeyCode = pConnSetup->minKeyCode;
+ pConnSetupT->maxKeyCode = pConnSetup->maxKeyCode;
+ pConnSetupT->numRoots = pConnSetup->numRoots;
+ pConnSetupT->numFormats = pConnSetup->numFormats;
+ pConnSetupT->imageByteOrder = pConnSetup->imageByteOrder;
+ pConnSetupT->bitmapBitOrder = pConnSetup->bitmapBitOrder;
+ pConnSetupT->bitmapScanlineUnit = pConnSetup->bitmapScanlineUnit;
+ pConnSetupT->bitmapScanlinePad = pConnSetup->bitmapScanlinePad;
+}
+
+void
+SwapWinRoot(pRoot, pRootT)
+ xWindowRoot *pRoot,
+ *pRootT;
+{
+ cpswapl(pRoot->windowId, pRootT->windowId);
+ cpswapl(pRoot->defaultColormap, pRootT->defaultColormap);
+ cpswapl(pRoot->whitePixel, pRootT->whitePixel);
+ cpswapl(pRoot->blackPixel, pRootT->blackPixel);
+ cpswapl(pRoot->currentInputMask, pRootT->currentInputMask);
+ cpswaps(pRoot->pixWidth, pRootT->pixWidth);
+ cpswaps(pRoot->pixHeight, pRootT->pixHeight);
+ cpswaps(pRoot->mmWidth, pRootT->mmWidth);
+ cpswaps(pRoot->mmHeight, pRootT->mmHeight);
+ cpswaps(pRoot->minInstalledMaps, pRootT->minInstalledMaps);
+ cpswaps(pRoot->maxInstalledMaps, pRootT->maxInstalledMaps);
+ cpswapl(pRoot->rootVisualID, pRootT->rootVisualID);
+ pRootT->backingStore = pRoot->backingStore;
+ pRootT->saveUnders = pRoot->saveUnders;
+ pRootT->rootDepth = pRoot->rootDepth;
+ pRootT->nDepths = pRoot->nDepths;
+}
+
+void
+SwapVisual(pVis, pVisT)
+ xVisualType *pVis,
+ *pVisT;
+{
+ cpswapl(pVis->visualID, pVisT->visualID);
+ pVisT->class = pVis->class;
+ pVisT->bitsPerRGB = pVis->bitsPerRGB;
+ cpswaps(pVis->colormapEntries, pVisT->colormapEntries);
+ cpswapl(pVis->redMask, pVisT->redMask);
+ cpswapl(pVis->greenMask, pVisT->greenMask);
+ cpswapl(pVis->blueMask, pVisT->blueMask);
+}
+
+void
+WriteSConnSetupPrefix(pClient, pcsp)
+ ClientPtr pClient;
+ xConnSetupPrefix *pcsp;
+{
+ xConnSetupPrefix cspT;
+
+ cspT.success = pcsp->success;
+ cspT.lengthReason = pcsp->lengthReason;
+ cpswaps(pcsp->majorVersion, cspT.majorVersion);
+ cpswaps(pcsp->minorVersion, cspT.minorVersion);
+ cpswaps(pcsp->length, cspT.length);
+ (void)WriteToClient(pClient, sizeof(cspT), (char *) &cspT);
+}
+
+void
+WriteSConnectionInfo(pClient, size, pInfo)
+ ClientPtr pClient;
+ unsigned long size;
+ char *pInfo;
+{
+ int i,
+ j,
+ k;
+ xDepth *pDepth;
+ int numDepths;
+ char *pInfoT,
+ *pInfoTBase;
+ xConnSetup *pConnSetup = (xConnSetup *) pInfo;
+
+ pInfoT = pInfoTBase = (char *) ALLOCATE_LOCAL(size);
+ if (!pInfoTBase) {
+ pClient->noClientException = -1;
+ return;
+ }
+ SwapConnSetup(pConnSetup, (xConnSetup *) pInfoT);
+ pInfo += sizeof(xConnSetup);
+ pInfoT += sizeof(xConnSetup);
+
+ /* Copy the vendor string */
+ i = (pConnSetup->nbytesVendor + 3) & ~3;
+ memmove(pInfoT, pInfo, i);
+ pInfo += i;
+ pInfoT += i;
+
+ /* The Pixmap formats don't need to be swapped, just copied. */
+ i = sizeof(xPixmapFormat) * pConnSetup->numFormats;
+ memmove(pInfoT, pInfo, i);
+ pInfo += i;
+ pInfoT += i;
+
+ for (i = 0; i < pConnSetup->numRoots; i++) {
+ SwapWinRoot((xWindowRoot *) pInfo, (xWindowRoot *) pInfoT);
+ numDepths = ((xWindowRoot *) pInfo)->nDepths;
+ pInfo += sizeof(xWindowRoot);
+ pInfoT += sizeof(xWindowRoot);
+ pDepth = (xDepth *) pInfo;
+ for (j = 0; j < numDepths; j++, pDepth = (xDepth *) pInfo) {
+ ((xDepth *) pInfoT)->depth = ((xDepth *) pInfo)->depth;
+ cpswaps(((xDepth *) pInfo)->nVisuals, ((xDepth *) pInfoT)->nVisuals);
+ pInfo += sizeof(xDepth);
+ pInfoT += sizeof(xDepth);
+ for (k = 0; k < pDepth->nVisuals; k++) {
+ SwapVisual((xVisualType *) pInfo, (xVisualType *) pInfoT);
+ pInfo += sizeof(xVisualType);
+ pInfoT += sizeof(xVisualType);
+ }
+ }
+ }
+ (void) WriteToClient(pClient, (int) size, (char *) pInfoTBase);
+ DEALLOCATE_LOCAL(pInfoTBase);
+}
+
+void
+SwapGetPropertyReply(rep)
+ xGetPropertyReply *rep;
+{
+ char n;
+
+ swaps(&rep->sequenceNumber, n);
+ swapl(&rep->length, n);
+ swapl(&rep->propertyType, n);
+ swapl(&rep->bytesAfter, n);
+ swapl(&rep->nItems, n);
+}
+
+void
+SwapInternAtomReply(rep)
+ xInternAtomReply *rep;
+{
+ char n;
+
+ swaps(&rep->sequenceNumber, n);
+ swapl(&rep->length, n);
+ swapl(&rep->atom, n);
+}
+
+void
+SwapGetAtomNameReply(rep)
+ xGetAtomNameReply *rep;
+{
+ char n;
+
+ swaps(&rep->sequenceNumber, n);
+ swapl(&rep->length, n);
+ swaps(&rep->nameLength, n);
+}
+
+void
+SwapLookupColorReply(rep)
+ xLookupColorReply *rep;
+{
+ char n;
+
+ swaps(&rep->sequenceNumber, n);
+ swapl(&rep->length, n);
+ swaps(&rep->exactRed, n);
+ swaps(&rep->exactGreen, n);
+ swaps(&rep->exactBlue, n);
+ swaps(&rep->screenRed, n);
+ swaps(&rep->screenGreen, n);
+ swaps(&rep->screenBlue, n);
+}
+
+void
+SwapAllocColorReply(rep)
+ xAllocColorReply *rep;
+{
+ char n;
+
+ swaps(&rep->sequenceNumber, n);
+ swapl(&rep->length, n);
+ swaps(&rep->red, n);
+ swaps(&rep->green, n);
+ swaps(&rep->blue, n);
+ swapl(&rep->pixel, n);
+}
+
+void
+SwapAllocNamedColorReply(rep)
+ xAllocNamedColorReply *rep;
+{
+ char n;
+
+ swaps(&rep->sequenceNumber, n);
+ swapl(&rep->length, n);
+ swaps(&rep->exactRed, n);
+ swaps(&rep->exactGreen, n);
+ swaps(&rep->exactBlue, n);
+ swaps(&rep->screenRed, n);
+ swaps(&rep->screenGreen, n);
+ swaps(&rep->screenBlue, n);
+ swapl(&rep->pixel, n);
+}
+
+void
+SwapModmapReply(rep)
+ xGetModifierMappingReply *rep;
+{
+ char n;
+
+ swaps(&rep->sequenceNumber, n);
+ swapl(&rep->length, n);
+}
+
+void
+SwapKeymapReply(rep)
+ xGetKeyboardMappingReply *rep;
+{
+ char n;
+
+ swaps(&rep->sequenceNumber, n);
+ swapl(&rep->length, n);
+}
+
+void
+SwapGetImageReply(rep)
+ xGetImageReply *rep;
+{
+ char n;
+
+ swaps(&rep->sequenceNumber, n);
+ swapl(&rep->length, n);
+ swapl(&rep->visual, n);
+}
+
+void
+SwapQueryExtensionReply(rep)
+ xQueryExtensionReply *rep;
+{
+ char n;
+
+ swaps(&rep->sequenceNumber, n);
+ swapl(&rep->length, n);
+}
+
+static void
+SwapCharInfo(pInfo)
+ xCharInfo *pInfo;
+{
+ register char n;
+
+ swaps(&pInfo->leftSideBearing, n);
+ swaps(&pInfo->rightSideBearing, n);
+ swaps(&pInfo->characterWidth, n);
+ swaps(&pInfo->ascent, n);
+ swaps(&pInfo->descent, n);
+ swaps(&pInfo->attributes, n);
+}
+
+static void
+SwapFontInfo(pr)
+ xQueryFontReply *pr;
+{
+ register char n;
+
+ swaps(&pr->minCharOrByte2, n);
+ swaps(&pr->maxCharOrByte2, n);
+ swaps(&pr->defaultChar, n);
+ swaps(&pr->nFontProps, n);
+ swaps(&pr->fontAscent, n);
+ swaps(&pr->fontDescent, n);
+ SwapCharInfo(&pr->minBounds);
+ SwapCharInfo(&pr->maxBounds);
+ swapl(&pr->nCharInfos, n);
+}
+
+static void
+SwapLbxFontInfo(pr)
+ xLbxFontInfo *pr;
+{
+ register char n;
+
+ swaps(&pr->minCharOrByte2, n);
+ swaps(&pr->maxCharOrByte2, n);
+ swaps(&pr->defaultChar, n);
+ swaps(&pr->nFontProps, n);
+ swaps(&pr->fontAscent, n);
+ swaps(&pr->fontDescent, n);
+ SwapCharInfo(&pr->minBounds);
+ SwapCharInfo(&pr->maxBounds);
+ swapl(&pr->nCharInfos, n);
+}
+
+/* native flag specifies whether its usable and we're trying
+ * to swap it for external use
+ */
+void
+SwapFont(pr, native)
+ xQueryFontReply *pr;
+ Bool native;
+{
+ unsigned i;
+ xCharInfo *pxci;
+ unsigned nchars,
+ nprops;
+ char *pby;
+ register char n;
+
+ swaps(&pr->sequenceNumber, n);
+ swapl(&pr->length, n);
+ if (!native)
+ SwapFontInfo(pr);
+ nchars = pr->nCharInfos;
+ nprops = pr->nFontProps;
+ if (native)
+ SwapFontInfo(pr);
+ pby = (char *) &pr[1];
+ /*
+ * Font properties are an atom and either an int32 or a CARD32, so they
+ * are always 2 4 byte values
+ */
+ for (i = 0; i < nprops; i++) {
+ swapl(pby, n);
+ pby += 4;
+ swapl(pby, n);
+ pby += 4;
+ }
+ pxci = (xCharInfo *) pby;
+ for (i = 0; i < nchars; i++, pxci++)
+ SwapCharInfo(pxci);
+}
+
+void
+LbxSwapFontInfo(pr, compressed)
+ xLbxFontInfo *pr;
+ Bool compressed;
+{
+ unsigned i;
+ xCharInfo *pxci;
+ unsigned nchars,
+ nprops;
+ char *pby;
+ register char n;
+
+ SwapLbxFontInfo(pr);
+ nchars = pr->nCharInfos;
+ nprops = pr->nFontProps;
+ pby = (char *) &pr[1];
+ /*
+ * Font properties are an atom and either an int32 or a CARD32, so they
+ * are always 2 4 byte values
+ */
+ for (i = 0; i < nprops; i++) {
+ swapl(pby, n);
+ pby += 4;
+ swapl(pby, n);
+ pby += 4;
+ }
+ pxci = (xCharInfo *) pby;
+ if (!compressed) {
+ for (i = 0; i < nchars; i++, pxci++)
+ SwapCharInfo(pxci);
+ } else {
+ SwapLongs((CARD32 *) pxci, nchars);
+ }
+}
diff --git a/di/swapreq.c b/di/swapreq.c
new file mode 100644
index 0000000..ab35a7b
--- /dev/null
+++ b/di/swapreq.c
@@ -0,0 +1,327 @@
+/* $Xorg: swapreq.c,v 1.4 2001/02/09 02:05:32 xorgcvs Exp $ */
+/*
+
+Copyright 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+*/
+/*
+ *
+ * Copyright 1994 Network Computing Devices, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name Network Computing Devices, Inc. not be
+ * used in advertising or publicity pertaining to distribution of this
+ * software without specific, written prior permission.
+ *
+ * THIS SOFTWARE IS PROVIDED `AS-IS'. NETWORK COMPUTING DEVICES, INC.,
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT
+ * LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, OR NONINFRINGEMENT. IN NO EVENT SHALL NETWORK
+ * COMPUTING DEVICES, INC., BE LIABLE FOR ANY DAMAGES WHATSOEVER, INCLUDING
+ * SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES, INCLUDING LOSS OF USE, DATA,
+ * OR PROFITS, EVEN IF ADVISED OF THE POSSIBILITY THEREOF, AND REGARDLESS OF
+ * WHETHER IN AN ACTION IN CONTRACT, TORT OR NEGLIGENCE, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include <stdio.h>
+#include "misc.h"
+#include "assert.h"
+#include "lbx.h"
+#include "swap.h"
+
+/* Byte swap a list of longs */
+void
+SwapLongs(list, count)
+ register CARD32 *list;
+ register unsigned long count;
+{
+ register char n;
+
+ while (count >= 8) {
+ swapl(list + 0, n);
+ swapl(list + 1, n);
+ swapl(list + 2, n);
+ swapl(list + 3, n);
+ swapl(list + 4, n);
+ swapl(list + 5, n);
+ swapl(list + 6, n);
+ swapl(list + 7, n);
+ list += 8;
+ count -= 8;
+ }
+ if (count != 0) {
+ do {
+ swapl(list, n);
+ list++;
+ } while (--count != 0);
+ }
+}
+
+/* Byte swap a list of shorts */
+void
+SwapShorts(list, count)
+ register short *list;
+ register unsigned long count;
+{
+ register char n;
+
+ while (count >= 16) {
+ swaps(list + 0, n);
+ swaps(list + 1, n);
+ swaps(list + 2, n);
+ swaps(list + 3, n);
+ swaps(list + 4, n);
+ swaps(list + 5, n);
+ swaps(list + 6, n);
+ swaps(list + 7, n);
+ swaps(list + 8, n);
+ swaps(list + 9, n);
+ swaps(list + 10, n);
+ swaps(list + 11, n);
+ swaps(list + 12, n);
+ swaps(list + 13, n);
+ swaps(list + 14, n);
+ swaps(list + 15, n);
+ list += 16;
+ count -= 16;
+ }
+ if (count != 0) {
+ do {
+ swaps(list, n);
+ list++;
+ } while (--count != 0);
+ }
+}
+
+void
+SwapConnClientPrefix(pCCP)
+ xConnClientPrefix *pCCP;
+{
+ register char n;
+
+ swaps(&pCCP->majorVersion, n);
+ swaps(&pCCP->minorVersion, n);
+ swaps(&pCCP->nbytesAuthProto, n);
+ swaps(&pCCP->nbytesAuthString, n);
+}
+
+void
+SwapNewClient(r)
+ xLbxNewClientReq *r;
+{
+ char n;
+
+ swapl(&r->client, n);
+}
+
+void
+SwapCloseClient(r)
+ xLbxCloseClientReq *r;
+{
+ char n;
+
+ swapl(&r->client, n);
+}
+
+void
+SwapModifySequence(r)
+ xLbxModifySequenceReq *r;
+{
+ char n;
+
+ swapl(&r->adjust, n);
+}
+
+void
+SwapIncrementPixel(r)
+ xLbxIncrementPixelReq *r;
+{
+ char n;
+
+ swapl(&r->cmap, n);
+ swapl(&r->pixel, n);
+}
+
+/* ARGSUSED */
+void
+SwapGetModifierMapping(r)
+ xLbxGetModifierMappingReq *r;
+{
+}
+
+/* ARGSUSED */
+void
+SwapGetKeyboardMapping(r)
+ xLbxGetKeyboardMappingReq *r;
+{
+}
+
+void
+SwapQueryFont(r)
+ xLbxQueryFontReq *r;
+{
+ char n;
+
+ swapl(&r->fid, n);
+}
+
+void
+SwapChangeProperty(r)
+ xLbxChangePropertyReq *r;
+{
+ char n;
+
+ swapl(&r->window, n);
+ swapl(&r->property, n);
+ swapl(&r->type, n);
+ swapl(&r->nUnits, n);
+}
+
+void
+SwapGetProperty(r)
+ xLbxGetPropertyReq *r;
+{
+ char n;
+
+ swapl(&r->window, n);
+ swapl(&r->property, n);
+ swapl(&r->type, n);
+ swapl(&r->longOffset, n);
+ swapl(&r->longLength, n);
+}
+
+void
+SwapGetImage (r)
+ xLbxGetImageReq *r;
+{
+ char n;
+
+ swapl(&r->drawable, n);
+ swaps(&r->x, n);
+ swaps(&r->y, n);
+ swaps(&r->width, n);
+ swaps(&r->height, n);
+ swapl(&r->planeMask, n);
+}
+
+
+void
+SwapInternAtoms(r)
+ xLbxInternAtomsReq *r;
+{
+ char n;
+ char *ptr;
+ char lenbuf[2];
+ CARD16 len;
+ int i;
+
+ ptr = (char *) r + sz_xLbxInternAtomsReq;
+ for (i = 0; i < r->num; i++)
+ {
+ lenbuf[0] = ptr[0];
+ lenbuf[1] = ptr[1];
+ len = *((CARD16 *) lenbuf);
+ swaps (ptr, n);
+ ptr += (len + 2);
+ }
+
+ swaps(&r->num, n);
+}
+
+
+void
+SwapInvalidateTag(r)
+ xLbxInvalidateTagReq *r;
+{
+ char n;
+
+ swapl(&r->tag, n);
+}
+
+void
+SwapTagData(r)
+ xLbxTagDataReq *r;
+{
+ char n;
+
+ swapl(&r->real_length, n);
+ swapl(&r->tag, n);
+}
+
+void
+SwapQueryExtension(r)
+ xLbxQueryExtensionReq *r;
+{
+ char n;
+
+ swapl(&r->nbytes, n);
+}
+
+void
+SwapLbxConnSetupPrefix(csp)
+ xLbxConnSetupPrefix *csp;
+{
+ char n;
+
+ swaps(&csp->majorVersion, n);
+ swaps(&csp->minorVersion, n);
+ swapl(&csp->tag, n);
+}
+
+void
+SwapAllocColor(r)
+ xLbxAllocColorReq *r;
+{
+ char n;
+
+ swapl(&r->cmap, n);
+ swapl(&r->pixel, n);
+ swaps(&r->red, n);
+ swaps(&r->green, n);
+ swaps(&r->blue, n);
+}
+
+
+void
+SwapGrabCmap(r)
+ xLbxGrabCmapReq *r;
+{
+ char n;
+
+ swapl(&r->cmap, n);
+}
+
+void
+SwapReleaseCmap(r)
+ xLbxReleaseCmapReq *r;
+{
+ char n;
+
+ swapl(&r->cmap, n);
+}
+
diff --git a/di/tables.c b/di/tables.c
new file mode 100644
index 0000000..4774d60
--- /dev/null
+++ b/di/tables.c
@@ -0,0 +1,593 @@
+/* $Xorg: tables.c,v 1.3 2000/08/17 19:53:56 cpqbld Exp $ */
+/*
+ * Copyright 1992 Network Computing Devices
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of NCD. not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. NCD. makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * NCD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL NCD.
+ * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+extern int ProcInitialConnection(), ProcEstablishConnection();
+
+extern int ProcStandardRequest();
+
+extern int ProcLBXChangeWindowAttributes(),
+ ProcLBXGetWindowAttributes(),
+ ProcLBXGetGeometry(),
+ ProcLBXInternAtom(),
+ ProcLBXGetAtomName(),
+ ProcLBXCreateColormap(),
+ ProcLBXFreeColormap(),
+ ProcLBXCopyColormapAndFree(),
+ ProcLBXFreeColors(),
+ ProcLBXLookupColor(),
+ ProcLBXAllocColor(),
+ ProcLBXAllocNamedColor(),
+ ProcLBXAllocColorCells(),
+ ProcLBXAllocColorPlanes(),
+ ProcLBXGetModifierMapping(),
+ ProcLBXGetKeyboardMapping(),
+ ProcLBXQueryFont(),
+ ProcLBXChangeProperty(),
+ ProcLBXGetProperty(),
+ ProcLBXCopyArea(),
+ ProcLBXCopyPlane(),
+ ProcLBXPolyPoint(),
+ ProcLBXPolyLine(),
+ ProcLBXPolySegment(),
+ ProcLBXPolyRectangle(),
+ ProcLBXPolyArc(),
+ ProcLBXFillPoly(),
+ ProcLBXPolyFillRectangle(),
+ ProcLBXPolyFillArc(),
+ ProcLBXPolyText(),
+ ProcLBXImageText(),
+ ProcLBXQueryExtension(),
+ ProcLBXGetImage(),
+ ProcLBXPutImage();
+
+extern int ProcBadRequest();
+
+int (*InitialVector[3]) () =
+{
+ 0,
+ ProcInitialConnection,
+ ProcEstablishConnection
+};
+
+int (*ProcVector[256]) () =
+{
+ ProcBadRequest,
+ ProcStandardRequest,
+ ProcLBXChangeWindowAttributes,
+ ProcLBXGetWindowAttributes,
+ ProcStandardRequest,
+ ProcStandardRequest, /* 5 */
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest, /* 10 */
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcLBXGetGeometry,
+ ProcStandardRequest, /* 15 */
+ ProcLBXInternAtom,
+ ProcLBXGetAtomName,
+ ProcLBXChangeProperty,
+ ProcStandardRequest,
+ ProcLBXGetProperty, /* 20 */
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest, /* 25 */
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest, /* 30 */
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest, /* 35 */
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest, /* 40 */
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest, /* 45 */
+ ProcStandardRequest,
+ ProcLBXQueryFont,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest, /* 50 */
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest, /* 55 */
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest, /* 60 */
+ ProcStandardRequest,
+ ProcLBXCopyArea,
+ ProcLBXCopyPlane,
+ ProcLBXPolyPoint,
+ ProcLBXPolyLine, /* 65 */
+ ProcLBXPolySegment,
+ ProcLBXPolyRectangle,
+ ProcLBXPolyArc,
+ ProcLBXFillPoly,
+ ProcLBXPolyFillRectangle, /* 70 */
+ ProcLBXPolyFillArc,
+ ProcLBXPutImage,
+ ProcLBXGetImage,
+ ProcLBXPolyText,
+ ProcLBXPolyText, /* 75 */
+ ProcLBXImageText,
+ ProcLBXImageText,
+ ProcLBXCreateColormap,
+ ProcLBXFreeColormap,
+ ProcLBXCopyColormapAndFree, /* 80 */
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcLBXAllocColor,
+ ProcLBXAllocNamedColor, /* 85 */
+ ProcLBXAllocColorCells,
+ ProcLBXAllocColorPlanes,
+ ProcLBXFreeColors,
+ ProcStandardRequest,
+ ProcStandardRequest, /* 90 */
+ ProcStandardRequest,
+ ProcLBXLookupColor,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest, /* 95 */
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcLBXQueryExtension,
+ ProcStandardRequest,
+ ProcStandardRequest, /* 100 */
+ ProcLBXGetKeyboardMapping,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest, /* 105 */
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest, /* 110 */
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest, /* 115 */
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcLBXGetModifierMapping,
+ 0, /* 120 */
+ 0,
+ 0,
+ 0,
+ 0,
+ 0, /* 125 */
+ 0,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+ ProcStandardRequest,
+};
+
+
+extern int ServerProcError(), ServerProcReply(),
+ ServerProcStandardEvent();
+
+int (*ServerVector[256]) () = {
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+ ServerProcStandardEvent,
+};
diff --git a/di/tags.c b/di/tags.c
new file mode 100644
index 0000000..0e800f2
--- /dev/null
+++ b/di/tags.c
@@ -0,0 +1,192 @@
+/* $Xorg: tags.c,v 1.4 2001/02/09 02:05:32 xorgcvs Exp $ */
+/*
+
+Copyright 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+*/
+/*
+ * Copyright 1993 Network Computing Devices, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name Network Computing Devices, Inc. not be
+ * used in advertising or publicity pertaining to distribution of this
+ * software without specific, written prior permission.
+ *
+ * THIS SOFTWARE IS PROVIDED `AS-IS'. NETWORK COMPUTING DEVICES, INC.,
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT
+ * LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, OR NONINFRINGEMENT. IN NO EVENT SHALL NETWORK
+ * COMPUTING DEVICES, INC., BE LIABLE FOR ANY DAMAGES WHATSOEVER, INCLUDING
+ * SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES, INCLUDING LOSS OF USE, DATA,
+ * OR PROFITS, EVEN IF ADVISED OF THE POSSIBILITY THEREOF, AND REGARDLESS OF
+ * WHETHER IN AN ACTION IN CONTRACT, TORT OR NEGLIGENCE, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include "misc.h"
+#include "util.h"
+#include "cache.h"
+#include "tags.h"
+#include "assert.h"
+#include "wire.h"
+#include "proxyopts.h"
+
+int lbxTagCacheSize = 1 << 20;
+
+void
+TagsInit(server, useTags)
+ XServerPtr server;
+ Bool useTags;
+{
+ if (!useTags) {
+ lbxTagCacheSize = 0;
+ }
+ server->global_cache = CacheInit(server, lbxTagCacheSize);
+ server->prop_cache = CacheInit(server, lbxTagCacheSize);
+}
+
+void
+FreeTags()
+{
+ int i;
+
+ for (i=0; i < lbxMaxServers; i++) {
+ if (servers[i] && servers[i]->caches[servers[i]->global_cache])
+ CacheFreeCache(servers[i], servers[i]->global_cache);
+ if (servers[i] && servers[i]->caches[servers[i]->prop_cache])
+ CacheFreeCache(servers[i], servers[i]->prop_cache);
+ }
+}
+
+/* ARGSUSED */
+static void
+cache_free(id, client, data, reason)
+ CacheID id;
+ ClientPtr client;
+ pointer data;
+ int reason;
+{
+ TagData tag = (TagData) data;
+
+ /* tell server we toasted this one */
+ if (reason != CacheEntryFreed)
+ SendInvalidateTag(client, tag->tid);
+ xfree(tag->tdata);
+ xfree(data);
+}
+
+Bool
+TagStoreData(server, cache, id, size, dtype, data)
+ XServerPtr server;
+ Cache cache;
+ CacheID id;
+ int size;
+ int dtype;
+ pointer data;
+{
+ pointer tdata;
+
+ tdata = (pointer) xalloc(size);
+ if (!tdata)
+ return FALSE;
+ memcpy((char *) tdata, (char *) data, size);
+ return TagStoreDataNC(server, cache, id, size, dtype, tdata);
+}
+
+Bool
+TagStoreDataNC(server, cache, id, size, dtype, data)
+ XServerPtr server;
+ Cache cache;
+ CacheID id;
+ int size;
+ int dtype;
+ pointer data;
+{
+ TagData tag;
+ Bool ret;
+
+ assert(server->lbxNegOpt.useTags);
+
+ tag = (TagData) xalloc(sizeof(TagDataRec));
+ if (!tag)
+ return FALSE;
+ tag->tdata = data;
+ tag->tid = id;
+ tag->data_type = dtype;
+ tag->size = size;
+
+ ret = CacheStoreMemory(server, cache, id, (pointer) tag, size, cache_free,
+ !AnyTagBearingReplies(server, cache));
+ if (!ret) {
+ xfree(tag->tdata);
+ xfree(tag);
+ }
+ return ret;
+}
+
+TagData
+TagGetTag(server, cache, id)
+ XServerPtr server;
+ Cache cache;
+ CacheID id;
+{
+ TagData tag;
+
+ assert(server->lbxNegOpt.useTags);
+
+ tag = (TagData) CacheFetchMemory(server, cache, id, TRUE);
+ return tag;
+}
+
+pointer
+TagGetData(server, cache, id)
+ XServerPtr server;
+ Cache cache;
+ CacheID id;
+{
+ TagData tag;
+
+ assert(server->lbxNegOpt.useTags);
+
+ tag = (TagData) CacheFetchMemory(server, cache, id, TRUE);
+ if (tag)
+ return tag->tdata;
+ else
+ return (pointer) NULL;
+}
+
+void
+TagFreeData(server, cache, id, notify)
+ XServerPtr server;
+ Cache cache;
+ CacheID id;
+ Bool notify;
+{
+ assert(server->lbxNegOpt.useTags);
+
+ CacheFreeMemory(server, cache, id, notify);
+}
diff --git a/di/unsquish.c b/di/unsquish.c
new file mode 100644
index 0000000..8738979
--- /dev/null
+++ b/di/unsquish.c
@@ -0,0 +1,123 @@
+/* $Xorg: unsquish.c,v 1.4 2001/02/09 02:05:32 xorgcvs Exp $ */
+/*
+
+Copyright 1987, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+*/
+/*
+ * Copyright 1994 Network Computing Devices, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name Network Computing Devices, Inc. not be
+ * used in advertising or publicity pertaining to distribution of this
+ * software without specific, written prior permission.
+ *
+ * THIS SOFTWARE IS PROVIDED `AS-IS'. NETWORK COMPUTING DEVICES, INC.,
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT
+ * LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, OR NONINFRINGEMENT. IN NO EVENT SHALL NETWORK
+ * COMPUTING DEVICES, INC., BE LIABLE FOR ANY DAMAGES WHATSOEVER, INCLUDING
+ * SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES, INCLUDING LOSS OF USE, DATA,
+ * OR PROFITS, EVEN IF ADVISED OF THE POSSIBILITY THEREOF, AND REGARDLESS OF
+ * WHETHER IN AN ACTION IN CONTRACT, TORT OR NEGLIGENCE, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+/* handles unsquishing events */
+
+#include "X.h"
+#define NEED_REPLIES
+#define NEED_EVENTS
+#include "Xproto.h"
+#include "misc.h"
+#define _XLBX_SERVER_
+#include "lbxstr.h"
+#include "proxyopts.h"
+
+#include <stdio.h>
+
+static char lbxevsize[] = {
+ sz_xError,
+ sz_xReply,
+ lbxsz_KeyButtonEvent,
+ lbxsz_KeyButtonEvent,
+ lbxsz_KeyButtonEvent,
+ lbxsz_KeyButtonEvent,
+ lbxsz_KeyButtonEvent,
+ lbxsz_EnterLeaveEvent,
+ lbxsz_EnterLeaveEvent,
+ lbxsz_FocusEvent,
+ lbxsz_FocusEvent,
+ lbxsz_KeymapEvent,
+ lbxsz_ExposeEvent,
+ lbxsz_GfxExposeEvent,
+ lbxsz_NoExposeEvent,
+ lbxsz_VisibilityEvent,
+ lbxsz_CreateNotifyEvent,
+ lbxsz_DestroyNotifyEvent,
+ lbxsz_UnmapNotifyEvent,
+ lbxsz_MapNotifyEvent,
+ lbxsz_MapRequestEvent,
+ lbxsz_ReparentEvent,
+ lbxsz_ConfigureNotifyEvent,
+ lbxsz_ConfigureRequestEvent,
+ lbxsz_GravityEvent,
+ lbxsz_ResizeRequestEvent,
+ lbxsz_CirculateEvent,
+ lbxsz_CirculateEvent,
+ lbxsz_PropertyEvent,
+ lbxsz_SelectionClearEvent,
+ lbxsz_SelectionRequestEvent,
+ lbxsz_SelectionNotifyEvent,
+ lbxsz_ColormapEvent,
+ lbxsz_ClientMessageEvent,
+ lbxsz_MappingNotifyEvent
+};
+
+int
+EventLength(ev, squish)
+ xEvent *ev;
+ Bool squish;
+{
+ if (!squish || ev->u.u.type >= LASTEvent)
+ return sz_xEvent;
+ return lbxevsize[ev->u.u.type];
+}
+
+Bool
+UnsquishEvent(rep, ev, lenp)
+ xReply *rep;
+ xEvent *ev;
+ int *lenp;
+{
+ if (*lenp < sz_xEvent) {
+ memcpy((char *)ev, (char *)rep, *lenp);
+ *lenp = sz_xEvent;
+ return TRUE;
+ }
+ return FALSE;
+}
diff --git a/di/utils.c b/di/utils.c
new file mode 100644
index 0000000..3846d3d
--- /dev/null
+++ b/di/utils.c
@@ -0,0 +1,1017 @@
+/* $Xorg: utils.c,v 1.5 2001/02/09 02:05:32 xorgcvs Exp $ */
+/***********************************************************
+
+Copyright 1987, 1996, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+
+Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+******************************************************************/
+
+#include "lbx.h"
+#include <stdio.h>
+#include <stdlib.h> /* getenv(), {m,re}alloc() */
+#ifdef X_POSIX_C_SOURCE
+#define _POSIX_C_SOURCE X_POSIX_C_SOURCE
+#include <signal.h>
+#undef _POSIX_C_SOURCE
+#else
+#if defined(X_NOT_POSIX) || defined(_POSIX_SOURCE)
+#include <signal.h>
+#else
+#define _POSIX_SOURCE
+#include <signal.h>
+#undef _POSIX_SOURCE
+#endif
+#endif
+#ifndef SYSV
+#include <sys/resource.h>
+#endif
+
+/* lifted from Xt/VarargsI.h */
+#if NeedVarargsPrototypes
+#include <stdarg.h>
+#endif
+
+#if NeedVarargsPrototypes
+static void VErrorF(char*, va_list);
+#endif
+
+#ifdef SIGNALRETURNSINT
+#define SIGVAL int
+#else
+#define SIGVAL void
+#endif
+
+#include "util.h"
+#include "wire.h"
+#include "atomcache.h"
+#include "proxyopts.h"
+
+/*
+ * External declarations not in header files
+ */
+extern char *display_name;
+extern char *display;
+extern Bool PartialNetwork;
+extern int lbxDebug;
+
+extern char protocolMode;
+extern Bool reconnectAfterCloseServer;
+extern Bool resetAfterLastClient;
+extern Bool terminateAfterLastClient;
+extern int lbxTagCacheSize;
+extern Bool lbxUseLbx;
+extern Bool lbxUseTags;
+extern Bool lbxDoSquishing;
+extern Bool lbxCompressImages;
+extern Bool lbxDoAtomShortCircuiting;
+extern Bool lbxDoLbxGfx;
+extern Bool compStats;
+
+/*
+ * Static vars
+ */
+static Bool CoreDump;
+static Bool Must_have_memory = FALSE;
+static char *dev_tty_from_init = NULL; /* since we need to parse it anyway */
+
+/*
+ * Debug stuff
+ */
+#ifdef DEBUG
+#ifndef SPECIAL_MALLOC
+#define MEMBUG
+#endif
+#endif
+
+#ifdef MEMBUG
+#define MEM_FAIL_SCALE 100000
+long Memory_fail = 0;
+#endif
+
+/*
+ * Global vars that may get set when the command line opts are parsed.
+ */
+#ifdef RGB_DB
+char *rgbPath = RGB_DB;
+#else
+char *rgbPath;
+#endif
+
+Bool lbxZeroPad = TRUE; /* zero out pad bytes in X requests */
+
+char *atomsFile = DEF_ATOMS_FILE;
+
+Bool lbxWinAttr = TRUE; /* group GetWindowAttributes/GetGeometry into 1 trip */
+
+Bool lbxDoCmapGrabbing = TRUE; /* do colormap grabbing? */
+
+int lbxMaxMotionEvents = NUM_MOTION_EVENTS; /* max # motion events */
+
+int min_keep_prop_size = DEF_KEEP_PROP_SIZE;
+
+/*
+ * zlevel = 1..9, 9 == max compression. 6 == good tradeoff between
+ * compression and speed. Try gzipping a large file at the default
+ * level (which is 6) and at max compression (9) and notice the
+ * difference in time it takes to compress the file and the difference
+ * in file size. level 9 compression takes ~50 more (time, cpu) but
+ * only yields a very small improvement in compression.
+ */
+int zlevel = 6;
+
+
+/*
+ * The functions
+ */
+OsSigHandlerPtr
+OsSignal(sig, handler)
+ int sig;
+ OsSigHandlerPtr handler;
+{
+#ifdef X_NOT_POSIX
+ return signal(sig, handler);
+#else
+ struct sigaction act, oact;
+
+ sigemptyset(&act.sa_mask);
+ if (handler != SIG_IGN)
+ sigaddset(&act.sa_mask, sig);
+ act.sa_flags = 0;
+ act.sa_handler = handler;
+ sigaction(sig, &act, &oact);
+ return oact.sa_handler;
+#endif
+}
+
+/* Force connections to close on SIGHUP from init */
+
+/* ARGSUSED */
+SIGVAL
+AutoResetServer (sig)
+ int sig;
+{
+ dispatchException |= DE_RESET;
+ isItTimeToYield = TRUE;
+#ifdef GPROF
+ chdir ("/tmp");
+ exit (0);
+#endif
+#ifdef SYSV
+ signal (SIGHUP, AutoResetServer);
+#endif
+}
+
+/* Force connections to close and then exit on SIGTERM, SIGINT */
+
+/* ARGSUSED */
+SIGVAL
+GiveUp(sig)
+ int sig;
+{
+ dispatchException |= DE_TERMINATE;
+ isItTimeToYield = TRUE;
+}
+
+static void
+AbortServer()
+{
+ fflush(stderr);
+ if (CoreDump)
+ abort();
+ exit (1);
+}
+
+void
+Error(str)
+ char *str;
+{
+ perror(str);
+}
+
+void UseMsg()
+{
+ ErrorF("use: lbxproxy [:<display>] [option]\n");
+#ifdef MEMBUG
+ ErrorF("-alloc int chance alloc should fail\n");
+#endif
+ ErrorF("-help prints message with these options\n");
+ ErrorF("-display specify address of LBX server\n");
+ ErrorF("-motion # allow # motion events in flight\n");
+ ErrorF("-[terminate|reset] terminate or reset after last client exits\n");
+ ErrorF(" (default is continue running)\n");
+ ErrorF("-I ignore all remaining arguments\n");
+ ErrorF("-reconnect reset if server connection is broken\n");
+ ErrorF(" (default is to exit if connection is broken)\n");
+ ErrorF("-nolbx disable LBX reencoding of X requests\n");
+ ErrorF("-nocomp disable stream compression\n");
+ ErrorF("-nodelta disable request deltas\n");
+ ErrorF("-notags disable tags\n");
+ ErrorF("-nogfx disable graphics enhancements\n");
+ ErrorF("-noimage disable image compression\n");
+ ErrorF("-nosquish disable event squishing\n");
+ ErrorF("-nointernsc disable InternAtom short circuiting\n");
+ ErrorF("-noatomsfile disable atom control file\n");
+ ErrorF("-atomsfile override AtomControl file\n");
+ ErrorF("-nowinattr disable GetWindowAttributes/GetGeometry\n");
+ ErrorF(" grouping into one round trip\n");
+ ErrorF("-nograbcmap disable colormap grabbing\n");
+ ErrorF("-norgbfile disables color name to RGB resolution\n");
+ ErrorF("-rgbfile <path> path specifies an alternate RGB database\n");
+ ErrorF(" for color name to RGB resolution\n");
+ ErrorF("-tagcachesize # set tag cache size\n");
+ ErrorF("-maxservers # maximum number of servers to use\n");
+ ErrorF(" default is 20, but this is overrided\n");
+ ErrorF(" the following environment variable:\n");
+ ErrorF(" LBXPROXY_MAXSERVERS=<max servers>\n");
+ ErrorF("-zlevel # zlib compression level (1-9)\n");
+ ErrorF(" default is 9\n");
+ ErrorF(" 1 = worst compression, fastest\n");
+ ErrorF(" 9 = best compression, slowest\n");
+ ErrorF("-compstats report stream compression statistics\n");
+ ErrorF("-nozeropad don't zero out pad bytes in X requests\n");
+ ErrorF("-cheaterrors cheat on X protocol errors for better performance\n");
+ ErrorF("-cheatevents cheat on events and errors for better performance\n");
+}
+
+void
+ShowHelpAndExit (status)
+
+{
+ UseMsg ();
+ exit (status);
+}
+
+static int
+proxyProcessArgument (argc, argv, i)
+ int argc;
+ char **argv;
+ int i;
+{
+ if (strcmp (argv[i], "-debug") == 0)
+ {
+ if (++i < argc)
+ lbxDebug = atoi(argv[i]);
+ else
+ ShowHelpAndExit (1);
+ return 2;
+ }
+ if (strcmp (argv[i], "-cheaterrors") == 0)
+ {
+ protocolMode = PROTOCOL_MOST;
+ return 1;
+ }
+ if (strcmp (argv[i], "-cheatevents") == 0)
+ {
+ protocolMode = PROTOCOL_POOR;
+ return 1;
+ }
+ if (strcmp (argv[i], "-nolbx") == 0)
+ {
+ lbxUseLbx = FALSE;
+ return 1;
+ }
+ if (strcmp (argv[i], "-nointernsc") == 0)
+ {
+ lbxDoAtomShortCircuiting = FALSE;
+ return 1;
+ }
+ if (strcmp (argv[i], "-nocomp") == 0)
+ {
+ LbxNoComp();
+ return 1;
+ }
+ if (strcmp (argv[i], "-nodelta") == 0)
+ {
+ LbxNoDelta();
+ return 1;
+ }
+ if (strcmp (argv[i], "-notags") == 0)
+ {
+ lbxUseTags = FALSE;
+ return 1;
+ }
+ if (strcmp (argv[i], "-nogfx") == 0)
+ {
+ lbxDoLbxGfx = FALSE;
+ return 1;
+ }
+ if (strcmp (argv[i], "-noimage") == 0)
+ {
+ lbxCompressImages = FALSE;
+ return 1;
+ }
+ if (strcmp (argv[i], "-nosquish") == 0)
+ {
+ lbxDoSquishing = FALSE;
+ return 1;
+ }
+ if (strcmp (argv[i], "-nograbcmap") == 0)
+ {
+ lbxDoCmapGrabbing = FALSE;
+ return 1;
+ }
+ if (strcmp (argv[i], "-reconnect") == 0)
+ {
+ reconnectAfterCloseServer = TRUE;
+ return 1;
+ }
+ if (strcmp (argv[i], "-norgbfile") == 0)
+ {
+ rgbPath = NULL;
+ return 1;
+ }
+ if (strcmp (argv[i], "-rgbfile") == 0)
+ {
+ if (++i < argc)
+ if (argv[i][0] == '-')
+ ShowHelpAndExit (1);
+ else
+ rgbPath = argv[i];
+ else
+ ShowHelpAndExit (1);
+ return 2;
+ }
+ if (strcmp (argv[i], "-nowinattr") == 0)
+ {
+ lbxWinAttr = FALSE;
+ return 1;
+ }
+ if (strcmp (argv[i], "-noatomsfile") == 0)
+ {
+ atomsFile = NULL;
+ return 1;
+ }
+ if (strcmp (argv[i], "-atomsfile") == 0)
+ {
+ if (++i < argc)
+ {
+ if (argv[i][0] == '-')
+ ShowHelpAndExit (1);
+ else
+ atomsFile = argv[i];
+ }
+ else
+ ShowHelpAndExit (1);
+ return 2;
+ }
+ if (strcmp (argv[i], "-tagcachesize") == 0)
+ {
+ if (++i < argc)
+ lbxTagCacheSize = atoi(argv[i]);
+ else
+ ShowHelpAndExit (1);
+ return 2;
+ }
+ if (strcmp (argv[i], "-maxservers") == 0)
+ {
+ if (++i < argc)
+ lbxMaxServers = atoi(argv[i]);
+ else
+ ShowHelpAndExit (1);
+ return 2;
+ }
+ if (strcmp (argv[i], "-motion") == 0)
+ {
+ if (++i < argc)
+ lbxMaxMotionEvents = atoi(argv[i]);
+ else
+ ShowHelpAndExit (1);
+ return 2;
+ }
+ if (strcmp (argv[i], "-zlevel") == 0)
+ {
+ if (++i < argc)
+ {
+ zlevel = atoi(argv[i]);
+ if (zlevel < 1 || zlevel > 9)
+ ShowHelpAndExit (1);
+ }
+ else
+ ShowHelpAndExit (1);
+ return 2;
+ }
+ if (strcmp (argv[i], "-compstats") == 0)
+ {
+ compStats = TRUE;
+ return 1;
+ }
+ if (strcmp (argv[i], "-nozeropad") == 0)
+ {
+ lbxZeroPad = FALSE;
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * This function parses the command line. Handles device-independent fields
+ * and allows ddx to handle additional fields. It is not allowed to modify
+ * argc or any of the strings pointed to by argv.
+ */
+void
+ProcessCommandLine ( argc, argv )
+int argc;
+char *argv[];
+
+{
+ int i, skip;
+ char *env;
+
+ /*
+ * Some options may also be defined by environment variables.
+ * However, if this is the case, the command line options will
+ * take precedence so check the environment first.
+ */
+ if ((env = getenv ("LBXPROXY_MAXSERVERS")))
+ lbxMaxServers = atoi (env);
+
+ for ( i = 1; i < argc; i++ )
+ {
+ /* do proxy-specific stuff first */
+ if((skip = proxyProcessArgument(argc, argv, i)))
+ {
+ i += (skip - 1);
+ }
+ else if(argv[i][0] == ':')
+ {
+ /* initialize display */
+ display = argv[i];
+ display++;
+ }
+#ifdef MEMBUG
+ else if ( strcmp( argv[i], "-alloc") == 0)
+ {
+ if(++i < argc)
+ Memory_fail = atoi(argv[i]);
+ else
+ ShowHelpAndExit (1);
+ }
+#endif
+ else if ( strcmp( argv[i], "-display") == 0)
+ {
+ if(++i < argc)
+ display_name = argv[i];
+ else
+ ShowHelpAndExit (1);
+ }
+ else if ( strcmp( argv[i], "-core") == 0)
+ CoreDump = TRUE;
+ else if ( strcmp( argv[i], "-help") == 0)
+ ShowHelpAndExit (0);
+ else if ( strcmp( argv[i], "-pn") == 0)
+ PartialNetwork = TRUE;
+ else if ( strcmp( argv[i], "-reset") == 0)
+ {
+ if (terminateAfterLastClient)
+ ShowHelpAndExit (1);
+
+ resetAfterLastClient = TRUE;
+ }
+ else if ( strcmp( argv[i], "-terminate") == 0)
+ {
+ if (resetAfterLastClient)
+ ShowHelpAndExit (1);
+
+ terminateAfterLastClient = TRUE;
+ }
+ else if ( strcmp( argv[i], "-I") == 0)
+ {
+ /* ignore all remaining arguments */
+ break;
+ }
+ else if (strncmp (argv[i], "tty", 3) == 0)
+ {
+ /* just in case any body is interested */
+ dev_tty_from_init = argv[i];
+ }
+ else
+ ShowHelpAndExit (1);
+ }
+}
+
+/* XALLOC -- X's internal memory allocator. Why does it return unsigned
+ * int * instead of the more common char *? Well, if you read K&R you'll
+ * see they say that alloc must return a pointer "suitable for conversion"
+ * to whatever type you really want. In a full-blown generic allocator
+ * there's no way to solve the alignment problems without potentially
+ * wasting lots of space. But we have a more limited problem. We know
+ * we're only ever returning pointers to structures which will have to
+ * be long word aligned. So we are making a stronger guarantee. It might
+ * have made sense to make Xalloc return char * to conform with people's
+ * expectations of malloc, but this makes lint happier.
+ */
+
+unsigned long *
+Xalloc (amount)
+ unsigned long amount;
+{
+ register pointer ptr;
+
+ if ((long)amount <= 0)
+ return (unsigned long *)NULL;
+ /* aligned extra on long word boundary */
+ amount = (amount + 3) & ~3;
+#ifdef MEMBUG
+ if (!Must_have_memory && Memory_fail &&
+ ((random() % MEM_FAIL_SCALE) < Memory_fail))
+ return (unsigned long *)NULL;
+#endif
+ if ((ptr = (pointer)malloc(amount)))
+ return (unsigned long *)ptr;
+ if (Must_have_memory)
+ FatalError("Out of memory");
+ return (unsigned long *)NULL;
+}
+
+/*****************
+ * Xcalloc
+ *****************/
+
+unsigned long *
+Xcalloc (amount)
+ unsigned long amount;
+{
+ unsigned long *ret;
+
+ ret = Xalloc (amount);
+ if (ret)
+ bzero ((char *) ret, (int) amount);
+ return ret;
+}
+
+/*****************
+ * Xrealloc
+ *****************/
+
+unsigned long *
+Xrealloc (ptr, amount)
+ register pointer ptr;
+ unsigned long amount;
+{
+#ifdef MEMBUG
+ if (!Must_have_memory && Memory_fail &&
+ ((random() % MEM_FAIL_SCALE) < Memory_fail))
+ return (unsigned long *)NULL;
+#endif
+ if ((long)amount <= 0)
+ {
+ if (ptr && !amount)
+ free(ptr);
+ return (unsigned long *)NULL;
+ }
+ amount = (amount + 3) & ~3;
+ if (ptr)
+ ptr = (pointer)realloc((char *)ptr, amount);
+ else
+ ptr = (pointer)malloc(amount);
+ if (ptr)
+ return (unsigned long *)ptr;
+ if (Must_have_memory)
+ FatalError("Out of memory");
+ return (unsigned long *)NULL;
+}
+
+/*****************
+ * Xfree
+ * calls free
+ *****************/
+
+void
+Xfree(ptr)
+ register pointer ptr;
+{
+ if (ptr)
+ free((char *)ptr);
+}
+
+void
+OsInitAllocator ()
+{
+#ifdef MEMBUG
+ static int been_here;
+
+ /* Check the memory system after each generation */
+ if (been_here)
+ CheckMemory ();
+ else
+ been_here = 1;
+#endif
+}
+
+/*VARARGS1*/
+void
+AuditF(
+#if NeedVarargsPrototypes
+ char * f, ...)
+#else
+ f, s0, s1, s2, s3, s4, s5, s6, s7, s8, s9) /* limit of ten args */
+ char *f;
+ char *s0, *s1, *s2, *s3, *s4, *s5, *s6, *s7, *s8, *s9;
+#endif
+{
+#ifdef notyet /* ever ? */
+#ifdef X_NOT_STDC_ENV
+ long tm;
+#else
+ time_t tm;
+#endif
+ char *autime, *s;
+#if NeedVarargsPrototypes
+ va_list args;
+#endif
+
+ if (*f != ' ')
+ {
+ time(&tm);
+ autime = ctime(&tm);
+ if (s = strchr(autime, '\n'))
+ *s = '\0';
+ if (s = strrchr(argvGlobal[0], '/'))
+ s++;
+ else
+ s = argvGlobal[0];
+ ErrorF("AUDIT: %s: %d %s: ", autime, getpid(), s);
+ }
+#if NeedVarargsPrototypes
+ va_start(args, f);
+ VErrorF(f, args);
+ va_end(args);
+#else
+ ErrorF(f, s0, s1, s2, s3, s4, s5, s6, s7, s8, s9);
+#endif
+#endif
+}
+
+/*VARARGS1*/
+void
+FatalError(
+#if NeedVarargsPrototypes
+ char *f, ...)
+#else
+f, s0, s1, s2, s3, s4, s5, s6, s7, s8, s9) /* limit of ten args */
+ char *f;
+ char *s0, *s1, *s2, *s3, *s4, *s5, *s6, *s7, *s8, *s9;
+#endif
+{
+#if NeedVarargsPrototypes
+ va_list args;
+#endif
+ ErrorF("\nFatal lbxproxy error: ");
+#if NeedVarargsPrototypes
+ va_start(args, f);
+ VErrorF(f, args);
+ va_end(args);
+#else
+ ErrorF(f, s0, s1, s2, s3, s4, s5, s6, s7, s8, s9);
+#endif
+ ErrorF("\n");
+ AbortServer();
+ /*NOTREACHED*/
+}
+
+#if NeedVarargsPrototypes
+static void
+VErrorF(f, args)
+ char *f;
+ va_list args;
+{
+ vfprintf(stderr, f, args);
+}
+#endif
+
+/*VARARGS1*/
+void
+ErrorF(
+#if NeedVarargsPrototypes
+ char * f, ...)
+#else
+ f, s0, s1, s2, s3, s4, s5, s6, s7, s8, s9) /* limit of ten args */
+ char *f;
+ char *s0, *s1, *s2, *s3, *s4, *s5, *s6, *s7, *s8, *s9;
+#endif
+{
+#if NeedVarargsPrototypes
+ va_list args;
+ va_start(args, f);
+ VErrorF(f, args);
+ va_end(args);
+#else
+ fprintf( stderr, f, s0, s1, s2, s3, s4, s5, s6, s7, s8, s9);
+#endif
+}
+
+char *
+strnalloc(str, len)
+ char *str;
+ int len;
+{
+ char *t;
+
+ t = (char *) Xalloc(len);
+ if (!t)
+ return (char *) 0;
+ memcpy(t, str, len);
+ return t;
+}
+
+/*
+ * A general work queue. Perform some task before the server
+ * sleeps for input.
+ */
+
+typedef struct _WorkQueue {
+ struct _WorkQueue *next;
+ Bool (*function) (
+#if NeedNestedPrototypes
+ ClientPtr /* pClient */,
+ pointer /* closure */
+#endif
+);
+ ClientPtr client;
+ pointer closure;
+} WorkQueueRec;
+
+WorkQueuePtr workQueue;
+static WorkQueuePtr *workQueueLast = &workQueue;
+
+/* ARGSUSED */
+void
+ProcessWorkQueue()
+{
+ WorkQueuePtr q, n, p;
+
+ p = NULL;
+ /*
+ * Scan the work queue once, calling each function. Those
+ * which return TRUE are removed from the queue, otherwise
+ * they will be called again. This must be reentrant with
+ * QueueWorkProc, hence the crufty usage of variables.
+ */
+ for (q = workQueue; q; q = n)
+ {
+ if ((*q->function) (q->client, q->closure))
+ {
+ /* remove q from the list */
+ n = q->next; /* don't fetch until after func called */
+ if (p)
+ p->next = n;
+ else
+ workQueue = n;
+ xfree (q);
+ }
+ else
+ {
+ n = q->next; /* don't fetch until after func called */
+ p = q;
+ }
+ }
+ if (p)
+ workQueueLast = &p->next;
+ else
+ {
+ workQueueLast = &workQueue;
+ }
+}
+
+Bool
+QueueWorkProc (function, client, closure)
+ Bool (*function)();
+ ClientPtr client;
+ pointer closure;
+{
+ WorkQueuePtr q;
+
+ q = (WorkQueuePtr) xalloc (sizeof *q);
+ if (!q)
+ return FALSE;
+ q->function = function;
+ q->client = client;
+ q->closure = closure;
+ q->next = NULL;
+ *workQueueLast = q;
+ workQueueLast = &q->next;
+ return TRUE;
+}
+
+/*
+ * Manage a queue of sleeping clients, awakening them
+ * when requested, by using the OS functions IgnoreClient
+ * and AttendClient. Note that this *ignores* the troubles
+ * with request data interleaving itself with events, but
+ * we'll leave that until a later time.
+ */
+
+typedef struct _SleepQueue {
+ struct _SleepQueue *next;
+ ClientPtr client;
+ Bool (*function)();
+ pointer closure;
+} SleepQueueRec, *SleepQueuePtr;
+
+static SleepQueuePtr sleepQueue = NULL;
+
+Bool
+ClientSleep (client, function, closure)
+ ClientPtr client;
+ Bool (*function)();
+ pointer closure;
+{
+ SleepQueuePtr q;
+
+ q = (SleepQueuePtr) xalloc (sizeof *q);
+ if (!q)
+ return FALSE;
+
+ IgnoreClient (client);
+ q->next = sleepQueue;
+ q->client = client;
+ q->function = function;
+ q->closure = closure;
+ sleepQueue = q;
+ return TRUE;
+}
+
+Bool
+ClientSignal (client)
+ ClientPtr client;
+{
+ SleepQueuePtr q;
+
+ for (q = sleepQueue; q; q = q->next)
+ if (q->client == client)
+ {
+ return QueueWorkProc (q->function, q->client, q->closure);
+ }
+ return FALSE;
+}
+
+void
+ClientWakeup (client)
+ ClientPtr client;
+{
+ SleepQueuePtr q, *prev;
+
+ prev = &sleepQueue;
+ while ((q = *prev))
+ {
+ if (q->client == client)
+ {
+ *prev = q->next;
+ xfree (q);
+ if (!client->clientGone)
+ AttendClient (client);
+ break;
+ }
+ prev = &q->next;
+ }
+}
+
+Bool
+ClientIsAsleep (client)
+ ClientPtr client;
+{
+ SleepQueuePtr q;
+
+ for (q = sleepQueue; q; q = q->next)
+ if (q->client == client)
+ return TRUE;
+ return FALSE;
+}
+
+
+void
+LBXReadAtomsFile (server)
+ XServerPtr server;
+{
+ FILE *f;
+ char buf[256], *p;
+ int len;
+
+ if (!atomsFile)
+ return;
+
+ while (server->atom_control_count)
+ xfree(server->atom_control[--server->atom_control_count].name);
+ xfree(server->atom_control);
+ server->atom_control = NULL;
+ min_keep_prop_size = DEF_KEEP_PROP_SIZE;
+
+ if (!(f = fopen (atomsFile, "r"))) {
+ ErrorF ("Could not load atom control file: %s\n", atomsFile);
+ return;
+ }
+
+ while (fgets (buf, 256, f))
+ if (*buf != '!' && *buf != 0 && *buf != '\n')
+ server->atom_control_count++;
+
+ if (!server->atom_control_count) {
+ fclose(f);
+ return;
+ }
+
+ server->atom_control = (AtomControlPtr) xalloc (server->atom_control_count *
+ sizeof(AtomControlRec));
+
+ server->atom_control_count = 0;
+
+ if (!server->atom_control) {
+ fclose(f);
+ return;
+ }
+
+ fseek (f, 0, 0);
+
+ while (fgets (buf, 256, f))
+ {
+ if (*buf == '!' || *buf == 0 || *buf == '\n')
+ continue;
+
+ len = strlen(buf);
+ if (buf[len - 1] == '\n')
+ buf[--len] = 0;
+ p = buf;
+ if (*p == 'z') {
+ do {
+ p++;
+ } while (*p == ' ' || *p == '\t');
+ min_keep_prop_size = atoi(p);
+ continue;
+ }
+ server->atom_control[server->atom_control_count].flags = 0;
+ while (*p && *p != ' ' && *p != '\t') {
+ switch (*p) {
+ case 'i':
+ server->atom_control[server->atom_control_count].flags
+ |= AtomPreInternFlag;
+ break;
+ case 'n':
+ server->atom_control[server->atom_control_count].flags
+ |= AtomNoCacheFlag;
+ break;
+ case 'w':
+ server->atom_control[server->atom_control_count].flags
+ |= AtomWMCacheFlag;
+ break;
+ default:
+ fprintf(stderr, "bad atom control: %c\n", *p);
+ break;
+ }
+ p++;
+ }
+ while (*p == ' ' || *p == '\t')
+ p++;
+ if (!*p)
+ continue;
+ len = strlen(p);
+ server->atom_control[server->atom_control_count].name =
+ (char *) xalloc(len + 1);
+ if (server->atom_control[server->atom_control_count].name) {
+ server->atom_control[server->atom_control_count].len = len;
+ strcpy(server->atom_control[server->atom_control_count].name, p);
+ server->atom_control_count++;
+ }
+ }
+
+ fclose(f);
+}
diff --git a/di/wire.c b/di/wire.c
new file mode 100644
index 0000000..41bc3a3
--- /dev/null
+++ b/di/wire.c
@@ -0,0 +1,1577 @@
+/* $Xorg: wire.c,v 1.4 2001/02/09 02:05:32 xorgcvs Exp $ */
+/*
+
+Copyright 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+*/
+/*
+ * Copyright 1992 Network Computing Devices
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of NCD. not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. NCD. makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * NCD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL NCD.
+ * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include "lbx.h"
+#include <stdio.h>
+#include "wire.h"
+#include "init.h"
+#include <sys/uio.h>
+#include <errno.h>
+#include "proxyopts.h"
+#include "swap.h"
+#include "assert.h"
+#include "os.h"
+#include "resource.h"
+#include "colormap.h"
+#include "lbxext.h"
+#include "atomcache.h"
+#include "util.h"
+#include "pm.h"
+#include "misc.h"
+
+#include <X11/ICE/ICElib.h>
+#ifdef BIGREQS
+#include "bigreqstr.h"
+#endif
+
+/*
+ * The following include for utsname.h is from lib/xtrans
+ */
+#if (defined(_POSIX_SOURCE) && !defined(AIXV3)) || defined(hpux) || defined(USG) || defined(SVR4)
+#define NEED_UTSNAME
+#include <sys/utsname.h> /* uname() */
+#else
+#include <unistd.h> /* gethostname() */
+#endif
+
+#ifdef LBX_STATS
+extern int delta_out_total;
+extern int delta_out_attempts;
+extern int delta_out_hits;
+extern int delta_in_total;
+extern int delta_in_attempts;
+extern int delta_in_hits;
+#endif
+
+/*
+ * Local constants
+ */
+#define MAXBYTESDIFF 8
+#define PM_Unable 0
+#define PM_Success 1
+#define PM_Failure 2
+
+/*
+ * Global vars
+ */
+int lbxDebug = 0;
+
+/*
+ * Local functions
+ */
+static void LbxOnlyListenToOneClient();
+static void LbxListenToAllClients();
+
+/*
+ * Any request that could be delta compressed comes through here
+ */
+void
+WriteReqToServer(client, len, buf, checkLargeRequest)
+ ClientPtr client;
+ int len;
+ char *buf;
+ Bool checkLargeRequest;
+{
+ XServerPtr server = client->server;
+ xLbxDeltaReq *p = (xLbxDeltaReq *) server->tempdeltabuf;
+ int diffs;
+ int cindex;
+ int newlen;
+ Bool written = FALSE;
+
+#ifdef LBX_STATS
+ delta_out_total++;
+#endif
+
+ if (DELTA_CACHEABLE(&server->outdeltas, len)) {
+
+#ifdef LBX_STATS
+ delta_out_attempts++;
+#endif
+
+ if ((diffs = LBXDeltaMinDiffs(&server->outdeltas, buf, len,
+ min(MAXBYTESDIFF, (len - sz_xLbxDeltaReq) >> 1),
+ &cindex)) >= 0) {
+
+#ifdef LBX_STATS
+ delta_out_hits++;
+#endif
+
+ LBXEncodeDelta(&server->outdeltas, buf, diffs, cindex,
+ &server->tempdeltabuf[sz_xLbxDeltaReq]);
+ p->reqType = server->lbxReq;
+ p->lbxReqType = X_LbxDelta;
+ p->diffs = diffs;
+ p->cindex = cindex;
+ newlen = sz_xLbxDeltaReq + sz_xLbxDiffItem * diffs;
+ p->length = (newlen + 3) >> 2;
+ /* Don't byte swap -- lengths are always in proxy order */
+ WriteToServer(client, newlen, (char *) p, TRUE, checkLargeRequest);
+ written = TRUE;
+ }
+ LBXAddDeltaOut(&server->outdeltas, buf, len);
+ }
+ if (!written) {
+#ifdef BIGREQS
+ if (len > (0xffff << 2)) {
+ xBigReq bigreq;
+ bigreq.reqType = ((xReq *)buf)->reqType;
+ bigreq.data = ((xReq *)buf)->data;
+ bigreq.zero = 0;
+ bigreq.length = (len + sizeof(xBigReq) - sizeof(xReq)) >> 2;
+ WriteToServer(client, sizeof(xBigReq), (char *)&bigreq,
+ TRUE, checkLargeRequest);
+ WriteToServer(client, len - sizeof(xReq), buf + sizeof(xReq),
+ FALSE, checkLargeRequest);
+ return;
+ }
+#endif
+ WriteToServer(client, len, buf, TRUE, checkLargeRequest);
+ }
+}
+
+void
+_write_to_server(client, compressed, len, buf, checkLarge, startOfRequest)
+ ClientPtr client;
+ Bool compressed;
+ int len;
+ char *buf;
+ Bool checkLarge;
+ Bool startOfRequest;
+{
+ XServerPtr server = client->server;
+ unsigned reqSize;
+
+ if (server->serverClient->clientGone)
+ return;
+
+ if (checkLarge && client != clients[0] && nClients > 1 &&
+ ((client != server->prev_exec) || numLargeRequestsInQueue)) {
+ /*
+ * Check if this is a large request only if there is more than
+ * one client and a different client was the last to execute or
+ * there are already large requests queued.
+ *
+ * If it is a large request, and there is room in the large request
+ * queue, add it to the queue. lbxproxy will send the large request
+ * in chunks, preventing this client from hogging the wire.
+ *
+ * By checking that the previous client was someone else,
+ * we hope that we can prevent splitting a large request
+ * when the other clients appear to be idle (based on their past
+ * history).
+ */
+
+ if (startOfRequest &&
+ (!(reqSize = (((xReq *) buf)->length) << 2) ||
+ reqSize >= LBX_LARGE_REQUEST_MIN_SIZE) &&
+ numLargeRequestsInQueue < LARGE_REQUEST_QUEUE_LEN) {
+ LbxLargeRequestRec *largeRequest;
+
+ if (!reqSize)
+ reqSize = ((xBigReq *)buf)->length << 2;
+ largeRequest = (LbxLargeRequestRec *)
+ xalloc (sizeof (LbxLargeRequestRec) + reqSize);
+
+ /*
+ * Add this large request to the queue
+ */
+
+ largeRequest->client = client;
+ largeRequest->compressed = compressed;
+ largeRequest->buf = (char *) largeRequest +
+ sizeof (LbxLargeRequestRec);
+ memcpy (largeRequest->buf, buf, len);
+ largeRequest->totalBytes = reqSize;
+ largeRequest->bytesRead = len;
+ largeRequest->bytesWritten = 0;
+ client->largeRequest = largeRequest;
+
+ largeRequestQueue[numLargeRequestsInQueue++] = largeRequest;
+
+ /*
+ * Once we have the whole large request, we want to disable
+ * input from this client - we don't want to read new requests
+ * until we are done sending the whole large request.
+ */
+
+ if (reqSize == len)
+ IgnoreClient(client);
+
+ return;
+ } else if (client->largeRequest) {
+
+ /*
+ * Append to the large request
+ */
+
+ char *dst = client->largeRequest->buf +
+ client->largeRequest->bytesRead;
+ memcpy (dst, buf, len);
+ client->largeRequest->bytesRead += len;
+
+ /*
+ * Once we have the whole large request, we want to disable
+ * input from this client - we don't want to read new requests
+ * until we are done sending the whole large request.
+ */
+
+ if (client->largeRequest->bytesRead ==
+ client->largeRequest->totalBytes)
+ IgnoreClient(client);
+
+ return;
+ }
+ }
+
+ if (server->send != client) {
+ xLbxSwitchReq s;
+
+ DBG(DBG_SWITCH, (stderr, "switch downstream to %d\n", client->index));
+ s.reqType = server->lbxReq;
+ s.lbxReqType = X_LbxSwitch;
+ s.length = 2;
+ s.client = client->index;
+ WriteToClient(server->serverClient, sizeof(s), &s);
+ server->send = client;
+ }
+ DBG(DBG_IO, (stderr, "downstream %d len %d\n", client->index, len));
+ if (compressed || !server->compHandle)
+ WriteToClient(server->serverClient, len, buf);
+ else
+ UncompressWriteToClient(server->serverClient, len, buf);
+}
+
+void
+WriteToServer(client, len, buf, startOfRequest, checkLargeRequest)
+ ClientPtr client;
+ int len;
+ char *buf;
+ Bool startOfRequest;
+ Bool checkLargeRequest;
+{
+ _write_to_server(client, TRUE, len, buf, checkLargeRequest, startOfRequest);
+}
+
+void
+WriteToServerUncompressed(client, len, buf, startOfRequest)
+ ClientPtr client;
+ int len;
+ char *buf;
+ Bool startOfRequest;
+{
+ _write_to_server(client, FALSE, len, buf, TRUE, startOfRequest);
+}
+
+/* all these requests may need to be swapped back to the order of
+ * the client they're being executed for
+ */
+Bool
+NewClient(client, setuplen)
+ ClientPtr client;
+ int setuplen;
+{
+ xLbxNewClientReq n;
+ XServerPtr server = client->server;
+
+ DBG(DBG_CLIENT, (stderr, "new client %d\n", client->index));
+ n.reqType = server->lbxReq;
+ n.lbxReqType = X_LbxNewClient;
+ n.length = 2 + (setuplen >> 2);
+ n.client = client->index;
+ WriteToServer(server->serverClient, sizeof(n), (char *) &n, TRUE, FALSE);
+ ++server->serverClient->sequence;
+ return TRUE;
+}
+
+void
+CloseClient(client)
+ ClientPtr client;
+{
+ xLbxCloseClientReq n;
+ XServerPtr server = client->server;
+
+ if (!client->server)
+ return;
+
+ if (client->server->serverClient == client)
+ return;
+ if (client->server->serverClient->clientGone)
+ return;
+ DBG(DBG_CLIENT, (stderr, "closing down client %d\n", client->index));
+ if (client->closeDownMode != DestroyAll) {
+ n.reqType = server->lbxReq;
+ n.lbxReqType = X_LbxCloseClient;
+ n.length = 2;
+ n.client = client->index;
+ if (client->swapped) {
+ SwapCloseClient(&n);
+ }
+ WriteReqToServer(client, sizeof(n), (char *) &n, TRUE);
+ }
+}
+
+void
+ModifySequence(client, num)
+ ClientPtr client;
+ int num;
+{
+ xLbxModifySequenceReq req;
+ XServerPtr server = client->server;
+
+ if (client->server->serverClient == client)
+ return;
+ req.reqType = server->lbxReq;
+ req.lbxReqType = X_LbxModifySequence;
+ req.length = 2;
+ req.adjust = num;
+ if (client->swapped) {
+ SwapModifySequence(&req);
+ }
+ WriteReqToServer(client, sizeof(req), (char *) &req, TRUE);
+}
+
+void
+AllowMotion(client, num)
+ ClientPtr client;
+ int num;
+{
+ client->server->motion_allowed += num;
+}
+
+void
+SendIncrementPixel(client, cmap, pixel)
+ ClientPtr client;
+ XID cmap;
+ unsigned long pixel;
+{
+ xLbxIncrementPixelReq req;
+ XServerPtr server = client->server;
+
+ if (client->server->serverClient == client)
+ return;
+ req.reqType = server->lbxReq;
+ req.lbxReqType = X_LbxIncrementPixel;
+ req.length = 3;
+ req.cmap = cmap;
+ req.pixel = pixel;
+ if (client->swapped) {
+ SwapIncrementPixel(&req);
+ }
+ WriteReqToServer(client, sizeof(req), (char *) &req, TRUE);
+}
+
+void
+SendAllocColor(client, cmap, pixel, red, green, blue)
+ ClientPtr client;
+ XID cmap;
+ CARD16 red, green, blue;
+{
+ xLbxAllocColorReq req;
+
+ req.reqType = client->server->lbxReq;
+ req.lbxReqType = X_LbxAllocColor;
+ req.length = sz_xLbxAllocColorReq >> 2;
+ req.cmap = cmap;
+ req.pixel = pixel;
+ req.red = red;
+ req.green = green;
+ req.blue = blue;
+ req.pad = 0;
+
+ if (client->swapped)
+ SwapAllocColor (&req);
+
+ WriteReqToServer (client, sizeof(req), (char *) &req, TRUE);
+}
+
+void
+SendGetModifierMapping(client)
+ ClientPtr client;
+{
+ xLbxGetModifierMappingReq req;
+ XServerPtr server = client->server;
+
+ if (client->server->serverClient == client)
+ return;
+
+ req.reqType = server->lbxReq;
+ req.lbxReqType = X_LbxGetModifierMapping;
+ req.length = 1;
+ if (client->swapped) {
+ SwapGetModifierMapping(&req);
+ }
+ WriteReqToServer(client, sizeof(req), (char *) &req, TRUE);
+}
+
+void
+SendGetKeyboardMapping(client)
+ ClientPtr client;
+{
+ xLbxGetKeyboardMappingReq req;
+ XServerPtr server = client->server;
+
+ if (client->server->serverClient == client)
+ return;
+
+ /*
+ * always ask for entire thing so tag always works, and pass on requested
+ * subset
+ */
+ req.reqType = server->lbxReq;
+ req.lbxReqType = X_LbxGetKeyboardMapping;
+ req.length = 2;
+ req.firstKeyCode = LBXMinKeyCode(client);
+ req.count = LBXMaxKeyCode(client) - LBXMinKeyCode(client) + 1;
+ req.pad1 = 0;
+ if (client->swapped) {
+ SwapGetKeyboardMapping(&req);
+ }
+ WriteReqToServer(client, sizeof(req), (char *) &req, TRUE);
+}
+
+void
+SendQueryFont(client, fid)
+ ClientPtr client;
+ XID fid;
+{
+ xLbxQueryFontReq req;
+ XServerPtr server = client->server;
+
+ if (client->server->serverClient == client)
+ return;
+
+ req.reqType = server->lbxReq;
+ req.lbxReqType = X_LbxQueryFont;
+ req.length = 2;
+ req.fid = fid;
+ if (client->swapped) {
+ SwapQueryFont(&req);
+ }
+ WriteReqToServer(client, sizeof(req), (char *) &req, TRUE);
+}
+
+void
+SendChangeProperty(client, win, prop, type, format, mode, num)
+ ClientPtr client;
+ Window win;
+ Atom prop,
+ type;
+ int format,
+ mode;
+ unsigned long num;
+{
+ xLbxChangePropertyReq req;
+ XServerPtr server = client->server;
+
+ if (client->server->serverClient == client)
+ return;
+
+ req.reqType = server->lbxReq;
+ req.lbxReqType = X_LbxChangeProperty;
+ req.length = 6;
+ req.window = win;
+ req.property = prop;
+ req.type = type;
+ req.format = format;
+ req.mode = mode;
+ req.nUnits = num;
+ req.pad[0] = req.pad[1] = 0;
+ if (client->swapped) {
+ SwapChangeProperty(&req);
+ }
+ WriteReqToServer(client, sizeof(req), (char *) &req, TRUE);
+}
+
+void
+SendGetProperty(client, win, prop, type, delete, off, len)
+ ClientPtr client;
+ Window win;
+ Atom prop,
+ type;
+ Bool delete;
+ unsigned long off,
+ len;
+{
+ xLbxGetPropertyReq req;
+ XServerPtr server = client->server;
+
+ if (client->server->serverClient == client)
+ return;
+
+ req.reqType = server->lbxReq;
+ req.lbxReqType = X_LbxGetProperty;
+ req.length = 7;
+ req.window = win;
+ req.property = prop;
+ req.type = type;
+ req.delete = delete;
+ req.longOffset = off;
+ req.longLength = len;
+ req.pad[0] = req.pad[1] = req.pad[2] = 0;
+ if (client->swapped) {
+ SwapGetProperty(&req);
+ }
+ WriteReqToServer(client, sizeof(req), (char *) &req, TRUE);
+}
+
+void
+SendInvalidateTag(client, tag)
+ ClientPtr client;
+ XID tag;
+{
+ xLbxInvalidateTagReq req;
+ XServerPtr server;
+
+ if (!servers[0]) /* proxy resetting */
+ return;
+
+ server = client->server;
+
+ req.reqType = server->lbxReq;
+ req.lbxReqType = X_LbxInvalidateTag;
+ req.length = 2;
+ req.tag = tag;
+ /* need tag type ? */
+ if (client->swapped) {
+ SwapInvalidateTag(&req);
+ }
+ WriteReqToServer(client, sizeof(req), (char *) &req, TRUE);
+}
+
+void
+SendTagData(client, tag, len, data)
+ ClientPtr client;
+ XID tag;
+ unsigned long len;
+ pointer data;
+{
+ xLbxTagDataReq req,
+ *reqp;
+ int req_len;
+ XServerPtr server;
+
+ server = client->server;
+
+ req_len = 3 + ((len + 3) >> 2);
+ if (DELTA_CACHEABLE(&server->outdeltas, req_len << 2)) {
+ reqp = (xLbxTagDataReq *) xalloc(req_len << 2);
+ memcpy((pointer) (reqp + 1), data, len);
+ } else {
+ reqp = &req;
+ }
+ reqp->reqType = server->lbxReq;
+ reqp->lbxReqType = X_LbxTagData;
+ reqp->length = req_len;
+ reqp->real_length = len;
+ reqp->tag = tag;
+ /* need tag type ? */
+ if (reqp == &req) {
+ WriteToServer(server->serverClient,
+ sizeof(req), (char *) &req, TRUE, FALSE);
+ if (len)
+ WriteToServer(server->serverClient,
+ len, (char *) data, FALSE, FALSE);
+ } else {
+ WriteReqToServer(server->serverClient,
+ req_len << 2, (char *) reqp, FALSE);
+ xfree(reqp);
+ }
+}
+
+void
+SendGetImage(client, drawable, x, y, width, height, planeMask, format)
+ ClientPtr client;
+ Drawable drawable;
+ int x;
+ int y;
+ unsigned int width;
+ unsigned int height;
+ unsigned long planeMask;
+ int format;
+{
+ xLbxGetImageReq req;
+ XServerPtr server = client->server;
+
+ if (client->server->serverClient == client)
+ return;
+
+ req.reqType = server->lbxReq;
+ req.lbxReqType = X_LbxGetImage;
+ req.length = 6;
+ req.drawable = drawable;
+ req.x = x;
+ req.y = y;
+ req.width = width;
+ req.height = height;
+ req.planeMask = planeMask;
+ req.format = format;
+ req.pad1 = 0;
+ req.pad2 = 0;
+
+ if (client->swapped) {
+ SwapGetImage(&req);
+ }
+ WriteReqToServer(client, sizeof(req), (char *) &req, TRUE);
+}
+
+static Bool
+SendInternAtoms (server)
+ XServerPtr server;
+{
+ xLbxInternAtomsReq *req;
+ int reqSize, i, num;
+ char lenbuf[2];
+ char *ptr;
+
+ reqSize = sz_xLbxInternAtomsReq;
+ num = 0;
+ for (i = 0; i < server->atom_control_count; i++) {
+ if (server->atom_control[i].flags & AtomPreInternFlag) {
+ reqSize += (2 + server->atom_control[i].len);
+ num++;
+ }
+ }
+ if (!num)
+ return FALSE;
+
+ if (!(req = (xLbxInternAtomsReq *) xalloc (reqSize)))
+ return FALSE;
+
+ req->reqType = server->lbxReq;
+ req->lbxReqType = X_LbxInternAtoms;
+ req->length = (reqSize + 3) >> 2;
+ req->num = num;
+
+ ptr = (char *) req + sz_xLbxInternAtomsReq;
+
+ for (i = 0; i < server->atom_control_count; i++)
+ {
+ if (server->atom_control[i].flags & AtomPreInternFlag) {
+ *((CARD16 *) lenbuf) = server->atom_control[i].len;
+ ptr[0] = lenbuf[0];
+ ptr[1] = lenbuf[1];
+ ptr += 2;
+ memcpy (ptr,
+ server->atom_control[i].name,
+ server->atom_control[i].len);
+ ptr += server->atom_control[i].len;
+ }
+ }
+
+ WriteToClient(server->serverClient, reqSize, (char *) req);
+
+ xfree (req);
+ return TRUE;
+}
+
+/*ARGSUSED*/
+static void
+InternAtomsReply (server, rep)
+ XServerPtr server;
+ xLbxInternAtomsReply *rep;
+{
+ Atom *atoms = (Atom *) ((char *) rep + sz_xLbxInternAtomsReplyHdr);
+ int i;
+
+ for (i = 0; i < server->atom_control_count; i++) {
+ if (server->atom_control[i].flags & AtomPreInternFlag)
+ (void) LbxMakeAtom (server,
+ server->atom_control[i].name,
+ server->atom_control[i].len,
+ *atoms++, TRUE);
+ }
+
+ SendInitLBXPackets(server);
+
+ /*
+ * Now the proxy is ready to accept connections from clients.
+ */
+
+ (void) ListenWellKnownSockets ();
+}
+
+
+static unsigned long pendingServerReplySequence;
+static void (*serverReplyFunc) ();
+
+static void
+ServerReply(server, rep)
+ XServerPtr server;
+ xReply *rep;
+{
+ if (serverReplyFunc &&
+ rep->generic.sequenceNumber == pendingServerReplySequence) {
+ /*
+ * We got the reply we were waiting from the server
+ */
+
+ (*serverReplyFunc) (server, rep);
+
+ /*
+ * ExpectServerReply() might have been called within the server
+ * reply func just processed.
+ */
+
+ if (rep->generic.sequenceNumber == pendingServerReplySequence)
+ serverReplyFunc = 0;
+ }
+}
+
+static void
+ExpectServerReply(server, func)
+ XServerPtr server;
+ void (*func) ();
+{
+ pendingServerReplySequence = server->serverClient->sequence;
+ serverReplyFunc = func;
+}
+
+extern int (*ServerVector[]) ();
+
+static unsigned long
+ServerRequestLength(req, sc, gotnow, partp)
+ xReq *req;
+ ClientPtr sc;
+ int gotnow;
+ Bool *partp;
+{
+ XServerPtr server = servers[sc->lbxIndex];
+ ClientPtr client = server->recv;
+ xReply *rep;
+ xConnSetupPrefix *pre;
+
+ if (!req)
+ req = (xReq *) sc->requestBuffer;
+ if (gotnow < sizeof(xReq)) {
+ *partp = TRUE;
+ return sizeof(xReq);
+ }
+ if (req->reqType == server->lbxEvent && req->data == LbxDeltaEvent) {
+ *partp = FALSE;
+ return req->length << 2;
+ }
+ if (req->reqType == server->lbxEvent && req->data == LbxSwitchEvent) {
+ *partp = FALSE;
+ return sz_xLbxSwitchEvent;
+ }
+ if (req->reqType == server->lbxEvent + LbxQuickMotionDeltaEvent) {
+ *partp = FALSE;
+ return sz_lbxQuickMotionDeltaEvent;
+ }
+ if (req->reqType == server->lbxEvent && req->data == LbxMotionDeltaEvent) {
+ *partp = FALSE;
+ return sz_lbxMotionDeltaEvent;
+ }
+ if (client->awaitingSetup) {
+ if (gotnow < 8) {
+ *partp = TRUE;
+ return 8;
+ }
+ pre = (xConnSetupPrefix *) req;
+ *partp = FALSE;
+ return 8 + (pre->length << 2);
+ }
+ if (gotnow < 8) {
+ *partp = TRUE;
+ return 8;
+ }
+ *partp = FALSE;
+ rep = (xReply *) req;
+ if (rep->generic.type != X_Reply) {
+ return EventLength((xEvent *)rep, server->lbxNegOpt.squish);
+ }
+ return sz_xReply + (rep->generic.length << 2);
+}
+
+int
+ServerProcStandardEvent(sc)
+ ClientPtr sc;
+{
+ xReply *rep;
+ XServerPtr server = servers[sc->lbxIndex];
+ ClientPtr client = server->recv;
+ int len;
+ Bool part;
+ Bool cacheable = (server->initialized) ? TRUE : FALSE;
+
+ rep = (xReply *) sc->requestBuffer;
+
+ /* need to calculate length up from for Delta cache */
+ len = RequestLength(rep, sc, 8, &part);
+
+#ifdef LBX_STATS
+ delta_in_total++;
+#endif
+
+ if (rep->generic.type == server->lbxEvent &&
+ rep->generic.data1 == LbxDeltaEvent) {
+ xLbxDeltaReq *delta = (xLbxDeltaReq *) rep;
+
+#ifdef LBX_STATS
+ delta_in_attempts++;
+ delta_in_hits++;
+#endif
+
+ /* Note that LBXDecodeDelta decodes and adds current msg to the cache */
+ len = LBXDecodeDelta(&server->indeltas, ((char *) rep) + sz_xLbxDeltaReq,
+ delta->diffs, delta->cindex, &rep);
+
+ /* Make local copy in case someone writes to the request buffer */
+ memcpy(server->tempdeltabuf, (char *) rep, len);
+ rep = (xReply *) server->tempdeltabuf;
+
+ cacheable = FALSE;
+ }
+
+ /* stick in delta buffer before LBX code modified things */
+ if (cacheable && DELTA_CACHEABLE(&server->indeltas, len)) {
+
+#ifdef LBX_STATS
+ delta_in_attempts++;
+#endif
+
+ LBXAddDeltaIn(&server->indeltas, (char *) rep, len);
+ }
+ if (rep->generic.type == server->lbxEvent &&
+ rep->generic.data1 != LbxMotionDeltaEvent) {
+ switch (rep->generic.data1) {
+ case LbxSwitchEvent:
+ DBG(DBG_SWITCH, (stderr, "switch upstream to %d\n",
+ ((xLbxSwitchEvent *)rep)->client));
+ client = clients[((xLbxSwitchEvent *)rep)->client];
+ server->recv = client;
+ (void) CheckPendingClientInput(sc);
+ break;
+ case LbxCloseEvent:
+ DBG(DBG_CLIENT, (stderr, "close client %d\n",
+ ((xLbxCloseEvent *)rep)->client));
+ client = clients[((xLbxCloseEvent *)rep)->client];
+ client->closeDownMode = DestroyAll;
+ CloseDownClient(client);
+ break;
+ case LbxInvalidateTagEvent:
+ DBG(DBG_CLIENT, (stderr, "invalidate tag %d type %d\n",
+ ((xLbxInvalidateTagEvent *)rep)->tag,
+ ((xLbxInvalidateTagEvent *)rep)->tagType));
+ LbxFreeTag(server,
+ ((xLbxInvalidateTagEvent *)rep)->tag,
+ ((xLbxInvalidateTagEvent *)rep)->tagType);
+ break;
+ case LbxSendTagDataEvent:
+ DBG(DBG_CLIENT, (stderr, "send tag data %d type %d\n",
+ ((xLbxSendTagDataEvent *)rep)->tag,
+ ((xLbxSendTagDataEvent *)rep)->tagType));
+ LbxSendTagData(sc,
+ ((xLbxSendTagDataEvent *)rep)->tag,
+ ((xLbxSendTagDataEvent *)rep)->tagType);
+ break;
+ case LbxListenToOne:
+ DBG(DBG_CLIENT, (stderr, "listen to one client %d\n",
+ ((xLbxListenToOneEvent *)rep)->client));
+ if (((xLbxListenToOneEvent *)rep)->client == 0xffffffff)
+ LbxOnlyListenToOneClient(server->serverClient);
+ else
+ LbxOnlyListenToOneClient(clients[((xLbxListenToOneEvent *)rep)->client]);
+ break;
+ case LbxListenToAll:
+ DBG(DBG_CLIENT, (stderr, "listen to all clients\n"));
+ LbxListenToAllClients(server);
+ break;
+ case LbxReleaseCmapEvent:
+ {
+ Colormap cmap = ((xLbxReleaseCmapEvent *)rep)->colormap;
+ ColormapPtr pmap;
+
+ pmap = (ColormapPtr) LookupIDByType (client, cmap, RT_COLORMAP);
+#ifdef COLOR_DEBUG
+ fprintf (stderr, "\nGot LbxReleaseCmapEvent, cmap = 0x%x\n\n", cmap);
+#endif
+ if (pmap && pmap->grab_status == CMAP_GRABBED)
+ ReleaseCmap (client, pmap);
+ break;
+ }
+ case LbxFreeCellsEvent:
+ {
+ Colormap cmap = ((xLbxFreeCellsEvent *)rep)->colormap;
+ Pixel start = ((xLbxFreeCellsEvent *)rep)->pixelStart;
+ Pixel end = ((xLbxFreeCellsEvent *)rep)->pixelEnd;
+ ColormapPtr pmap;
+
+ pmap = (ColormapPtr) LookupIDByType (client, cmap, RT_COLORMAP);
+#ifdef COLOR_DEBUG
+ fprintf (stderr, "\nGot LbxFreeCellsEvent, cmap = 0x%x, ", cmap);
+ fprintf (stderr, "startPixel = %d, endPixel = %d\n\n",
+ start, end);
+#endif
+ if (pmap && pmap->grab_status == CMAP_GRABBED)
+ GotServerFreeCellsEvent (pmap, start, end, 1);
+ break;
+ }
+ }
+ } else if ((rep->generic.type == server->lbxEvent &&
+ rep->generic.data1 == LbxMotionDeltaEvent) ||
+ (rep->generic.type == server->lbxEvent + LbxQuickMotionDeltaEvent))
+ {
+ lbxMotionCache *motionCache = &server->motionCache;
+
+ /*
+ * We use the motion delta event to generate a real MotionNotify event.
+ *
+ * The motion cache contains the last motion event we got from
+ * the server.
+ *
+ * The following are always stored in the cache in the proxy's
+ * byte order:
+ * sequenceNumber, time, rootX, rootY, eventX, eventY
+ * This is because when constructing the MotionNotify event using
+ * the delta event, we must do arithmetic in the proxy's byte order.
+ *
+ * The following are stored in the byte order of the latest client
+ * receiving a motion event (indicated by motionCache->swapped):
+ * root, event, child, state
+ * The assumption is that a client will receive a series of motion
+ * events, and we don't want to unnecessarily swap these fields.
+ * If the next motion event goes to a client with a byte order
+ * different from the previous client, we will have to swap these
+ * fields.
+ */
+
+ AllowMotion(client, 1);
+
+ if (rep->generic.type == server->lbxEvent)
+ {
+ lbxMotionDeltaEvent *mev = (lbxMotionDeltaEvent *) rep;
+
+ motionCache->sequenceNumber += mev->deltaSequence;
+ motionCache->time += mev->deltaTime;
+ motionCache->rootX += mev->deltaX;
+ motionCache->rootY += mev->deltaY;
+ motionCache->eventX += mev->deltaX;
+ motionCache->eventY += mev->deltaY;
+ }
+ else
+ {
+ lbxQuickMotionDeltaEvent *qmev = (lbxQuickMotionDeltaEvent *) rep;
+
+ motionCache->time += qmev->deltaTime;
+ motionCache->rootX += qmev->deltaX;
+ motionCache->rootY += qmev->deltaY;
+ motionCache->eventX += qmev->deltaX;
+ motionCache->eventY += qmev->deltaY;
+ }
+
+ if (!client->clientGone) {
+ xEvent ev;
+ int n;
+
+ if (motionCache->swapped != client->swapped)
+ {
+ swapl (&motionCache->root, n);
+ swapl (&motionCache->event, n);
+ swapl (&motionCache->child, n);
+ swaps (&motionCache->state, n);
+ motionCache->swapped = client->swapped;
+ }
+
+ ev.u.u.type = MotionNotify;
+ ev.u.u.detail = motionCache->detail;
+ ev.u.u.sequenceNumber = motionCache->sequenceNumber;
+ ev.u.keyButtonPointer.time = motionCache->time;
+ ev.u.keyButtonPointer.rootX = motionCache->rootX;
+ ev.u.keyButtonPointer.rootY = motionCache->rootY;
+ ev.u.keyButtonPointer.eventX = motionCache->eventX;
+ ev.u.keyButtonPointer.eventY = motionCache->eventY;
+ ev.u.keyButtonPointer.root = motionCache->root;
+ ev.u.keyButtonPointer.event = motionCache->event;
+ ev.u.keyButtonPointer.child = motionCache->child;
+ ev.u.keyButtonPointer.state = motionCache->state;
+ ev.u.keyButtonPointer.sameScreen = motionCache->sameScreen;
+
+ if (client->swapped) {
+ swaps (&ev.u.u.sequenceNumber, n);
+ swapl (&ev.u.keyButtonPointer.time, n);
+ swaps (&ev.u.keyButtonPointer.rootX, n);
+ swaps (&ev.u.keyButtonPointer.rootY, n);
+ swaps (&ev.u.keyButtonPointer.eventX, n);
+ swaps (&ev.u.keyButtonPointer.eventY, n);
+ }
+ /*
+ * Write the reply
+ */
+
+ DoLBXReply (client, (char *) &ev, sz_xEvent);
+ }
+
+ } else {
+ len = RequestLength(rep, sc, 8, &part);
+ DBG(DBG_IO, (stderr, "upstream %d len %d\n", client->index, len));
+ if (client->index == 0) {
+ ServerReply(server, rep);
+ } else {
+ xEvent ev;
+ char *rp;
+ int n;
+
+ if (!client->awaitingSetup && UnsquishEvent(rep, &ev, &len))
+ rp = (char *) &ev;
+ else
+ rp = (char *) rep;
+
+ if (rep->generic.type == MotionNotify) {
+ xEvent *mev = (xEvent *) rp;
+ lbxMotionCache *motionCache = &server->motionCache;
+
+ AllowMotion(client, 1);
+ motionCache->swapped = client->swapped;
+ motionCache->detail = mev->u.u.detail;
+ motionCache->root = mev->u.keyButtonPointer.root;
+ motionCache->event = mev->u.keyButtonPointer.event;
+ motionCache->child = mev->u.keyButtonPointer.child;
+ motionCache->state = mev->u.keyButtonPointer.state;
+ motionCache->sameScreen = mev->u.keyButtonPointer.sameScreen;
+ motionCache->sequenceNumber = mev->u.u.sequenceNumber;
+ motionCache->time = mev->u.keyButtonPointer.time;
+ motionCache->rootX = mev->u.keyButtonPointer.rootX;
+ motionCache->rootY = mev->u.keyButtonPointer.rootY;
+ motionCache->eventX = mev->u.keyButtonPointer.eventX;
+ motionCache->eventY = mev->u.keyButtonPointer.eventY;
+ if (client->swapped)
+ {
+ swaps(&motionCache->sequenceNumber, n);
+ swapl(&motionCache->time, n);
+ swaps(&motionCache->rootX, n);
+ swaps(&motionCache->rootY, n);
+ swaps(&motionCache->eventX, n);
+ swaps(&motionCache->eventY, n);
+ }
+ }
+
+ /*
+ * Write the reply
+ */
+
+ if (!client->clientGone)
+ DoLBXReply (client, rp, len);
+ client->awaitingSetup = FALSE;
+ }
+ }
+
+ return Success;
+}
+
+static void
+LbxIgnoreAllClients(server)
+ XServerPtr server;
+{
+ if (!server->lbxIgnoringAll) {
+ if (GrabInProgress) {
+ server->lbxGrabInProgress = GrabInProgress;
+ ListenToAllClients();
+ }
+ OnlyListenToOneClient(server->serverClient);
+ server->lbxIgnoringAll = TRUE;
+ }
+}
+
+/* ARGSUSED */
+static void
+LbxAttendAllClients(server)
+ XServerPtr server;
+{
+ if (server->lbxIgnoringAll) {
+ ListenToAllClients();
+ server->lbxIgnoringAll = FALSE;
+ if (server->lbxGrabInProgress) {
+ OnlyListenToOneClient(clients[server->lbxGrabInProgress]);
+ server->lbxGrabInProgress = 0;
+ }
+ }
+}
+
+/* ARGSUSED */
+static void
+LbxOnlyListenToOneClient(client)
+ ClientPtr client;
+{
+ /*
+ * For a multi-display proxy, there is no need to do anything -
+ * don't want one server grab to impact the clients for a
+ * different server.
+ */
+ return;
+}
+
+/* ARGSUSED */
+static void
+LbxListenToAllClients(server)
+ XServerPtr server;
+{
+ /*
+ * For a multi-display proxy, there is no need to do anything -
+ * don't want one server grab to impact the clients for a
+ * different server.
+ */
+ return;
+}
+
+/* ARGSUSED */
+static Bool
+ProxyWorkProc(dummy, index)
+ pointer dummy;
+ int index;
+{
+ XServerPtr server;
+ xLbxAllowMotionReq req;
+
+ if ((server = servers[index]) == 0)
+ return TRUE;
+ if (!server->initialized)
+ return TRUE;
+
+ if (server->motion_allowed) {
+ DBG(DBG_CLIENT, (stderr, "allow %d motion events\n",
+ server->motion_allowed));
+ req.reqType = server->lbxReq;
+ req.lbxReqType = X_LbxAllowMotion;
+ req.length = 2;
+ req.num = server->motion_allowed;
+ server->motion_allowed = 0;
+ WriteToClient(server->serverClient, sizeof(req), &req);
+ }
+ /* Need to flush the output buffers before we flush compression buffer */
+ if (NewOutputPending)
+ FlushAllOutput();
+
+ if (server->compHandle) {
+ if (server->lbxNegOpt.streamOpts.streamCompInputAvail(server->fd))
+ AvailableClientInput(server->serverClient);
+ if (server->lbxNegOpt.streamOpts.streamCompFlush(server->fd) != 0)
+ MarkConnectionWriteBlocked(server->serverClient);
+ }
+ /*
+ * If we've got stuff remaining in the output buffers to the server, then
+ * don't allow reads from any other clients, otherwise we could overflow.
+ */
+ if (PendingClientOutput(server->serverClient))
+ LbxIgnoreAllClients(server);
+ else
+ LbxAttendAllClients(server);
+
+ return FALSE;
+}
+
+Bool reconnectAfterCloseServer = FALSE;
+
+void
+CloseServer(client)
+ ClientPtr client; /* This client is connected to a display server */
+{
+ XServerPtr server;
+ int i;
+ int found;
+
+ DBG(DBG_CLOSE, (stderr, "closing down server\n"));
+
+ server = client->server;
+ servers[server->index] = 0;
+ LBXFreeDeltaCache(&server->indeltas);
+ LBXFreeDeltaCache(&server->outdeltas);
+ if (server->compHandle)
+ server->lbxNegOpt.streamOpts.streamCompFreeHandle(server->compHandle);
+
+ /*
+ * If another server is still active, don't terminate
+ */
+ for (found = 0, i = 0; i < lbxMaxServers; i++) {
+ if (servers[i]) {
+ found = 1;
+ break;
+ }
+ }
+ if (!found && !reconnectAfterCloseServer)
+ dispatchException |= DE_TERMINATE;
+
+ /*
+ * Close all of the "real" clients for this server
+ */
+ for (i = 1; i < currentMaxClients; i++) {
+ if (clients[i] &&
+ clients[i] != client &&
+ clients[i]->server == server) {
+
+ client->clientGone = TRUE;
+ CloseClient (clients[i]);
+ FreeClientResources (clients[i]);
+ CloseDownConnection (clients[i]);
+ if (clients[i]->index < nextFreeClientID)
+ nextFreeClientID = clients[i]->index;
+ clients[i] = NullClient;
+ xfree (clients[i]);
+ --nClients;
+ while (!clients[currentMaxClients-1])
+ currentMaxClients--;
+ }
+ }
+
+ /*
+ * Need to remove this server's listen port(s)
+ */
+ for (i=0; i < MAXTRANSPORTS; i++)
+ if (server->listen_fds[i] != -1) {
+ close (server->listen_fds[i]);
+ FD_CLR (server->listen_fds[i], &WellKnownConnections);
+ FD_CLR (server->listen_fds[i], &AllSockets);
+ }
+
+ /* remove all back pointers */
+ for (i = 1; i < currentMaxClients; i++) {
+ if (clients[i] && clients[i]->server == server)
+ clients[i]->server = NULL;
+ }
+
+ /*
+ * Try to reconnect to this server
+ */
+ if (reconnectAfterCloseServer && !ConnectToServer (server->display_name)) {
+
+ fprintf (stderr, "could not reconnect to '%s'\n", server->display_name);
+
+ if (!found && !proxyMngr)
+ /*
+ * There is no need to continue if there is no proxyManager
+ */
+ dispatchException |= DE_TERMINATE;
+ }
+
+ if (server->display_name)
+ free (server->display_name);
+ if (server->proxy_name)
+ free (server->proxy_name);
+ xfree (server->requestVector);
+ xfree(server);
+
+ CloseDownFileDescriptor(client);
+
+ isItTimeToYield = 1;
+}
+
+
+static void
+StartProxyReply(server, rep)
+ XServerPtr server;
+ xLbxStartReply *rep;
+{
+ int replylen;
+
+ replylen = (rep->length << 2) + sz_xLbxStartReply - sz_xLbxStartReplyHdr;
+ if (rep->nOpts == 0xff) {
+ fprintf(stderr, "WARNING: option negotiation failed - using defaults\n");
+ LbxOptInit(server);
+ } else if (LbxOptParseReply(server, rep->nOpts,
+ (unsigned char *)&rep->optDataStart, replylen) < 0) {
+ FatalError("Bad options from server");
+ }
+
+#ifdef OPTDEBUG
+ fprintf(stderr, "server: N = %d, maxlen = %d, proxy: N = %d, maxlen = %d\n",
+ server->lbxNegOpt.serverDeltaN, server->lbxNegOpt.serverDeltaMaxLen,
+ server->lbxNegOpt.proxyDeltaN, server->lbxNegOpt.proxyDeltaMaxLen);
+#endif
+
+ LBXInitDeltaCache(&server->indeltas, server->lbxNegOpt.serverDeltaN,
+ server->lbxNegOpt.serverDeltaMaxLen);
+ LBXInitDeltaCache(&server->outdeltas, server->lbxNegOpt.proxyDeltaN,
+ server->lbxNegOpt.proxyDeltaMaxLen);
+ QueueWorkProc(ProxyWorkProc, NULL, (pointer) server->index);
+
+#ifdef OPTDEBUG
+ fprintf(stderr, "squishing = %d\n", server->lbxNegOpt.squish);
+ fprintf(stderr, "useTags = %d\n", server->lbxNegOpt.useTags);
+#endif
+
+ TagsInit(server, server->lbxNegOpt.useTags);
+
+ if (!server->lbxNegOpt.useTags)
+ {
+ ProcVector[X_GetModifierMapping] = ProcStandardRequest;
+ ProcVector[X_GetKeyboardMapping] = ProcStandardRequest;
+ ProcVector[X_QueryFont] = ProcStandardRequest;
+ ProcVector[X_ChangeProperty] = ProcStandardRequest;
+ ProcVector[X_GetProperty] = ProcStandardRequest;
+ }
+
+ if (server->lbxNegOpt.streamOpts.streamCompInit) {
+ unsigned char *extra = (unsigned char *) rep;
+ int len = sizeof(xReply) + (rep->length << 2);
+ int left = BytesInClientBuffer(server->serverClient);
+
+ server->compHandle =
+ (*server->lbxNegOpt.streamOpts.streamCompInit) (
+ server->fd, server->lbxNegOpt.streamOpts.streamCompArg);
+ SwitchConnectionFuncs(server->serverClient,
+ server->lbxNegOpt.streamOpts.streamCompRead,
+ server->lbxNegOpt.streamOpts.streamCompWriteV);
+ extra += len;
+ server->lbxNegOpt.streamOpts.streamCompStuffInput(server->fd,
+ extra,
+ left);
+ SkipInClientBuffer(server->serverClient, left + len, 0);
+ StartOutputCompression(server->serverClient,
+ server->lbxNegOpt.streamOpts.streamCompOn,
+ server->lbxNegOpt.streamOpts.streamCompOff);
+ }
+ server->initialized = TRUE;
+ MakeClientGrabImpervious(server->serverClient);
+
+ if (SendInternAtoms(server))
+ ExpectServerReply (server, InternAtomsReply);
+ else
+ {
+ SendInitLBXPackets(server);
+
+ /*
+ * Now the proxy is ready to accept connections from clients.
+ */
+
+ (void) ListenWellKnownSockets ();
+ }
+}
+
+static void
+StartProxy(server)
+ XServerPtr server;
+{
+ char buf[1024];
+ int reqlen;
+ xLbxStartProxyReq *n = (xLbxStartProxyReq *) buf;
+
+ LbxOptInit(server);
+ n->reqType = server->lbxReq;
+ n->lbxReqType = X_LbxStartProxy;
+ reqlen = LbxOptBuildReq(server, buf + sz_xLbxStartProxyReq);
+ assert(reqlen > 0 && reqlen + sz_xLbxStartProxyReq <= 1024);
+ n->length = (reqlen + sz_xLbxStartProxyReq + 3) >> 2;
+ /*
+ * Don't call WriteToServer because we don't want to switch.
+ */
+ WriteToClient(server->serverClient, n->length << 2, (char *) n);
+ server->serverClient->sequence++;
+ ExpectServerReply(server, StartProxyReply);
+ while (NewOutputPending)
+ FlushAllOutput();
+}
+
+static Bool
+InitServer (dpy_name, i, server, sequencep)
+ char* dpy_name;
+ int i;
+ XServerPtr server;
+ int* sequencep;
+{
+ server->index = i;
+
+ DBG(DBG_IO, (stderr, "making server connection\n"));
+ server->dpy = DisplayOpen (dpy_name,
+ &server->lbxReq,
+ &server->lbxEvent,
+ &server->lbxError,
+ sequencep);
+ if (!server->dpy) return FALSE;
+
+ server->fd = DisplayConnectionNumber (server->dpy);
+ server->compHandle = NULL;
+ server->initialized = FALSE;
+ server->prev_exec = clients[0];
+ server->send = clients[0];
+ server->recv = clients[0];
+ server->motion_allowed = 0;
+ server->wm_running = FALSE;
+ server->extensions = NULL;
+
+ /*
+ * Initialize the atom fields
+ */
+ server->atom_control_count = 0;
+ server->atom_control = NULL;
+ LBXReadAtomsFile(server);
+
+ /*
+ * Initialize global and property caches
+ */
+ server->num_caches = 0;
+ server->seed = 0;
+
+ /*
+ * The ProcVector table contains the default functions plus any
+ * changes that were made when the command line options were
+ * parsed.
+ *
+ * In multi-display lbxproxy, each server may have different
+ * lbx options that are negotiated. Consequently, a version
+ * of ProcVector must be maintained for each server. The field
+ * requestVector is used for this purpose.
+ *
+ * When a client connects, its requestVector will be set to its
+ * server's requestVector.
+ */
+ server->requestVector = (int (**)()) xalloc (sizeof (ProcVector));
+ if (!server->requestVector) return FALSE;
+ memcpy (server->requestVector, ProcVector, sizeof (ProcVector));
+
+ /*
+ * Initialize the resource fields
+ */
+ server->lastLbxClientIndexLookup = NULL;
+
+ /*
+ * Initialize the grab state variables
+ */
+ server->lbxIgnoringAll = 0;
+ server->lbxGrabInProgress = 0;
+
+ return TRUE;
+}
+
+Bool
+ConnectToServer(dpy_name)
+ char *dpy_name;
+{
+ int i, j;
+ XServerPtr server;
+ int sequence;
+ ClientPtr sc;
+ static int been_there;
+ static char my_host[250];
+ char proxy_address[250+6];
+
+#ifdef NEED_UTSNAME
+ struct utsname name;
+#endif
+
+ for (i = 0; i < lbxMaxServers; i++)
+ if (!servers[i])
+ break;
+ if (i == lbxMaxServers) {
+ if (proxyMngr)
+ SendGetProxyAddrReply( PM_iceConn, PM_Unable, NULL,
+ "too many servers" );
+ return FALSE;
+ }
+ server = (XServerPtr) xalloc(sizeof(XServerRec));
+ if (!server) {
+ if (proxyMngr)
+ SendGetProxyAddrReply( PM_iceConn, PM_Unable, NULL,
+ "memory allocation failure");
+ return FALSE;
+ }
+ bzero(server, sizeof(XServerRec));
+ if (!InitServer (dpy_name, i, server, &sequence)) {
+ if (proxyMngr) {
+ (void) sprintf (proxy_address,
+ "could not connect to server '%s'",
+ dpy_name);
+ SendGetProxyAddrReply( PM_iceConn, PM_Failure, NULL, proxy_address);
+ }
+ xfree(server);
+ return FALSE;
+ }
+
+ /*
+ * Create the socket(s) this display will listen on
+ */
+ for (j=0; j < MAXTRANSPORTS; j++)
+ server->listen_fds[j] = -1;
+ CreateServerSockets(server->listen_fds);
+
+ /*
+ * Generate the proxy address and save the host name part
+ */
+ if (!been_there || i == 0) {
+ been_there++;
+
+ clients[0]->server = server;
+
+#ifdef NEED_UTSNAME
+ uname (&name);
+ (void) strcpy (my_host, name.nodename);
+#else
+ (void) gethostname (my_host, 250);
+#endif
+ }
+ (void) sprintf (proxy_address, "%s:%s", my_host, display);
+
+ servers[i] = server;
+
+ sc = AllocNewConnection(server->fd, -1, TRUE, NULL);
+ sc->server = server;
+ sc->public.requestLength = ServerRequestLength;
+ sc->lbxIndex = i;
+ sc->requestVector = ServerVector;
+ sc->awaitingSetup = FALSE;
+ sc->sequence = sequence;
+
+ /*
+ * AllocNewConn didn't initialize the client resources so
+ * it needs to be done here
+ */
+ InitClientResources(sc);
+
+ server->serverClient = sc;
+ server->proxy_name = strdup (proxy_address);
+ if (dpy_name)
+ server->display_name = strdup (dpy_name);
+
+ StartProxy(server);
+
+ if (proxyMngr) {
+ SendGetProxyAddrReply( PM_iceConn, PM_Success, proxy_address, NULL );
+ }
+
+ return TRUE;
+}
diff --git a/di/zeropad.c b/di/zeropad.c
new file mode 100644
index 0000000..e57f547
--- /dev/null
+++ b/di/zeropad.c
@@ -0,0 +1,605 @@
+/* $Xorg: zeropad.c,v 1.4 2001/02/09 02:05:32 xorgcvs Exp $ */
+
+/*
+
+Copyright 1996, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from The Open Group.
+
+*/
+
+/*
+ * This module handles zeroing out unused pad bytes in X requests.
+ * This will hopefully improve both stream and delta compression,
+ * since we are removing the random values in pad bytes.
+ */
+
+#include <X11/Xproto.h>
+
+static void
+ZeroEmptyReq (req)
+ xReq *req;
+{
+ req->data = 0;
+}
+
+#define ZeroGetInputFocusReq ZeroEmptyReq
+#define ZeroGetFontPathReq ZeroEmptyReq
+#define ZeroGetKeyboardControlReq ZeroEmptyReq
+#define ZeroGetPointerControlReq ZeroEmptyReq
+#define ZeroGetPointerMappingReq ZeroEmptyReq
+#define ZeroGetScreenSaverReq ZeroEmptyReq
+#define ZeroGrabServerReq ZeroEmptyReq
+#define ZeroListExtensionsReq ZeroEmptyReq
+#define ZeroNoOperationReq ZeroEmptyReq
+#define ZeroGetModifierMappingReq ZeroEmptyReq
+#define ZeroQueryKeymapReq ZeroEmptyReq
+#define ZeroUngrabServerReq ZeroEmptyReq
+
+
+static void
+ZeroResourceReq (req)
+ xResourceReq *req;
+{
+ req->pad = 0;
+}
+
+#define ZeroFreePixmapReq ZeroResourceReq
+#define ZeroGetAtomNameReq ZeroResourceReq
+#define ZeroDestroySubwindowsReq ZeroResourceReq
+#define ZeroDestroyWindowReq ZeroResourceReq
+#define ZeroCloseFontReq ZeroResourceReq
+#define ZeroQueryFontReq ZeroResourceReq
+#define ZeroFreeCursorReq ZeroResourceReq
+#define ZeroFreeGCReq ZeroResourceReq
+#define ZeroGetGeometryReq ZeroResourceReq
+#define ZeroGetSelectionOwnerReq ZeroResourceReq
+#define ZeroGetWindowAttributesReq ZeroResourceReq
+#define ZeroInstallColormapReq ZeroResourceReq
+#define ZeroListInstalledColormapsReq ZeroResourceReq
+#define ZeroListPropertiesReq ZeroResourceReq
+#define ZeroMapSubwindowsReq ZeroResourceReq
+#define ZeroMapWindowReq ZeroResourceReq
+#define ZeroQueryPointerReq ZeroResourceReq
+#define ZeroQueryTreeReq ZeroResourceReq
+#define ZeroUngrabKeyboardReq ZeroResourceReq
+#define ZeroUngrabPointerReq ZeroResourceReq
+#define ZeroUninstallColormapReq ZeroResourceReq
+#define ZeroUnmapSubwindowsReq ZeroResourceReq
+#define ZeroUnmapWindowReq ZeroResourceReq
+#define ZeroKillClientReq ZeroResourceReq
+#define ZeroFreeColormapReq ZeroResourceReq
+
+
+static void
+ZeroChangeWindowAttributesReq (req)
+ xChangeWindowAttributesReq *req;
+{
+ req->pad = 0;
+}
+
+static void
+ZeroReparentWindowReq (req)
+ xReparentWindowReq *req;
+{
+ req->pad = 0;
+}
+
+static void
+ZeroConfigureWindowReq (req)
+ xConfigureWindowReq *req;
+{
+ req->pad = 0;
+ req->pad2 = 0;
+}
+
+static void
+ZeroInternAtomReq (req)
+ xInternAtomReq *req;
+{
+ req->pad = 0;
+}
+
+static void
+ZeroChangePropertyReq (req)
+ xChangePropertyReq *req;
+{
+ req->pad[0] = 0;
+ req->pad[1] = 0;
+ req->pad[2] = 0;
+}
+
+static void
+ZeroDeletePropertyReq (req)
+ xDeletePropertyReq *req;
+{
+ req->pad = 0;
+}
+
+static void
+ZeroSetSelectionOwnerReq (req)
+ xSetSelectionOwnerReq *req;
+{
+ req->pad = 0;
+}
+
+static void
+ZeroConvertSelectionReq (req)
+ xConvertSelectionReq *req;
+{
+ req->pad = 0;
+}
+
+static void
+ZeroGrabButtonReq (req)
+ xGrabButtonReq *req;
+{
+ req->pad = 0;
+}
+
+static void
+ZeroUngrabButtonReq (req)
+ xUngrabButtonReq *req;
+{
+ req->pad = 0;
+}
+
+static void
+ZeroChangeActivePointerGrabReq (req)
+ xChangeActivePointerGrabReq *req;
+{
+ req->pad = 0;
+ req->pad2 = 0;
+}
+
+static void
+ZeroGrabKeyboardReq (req)
+ xGrabKeyboardReq *req;
+{
+ req->pad = 0;
+}
+
+static void
+ZeroGrabKeyReq (req)
+ xGrabKeyReq *req;
+{
+ req->pad1 = 0;
+ req->pad2 = 0;
+ req->pad3 = 0;
+}
+
+static void
+ZeroUngrabKeyReq (req)
+ xUngrabKeyReq *req;
+{
+ req->pad = 0;
+}
+
+static void
+ZeroGetMotionEventsReq (req)
+ xGetMotionEventsReq *req;
+{
+ req->pad = 0;
+}
+
+static void
+ZeroTranslateCoordsReq (req)
+ xTranslateCoordsReq *req;
+{
+ req->pad = 0;
+}
+
+static void
+ZeroWarpPointerReq (req)
+ xWarpPointerReq *req;
+{
+ req->pad = 0;
+}
+
+static void
+ZeroOpenFontReq (req)
+ xOpenFontReq *req;
+{
+ req->pad = 0;
+ req->pad1 = 0;
+ req->pad2 = 0;
+}
+
+static void
+ZeroListFontsReq (req)
+ xListFontsReq *req;
+{
+ req->pad = 0;
+}
+
+#define ZeroListFontsWithInfoReq ZeroListFontsReq
+
+static void
+ZeroSetFontPathReq (req)
+ xSetFontPathReq *req;
+{
+ req->pad = 0;
+ req->pad1 = 0;
+ req->pad2 = 0;
+}
+
+static void
+ZeroCreateGCReq (req)
+ xCreateGCReq *req;
+{
+ req->pad = 0;
+}
+
+static void
+ZeroChangeGCReq (req)
+ xChangeGCReq *req;
+{
+ req->pad = 0;
+}
+
+static void
+ZeroCopyGCReq (req)
+ xCopyGCReq *req;
+{
+ req->pad = 0;
+}
+
+static void
+ZeroSetDashesReq (req)
+ xSetDashesReq *req;
+{
+ req->pad = 0;
+}
+
+static void
+ZeroCopyAreaReq (req)
+ xCopyAreaReq *req;
+{
+ req->pad = 0;
+}
+
+static void
+ZeroCopyPlaneReq (req)
+ xCopyPlaneReq *req;
+{
+ req->pad = 0;
+}
+
+static void
+ZeroPolySegmentReq (req)
+ xPolySegmentReq *req;
+{
+ req->pad = 0;
+}
+
+#define ZeroPolyArcReq ZeroPolySegmentReq
+#define ZeroPolyRectangleReq ZeroPolySegmentReq
+#define ZeroPolyFillRectangleReq ZeroPolySegmentReq
+#define ZeroPolyFillArcReq ZeroPolySegmentReq
+
+static void
+ZeroFillPolyReq (req)
+ xFillPolyReq *req;
+{
+ req->pad = 0;
+ req->pad1 = 0;
+}
+
+static void
+ZeroPutImageReq (req)
+ xPutImageReq *req;
+{
+ req->pad = 0;
+}
+
+static void
+ZeroPolyTextReq (req)
+ xPolyTextReq *req;
+{
+ req->pad = 0;
+}
+
+#define ZeroPolyText8Req ZeroPolyTextReq
+#define ZeroPolyText16Req ZeroPolyTextReq
+
+static void
+ZeroCopyColormapAndFreeReq (req)
+ xCopyColormapAndFreeReq *req;
+{
+ req->pad = 0;
+}
+
+static void
+ZeroAllocColorReq (req)
+ xAllocColorReq *req;
+{
+ req->pad = 0;
+ req->pad2 = 0;
+}
+
+static void
+ZeroAllocNamedColorReq (req)
+ xAllocNamedColorReq *req;
+{
+ req->pad = 0;
+ req->pad1 = 0;
+ req->pad2 = 0;
+}
+
+static void
+ZeroFreeColorsReq (req)
+ xFreeColorsReq *req;
+{
+ req->pad = 0;
+}
+
+static void
+ZeroStoreColorsReq (req)
+ xStoreColorsReq *req;
+{
+ req->pad = 0;
+}
+
+static void
+ZeroStoreNamedColorReq (req)
+ xStoreNamedColorReq *req;
+{
+ req->pad1 = 0;
+ req->pad2 = 0;
+}
+
+static void
+ZeroQueryColorsReq (req)
+ xQueryColorsReq *req;
+{
+ req->pad = 0;
+}
+
+static void
+ZeroLookupColorReq (req)
+ xLookupColorReq *req;
+{
+ req->pad = 0;
+ req->pad1 = 0;
+ req->pad2 = 0;
+}
+
+static void
+ZeroCreateCursorReq (req)
+ xCreateCursorReq *req;
+{
+ req->pad = 0;
+}
+
+static void
+ZeroCreateGlyphCursorReq (req)
+ xCreateGlyphCursorReq *req;
+{
+ req->pad = 0;
+}
+
+static void
+ZeroRecolorCursorReq (req)
+ xRecolorCursorReq *req;
+{
+ req->pad = 0;
+}
+
+static void
+ZeroQueryExtensionReq (req)
+ xQueryExtensionReq *req;
+{
+ req->pad = 0;
+ req->pad1 = 0;
+ req->pad2 = 0;
+}
+
+static void
+ZeroGetKeyboardMappingReq (req)
+ xGetKeyboardMappingReq *req;
+{
+ req->pad = 0;
+ req->pad1 = 0;
+}
+
+static void
+ZeroChangeKeyboardMappingReq (req)
+ xChangeKeyboardMappingReq *req;
+{
+ req->pad1 = 0;
+}
+
+static void
+ZeroChangeKeyboardControlReq (req)
+ xChangeKeyboardControlReq *req;
+{
+ req->pad = 0;
+}
+
+static void
+ZeroChangePointerControlReq (req)
+ xChangePointerControlReq *req;
+{
+ req->pad = 0;
+}
+
+static void
+ZeroSetScreenSaverReq (req)
+ xSetScreenSaverReq *req;
+{
+ req->pad = 0;
+ req->pad2 = 0;
+}
+
+static void
+ZeroChangeHostsReq (req)
+ xChangeHostsReq *req;
+{
+ req->pad = 0;
+}
+
+static void
+ZeroListHostsReq (req)
+ xListHostsReq *req;
+{
+ req->pad = 0;
+}
+
+static void
+ZeroRotatePropertiesReq (req)
+ xRotatePropertiesReq *req;
+{
+ req->pad = 0;
+}
+
+void (*ZeroPadReqVector[128]) () =
+{
+ 0,
+ 0, /* CreateWindowReq */
+ ZeroChangeWindowAttributesReq,
+ ZeroGetWindowAttributesReq,
+ ZeroDestroyWindowReq,
+ ZeroDestroySubwindowsReq, /* 5 */
+ 0, /* ChangeSaveSetReq */
+ ZeroReparentWindowReq,
+ ZeroMapWindowReq,
+ ZeroMapSubwindowsReq,
+ ZeroUnmapWindowReq, /* 10 */
+ ZeroUnmapSubwindowsReq,
+ ZeroConfigureWindowReq,
+ 0, /* CirculateWindowReq */
+ ZeroGetGeometryReq,
+ ZeroQueryTreeReq, /* 15 */
+ ZeroInternAtomReq,
+ ZeroGetAtomNameReq,
+ ZeroChangePropertyReq,
+ ZeroDeletePropertyReq,
+ 0, /* GetPropertyReq */ /* 20 */
+ ZeroListPropertiesReq,
+ ZeroSetSelectionOwnerReq,
+ ZeroGetSelectionOwnerReq,
+ ZeroConvertSelectionReq,
+ 0, /* SendEventReq */ /* 25 */
+ 0, /* GrabPointerReq */
+ ZeroUngrabPointerReq,
+ ZeroGrabButtonReq,
+ ZeroUngrabButtonReq,
+ ZeroChangeActivePointerGrabReq, /* 30 */
+ ZeroGrabKeyboardReq,
+ ZeroUngrabKeyboardReq,
+ ZeroGrabKeyReq,
+ ZeroUngrabKeyReq,
+ 0, /* AllowEventsReq */ /* 35 */
+ ZeroGrabServerReq,
+ ZeroUngrabServerReq,
+ ZeroQueryPointerReq,
+ ZeroGetMotionEventsReq,
+ ZeroTranslateCoordsReq, /* 40 */
+ ZeroWarpPointerReq,
+ 0, /* SetInputFocusReq */
+ ZeroGetInputFocusReq,
+ ZeroQueryKeymapReq,
+ ZeroOpenFontReq, /* 45 */
+ ZeroCloseFontReq,
+ ZeroQueryFontReq,
+ 0, /* QueryTextExtentsReq */
+ ZeroListFontsReq,
+ ZeroListFontsWithInfoReq, /* 50 */
+ ZeroSetFontPathReq,
+ ZeroGetFontPathReq,
+ 0, /* CreatePixmapReq */
+ ZeroFreePixmapReq,
+ ZeroCreateGCReq, /* 55 */
+ ZeroChangeGCReq,
+ ZeroCopyGCReq,
+ ZeroSetDashesReq,
+ 0, /* SetClipRectanglesReq */
+ ZeroFreeGCReq, /* 60 */
+ 0, /* ClearToBackgroundReq */
+ ZeroCopyAreaReq,
+ ZeroCopyPlaneReq,
+ 0, /* PolyPointReq */
+ 0, /* PolyLineReq */ /* 65 */
+ ZeroPolySegmentReq,
+ ZeroPolyRectangleReq,
+ ZeroPolyArcReq,
+ ZeroFillPolyReq,
+ ZeroPolyFillRectangleReq, /* 70 */
+ ZeroPolyFillArcReq,
+ ZeroPutImageReq,
+ 0, /* GetImageReq */
+ ZeroPolyText8Req,
+ ZeroPolyText16Req, /* 75 */
+ 0, /* ImageText8Req */
+ 0, /* ImageText16Req */
+ 0, /* CreateColormapReq */
+ ZeroFreeColormapReq,
+ ZeroCopyColormapAndFreeReq, /* 80 */
+ ZeroInstallColormapReq,
+ ZeroUninstallColormapReq,
+ ZeroListInstalledColormapsReq,
+ ZeroAllocColorReq,
+ ZeroAllocNamedColorReq, /* 85 */
+ 0, /* AllocColorCellsReq */
+ 0, /* AllocColorPlanesReq */
+ ZeroFreeColorsReq,
+ ZeroStoreColorsReq,
+ ZeroStoreNamedColorReq, /* 90 */
+ ZeroQueryColorsReq,
+ ZeroLookupColorReq,
+ ZeroCreateCursorReq,
+ ZeroCreateGlyphCursorReq,
+ ZeroFreeCursorReq, /* 95 */
+ ZeroRecolorCursorReq,
+ 0, /* QueryBestSizeReq */
+ ZeroQueryExtensionReq,
+ ZeroListExtensionsReq,
+ ZeroChangeKeyboardMappingReq, /* 100 */
+ ZeroGetKeyboardMappingReq,
+ ZeroChangeKeyboardControlReq,
+ ZeroGetKeyboardControlReq,
+ 0, /* BellReq */
+ ZeroChangePointerControlReq, /* 105 */
+ ZeroGetPointerControlReq,
+ ZeroSetScreenSaverReq,
+ ZeroGetScreenSaverReq,
+ ZeroChangeHostsReq,
+ ZeroListHostsReq, /* 110 */
+ 0, /* ChangeAccessControlReq */
+ 0, /* ChangeCloseDownModeReq */
+ ZeroKillClientReq,
+ ZeroRotatePropertiesReq,
+ 0, /* ForceScreenSaverReq */ /* 115 */
+ 0, /* SetPointerMappingReq */
+ ZeroGetPointerMappingReq,
+ 0, /* SetModifierMappingReq */
+ ZeroGetModifierMappingReq,
+ 0, /* 120 */
+ 0,
+ 0,
+ 0,
+ 0,
+ 0, /* 125 */
+ 0,
+ ZeroNoOperationReq
+};
diff --git a/include/assert.h b/include/assert.h
new file mode 100644
index 0000000..3e0b8c2
--- /dev/null
+++ b/include/assert.h
@@ -0,0 +1,34 @@
+/* $Xorg: assert.h,v 1.3 2000/08/17 19:53:57 cpqbld Exp $ */
+/*
+ * Copyright 1994 Network Computing Devices, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name Network Computing Devices, Inc. not be
+ * used in advertising or publicity pertaining to distribution of this
+ * software without specific, written prior permission.
+ *
+ * THIS SOFTWARE IS PROVIDED `AS-IS'. NETWORK COMPUTING DEVICES, INC.,
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT
+ * LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, OR NONINFRINGEMENT. IN NO EVENT SHALL NETWORK
+ * COMPUTING DEVICES, INC., BE LIABLE FOR ANY DAMAGES WHATSOEVER, INCLUDING
+ * SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES, INCLUDING LOSS OF USE, DATA,
+ * OR PROFITS, EVEN IF ADVISED OF THE POSSIBILITY THEREOF, AND REGARDLESS OF
+ * WHETHER IN AN ACTION IN CONTRACT, TORT OR NEGLIGENCE, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $NCDId$
+ */
+#ifdef DEBUG
+#include <stdio.h>
+#ifdef SABER
+#define assert(ex) {if (!(ex)){(void)fprintf(stderr,"Assertion \"ex\" failed: file \"%s\", line %d\n", __FILE__, __LINE__);saber_stop();}}
+#else
+#define assert(ex) {if (!(ex)){(void)fprintf(stderr,"Assertion \"ex\" failed: file \"%s\", line %d\n", __FILE__, __LINE__);abort();}}
+#endif
+#else
+#define assert(ex)
+#endif
diff --git a/include/atomcache.h b/include/atomcache.h
new file mode 100644
index 0000000..d94228d
--- /dev/null
+++ b/include/atomcache.h
@@ -0,0 +1,104 @@
+/* $Xorg: atomcache.h,v 1.4 2001/02/09 02:05:32 xorgcvs Exp $ */
+/*
+
+Copyright 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+*/
+/*
+ * Copyright 1994 Network Computing Devices, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name Network Computing Devices, Inc. not be
+ * used in advertising or publicity pertaining to distribution of this
+ * software without specific, written prior permission.
+ *
+ * THIS SOFTWARE IS PROVIDED `AS-IS'. NETWORK COMPUTING DEVICES, INC.,
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT
+ * LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, OR NONINFRINGEMENT. IN NO EVENT SHALL NETWORK
+ * COMPUTING DEVICES, INC., BE LIABLE FOR ANY DAMAGES WHATSOEVER, INCLUDING
+ * SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES, INCLUDING LOSS OF USE, DATA,
+ * OR PROFITS, EVEN IF ADVISED OF THE POSSIBILITY THEREOF, AND REGARDLESS OF
+ * WHETHER IN AN ACTION IN CONTRACT, TORT OR NEGLIGENCE, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+#ifndef _ATOMCACHE_H_
+#define _ATOMCACHE_H_
+
+#define AtomPreInternFlag 0x1
+#define AtomWMCacheFlag 0x2
+#define AtomNoCacheFlag 0x4
+
+typedef struct {
+ unsigned char flags;
+ int len;
+ char *name;
+} AtomControlRec, *AtomControlPtr;
+
+typedef struct _AtomList {
+ char *name;
+ unsigned char flags;
+ int len;
+ int hash;
+ Atom atom;
+} AtomListRec, *AtomListPtr;
+
+#define DEF_KEEP_PROP_SIZE 8
+
+extern int min_keep_prop_size;
+
+extern Atom LbxMakeAtom(
+#if NeedFunctionPrototypes
+ XServerPtr /*server*/,
+ char * /*string*/,
+ unsigned /*len*/,
+ Atom /*atom*/,
+ int /*makeit*/
+#endif
+);
+
+extern char *NameForAtom(
+#if NeedFunctionPrototypes
+ XServerPtr /*server*/,
+ Atom /*atom*/
+#endif
+);
+
+extern unsigned FlagsForAtom(
+#if NeedFunctionPrototypes
+ XServerPtr /*server*/,
+ Atom /*atom*/
+#endif
+);
+
+extern void FreeAtoms(
+#if NeedFunctionPrototypes
+ void
+#endif
+);
+
+#endif /* _ATOMCACHE_H_ */
diff --git a/include/cache.h b/include/cache.h
new file mode 100644
index 0000000..3637a09
--- /dev/null
+++ b/include/cache.h
@@ -0,0 +1,128 @@
+/* $Xorg: cache.h,v 1.4 2001/02/09 02:05:32 xorgcvs Exp $ */
+/*
+
+Copyright 1994, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from The Open Group.
+
+*/
+/*
+ * Copyright 1990, 1991 Network Computing Devices;
+ * Portions Copyright 1987 by Digital Equipment Corporation
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the names of Network Computing Devices
+ * or Digital not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Network Computing Devices and Digital
+ * make no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * NETWORK COMPUTING DEVICES AND DIGITAL DISCLAIM ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS, IN NO EVENT SHALL NETWORK COMPUTING DEVICES OR DIGITAL BE
+ * LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#ifndef _CACHE_H_
+#define _CACHE_H_
+
+#define CacheWasReset 1
+#define CacheEntryFreed 2
+#define CacheEntryOld 3
+
+#define MAX_NUM_CACHES 2
+
+typedef unsigned long CacheID;
+typedef unsigned long Cache;
+typedef void (*CacheFree) ();
+
+typedef struct _cache *CachePtr;
+
+extern Cache CacheInit(
+#if NeedFunctionPrototypes
+ XServerPtr /*server*/,
+ unsigned long /*maxsize*/
+#endif
+);
+
+extern void CacheFreeCache(
+#if NeedFunctionPrototypes
+ XServerPtr /*server*/,
+ Cache /*cid*/
+#endif
+);
+
+extern Bool CacheTrimNeeded(
+#if NeedFunctionPrototypes
+ XServerPtr /*server*/,
+ Cache /*cid*/
+#endif
+);
+
+extern void CacheTrim(
+#if NeedFunctionPrototypes
+ XServerPtr /*server*/,
+ Cache /*cid*/
+#endif
+);
+
+extern Bool CacheStoreMemory(
+#if NeedFunctionPrototypes
+ XServerPtr /*server*/,
+ Cache /*cid*/,
+ CacheID /*id*/,
+ pointer /*data*/,
+ unsigned long /*size*/,
+ CacheFree /*free_func*/,
+ Bool /*can_flush*/
+#endif
+);
+
+extern pointer CacheFetchMemory(
+#if NeedFunctionPrototypes
+ XServerPtr /*server*/,
+ Cache /*cid*/,
+ CacheID /*id*/,
+ Bool /*update*/
+#endif
+);
+
+extern void CacheFreeMemory(
+#if NeedFunctionPrototypes
+ XServerPtr /*server*/,
+ Cache /*cacheid*/,
+ CacheID /*cid*/,
+ Bool /*notify*/
+#endif
+);
+
+#endif /* _CACHE_H_ */
diff --git a/include/colormap.h b/include/colormap.h
new file mode 100644
index 0000000..39fdf3a
--- /dev/null
+++ b/include/colormap.h
@@ -0,0 +1,310 @@
+/* $Xorg: colormap.h,v 1.4 2001/02/09 02:05:32 xorgcvs Exp $ */
+/*
+
+Copyright 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+*/
+/*
+ * Copyright 1994 Network Computing Devices, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name Network Computing Devices, Inc. not be
+ * used in advertising or publicity pertaining to distribution of this
+ * software without specific, written prior permission.
+ *
+ * THIS SOFTWARE IS PROVIDED `AS-IS'. NETWORK COMPUTING DEVICES, INC.,
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT
+ * LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, OR NONINFRINGEMENT. IN NO EVENT SHALL NETWORK
+ * COMPUTING DEVICES, INC., BE LIABLE FOR ANY DAMAGES WHATSOEVER, INCLUDING
+ * SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES, INCLUDING LOSS OF USE, DATA,
+ * OR PROFITS, EVEN IF ADVISED OF THE POSSIBILITY THEREOF, AND REGARDLESS OF
+ * WHETHER IN AN ACTION IN CONTRACT, TORT OR NEGLIGENCE, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#ifndef COLORMAP_H_
+#define COLORMAP_H_
+
+typedef struct _rgbentry {
+ char *name;
+ int namelen;
+ VisualID visual;
+ CARD16 xred,
+ xblue,
+ xgreen; /* exact */
+ CARD16 vred,
+ vblue,
+ vgreen; /* visual */
+} RGBEntryRec, *RGBEntryPtr;
+
+typedef struct _RGBEntry {
+ struct _RGBEntry *next;
+ RGBEntryRec color;
+} RGBCacheEntryRec, *RGBCacheEntryPtr;
+
+#define NBUCKETS 16
+
+typedef CARD32 Pixel;
+
+#define PIXEL_FREE 0
+#define PIXEL_PRIVATE 1
+#define PIXEL_SHARED 2
+
+typedef struct _entry {
+ CARD16 red,
+ green,
+ blue;
+ char status;
+ char server_ref;
+ int refcnt;
+ Pixel pixel;
+} Entry;
+
+
+#define CMAP_NOT_GRABBED 0
+#define CMAP_GRAB_REQUESTED 1
+#define CMAP_GRABBED 2
+
+#define DynamicClass 1
+
+typedef struct _visual {
+ int class;
+ VisualID id;
+ int depth;
+ int bitsPerRGB;
+ int colormapEntries;
+ CARD32 redMask, greenMask, blueMask;
+ int offsetRed, offsetGreen, offsetBlue;
+} LbxVisualRec, *LbxVisualPtr;
+
+#define NUMRED(pv) (((pv)->redMask >> (pv)->offsetRed) + 1)
+#define NUMGREEN(pv) (((pv)->greenMask >> (pv)->offsetGreen) + 1)
+#define NUMBLUE(pv) (((pv)->blueMask >> (pv)->offsetBlue) + 1)
+#define REDPART(pv,pix) (((pix) & (pv)->redMask) >> (pv)->offsetRed)
+#define GREENPART(pv,pix) (((pix) & (pv)->greenMask) >> (pv)->offsetGreen)
+#define BLUEPART(pv,pix) (((pix) & (pv)->blueMask) >> (pv)->offsetBlue)
+
+typedef struct _cmap {
+ Colormap id;
+ LbxVisualPtr pVisual;
+ Bool grab_status;
+ Entry *red;
+ Entry *green;
+ Entry *blue;
+ int *numPixelsRed;
+ int *numPixelsGreen;
+ int *numPixelsBlue;
+ Pixel **clientPixelsRed;
+ Pixel **clientPixelsGreen;
+ Pixel **clientPixelsBlue;
+} ColormapRec, *ColormapPtr;
+
+
+extern void (* LbxResolveColor)(
+#if NeedNestedPrototypes
+ LbxVisualPtr /* pVisual */,
+ CARD16* /* red */,
+ CARD16* /* green */,
+ CARD16* /* blue */
+#endif
+);
+
+extern void ResolveColor(
+#if NeedFunctionPrototypes
+ LbxVisualPtr /* pVisual */,
+ CARD16* /* red */,
+ CARD16* /* green */,
+ CARD16* /* blue */
+#endif
+);
+
+extern Pixel (* LbxFindFreePixel)(
+#if NeedFunctionPrototypes
+ ColormapPtr /* pmap */,
+ CARD32 /* red */,
+ CARD32 /* green */,
+ CARD32 /* blue */
+#endif
+);
+
+extern Pixel FindFreePixel(
+#if NeedFunctionPrototypes
+ ColormapPtr /* pmap */,
+ CARD32 /* red */,
+ CARD32 /* green */,
+ CARD32 /* blue */
+#endif
+);
+
+extern Entry * (* LbxFindBestPixel)(
+#if NeedNestedPrototypes
+ ColormapPtr /* pmap */,
+ CARD32 /* red */,
+ CARD32 /* green */,
+ CARD32 /* blue */,
+ int /* channels */
+#endif
+);
+
+extern Entry * FindBestPixel(
+#if NeedNestedPrototypes
+ ColormapPtr /* pmap */,
+ CARD32 /* red */,
+ CARD32 /* green */,
+ CARD32 /* blue */,
+ int /* channels */
+#endif
+);
+
+extern RGBEntryPtr FindColorName(
+#if NeedFunctionPrototypes
+ XServerPtr /*server*/,
+ char * /*name*/,
+ int /*len*/,
+ LbxVisualPtr /*pVisual*/
+#endif
+);
+
+extern Bool AddColorName(
+#if NeedFunctionPrototypes
+ XServerPtr /*server*/,
+ char * /*name*/,
+ int /*len*/,
+ RGBEntryRec * /*rgbe*/
+#endif
+);
+
+extern int CreateVisual(
+#if NeedFunctionPrototypes
+ int /*depth*/,
+ xVisualType * /*vis*/
+#endif
+);
+
+extern LbxVisualPtr GetVisual(
+#if NeedFunctionPrototypes
+ VisualID /*vid*/
+#endif
+);
+
+extern int FindPixel(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/,
+ ColormapPtr /*pmap*/,
+ CARD32 /*red*/,
+ CARD32 /*green*/,
+ CARD32 /*blue*/,
+ Entry ** /*pent*/
+#endif
+);
+
+extern int StorePixel(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/,
+ ColormapPtr /*pmap*/,
+ CARD32 /*red*/,
+ CARD32 /*green*/,
+ CARD32 /*blue*/,
+ Pixel /*pixel*/,
+ Bool /*from_server*/
+#endif
+);
+
+extern int FreeClientPixels(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/,
+ pointer /*pcr*/,
+ XID /*id*/
+#endif
+);
+
+extern int IncrementPixel(
+#if NeedFunctionPrototypes
+ ClientPtr /*pclient*/,
+ ColormapPtr /*pmap*/,
+ Entry * /*pent*/,
+ Bool /*from_server*/
+#endif
+);
+
+extern int AllocCell(
+#if NeedFunctionPrototypes
+ ClientPtr /*pclient*/,
+ ColormapPtr /*pmap*/,
+ Pixel /*pixel*/
+#endif
+);
+
+extern int FreePixels(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/,
+ ColormapPtr /*pmap*/,
+ int /*num*/,
+ Pixel * /*pixels*/,
+ Pixel /*mask*/
+#endif
+);
+
+extern int CreateColormap(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/,
+ Colormap /*cmap*/,
+ VisualID /*visual*/
+#endif
+);
+
+extern int DestroyColormap(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/,
+ pointer /*pmap*/,
+ XID /*id*/
+#endif
+);
+
+extern int FreeColormap(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/,
+ Colormap /*cmap*/
+#endif
+);
+
+extern int CopyAndFreeColormap(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/,
+ Colormap /*new*/,
+ Colormap /*old*/
+#endif
+);
+
+extern void FreeColors(
+#if NeedFunctionPrototypes
+ void
+#endif
+);
+
+#endif /* COLORMAP_H_ */
diff --git a/include/init.h b/include/init.h
new file mode 100644
index 0000000..3de79fc
--- /dev/null
+++ b/include/init.h
@@ -0,0 +1,79 @@
+/* $Xorg: init.h,v 1.4 2001/02/09 02:05:32 xorgcvs Exp $ */
+/*
+
+Copyright 1996, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+*/
+/*
+ * Copyright 1992 Network Computing Devices
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of NCD. not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. NCD. makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * NCD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL NCD.
+ * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#ifndef _INIT_H_
+#define _INIT_H_
+
+extern struct _XDisplay* DisplayOpen(
+#if NeedFunctionPrototypes
+ char * /*dpy_name*/,
+ int * /*request*/,
+ int * /*event*/,
+ int * /*error*/,
+ int * /*sequencep*/
+#endif
+);
+
+extern int DisplayConnectionNumber(
+#if NeedFunctionPrototypes
+ struct _XDisplay* /* dpy */
+#endif
+);
+
+extern void DisplayGetConnSetup (
+#if NeedFunctionPrototypes
+ struct _XDisplay* /* dpy */,
+ xConnSetup** /* tag_data */,
+ int* /* len */,
+ int /* change_type */,
+ CARD32* /* changes */,
+ int /* change_len */
+#endif
+);
+
+#endif
diff --git a/include/lbx.h b/include/lbx.h
new file mode 100644
index 0000000..04e46af
--- /dev/null
+++ b/include/lbx.h
@@ -0,0 +1,736 @@
+/* $Xorg: lbx.h,v 1.4 2001/02/09 02:05:32 xorgcvs Exp $ */
+/*
+
+Copyright 1996, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+*/
+/*
+ * Copyright 1992 Network Computing Devices
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of NCD. not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. NCD. makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * NCD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL NCD.
+ * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#ifndef _LBX_H_
+#define _LBX_H_
+#include "misc.h"
+#include "os.h"
+#include "util.h"
+#define _XLBX_SERVER_
+#include "lbxstr.h"
+
+/* we keep the ifdefs in the code as a guide to what's going on */
+/* but we want the proxy to work with all possible servers */
+#ifndef BIGREQS
+#define BIGREQS
+#endif
+
+/* cache stuff */
+#define MAX_ATOM_LENGTH 256 /* screw any large ones */
+#define MAX_COLORNAME_LENGTH 256 /* screw any large ones */
+
+
+typedef struct proptagdata {
+ Atom type;
+ int format;
+ int length; /* in bytes */
+ pointer data;
+} PropertyTagDataRec, *PropertyTagDataPtr;
+
+typedef struct _replystuff *ReplyStuffPtr;
+
+typedef Bool (*ReplyFunc)(
+#if NeedNestedPrototypes
+ ClientPtr /*client*/,
+ ReplyStuffPtr /*nr*/,
+ char * /*data*/
+#endif
+);
+
+typedef struct _replystuff {
+ int sequenceNumber; /* expected sequence number */
+ int major; /* major opcode */
+ int minor; /* minor opcode */
+ ReplyFunc reply_func; /* function to handle reply */
+ union { /* reply data */
+ struct intern_data {
+ int len;
+ char str[MAX_ATOM_LENGTH];
+ } xintern;
+ struct get_atom {
+ Atom atom;
+ } xgetatom;
+ struct colorname {
+ char name[MAX_COLORNAME_LENGTH];
+ int namelen;
+ VisualID visual;
+ } xlookupcolor;
+ struct allocnamedcolor {
+ char name[MAX_COLORNAME_LENGTH];
+ int namelen;
+ struct _cmap *pmap;
+ } xallocnamedcolor;
+ struct alloccolorcells {
+ struct _cmap *pmap;
+ } xalloccolorcells;
+ struct alloccolorplanes {
+ struct _cmap *pmap;
+ } xalloccolorplanes;
+ struct grabcmap {
+ struct _cmap *pmap;
+ Bool alloc_named;
+ CARD16 vred,
+ vgreen,
+ vblue;
+ CARD16 xred,
+ xgreen,
+ xblue;
+ } lbxgrabcmap;
+ struct getkeymap {
+ int count;
+ int first;
+ } lbxgetkeymap;
+ struct getprop {
+ CARD32 offset;
+ CARD32 length;
+ } lbxgetprop;
+ struct changeprop {
+ PropertyTagDataRec ptd;
+ } lbxchangeprop;
+ struct wingeom {
+ char got_geom_request;
+ char got_geom_reply;
+ CARD8 depth;
+ Window root B32;
+ INT16 x B16, y B16;
+ CARD16 width B16, height B16;
+ CARD16 borderWidth B16;
+ } lbxWinGeom;
+ struct queryextension {
+ char *name;
+ } lbxqueryextension;
+ struct getimage {
+#ifdef LBX_STATS
+ Drawable drawable;
+ INT16 x;
+ INT16 y;
+#endif
+ CARD16 width;
+ CARD16 height;
+ CARD8 format;
+ } lbxgetimage;
+ pointer lbxextensiondata;
+ } request_info;
+ ReplyStuffPtr next;
+} ReplyStuffRec;
+
+typedef struct _replydata {
+ int dlen;
+ xReply reply;
+ pointer data;
+ int delay_seq_no; /* what seq i'm waiting for */
+ struct _replydata *next;
+} ReplyDataRec, *ReplyDataPtr;
+
+
+#define LBX_LARGE_REQUEST_MIN_SIZE 1024
+#define LBX_LARGE_REQUEST_CHUNK_SIZE 512
+
+#define LARGE_REQUEST_QUEUE_LEN 16
+
+typedef struct {
+ ClientPtr client;
+ Bool compressed;
+ char *buf;
+ unsigned totalBytes;
+ unsigned bytesRead;
+ unsigned bytesWritten;
+} LbxLargeRequestRec;
+
+
+typedef struct _ClientPublic {
+ int (*writeToClient) ();
+ int (*uncompressedWriteToClient) ();
+ unsigned long (*requestLength) ();
+ int (*readRequest)();
+} ClientPublicRec, *ClientPublicPtr;
+
+typedef struct _Client {
+ int index;
+ XID ridBase;
+ XID ridMask;
+ pointer requestBuffer;
+ pointer osPrivate; /* for OS layer, including scheduler */
+ Bool swapped;
+ void (*pSwapReplyFunc) (
+#if NeedNestedPrototypes
+ ClientPtr /* pClient */,
+ int /* size */,
+ void * /* pbuf */
+#endif
+);
+ XID errorValue;
+ int sequence;
+ int closeDownMode;
+ int clientGone;
+ int noClientException; /* this client died or needs to be
+ * killed */
+ XServerPtr server;
+ Drawable serverID;
+ GContext lastGCID;
+ pointer *saveSet;
+ int awaitingSetup;
+ int (**requestVector) (
+#if NeedNestedPrototypes
+ ClientPtr /* pClient */
+#endif
+);
+ CARD32 req_len; /* length of current request */
+ Bool big_requests; /* supports large requests */
+
+#ifdef DEBUG
+#define MAX_REQUEST_LOG 100
+ unsigned char requestLog[MAX_REQUEST_LOG];
+ int requestLogIndex;
+#endif
+
+ ClientPublicRec public;
+ int lbxIndex;
+
+ Bool cache_safe; /* safe to short circuit request? */
+ Bool can_delay_reply;/* safe to delay short-circuit request? */
+
+ int sequenceNumber; /* what we've seen */
+ int sequence_lost; /* requests short-circuited */
+ int lastForReply; /* last request with reply known coming */
+ int lastForResponse;/* last request sent with event or reply */
+ int lastResponse; /* last sequence number seen from server */
+
+ int yanked; /* total requests short-circuited */
+
+ KeyCode minKeyCode,
+ maxKeyCode;
+
+ CARD8 imageByteOrder; /* LSBFirst, MSBFirst */
+ CARD8 bitmapBitOrder; /* LeastSignificant, MostSign...*/
+ CARD8 bitmapScanlineUnit, /* 8, 16, 32 */
+ bitmapScanlinePad; /* 8, 16, 32 */
+ CARD8 ZbitsPerPixel1; /* for ZPixmap depth 1 */
+ Window rootWindow; /* root window of screen 0 */
+
+ ReplyStuffPtr replylist; /* list of pending replies */
+ ReplyDataPtr replydata; /* list of delayed short-circuited replies */
+ Drawable drawableCache[GFX_CACHE_SIZE];
+ GContext gcontextCache[GFX_CACHE_SIZE];
+
+ LbxLargeRequestRec *largeRequest;
+
+} ClientRec;
+
+
+#define WriteToClient(client,len,buf) (((client)->public.writeToClient)(client,len,buf))
+#define ReadRequestFromClient(client) ((client)->public.readRequest(client))
+#define RequestLength(r,client,g,p) (*(client)->public.requestLength) (r,client,g,p)
+
+#define LBXSequenceNumber(client) ((client->sequenceNumber) & 0xffff)
+#define LBXCacheSafe(client) (client->cache_safe)
+#define LBXCanDelayReply(client) (client->can_delay_reply)
+#define LBXSequenceLost(client) (client->sequence_lost)
+#define LBXYanked(client) (client->yanked)
+#define LBXLastForReply(client) (client->lastForReply)
+#define LBXLastForResponse(client) (client->lastForResponse)
+#define LBXLastResponse(client) (client->lastResponse)
+#define LBXReplyList(client) (client->replylist)
+#define LBXReplyData(client) (client->replydata)
+#define LBXMinKeyCode(client) (client->minKeyCode)
+#define LBXMaxKeyCode(client) (client->maxKeyCode)
+#define LBXImageByteOrder(client) (client->imageByteOrder)
+#define LBXBitmapBitOrder(client) (client->bitmapBitOrder)
+#define LBXBitmapScanlineUnit(client) (client->bitmapScanlineUnit)
+#define LBXBitmapScanlinePad(client) (client->bitmapScanlinePad)
+#define LBXZBitsPerPixel1(client) (client->ZbitsPerPixel1)
+#define LBXRootWindow(client) (client->rootWindow)
+#define LBXDrawableCache(client)(client->drawableCache)
+#define LBXGContextCache(client)(client->gcontextCache)
+
+extern ClientPtr *clients;
+#define MAXCLIENTS 128
+#define NullClient ((ClientPtr) 0)
+extern int currentMaxClients;
+
+extern LbxLargeRequestRec *largeRequestQueue[];
+extern int numLargeRequestsInQueue;
+
+/*
+ * Notes on request short-circuiting
+ *
+ * X guarentees that any replies, events or errors generated by a
+ * previous request will be sent before those of a later request.
+ * this means that any requests that can be handled by the proxy
+ * must have their reply sent after any previous events or errors.
+ *
+ * there are 3 possible stages implemented here:
+ *
+ * - fully correct protocol, where nothing can be out of order
+ * - mostly correct protocol, where only errors can be out of order
+ * - poor protocol, where events & errors can be out of order
+ *
+ * for most applications, poor is 'good enough', because they don't
+ * depend on events coming in order, and instead let Xlib do
+ * the work.
+ *
+ * depending on the type of protocol being used, the cache_safe
+ * flag in the ClientRec will be set appropriately, and if TRUE,
+ * the proxy is cleared to short-circuit a request.
+ *
+ * for full correct protocol, the flag is set if the previous request
+ * was a round trip and the reply has come back.
+ *
+ * for a mostly correct protocol, the flag is set for the above
+ * case, and for requests that can generate only errors (mostly
+ * graphics)
+ *
+ * for a 'good enough' protocol, the flag is always on, and we let
+ * the client sort things out.
+ *
+ * (note than in no case do we allow replies to come out of order.)
+ *
+ *
+ * Note on Xlib's handling of sequences:
+ *
+ * Xlib usually waits for the reply to sync request before
+ * issuing another -- its archetecture depends on it. However,
+ * this is not required. Xlib itself misses this in at least one
+ * case (XGetWindowAttributes, which uses both the GetWindowAttributes
+ * and GetGeometry requests).
+ *
+ * The upshot is that the proxy has to be able to handle seeing
+ * another request before it receives an expected reply.
+ *
+ * this means we can't assume a single pending reply, but many.
+ * currently these get tacked onto a list.
+ *
+ *
+ * Notes on how the proxy attempts to solve all of this:
+ *
+ * There are 4 request that it will attempt to short-circuit:
+ * InternAtom, GetAtomName, LookupColor, AllocColor, and AllocNamedColor.
+ * All the code to do this is in lbxfuncs.c, and all of it works in
+ * essentially the same way -- whenever possible, it will try to respond
+ * to the client without sending the request all the way to the X server.
+ * The goal is to remove a roudn-trip entirely -- even though not a lot of data
+ * is involved, remving the roundtrip can make this useful.
+
+ * Unfortunately, figuring out *when* its safe is very nasty. First
+ * there are all the possibile stages outlined above. If the proxy
+ * isn't waiting, thinking there might be pending data, it can always
+ * short-circuit the request. However, this is the rare case. When
+ * the proxy can't immediately respond, it attempts to short-circuit anyways,
+ * delaying the reply until whatever it was waiting on arrives. Often
+ * it can't -- if the most paranoid type of checking is turned on, it'll
+ * never work. The complex part occurs with loose checking. If it knows
+ * a reply is coming back, it can delay the short-circuit until it gets
+ * the reply. This works fine for the core protocol, but breaks down
+ * again for extensions -- to be safe, any unknown extensions are assumed
+ * to have replies -- but since they may never arrive, the delayed
+ * short-circuit can never be flushed. To avoid this, whether a reply
+ * has been guessed at is tracked, and this info is used to decide
+ * whether a short-circuit can be delayed -- if not, it always needs
+ * to do the full round-trip.
+ *
+ * The complexity really makes me wonder if this stuff is worth the effort...
+ */
+
+
+/* short-circuiting protocol */
+
+#define PROTOCOL_FULL 0 /* DEFAULT - best w/ accuracy */
+#define PROTOCOL_MOST 1 /* cheat on errors */
+#define PROTOCOL_POOR 2 /* cheat on errors & events */
+
+#undef DEBUG
+
+#undef TRACE
+
+/* possible states of request handlers. some requests are short-circuited
+ * (yanked), some are replaced with LBX requests, and some are let through
+ * unchanged
+ *
+ * any replaced request expecting a reply needs to be sure the sequence
+ * number isn't lagging before its sends its data
+ */
+#define REQ_PASSTHROUGH 0 /* pass through */
+#define REQ_YANK 1 /* completely remove, reply sent */
+#define REQ_YANKLATE 2 /* completely remove, reply not sent yet */
+#define REQ_REPLACE 3 /* replaced with 1way, reply sent */
+#define REQ_REPLACELATE 4 /* replaced with 1way, reply not sent yet */
+
+/*
+ * size of motion event queue
+ *
+ * this specifies the maximum number of motion events that the server
+ * can spew out at once. the proxy will send it NUM_MOTION_EVENTS
+ * AllowMotion requests at startup, and then send a new one each time it
+ * processes a Motion event. this will prevent the wire from being
+ * swamped by MotionNotify.
+ */
+
+/* XXX this should be a calculation based on the wire latency */
+
+#define NUM_MOTION_EVENTS 8
+
+
+#ifdef LBX_STATS
+extern int intern_good,
+ intern_miss;
+extern int getatom_good,
+ getatom_miss;
+extern int luc_good,
+ luc_miss;
+extern int ac_good,
+ ac_miss;
+extern int anc_good,
+ anc_miss;
+
+extern int getmodmap_tag, /* tag only */
+ getmodmap_full;
+extern int getkeymap_tag, /* tag only */
+ getkeymap_full;
+extern int queryfont_tag, /* tag only */
+ queryfont_full;
+extern int getsetup_tag, /* tag only */
+ getsetup_full;
+
+extern int getprop_tag,
+ getprop_full;
+
+extern int tag_bytes_unsent; /* approx data kept off wire by tags */
+
+
+extern void DumpOtherStats();
+extern void ZeroOtherStats();
+
+#endif /* LBX_STATS */
+
+extern void DumpCompressionStats();
+extern void ZeroCompressionStats();
+
+/* tables.c */
+extern int ProcLBXInternAtom(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/
+#endif
+);
+
+extern int ProcLBXGetAtomName(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/
+#endif
+);
+
+extern int ProcLBXCreateColormap(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/
+#endif
+);
+
+extern int ProcLBXAllocColor(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/
+#endif
+);
+
+extern int ProcLBXAllocNamedColor(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/
+#endif
+);
+
+extern int ProcLBXFreeColormap(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/
+#endif
+);
+
+extern int ProcLBXCopyColormapAndFree(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/
+#endif
+);
+
+extern int ProcLBXFreeColors(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/
+#endif
+);
+
+extern int ProcLBXLookupColor(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/
+#endif
+);
+
+extern int ProcLBXGetModifierMapping(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/
+#endif
+);
+
+extern int ProcLBXGetKeyboardMapping(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/
+#endif
+);
+
+extern int ProcLBXQueryFont(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/
+#endif
+);
+
+extern void FinishLBXRequest(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/,
+ int /*yank*/
+#endif
+);
+
+extern void DoLBXReply(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/,
+ char * /*data*/,
+ int /*len*/
+#endif
+);
+
+extern void WriteError(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/,
+ unsigned /*int majorCode*/,
+ unsigned /*int minorCode*/,
+ XID /*resId*/,
+ int /*errorCode*/
+#endif
+);
+
+extern void SendLbxSync(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/
+#endif
+);
+
+/* dispatch.c */
+
+extern int Dispatch(
+#if NeedFunctionPrototypes
+ void
+#endif
+);
+
+extern void SendErrorToClient(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/,
+ unsigned int /*majorCode*/,
+ unsigned int /*minorCode*/,
+ XID /*resId*/,
+ int /*errorCode*/
+#endif
+);
+
+extern ClientPtr NextAvailableClient(
+#if NeedFunctionPrototypes
+ pointer /*ospriv*/,
+ int /* connect_fd */ /* the fd the client connected on */
+#endif
+);
+
+extern int ProcInitialConnection(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/
+#endif
+);
+
+extern int ProcEstablishConnection(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/
+#endif
+);
+
+extern void CloseDownClient(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/
+#endif
+);
+
+extern int ProcStandardRequest(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/
+#endif
+);
+
+extern int ProcBadRequest(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/
+#endif
+);
+
+extern void AdjustProcVector(
+#if NeedFunctionPrototypes
+ void
+#endif
+);
+
+/* lbxutil.c */
+
+extern ReplyStuffPtr NewReply(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/,
+ int /*major*/,
+ int /*minor*/,
+ ReplyFunc /*reply_func*/
+#endif
+);
+
+extern void RemoveReply(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/,
+ ReplyStuffPtr /*rp*/
+#endif
+);
+
+extern ReplyStuffPtr GetMatchingReply(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/,
+ int /*seqno*/,
+ Bool /*flush_older*/
+#endif
+);
+
+extern Bool AnyReplies(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/
+#endif
+);
+
+extern Bool SaveReplyData(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/,
+ xReply * /*rep*/,
+ int /*len*/,
+ pointer /*data*/
+#endif
+);
+
+extern Bool FlushDelayedReplies(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/
+#endif
+);
+
+extern void BumpSequence(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/
+#endif
+);
+
+extern void ForceSequenceUpdate(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/
+#endif
+);
+
+extern void LbxFreeTag(
+#if NeedFunctionPrototypes
+ XServerPtr /*server*/,
+ XID /*tag*/,
+ int /*tagtype*/
+#endif
+);
+
+extern void LbxSendTagData(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/,
+ XID /*tag*/,
+ int /*tagtype*/
+#endif
+);
+
+extern void SendInitLBXPackets(
+#if NeedFunctionPrototypes
+ XServerPtr /*server*/
+#endif
+);
+
+extern void LbxCleanupSession(
+#if NeedFunctionPrototypes
+ void
+#endif
+);
+
+/* unsquish.c */
+
+extern int EventLength(
+#if NeedFunctionPrototypes
+ xEvent * /*ev*/,
+ Bool /* squish */
+#endif
+);
+
+extern Bool UnsquishEvent(
+#if NeedFunctionPrototypes
+ xReply * /*rep*/,
+ xEvent * /*ev*/,
+ int * /*lenp*/
+#endif
+);
+
+/* props.c */
+
+extern int ProcLBXChangeProperty(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/
+#endif
+);
+
+extern int ProcLBXGetProperty(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/
+#endif
+);
+
+#endif
diff --git a/include/lbxext.h b/include/lbxext.h
new file mode 100644
index 0000000..daefe78
--- /dev/null
+++ b/include/lbxext.h
@@ -0,0 +1,167 @@
+/* $Xorg: lbxext.h,v 1.4 2001/02/09 02:05:32 xorgcvs Exp $ */
+/*
+
+Copyright 1996, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+*/
+/*
+ * Copyright 1994 Network Computing Devices, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name Network Computing Devices, Inc. not be
+ * used in advertising or publicity pertaining to distribution of this
+ * software without specific, written prior permission.
+ *
+ * THIS SOFTWARE IS PROVIDED `AS-IS'. NETWORK COMPUTING DEVICES, INC.,
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT
+ * LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, OR NONINFRINGEMENT. IN NO EVENT SHALL NETWORK
+ * COMPUTING DEVICES, INC., BE LIABLE FOR ANY DAMAGES WHATSOEVER, INCLUDING
+ * SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES, INCLUDING LOSS OF USE, DATA,
+ * OR PROFITS, EVEN IF ADVISED OF THE POSSIBILITY THEREOF, AND REGARDLESS OF
+ * WHETHER IN AN ACTION IN CONTRACT, TORT OR NEGLIGENCE, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#ifndef _LBXEXT_H_
+#define _LBXEXT_H_
+
+typedef int (*ExtensionRequests) (
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/
+#endif
+);
+typedef int (*ExtensionReplies) (
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/
+#endif
+);
+typedef int (*ExtensionEvents) (
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/
+#endif
+);
+typedef int (*ExtensionErrors) (
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/
+#endif
+);
+typedef int (*SExtensionRequests) (
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/
+#endif
+);
+typedef int (*SExtensionReplies) (
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/
+#endif
+);
+typedef int (*SExtensionEvents) (
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/
+#endif
+);
+typedef int (*SExtensionErrors) (
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/
+#endif
+);
+
+typedef struct _vectors {
+ char *name;
+ ExtensionRequests req_vector;
+ ExtensionReplies rep_vector;
+ ExtensionEvents ev_vector;
+ ExtensionErrors err_vector;
+ SExtensionRequests sreq_vector;
+} ExtensionVectors;
+
+extern int (*ProcVector[256]) (
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/
+#endif
+);
+extern int (*SwappedProcVector[256]) (
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/
+#endif
+);
+
+typedef struct _LbxQueryExtensionReply *xLbxQueryExtensionReplyPtr;
+
+extern void DeleteExtensions(
+#if NeedFunctionPrototypes
+ XServerPtr /*server*/
+#endif
+);
+
+typedef struct _replystuff *_ReplyStuffPtr;
+
+extern void HandleExtensionError(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/,
+ xError * /*err*/,
+ _ReplyStuffPtr /*nr*/
+#endif
+);
+
+extern void HandleExtensionEvent(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/,
+ xEvent * /*ev*/
+#endif
+);
+
+extern Bool HandleExtensionReply(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/,
+ xReply * /*reply*/,
+ _ReplyStuffPtr * /*nr*/
+#endif
+);
+
+extern Bool CheckExtensionForEvents(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/,
+ xReq * /*req*/
+#endif
+);
+
+extern Bool CheckExtensionForReplies(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/,
+ xReq * /*req*/
+#endif
+);
+
+extern int ProcLBXQueryExtension(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/
+#endif
+);
+
+#endif /* _LBXEXT_H_ */
diff --git a/include/misc.h b/include/misc.h
new file mode 100644
index 0000000..8d2d8a0
--- /dev/null
+++ b/include/misc.h
@@ -0,0 +1,120 @@
+/* $Xorg: misc.h,v 1.4 2001/02/09 02:05:32 xorgcvs Exp $ */
+
+/*
+
+Copyright 1995, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from The Open Group.
+
+*/
+
+#ifndef MISC_H
+#define MISC_H 1
+
+#define NEED_EVENTS
+#define NEED_REPLIES
+#define _XLBX_SERVER_
+#include <X11/X.h>
+#include <X11/Xproto.h>
+#include <X11/Xmd.h>
+#include "Xos.h"
+#define ALLOCATE_LOCAL_FALLBACK(_size) Xalloc(_size)
+#define DEALLOCATE_LOCAL_FALLBACK(_ptr) Xfree(_ptr)
+#include "Xalloca.h"
+#include "Xfuncs.h"
+#include "Xfuncproto.h"
+
+typedef void *pointer;
+#ifndef _BOOL_ALREADY_DEFINED_
+typedef int Bool;
+#endif
+#ifndef TRUE
+#define FALSE 0
+#define TRUE 1
+#endif
+typedef struct _Client *ClientPtr;
+typedef struct _XServer *XServerPtr;
+
+#ifndef NULL
+#define NULL 0
+#endif
+#define DE_RESET 1
+#define DE_TERMINATE 2
+#define MILLI_PER_SECOND (1000)
+
+/* XXX globals.h? */
+extern int nextFreeClientID;
+extern int nClients;
+extern char *display_name;
+extern char dispatchException;
+extern char isItTimeToYield;
+extern int MaxClients;
+
+/* The following byte swapping tools are duplicated in several places.
+ * Do they deserve their own header file? What else would logically go in
+ * such a header?
+ */
+
+/* byte swap a 32-bit literal */
+#define lswapl(x) ((((x) & 0xff) << 24) |\
+ (((x) & 0xff00) << 8) |\
+ (((x) & 0xff0000) >> 8) |\
+ (((x) >> 24) & 0xff))
+
+/* byte swap a short literal */
+#define lswaps(x) ((((x) & 0xff) << 8) | (((x) >> 8) & 0xff))
+
+/* byte swap a 32-bit value */
+#define swapl(x, n) { \
+ n = ((char *) (x))[0];\
+ ((char *) (x))[0] = ((char *) (x))[3];\
+ ((char *) (x))[3] = n;\
+ n = ((char *) (x))[1];\
+ ((char *) (x))[1] = ((char *) (x))[2];\
+ ((char *) (x))[2] = n; }
+
+/* byte swap a short */
+#define swaps(x, n) { \
+ n = ((char *) (x))[0];\
+ ((char *) (x))[0] = ((char *) (x))[1];\
+ ((char *) (x))[1] = n; }
+
+/* copy 32-bit value from src to dst byteswapping on the way */
+#define cpswapl(src, dst) { \
+ ((char *)&(dst))[0] = ((char *) &(src))[3];\
+ ((char *)&(dst))[1] = ((char *) &(src))[2];\
+ ((char *)&(dst))[2] = ((char *) &(src))[1];\
+ ((char *)&(dst))[3] = ((char *) &(src))[0]; }
+
+/* copy short from src to dst byteswapping on the way */
+#define cpswaps(src, dst) { \
+ ((char *) &(dst))[0] = ((char *) &(src))[1];\
+ ((char *) &(dst))[1] = ((char *) &(src))[0]; }
+
+#define min(a, b) (((a) < (b)) ? (a) : (b))
+#define lowbit(x) ((x) & (~(x) + 1))
+
+#define REQUEST(type) \
+ register type *stuff = (type *)client->requestBuffer
+
+#endif
diff --git a/include/os.h b/include/os.h
new file mode 100644
index 0000000..0ad6c0b
--- /dev/null
+++ b/include/os.h
@@ -0,0 +1,278 @@
+/* $Xorg: os.h,v 1.4 2001/02/09 02:05:32 xorgcvs Exp $ */
+
+/*
+
+Copyright 1995, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from The Open Group.
+
+*/
+#ifndef OS_H
+#define OS_H
+
+#include <X11/Xtrans.h>
+
+extern fd_set AllSockets;
+extern fd_set AllClients;
+extern fd_set LastSelectMask;
+extern fd_set WellKnownConnections;
+extern fd_set ClientsWithInput;
+extern fd_set ClientsWriteBlocked;
+extern fd_set OutputPending;
+
+/* WaitFor.c */
+
+extern int WaitForSomething(
+#if NeedFunctionPrototypes
+ int * /*pClientsReady*/,
+ Bool /* poll */
+#endif
+);
+
+/* connection.c */
+
+extern Bool NewOutputPending;
+extern Bool AnyClientsWriteBlocked;
+extern int GrabInProgress;
+
+extern void CreateServerSockets(
+#if NeedFunctionPrototypes
+ int * /*listen_fds[]*/
+#endif
+);
+
+extern void CreateWellKnownSockets(
+#if NeedFunctionPrototypes
+ void
+#endif
+);
+
+extern void ListenToProxyManager (
+#if NeedFunctionPrototypes
+ void
+#endif
+);
+
+extern void ListenWellKnownSockets (
+#if NeedFunctionPrototypes
+ void
+#endif
+);
+
+extern void ResetWellKnownSockets(
+#if NeedFunctionPrototypes
+ void
+#endif
+);
+
+extern void AvailableClientInput(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/
+#endif
+);
+
+extern ClientPtr AllocNewConnection(
+#if NeedFunctionPrototypes
+ int /*fd*/, /* the fd to the display */
+ int /*connect_fd*/, /* the fd the client connected on */
+ Bool /*to_server*/,
+ XtransConnInfo /*trans_conn*/
+#endif
+);
+
+extern void SwitchConnectionFuncs(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/,
+ int (* /*Read*/)(),
+ int (* /*Writev*/)()
+#endif
+);
+
+extern void StartOutputCompression(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/,
+ void (* /*CompressOn*/)(),
+ void (* /*CompressOff*/)()
+#endif
+);
+
+extern Bool EstablishNewConnections(
+#if NeedFunctionPrototypes
+ ClientPtr /*clientUnused*/,
+ pointer /*closure*/
+#endif
+);
+
+extern void CloseDownFileDescriptor(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/
+#endif
+);
+
+extern void CheckConnections(
+#if NeedFunctionPrototypes
+ void
+#endif
+);
+
+extern void CloseDownConnection(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/
+#endif
+);
+
+extern void OnlyListenToOneClient(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/
+#endif
+);
+
+extern void ListenToAllClients(
+#if NeedFunctionPrototypes
+ void
+#endif
+);
+
+extern void IgnoreClient(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/
+#endif
+);
+
+extern void AttendClient(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/
+#endif
+);
+
+extern void MakeClientGrabImpervious(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/
+#endif
+);
+
+extern void MakeClientGrabPervious(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/
+#endif
+);
+
+/* io.c */
+
+extern unsigned long StandardRequestLength(
+#if NeedFunctionPrototypes
+ xReq * /*req*/,
+ ClientPtr /*client*/,
+ int /*got*/,
+ Bool * /*partp*/
+#endif
+);
+
+extern int StandardReadRequestFromClient(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/
+#endif
+);
+
+extern int PendingClientOutput(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/
+#endif
+);
+
+extern int CheckPendingClientInput(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/
+#endif
+);
+
+extern void MarkConnectionWriteBlocked(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/
+#endif
+);
+
+extern int BytesInClientBuffer(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/
+#endif
+);
+
+extern void SkipInClientBuffer(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/,
+ int /*nbytes*/,
+ int /*lenLastReq*/
+#endif
+);
+
+extern Bool InsertFakeRequest(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/,
+ char * /*data*/,
+ int /*count*/
+#endif
+);
+
+extern void ResetCurrentRequest(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/
+#endif
+);
+
+extern void FlushAllOutput(
+#if NeedFunctionPrototypes
+ void
+#endif
+);
+extern int StandardWriteToClient(
+#if NeedFunctionPrototypes
+ ClientPtr /*who*/,
+ int /*count*/,
+ char * /*buf*/
+#endif
+);
+
+extern int UncompressWriteToClient(
+#if NeedFunctionPrototypes
+ ClientPtr /*who*/,
+ int /*count*/,
+ char * /*buf*/
+#endif
+);
+
+extern void ResetOsBuffers(
+#if NeedFunctionPrototypes
+ void
+#endif
+);
+
+/* osinit.c */
+
+extern void OsInit(
+#if NeedFunctionPrototypes
+ void
+#endif
+);
+
+#endif
diff --git a/include/pm.h b/include/pm.h
new file mode 100644
index 0000000..313c2e2
--- /dev/null
+++ b/include/pm.h
@@ -0,0 +1,60 @@
+/* $Xorg: pm.h,v 1.4 2001/02/09 02:05:32 xorgcvs Exp $ */
+
+/*
+Copyright 1996, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from The Open Group.
+*/
+
+#include <X11/ICE/ICElib.h>
+
+extern IceConn PM_iceConn;
+extern int proxy_manager_fd;
+extern Bool proxyMngr;
+
+extern Bool CheckForProxyManager (
+#if NeedFunctionPrototypes
+ void
+#endif
+);
+
+extern void ConnectToProxyManager (
+#if NeedFunctionPrototypes
+ void
+#endif
+);
+
+extern void SendGetProxyAddrReply (
+#if NeedFunctionPrototypes
+ IceConn /*requestor_iceConn*/,
+ int /*status*/,
+ char * /*addr*/,
+ char * /*error*/
+#endif
+);
+
+extern void HandleProxyManagerConnection (
+#if NeedFunctionPrototypes
+ void
+#endif
+);
diff --git a/include/pmP.h b/include/pmP.h
new file mode 100644
index 0000000..6b9b3ba
--- /dev/null
+++ b/include/pmP.h
@@ -0,0 +1,117 @@
+/* $Xorg: pmP.h,v 1.4 2001/02/09 02:05:32 xorgcvs Exp $ */
+
+/*
+Copyright 1996, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from The Open Group.
+*/
+
+/* Useful ICE message parsing macros */
+
+/*
+ * Pad to a 64 bit boundary
+ */
+#define PAD64(_bytes) ((8 - ((unsigned int) (_bytes) % 8)) % 8)
+
+#define PADDED_BYTES64(_bytes) (_bytes + PAD64 (_bytes))
+
+/*
+ * Number of 8 byte units in _bytes.
+ */
+#define WORD64COUNT(_bytes) (((unsigned int) ((_bytes) + 7)) >> 3)
+
+/*
+ * Compute the number of bytes for a STRING representation
+ */
+#define STRING_BYTES(_str) (2 + (_str ? strlen (_str) : 0) + \
+ PAD64 (2 + (_str ? strlen (_str) : 0)))
+
+#define SKIP_STRING(_pBuf, _swap) \
+{ \
+ CARD16 _len; \
+ EXTRACT_CARD16 (_pBuf, _swap, _len); \
+ _pBuf += _len; \
+ if (PAD64 (2 + _len)) \
+ _pBuf += PAD64 (2 + _len); \
+}
+
+/*
+ * STORE macros
+ */
+#define STORE_CARD16(_pBuf, _val) \
+{ \
+ *((CARD16 *) _pBuf) = _val; \
+ _pBuf += 2; \
+}
+
+#define STORE_STRING(_pBuf, _string) \
+{ \
+ int _len = _string ? strlen (_string) : 0; \
+ STORE_CARD16 (_pBuf, _len); \
+ if (_len) { \
+ memcpy (_pBuf, _string, _len); \
+ _pBuf += _len; \
+ } \
+ if (PAD64 (2 + _len)) \
+ _pBuf += PAD64 (2 + _len); \
+}
+
+/*
+ * EXTRACT macros
+ */
+#define EXTRACT_CARD16(_pBuf, _swap, _val) \
+{ \
+ _val = *((CARD16 *) _pBuf); \
+ _pBuf += 2; \
+ if (_swap) \
+ _val = lswaps (_val); \
+}
+
+#define EXTRACT_STRING(_pBuf, _swap, _string) \
+{ \
+ CARD16 _len; \
+ EXTRACT_CARD16 (_pBuf, _swap, _len); \
+ _string = (char *) malloc (_len + 1); \
+ memcpy (_string, _pBuf, _len); \
+ _string[_len] = '\0'; \
+ _pBuf += _len; \
+ if (PAD64 (2 + _len)) \
+ _pBuf += PAD64 (2 + _len); \
+}
+
+#define CHECK_AT_LEAST_SIZE(_iceConn, _majorOp, _minorOp, _expected_len, _actual_len, _severity) \
+ if ((((_actual_len) - SIZEOF (iceMsg)) >> 3) > _expected_len) \
+ { \
+ _IceErrorBadLength (_iceConn, _majorOp, _minorOp, _severity); \
+ return; \
+ }
+
+
+#define CHECK_COMPLETE_SIZE(_iceConn, _majorOp, _minorOp, _expected_len, _actual_len, _pStart, _severity) \
+ if (((PADDED_BYTES64((_actual_len)) - SIZEOF (iceMsg)) >> 3) \
+ != _expected_len) \
+ { \
+ _IceErrorBadLength (_iceConn, _majorOp, _minorOp, _severity); \
+ IceDisposeCompleteMessage (iceConn, _pStart); \
+ return; \
+ }
diff --git a/include/proxyopts.h b/include/proxyopts.h
new file mode 100644
index 0000000..fe22a68
--- /dev/null
+++ b/include/proxyopts.h
@@ -0,0 +1,144 @@
+/* $Xorg: proxyopts.h,v 1.4 2001/02/09 02:05:32 xorgcvs Exp $ */
+/*
+
+Copyright 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+*/
+/*
+ * Copyright 1994 Network Computing Devices, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name Network Computing Devices, Inc. not be
+ * used in advertising or publicity pertaining to distribution of this
+ * software without specific, written prior permission.
+ *
+ * THIS SOFTWARE IS PROVIDED `AS-IS'. NETWORK COMPUTING DEVICES, INC.,
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT
+ * LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, OR NONINFRINGEMENT. IN NO EVENT SHALL NETWORK
+ * COMPUTING DEVICES, INC., BE LIABLE FOR ANY DAMAGES WHATSOEVER, INCLUDING
+ * SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES, INCLUDING LOSS OF USE, DATA,
+ * OR PROFITS, EVEN IF ADVISED OF THE POSSIBILITY THEREOF, AND REGARDLESS OF
+ * WHETHER IN AN ACTION IN CONTRACT, TORT OR NEGLIGENCE, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#ifndef _LBX_PROXYOPTS_H_
+#define _LBX_PROXYOPTS_H_
+
+#include "lbximage.h"
+#include "lbxopts.h"
+
+typedef struct _LbxNegOpts {
+ short proxyDeltaN;
+ short proxyDeltaMaxLen;
+ short serverDeltaN;
+ short serverDeltaMaxLen;
+ LbxStreamOpts streamOpts;
+ int numBitmapCompMethods;
+ char *bitmapCompMethods; /* array of indices returned by server*/
+ int numPixmapCompMethods;
+ char *pixmapCompMethods; /* array of indices returned by server*/
+ Bool squish;
+ Bool useTags;
+} LbxNegOptsRec;
+
+typedef LbxNegOptsRec *LbxNegOptsPtr;
+
+extern LbxNegOptsRec lbxNegOpt;
+
+/* options.c */
+
+extern void LbxOptInit(
+#if NeedFunctionPrototypes
+ XServerPtr /*server*/
+#endif
+);
+
+extern int LbxOptBuildReq(
+#if NeedFunctionPrototypes
+ XServerPtr /*server*/,
+ char * /*buf*/
+#endif
+);
+
+extern int LbxOptParseReply(
+#if NeedFunctionPrototypes
+ XServerPtr /*server*/,
+ int /*nopts*/,
+ unsigned char * /*preply*/,
+ int /*replylen*/
+#endif
+);
+
+extern void LbxNoDelta(
+#if NeedFunctionPrototypes
+ void
+#endif
+);
+
+extern void LbxNoComp(
+#if NeedFunctionPrototypes
+ void
+#endif
+);
+
+extern void LbxNoSquish(
+#if NeedFunctionPrototypes
+ void
+#endif
+);
+
+extern LbxBitmapCompMethod *LbxLookupBitmapCompMethod (
+#if NeedFunctionPrototypes
+ XServerPtr /*server*/,
+ int /* methodOpCode */
+#endif
+);
+
+extern LbxPixmapCompMethod *LbxLookupPixmapCompMethod (
+#if NeedFunctionPrototypes
+ XServerPtr /*server*/,
+ int /* methodOpCode */
+#endif
+);
+
+extern LbxBitmapCompMethod *LbxFindPreferredBitmapCompMethod (
+#if NeedFunctionPrototypes
+ XServerPtr /*server*/
+#endif
+);
+
+extern LbxPixmapCompMethod *LbxFindPreferredPixmapCompMethod (
+#if NeedFunctionPrototypes
+ XServerPtr /*server*/,
+ int /* format */,
+ int /* depth */
+#endif
+);
+
+#endif /* _LBX_PROXYOPTS_H_ */
diff --git a/include/reqtype.h b/include/reqtype.h
new file mode 100644
index 0000000..bfed83a
--- /dev/null
+++ b/include/reqtype.h
@@ -0,0 +1,71 @@
+/* $Xorg: reqtype.h,v 1.4 2001/02/09 02:05:32 xorgcvs Exp $ */
+/*
+
+Copyright 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+*/
+/*
+ * Copyright 1994 Network Computing Devices, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name Network Computing Devices, Inc. not be
+ * used in advertising or publicity pertaining to distribution of this
+ * software without specific, written prior permission.
+ *
+ * THIS SOFTWARE IS PROVIDED `AS-IS'. NETWORK COMPUTING DEVICES, INC.,
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT
+ * LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, OR NONINFRINGEMENT. IN NO EVENT SHALL NETWORK
+ * COMPUTING DEVICES, INC., BE LIABLE FOR ANY DAMAGES WHATSOEVER, INCLUDING
+ * SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES, INCLUDING LOSS OF USE, DATA,
+ * OR PROFITS, EVEN IF ADVISED OF THE POSSIBILITY THEREOF, AND REGARDLESS OF
+ * WHETHER IN AN ACTION IN CONTRACT, TORT OR NEGLIGENCE, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#ifndef _REQTYPE_H_
+#define _REQTYPE_H_
+
+#define REQ_TYPE_NO 0
+#define REQ_TYPE_YES 1
+#define REQ_TYPE_MAYBE 2
+
+extern Bool GeneratesEvents(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/,
+ xReq * /*req*/
+#endif
+);
+
+extern int GeneratesReplies(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/,
+ xReq * /*req*/
+#endif
+);
+
+#endif /* _REQTYPE_H_ */
diff --git a/include/resource.h b/include/resource.h
new file mode 100644
index 0000000..2fc494e
--- /dev/null
+++ b/include/resource.h
@@ -0,0 +1,137 @@
+/* $Xorg: resource.h,v 1.4 2001/02/09 02:05:32 xorgcvs Exp $ */
+
+/*
+
+Copyright 1995, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from The Open Group.
+
+*/
+
+#ifndef RESOURCE_H
+#define RESOURCE_H 1
+
+#define RT_COLORMAP ((RESTYPE)1)
+#define RT_CMAPENTRY ((RESTYPE)2)
+#define RT_LASTPREDEF ((RESTYPE)2)
+#define RT_NONE ((RESTYPE)0)
+
+#define RC_NEVERRETAIN ((RESTYPE)1<<29)
+#define RC_LASTPREDEF RC_NEVERRETAIN
+#define RC_ANY (~(RESTYPE)0)
+
+typedef unsigned long RESTYPE;
+
+typedef struct _Resource {
+ struct _Resource *next;
+ XID id;
+ RESTYPE type;
+ pointer value;
+} ResourceRec, *ResourcePtr;
+#define NullResource ((ResourcePtr)NULL)
+
+typedef struct _ClientResource {
+ ResourcePtr *resources;
+ int elements;
+ int buckets;
+ int hashsize; /* log(2)(buckets) */
+ XID fakeID;
+ XID endFakeID;
+} ClientResourceRec;
+
+
+/* bits and fields within a resource id */
+#define PROXY_BIT 0x40000000 /* use illegal bit */
+
+typedef int (*DeleteType)(
+#if NeedNestedPrototypes
+ ClientPtr /*client*/,
+ pointer /*value*/,
+ XID /*id*/
+#endif
+);
+
+extern Bool InitDeleteFuncs(
+#if NeedFunctionPrototypes
+ void
+#endif
+);
+
+extern Bool InitClientResources(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/
+#endif
+);
+
+extern void FinishInitClientResources(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/,
+ XID /*ridBase*/,
+ XID /*ridMask*/
+#endif
+);
+
+extern XID FakeClientID(
+#if NeedFunctionPrototypes
+ int /*client*/
+#endif
+);
+
+extern Bool AddResource(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/,
+ XID /*id*/,
+ RESTYPE /*type*/,
+ pointer /*value*/
+#endif
+);
+
+extern void FreeResource(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/,
+ XID /*id*/,
+ RESTYPE /*skipDeleteFuncType*/
+#endif
+);
+
+extern void FreeClientResources(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/
+#endif
+);
+
+extern void FreeAllResources(
+#if NeedFunctionPrototypes
+ void
+#endif
+);
+
+extern pointer LookupIDByType(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/,
+ XID /*id*/,
+ RESTYPE /*rtype*/
+#endif
+);
+
+#endif
diff --git a/include/swap.h b/include/swap.h
new file mode 100644
index 0000000..d94d29d
--- /dev/null
+++ b/include/swap.h
@@ -0,0 +1,254 @@
+/*
+ * $Xorg: swap.h,v 1.3 2000/08/17 19:53:58 cpqbld Exp $
+ *
+ * Copyright 1994 Network Computing Devices, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name Network Computing Devices, Inc. not be
+ * used in advertising or publicity pertaining to distribution of this
+ * software without specific, written prior permission.
+ *
+ * THIS SOFTWARE IS PROVIDED `AS-IS'. NETWORK COMPUTING DEVICES, INC.,
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT
+ * LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, OR NONINFRINGEMENT. IN NO EVENT SHALL NETWORK
+ * COMPUTING DEVICES, INC., BE LIABLE FOR ANY DAMAGES WHATSOEVER, INCLUDING
+ * SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES, INCLUDING LOSS OF USE, DATA,
+ * OR PROFITS, EVEN IF ADVISED OF THE POSSIBILITY THEREOF, AND REGARDLESS OF
+ * WHETHER IN AN ACTION IN CONTRACT, TORT OR NEGLIGENCE, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#ifndef _SWAP_H_
+#define _SWAP_H_
+
+extern void SwapConnSetup(
+#if NeedFunctionPrototypes
+ xConnSetup * /*pConnSetup*/,
+ xConnSetup * /*pConnSetupT*/
+#endif
+);
+
+extern void SwapWinRoot(
+#if NeedFunctionPrototypes
+ xWindowRoot * /*pRoot*/,
+ xWindowRoot * /*pRootT*/
+#endif
+);
+
+extern void SwapVisual(
+#if NeedFunctionPrototypes
+ xVisualType * /*pVis*/,
+ xVisualType * /*pVisT*/
+#endif
+);
+
+extern void SwapConnectionInfo(
+#if NeedFunctionPrototypes
+ xConnSetup * /*pConnSetup*/
+#endif
+);
+
+extern void WriteSConnectionInfo(
+#if NeedFunctionPrototypes
+ ClientPtr /*pClient*/,
+ unsigned long /*size*/,
+ char * /*pInfo*/
+#endif
+);
+
+extern void SwapGetPropertyReply(
+#if NeedFunctionPrototypes
+ xGetPropertyReply * /*rep*/
+#endif
+);
+
+extern void SwapInternAtomReply(
+#if NeedFunctionPrototypes
+ xInternAtomReply * /*rep*/
+#endif
+);
+
+extern void SwapGetAtomNameReply(
+#if NeedFunctionPrototypes
+ xGetAtomNameReply * /*rep*/
+#endif
+);
+
+extern void SwapLookupColorReply(
+#if NeedFunctionPrototypes
+ xLookupColorReply * /*rep*/
+#endif
+);
+
+extern void SwapAllocColorReply(
+#if NeedFunctionPrototypes
+ xAllocColorReply * /*rep*/
+#endif
+);
+
+extern void SwapAllocNamedColorReply(
+#if NeedFunctionPrototypes
+ xAllocNamedColorReply * /*rep*/
+#endif
+);
+
+extern void SwapModmapReply(
+#if NeedFunctionPrototypes
+ xGetModifierMappingReply * /*rep*/
+#endif
+);
+
+extern void SwapKeymapReply(
+#if NeedFunctionPrototypes
+ xGetKeyboardMappingReply * /*rep*/
+#endif
+);
+
+extern void SwapGetImageReply(
+#if NeedFunctionPrototypes
+ xGetImageReply * /*rep*/
+#endif
+);
+
+extern void SwapQueryExtensionReply(
+#if NeedFunctionPrototypes
+ xQueryExtensionReply * /*rep*/
+#endif
+);
+
+extern void SwapFont(
+#if NeedFunctionPrototypes
+ xQueryFontReply * /*pr*/,
+ Bool /*native*/
+#endif
+);
+
+extern void LbxSwapFontInfo(
+#if NeedFunctionPrototypes
+ xLbxFontInfo * /*pr*/,
+ Bool /*compressed*/
+#endif
+);
+
+extern void SwapLongs(
+#if NeedFunctionPrototypes
+ CARD32 * /*list*/,
+ unsigned long /*count*/
+#endif
+);
+
+extern void SwapShorts(
+#if NeedFunctionPrototypes
+ short * /*list*/,
+ unsigned long /*count*/
+#endif
+);
+
+extern void SwapConnClientPrefix(
+#if NeedFunctionPrototypes
+ xConnClientPrefix * /*pCCP*/
+#endif
+);
+
+extern void SwapNewClient(
+#if NeedFunctionPrototypes
+ xLbxNewClientReq * /*r*/
+#endif
+);
+
+extern void SwapCloseClient(
+#if NeedFunctionPrototypes
+ xLbxCloseClientReq * /*r*/
+#endif
+);
+
+extern void SwapModifySequence(
+#if NeedFunctionPrototypes
+ xLbxModifySequenceReq * /*r*/
+#endif
+);
+
+extern void SwapIncrementPixel(
+#if NeedFunctionPrototypes
+ xLbxIncrementPixelReq * /*r*/
+#endif
+);
+
+extern void SwapGetModifierMapping(
+#if NeedFunctionPrototypes
+ xLbxGetModifierMappingReq * /*r*/
+#endif
+);
+
+extern void SwapGetKeyboardMapping(
+#if NeedFunctionPrototypes
+ xLbxGetKeyboardMappingReq * /*r*/
+#endif
+);
+
+extern void SwapQueryFont(
+#if NeedFunctionPrototypes
+ xLbxQueryFontReq * /*r*/
+#endif
+);
+
+extern void SwapChangeProperty(
+#if NeedFunctionPrototypes
+ xLbxChangePropertyReq * /*r*/
+#endif
+);
+
+extern void SwapGetProperty(
+#if NeedFunctionPrototypes
+ xLbxGetPropertyReq * /*r*/
+#endif
+);
+
+extern void SwapPutImage(
+#if NeedFunctionPrototypes
+ xLbxPutImageReq * /*r*/
+#endif
+);
+
+extern void SwapGetImage(
+#if NeedFunctionPrototypes
+ xLbxGetImageReq * /*r*/
+#endif
+);
+
+extern void SwapInvalidateTag(
+#if NeedFunctionPrototypes
+ xLbxInvalidateTagReq * /*r*/
+#endif
+);
+
+extern void SwapTagData(
+#if NeedFunctionPrototypes
+ xLbxTagDataReq * /*r*/
+#endif
+);
+
+extern void SwapQueryExtension(
+#if NeedFunctionPrototypes
+ xLbxQueryExtensionReq * /*r*/
+#endif
+);
+
+extern void SwapLbxConnSetupPrefix(
+#if NeedFunctionPrototypes
+ xLbxConnSetupPrefix * /*csp*/
+#endif
+);
+
+extern void SwapConnSetupPrefix(
+#if NeedFunctionPrototypes
+ xConnSetupPrefix * /*csp*/
+#endif
+);
+
+#endif /* _SWAP_H_ */
diff --git a/include/tags.h b/include/tags.h
new file mode 100644
index 0000000..d48be5f
--- /dev/null
+++ b/include/tags.h
@@ -0,0 +1,134 @@
+/* $Xorg: tags.h,v 1.4 2001/02/09 02:05:32 xorgcvs Exp $ */
+/*
+
+Copyright 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+*/
+/*
+ * Copyright 1993 Network Computing Devices, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name Network Computing Devices, Inc. not be
+ * used in advertising or publicity pertaining to distribution of this
+ * software without specific, written prior permission.
+ *
+ * THIS SOFTWARE IS PROVIDED `AS-IS'. NETWORK COMPUTING DEVICES, INC.,
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT
+ * LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, OR NONINFRINGEMENT. IN NO EVENT SHALL NETWORK
+ * COMPUTING DEVICES, INC., BE LIABLE FOR ANY DAMAGES WHATSOEVER, INCLUDING
+ * SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES, INCLUDING LOSS OF USE, DATA,
+ * OR PROFITS, EVEN IF ADVISED OF THE POSSIBILITY THEREOF, AND REGARDLESS OF
+ * WHETHER IN AN ACTION IN CONTRACT, TORT OR NEGLIGENCE, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#ifndef _TAGS_H_
+#define _TAGS_H_
+
+#include "cache.h"
+
+typedef struct _tagdata {
+ XID tid;
+ int data_type;
+ unsigned long size;
+ pointer tdata;
+} TagDataRec;
+
+typedef struct _tagdata *TagData;
+
+extern void TagsInit(
+#if NeedFunctionPrototypes
+ XServerPtr /*server*/,
+ Bool /*useTags*/
+#endif
+);
+
+extern void FreeTags(
+#if NeedFunctionPrototypes
+ void
+#endif
+);
+
+extern Bool TagStoreData(
+#if NeedFunctionPrototypes
+ XServerPtr /*server*/,
+ Cache /*cache*/,
+ CacheID /*id*/,
+ int /*size*/,
+ int /*dtype*/,
+ pointer /*data*/
+#endif
+);
+
+extern Bool TagStoreDataNC(
+#if NeedFunctionPrototypes
+ XServerPtr /*server*/,
+ Cache /*cache*/,
+ CacheID /*id*/,
+ int /*size*/,
+ int /*dtype*/,
+ pointer /*data*/
+#endif
+);
+
+extern TagData TagGetTag(
+#if NeedFunctionPrototypes
+ XServerPtr /*server*/,
+ Cache /*cache*/,
+ CacheID /*id*/
+#endif
+);
+
+extern pointer TagGetData(
+#if NeedFunctionPrototypes
+ XServerPtr /*server*/,
+ Cache /*cache*/,
+ CacheID /*id*/
+#endif
+);
+
+extern void TagFreeData(
+#if NeedFunctionPrototypes
+ XServerPtr /*server*/,
+ Cache /*cache*/,
+ CacheID /*id*/,
+ Bool /*notify*/
+#endif
+);
+
+extern Bool AnyTagBearingReplies(
+#if NeedFunctionPrototypes
+ XServerPtr /*server*/,
+ Cache /*cache*/
+#endif
+);
+
+extern Cache global_cache;
+extern Cache prop_cache;
+
+#endif /* _TAGS_H_ */
diff --git a/include/util.h b/include/util.h
new file mode 100644
index 0000000..a4ad597
--- /dev/null
+++ b/include/util.h
@@ -0,0 +1,227 @@
+/* $Xorg: util.h,v 1.4 2001/02/09 02:05:32 xorgcvs Exp $ */
+/*
+
+Copyright 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+*/
+/*
+ * Copyright 1994 Network Computing Devices, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name Network Computing Devices, Inc. not be
+ * used in advertising or publicity pertaining to distribution of this
+ * software without specific, written prior permission.
+ *
+ * THIS SOFTWARE IS PROVIDED `AS-IS'. NETWORK COMPUTING DEVICES, INC.,
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT
+ * LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, OR NONINFRINGEMENT. IN NO EVENT SHALL NETWORK
+ * COMPUTING DEVICES, INC., BE LIABLE FOR ANY DAMAGES WHATSOEVER, INCLUDING
+ * SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES, INCLUDING LOSS OF USE, DATA,
+ * OR PROFITS, EVEN IF ADVISED OF THE POSSIBILITY THEREOF, AND REGARDLESS OF
+ * WHETHER IN AN ACTION IN CONTRACT, TORT OR NEGLIGENCE, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+#ifndef _UTIL_H_
+#define _UTIL_H_
+
+#ifdef SIGNALRETURNSINT
+#define SIGVAL int
+#else
+#define SIGVAL void
+#endif
+
+typedef SIGVAL (*OsSigHandlerPtr)(
+#if NeedFunctionPrototypes
+ int /* sig */
+#endif
+);
+
+extern OsSigHandlerPtr OsSignal(
+#if NeedFunctionPrototypes
+ int /*sig*/,
+ OsSigHandlerPtr /*handler*/
+#endif
+);
+
+extern void AutoResetServer(
+#if NeedFunctionPrototypes
+ int /*sig*/
+#endif
+);
+
+extern void GiveUp(
+#if NeedFunctionPrototypes
+ int /*sig*/
+#endif
+);
+
+extern void Error(
+#if NeedFunctionPrototypes
+ char * /*str*/
+#endif
+);
+
+extern CARD32 GetTimeInMillis(
+#if NeedFunctionPrototypes
+ void
+#endif
+);
+
+extern int AdjustWaitForDelay(
+#if NeedFunctionPrototypes
+ pointer /*waitTime*/,
+ unsigned long /*newdelay*/
+#endif
+);
+
+extern void UseMsg(
+#if NeedFunctionPrototypes
+ void
+#endif
+);
+
+extern void ProcessCommandLine(
+#if NeedFunctionPrototypes
+ int /*argc*/,
+ char * /*argv*/[]
+#endif
+);
+
+#define xalloc(size) Xalloc((unsigned long)(size))
+#define xcalloc(size) Xcalloc((unsigned long)(size))
+#define xrealloc(ptr, size) Xrealloc((pointer)(ptr), (unsigned long)(size))
+#define xfree(ptr) Xfree((pointer)(ptr))
+
+extern unsigned long *Xalloc(
+#if NeedFunctionPrototypes
+ unsigned long /*amount*/
+#endif
+);
+
+extern unsigned long *Xcalloc(
+#if NeedFunctionPrototypes
+ unsigned long /*amount*/
+#endif
+);
+
+extern unsigned long *Xrealloc(
+#if NeedFunctionPrototypes
+ pointer /*ptr*/,
+ unsigned long /*amount*/
+#endif
+);
+
+extern void Xfree(
+#if NeedFunctionPrototypes
+ pointer /*ptr*/
+#endif
+);
+
+extern void OsInitAllocator(
+#if NeedFunctionPrototypes
+ void
+#endif
+);
+
+extern void AuditF(
+#if NeedVarargsPrototypes
+ char * /*f*/,
+ ...
+#endif
+);
+
+extern void FatalError(
+#if NeedVarargsPrototypes
+ char * /*f*/,
+ ...
+#endif
+);
+
+extern void ErrorF(
+#if NeedVarargsPrototypes
+ char * /*f*/,
+ ...
+#endif
+);
+
+extern char *strnalloc(
+#if NeedFunctionPrototypes
+ char * /*str*/,
+ int /*len*/
+#endif
+);
+
+typedef struct _WorkQueue *WorkQueuePtr;
+
+extern void ProcessWorkQueue(
+#if NeedFunctionPrototypes
+ void
+#endif
+);
+
+extern Bool QueueWorkProc(
+#if NeedFunctionPrototypes
+ Bool (* /*function*/)(),
+ ClientPtr /*client*/,
+ pointer /*closure*/
+#endif
+);
+
+extern Bool ClientSleep(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/,
+ Bool (* /*function*/)(),
+ pointer /*closure*/
+#endif
+);
+
+extern Bool ClientSignal(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/
+#endif
+);
+
+extern void ClientWakeup(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/
+#endif
+);
+
+extern Bool ClientIsAsleep(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/
+#endif
+);
+
+extern void LBXReadAtomsFile(
+#if NeedFunctionPrototypes
+ XServerPtr /*server*/
+#endif
+);
+
+#endif /* _UTIL_H_ */
diff --git a/include/wire.h b/include/wire.h
new file mode 100644
index 0000000..14e9761
--- /dev/null
+++ b/include/wire.h
@@ -0,0 +1,419 @@
+/* $Xorg: wire.h,v 1.4 2001/02/09 02:05:32 xorgcvs Exp $ */
+/*
+
+Copyright 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+*/
+/*
+ * Copyright 1992 Network Computing Devices
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of NCD. not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. NCD. makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * NCD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL NCD.
+ * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#ifdef DEBUG /* Need this here because lbx.h undef's DEBUG */
+extern int lbxDebug;
+#endif
+
+#include "misc.h"
+#include "lbx.h"
+#include "lbxdeltastr.h"
+#include "lbximage.h"
+#include "proxyopts.h"
+#include "colormap.h"
+#include "atomcache.h"
+#include "cache.h"
+#include "resource.h"
+
+typedef struct _extinfo *ExtensionInfoPtr;
+
+/*
+ * NOTES on the implementation of the multi-display lbxproxy.
+ *
+ * o Each display has its own listen port(s).
+ *
+ * o Depending on how the proxy is compiled, it may support multiple
+ * transports thus more than one fd may be associated with a display.
+ *
+ * o When a new client connects, the proxy must be able to determine
+ * which display the client is interested in. To facilitate this, when
+ * a display's listen port(s) are created, a list of the display's
+ * fd's is cached in the field listen_fds.
+ *
+ * o When accept is called, the listen_fds in the servers array is
+ * searched to find the client's display.
+ */
+
+/*
+ * MAXTRANSPORTS is the maximum number of transports or listen
+ * ports that a proxy can support. The number is determine at compile
+ * by the xtrans library but there is no public interface to this
+ * number. See lib/xtrans/Xtrans.c for more information.
+ */
+#define MAXTRANSPORTS 13
+
+/*
+ * The maximum number of options that is negotiable.
+ */
+#define MAX_NEG_OPTS 8
+
+typedef struct _LbxOptionsListRec {
+ CARD8 optcode;
+ Bool negotiate;
+ int (*req)();
+ int (*reply)();
+} LbxOptionsListRec;
+
+typedef struct _LbxDeltaOptionsRec {
+ CARD8 minN; /* min cache size */
+ CARD8 maxN; /* max cache size */
+ CARD8 prefN; /* preferred cache size */
+ CARD8 minMaxMsgLen; /* min max-message-len / 4 */
+ CARD8 maxMaxMsgLen; /* max max-message-len / 4 */
+ CARD8 prefMaxMsgLen; /* preferred max-message-len / 4 */
+} LbxDeltaOptionsRec;
+
+typedef struct _LbxStreamComp {
+ int typelen;
+ char *type;
+ int (*req)();
+ int (*reply)();
+} LbxStreamCompRec;
+
+typedef struct _LbxCmapAllMethod {
+ char *methodName;
+ void (*resolver)(
+#if NeedFunctionPrototypes
+ LbxVisualPtr /* pVisual */,
+ CARD16* /* red */,
+ CARD16* /* green */,
+ CARD16* /* blue */
+#endif
+ );
+ Pixel (*findfree)(
+#if NeedFunctionPrototypes
+ ColormapPtr /* pmap */,
+ CARD32 /* red */,
+ CARD32 /* green */,
+ CARD32 /* blue */
+#endif
+ );
+ Entry * (* findbest)(
+#if NeedFunctionPrototypes
+ ColormapPtr /* pmap */,
+ CARD32 /* red */,
+ CARD32 /* green */,
+ CARD32 /* blue */,
+ int /* channels */
+#endif
+ );
+
+} LbxCmapAllMethod;
+
+typedef struct _XServer {
+ int index;
+ int fd;
+ int lbxReq;
+ int lbxEvent;
+ int lbxError;
+ Bool initialized;
+ char *display_name; /* The name as requested by the client*/
+ char *proxy_name; /* The actual name used by the proxy */
+ int listen_fds[MAXTRANSPORTS];
+ ClientPtr prev_exec;
+ ClientPtr send, recv;
+ ClientPtr serverClient;
+ int recv_expect;
+ int motion_allowed;
+ Bool wm_running;
+ pointer compHandle;
+ lbxMotionCache motionCache;
+ ExtensionInfoPtr extensions;
+ LBXDeltasRec indeltas;
+ LBXDeltasRec outdeltas;
+
+ /*
+ * The following fields are needed to handle the option
+ * negotiation for a multi-display proxy.
+ */
+ LbxOptionsListRec LbxOptions[MAX_NEG_OPTS];
+ int optcount; /* Number of options actually negotiated */
+ int optlist[MAX_NEG_OPTS];
+ LbxNegOptsRec lbxNegOpt;
+ LbxDeltaOptionsRec proxyDeltaOpt;
+ LbxDeltaOptionsRec serverDeltaOpt;
+ LbxStreamCompRec LbxStreamComp[1];
+ LbxBitmapCompMethod LbxBitmapCompMethods[1];
+ LbxPixmapCompMethod LbxPixmapCompMethods[1];
+ LbxCmapAllMethod LbxCmapAllMethods[1];
+
+ /*
+ * requestVector is the function table to be used by the
+ * "real" clients associated with this server.
+ */
+ int (**requestVector) (
+#if NeedNestedPrototypes
+ ClientPtr /* pClient */
+#endif
+ );
+
+ /*
+ * The following fields are needed to handle the atom
+ * cache for a multi-display proxy.
+ */
+ AtomControlPtr atom_control;
+ int atom_control_count;
+ AtomListPtr *hashTable;
+ int hashSize;
+ int hashUsed;
+ int hashMask;
+ int rehash;
+ AtomListPtr *reverseMap;
+ int reverseMapSize;
+ Atom lastAtom;
+
+ /*
+ * The following fields are needed for each server's
+ * global and property caches.
+ */
+ Cache global_cache;
+ Cache prop_cache;
+ CachePtr caches[MAX_NUM_CACHES + 1];
+ int num_caches;
+ unsigned long seed;
+
+ /*
+ * The following fields are needed for each server's
+ * colormap caches.
+ */
+ RGBCacheEntryPtr rgb_cache[NBUCKETS];
+ RGBEntryRec rgb_buf;
+ Entry rgb_ent;
+
+ /*
+ * Server-specific temporary delta buffer
+ */
+ unsigned char tempdeltabuf[256];
+
+ /*
+ * The following fields are used to mange a server's resources
+ */
+ ClientResourceRec clientTable[MAXCLIENTS];
+ ClientPtr lastLbxClientIndexLookup;
+
+ /*
+ * The following fields maintain a server's state for grab's
+ */
+ int lbxIgnoringAll;
+ int lbxGrabInProgress;
+
+ struct _XDisplay* dpy;
+
+} XServerRec;
+
+
+/*
+ * External declarations for global variables defined in main.c
+ */
+extern XServerPtr * servers;
+extern char * display;
+extern int lbxMaxServers;
+
+extern void WriteReqToServer(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/,
+ int /*len*/,
+ char * /*buf*/,
+ Bool /*checkLargeRequest*/
+#endif
+);
+
+extern void WriteToServer(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/,
+ int /*len*/,
+ char * /*buf*/,
+ Bool /*startOfRequest*/,
+ Bool /*checkLargeRequest*/
+#endif
+);
+
+extern void _write_to_server(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/,
+ Bool /*compressed*/,
+ int /*len*/,
+ char* /*buf*/,
+ Bool /*checkLarge*/,
+ Bool /*startOfRequest*/
+#endif
+);
+
+extern void WriteToServerUncompressed(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/,
+ int /*len*/,
+ char * /*buf*/,
+ Bool /* startOfRequest */
+#endif
+);
+
+extern Bool NewClient(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/,
+ int /*setuplen*/
+#endif
+);
+
+extern void CloseClient(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/
+#endif
+);
+
+extern void ModifySequence(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/,
+ int /*num*/
+#endif
+);
+
+extern void AllowMotion(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/,
+ int /*num*/
+#endif
+);
+
+extern void SendIncrementPixel(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/,
+ XID /*cmap*/,
+ unsigned long /*pixel*/
+#endif
+);
+
+extern void SendGetModifierMapping(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/
+#endif
+);
+
+extern void SendGetKeyboardMapping(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/
+#endif
+);
+
+extern void SendQueryFont(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/,
+ XID /*fid*/
+#endif
+);
+
+extern void SendChangeProperty(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/,
+ Window /*win*/,
+ Atom /*prop*/,
+ Atom /*type*/,
+ int /*format*/,
+ int /*mode*/,
+ unsigned long /*num*/
+#endif
+);
+
+extern void SendGetProperty(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/,
+ Window /*win*/,
+ Atom /*prop*/,
+ Atom /*type*/,
+ Bool /*delete*/,
+ unsigned long /*off*/,
+ unsigned long /*len*/
+#endif
+);
+
+extern void SendInvalidateTag(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/,
+ XID /*tag*/
+#endif
+);
+
+extern void SendTagData(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/,
+ XID /*tag*/,
+ unsigned long /*len*/,
+ pointer /*data*/
+#endif
+);
+
+extern void SendGetImage(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/,
+ Drawable /*drawable*/,
+ int /*x*/,
+ int /*y*/,
+ unsigned int /*width*/,
+ unsigned int /*height*/,
+ unsigned long /*planeMask*/,
+ int /*format*/
+#endif
+);
+
+extern int ServerProcStandardEvent(
+#if NeedFunctionPrototypes
+ ClientPtr /*sc*/
+#endif
+);
+
+extern void CloseServer(
+#if NeedFunctionPrototypes
+ ClientPtr /*client*/
+#endif
+);
+
+extern Bool ConnectToServer(
+#if NeedFunctionPrototypes
+ char * /*dpy_name*/
+#endif
+);
diff --git a/lbxproxy.man b/lbxproxy.man
new file mode 100644
index 0000000..52c51af
--- /dev/null
+++ b/lbxproxy.man
@@ -0,0 +1,233 @@
+.\" $Xorg: lbxproxy.man,v 1.4 2001/02/09 02:05:31 xorgcvs Exp $
+.\" Copyright 1996, 1998 The Open Group
+.\"
+.\" Permission to use, copy, modify, distribute, and sell this software and its
+.\" documentation for any purpose is hereby granted without fee, provided that
+.\" the above copyright notice appear in all copies and that both that
+.\" copyright notice and this permission notice appear in supporting
+.\" documentation.
+.\"
+.\" The above copyright notice and this permission notice shall be included
+.\" in all copies or substantial portions of the Software.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+.\" OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+.\" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+.\" IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
+.\" OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+.\" ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+.\" OTHER DEALINGS IN THE SOFTWARE.
+.\"
+.\" Except as contained in this notice, the name of The Open Group shall
+.\" not be used in advertising or otherwise to promote the sale, use or
+.\" other dealings in this Software without prior written authorization
+.\" from The Open Group.
+.\"
+.TH LBXPROXY 1 "Release 6.4" "X Version 11"
+.SH NAME
+lbxproxy - Low BandWidth X proxy
+.SH SYNOPSIS
+.B lbxproxy [:<display>] [option]
+.SH DESCRIPTION
+Applications that would like to take advantage of the Low Bandwidth
+extension to X (LBX) must make their connections to an lbxproxy. These
+applications need to know nothing about LBX, they simply connect to the
+lbxproxy as if were a regular server. The lbxproxy accepts client
+connections, multiplexes them over a single connection to the X server, and
+performs various optimizations on the X protocol to make it faster over low
+bandwidth and/or high latency connections.
+.PP
+With regard to authentication/authorization, lbxproxy simply passes along
+to the server the credentials presented by the client. Since X clients will
+connect to lbxproxy, it is important that the user's .Xauthority file contain
+entries with valid keys associated with the network ID of the proxy. lbxproxy
+does not get involved with how these entries are added to the .Xauthority file.
+The user is responsible for setting it up.
+.PP
+The lbxproxy program has various options, all of which are optional.
+.PP
+If
+.B :<display>
+is specified, the proxy will use the given display port when
+listening for connections. The display port is an offset from port 6000,
+identical to the way in which regular X display connections are specified.
+If no port is specified on the command line option, lbxproxy will default
+to port 63. If the port number that the proxy tries to listen on is in
+use, the proxy will attempt to use another port number. If
+the proxy is not using the Proxy Manager and the default
+port number cannot be used, the port number that is used
+will be written to stderr.
+.PP
+The other command line options that can be specified are:
+.PP
+.TP 8
+.B \-help
+Prints a brief help message about the command line options.
+.TP 8
+.B \-display \fIdpy\fP
+Specifies the address of the X server supporting the LBX extension.
+If this option is not specified, the display is obtained by the
+DISPLAY environment variable.
+.TP 8
+.B \-motion \fIcount\fP
+A limited number of pointer motion events are allowed to be in flight
+between the server and the proxy at any given time. The maximimum
+number of motion events that can be in flight is set with this option;
+the default is 8.
+.TP 8
+.B \-maxservers \fInumber\fP
+The default behavior of lbxproxy is to manage a single server.
+However, lbxproxy can manage more than one server. The default
+maximum number of servers is 20. The number of servers can be
+overridden by setting the environment variable LBXPROXY_MAXSERVERS
+to the desired number. The order of precedence from highest
+to lowest: command line, environment variable, default number.
+.TP 8
+.B \-[terminate|reset]
+The default behavior of lbxproxy is to continue running as usual when
+it's last client exits. The
+.B \-terminate
+option will cause lbxproxy to
+exit when the last client exits. The
+.B \-reset
+option will cause
+lbxproxy to reset itself when the last client exits. Resetting causes
+lbxproxy to clean up it's state and reconnect to the server.
+.TP 8
+.B \-reconnect
+The default behavior of lbxproxy is to exit when its connection to the
+server is broken. The
+.B \-reconnect
+option will cause lbxproxy to just reset instead (see
+.B \-reset
+above) and attempt to reconnect to the server.
+.TP 8
+.B \-I
+Causes all remaining arguments to be ignored.
+.TP 8
+.B \-nolbx
+Disables all LBX optimizations.
+.TP 8
+.B \-nocomp
+Disables stream compression.
+.TP 8
+.B \-nodelta
+Disables delta request substitutions.
+.TP 8
+.B \-notags
+Disables usage of tags.
+.TP 8
+.B \-nogfx
+Disables reencoding of graphics requests (not including image
+related requests).
+.TP 8
+.B \-noimage
+Disables image compression.
+.TP 8
+.B \-nosquish
+Disables squishing of X events.
+.TP 8
+.B \-nointernsc
+Disables short circuiting of InternAtom requests.
+.TP 8
+.B \-noatomsfile
+Disables reading of the atoms control file. See the section on
+"Atom Control" for more details.
+.TP 8
+.B \-atomsfile \fIfile\fP
+Overrides the default AtomControl file. See the section on
+"Atom Control" for more details.
+.TP 8
+.B \-nowinattr
+Disables GetWindowAttributes/GetGeometry grouping into one round trip.
+.TP 8
+.B \-nograbcmap
+Disables colormap grabbing.
+.TP 8
+.B \-norgbfile
+Disables color name to RGB resolution in proxy.
+.TP 8
+.B \-rgbfile \fIpath\fP
+Specifies an alternate RGB database for color name to RGB resolution.
+.TP 8
+.B \-tagcachesize
+Set the size of the proxy's tag cache (in bytes).
+.TP 8
+.B \-zlevel \fIlevel\fP
+Set the Zlib compression level (used for stream compression).
+.br
+default is 6
+.br
+1 = worst compression, fastest
+.br
+9 = best compression, slowest
+.TP 8
+.B \-compstats
+Report stream compression statistics every time the proxy resets
+or receives a SIGHUP signal.
+.TP 8
+.B \-nozeropad
+Don't zero out unused pad bytes in X requests, replies, and events.
+.TP 8
+.B \-cheaterrors
+Allows cheating on X protocol for the sake of improved performance.
+The X protocol guarantees that any replies, events or
+errors generated by a previous request will be sent before those of
+a later request. This puts substantial restrictions on when lbxproxy
+can short circuit a request. The -cheaterrors option allows lbxproxy to
+violate X protocol rules with respect to errors. Use at your own risk.
+.TP 8
+.B \-cheatevents
+The -cheatevents option allows lbxproxy to violate X protocol rules with
+respect to events as well as errors. Use at your own risk.
+.PP
+.SH ATOM CONTROL
+.PP
+At startup, lbxproxy "pre-interns" a configurable list of
+atoms. This allows lbxproxy to intern a group of atoms in a single round
+trip and immediately store the results in its cache.
+.PP
+While running, lbxproxy uses heuristics to decide when to delay
+sending window property data to the server. The heuristics depend
+on the size of the data, the name of the property, and whether a
+window manager is running through the same lbxproxy.
+.PP
+Atom control is specified in the "AtomControl" file, set
+up during installation of lbxproxy, with command line overrides.
+.PP
+The file is a simple text file. There are three forms of lines:
+comments, length control, and name control. Lines starting with
+a '!' are treated as comments. A line of the form
+.sp
+.in +4
+.nf
+z \fIlength\fP
+.fi
+.in -4
+.sp
+specifies the minimum length in bytes before property data will be
+delayed. A line of the form
+.sp
+.in +4
+.nf
+\fIoptions\fP \fIatomname\fP
+.fi
+.in -4
+.sp
+controls the given atom, where \fIoptions\fP is any combination
+of the following characters: 'i' means the atom should be pre-interned;
+'n' means data for properties with this name should never be delayed;
+and 'w' means data for properties with this name should be delayed only
+if a window manager is also running through the same lbxproxy.
+.PP
+.SH BUGS
+.PP
+When the authorization protocol XDM-AUTHORIZATION-1 is used:
+.PP
+.in +4
+A client must be on the same host as lbxproxy for the client to be
+authorized to connect to the server.
+.PP
+.in +4
+If a client is not on the same host as lbxproxy, the client will
+not be authorized to connect to the server.
diff --git a/os/WaitFor.c b/os/WaitFor.c
new file mode 100644
index 0000000..cc42939
--- /dev/null
+++ b/os/WaitFor.c
@@ -0,0 +1,198 @@
+/* $Xorg: WaitFor.c,v 1.4 2001/02/09 02:05:33 xorgcvs Exp $ */
+/***********************************************************
+
+Copyright 1987, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+
+Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+******************************************************************/
+
+/*****************************************************************
+ * OS Dependent input routines:
+ *
+ * WaitForSomething
+ * TimerForce, TimerSet, TimerCheck, TimerFree
+ *
+ *****************************************************************/
+
+#include "Xos.h" /* for strings, fcntl, time */
+
+#include <errno.h>
+#ifdef X_NOT_STDC_ENV
+extern int errno;
+#endif
+
+#include <stdio.h>
+#include "misc.h"
+#include "util.h"
+#include <sys/param.h>
+
+#include <X11/Xpoll.h>
+#include "osdep.h"
+#include "os.h"
+#include "pm.h"
+
+extern int ConnectionTranslation[];
+
+extern WorkQueuePtr workQueue;
+
+/*****************
+ * WaitForSomething:
+ * Make the server suspend until there is
+ * 1. data from clients or
+ * 2. clients that have buffered replies/events are ready
+ *
+ * For more info on ClientsWithInput, see ReadRequestFromClient().
+ * pClientsReady is an array to store ready client->index values into.
+ *****************/
+
+int
+WaitForSomething(pClientsReady, poll)
+ int *pClientsReady;
+ Bool poll;
+{
+ int i;
+ struct timeval zerowt = {0, 0};
+ struct timeval *wt;
+ fd_set clientsReadable;
+ fd_set clientsWritable;
+ int curclient;
+ int selecterr;
+ int nready;
+
+ FD_ZERO(&clientsReadable);
+
+ /* We need a while loop here to handle
+ crashed connections and the screen saver timeout */
+ while (1)
+ {
+ /* deal with any blocked jobs */
+ if (workQueue)
+ ProcessWorkQueue();
+
+ if (XFD_ANYSET(&ClientsWithInput))
+ {
+ XFD_COPYSET(&ClientsWithInput, &clientsReadable);
+ break;
+ }
+ if (poll)
+ wt = &zerowt;
+ else
+ wt = NULL;
+ XFD_COPYSET(&AllSockets, &LastSelectMask);
+ if (NewOutputPending)
+ FlushAllOutput();
+ /* keep this check close to select() call to minimize race */
+ if (dispatchException)
+ i = -1;
+ else if (AnyClientsWriteBlocked)
+ {
+ XFD_COPYSET(&ClientsWriteBlocked, &clientsWritable);
+ i = Select (MAXSOCKS, &LastSelectMask, &clientsWritable, NULL, wt);
+ }
+ else
+ i = Select (MAXSOCKS, &LastSelectMask, NULL, NULL, wt);
+ selecterr = errno;
+
+ if (poll && i == 0)
+ return 0;
+ else if (i <= 0) /* An error or timeout occurred */
+ {
+
+ if (dispatchException)
+ return 0;
+ FD_ZERO(&clientsWritable);
+ if (i < 0)
+ if (selecterr == EBADF) /* Some client disconnected */
+ {
+ CheckConnections ();
+ if (! XFD_ANYSET (&AllClients))
+ return 0;
+ }
+ else if (selecterr != EINTR)
+ ErrorF("WaitForSomething(): select: errno=%d\n",
+ selecterr);
+ }
+ else
+ {
+ if (AnyClientsWriteBlocked && XFD_ANYSET (&clientsWritable))
+ {
+ NewOutputPending = TRUE;
+ XFD_ORSET(&OutputPending, &clientsWritable, &OutputPending);
+ XFD_UNSET(&ClientsWriteBlocked, &clientsWritable);
+ if (! XFD_ANYSET(&ClientsWriteBlocked))
+ AnyClientsWriteBlocked = FALSE;
+ }
+
+ XFD_ANDSET(&clientsReadable, &LastSelectMask, &AllClients);
+ if (LastSelectMask.fds_bits[0] & WellKnownConnections.fds_bits[0])
+ QueueWorkProc(EstablishNewConnections, NULL,
+ (pointer)&LastSelectMask);
+ if (proxy_manager_fd >= 0 &&
+ FD_ISSET(proxy_manager_fd, &LastSelectMask))
+ HandleProxyManagerConnection ();
+
+ if (XFD_ANYSET (&clientsReadable))
+ break;
+ }
+ }
+
+ nready = 0;
+ if (XFD_ANYSET(&clientsReadable))
+ {
+ for (i=0; i<howmany(XFD_SETSIZE, NFDBITS); i++)
+ {
+ while (clientsReadable.fds_bits[i])
+ {
+ int client_index;
+
+ curclient = ffs (clientsReadable.fds_bits[i]) - 1;
+ client_index = ConnectionTranslation[curclient + (i << 5)];
+ {
+ pClientsReady[nready++] = client_index;
+ }
+ clientsReadable.fds_bits[i] &= ~(((fd_mask)1) << curclient);
+ }
+ }
+ }
+ return nready;
+}
diff --git a/os/connection.c b/os/connection.c
new file mode 100644
index 0000000..1335e01
--- /dev/null
+++ b/os/connection.c
@@ -0,0 +1,886 @@
+/* $Xorg: connection.c,v 1.5 2001/02/09 02:05:33 xorgcvs Exp $ */
+/***********************************************************
+
+Copyright 1987, 1989, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+
+Copyright 1987, 1989 by Digital Equipment Corporation, Maynard, Massachusetts.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+/*****************************************************************
+ * Stuff to create connections --- OS dependent
+ *
+ * EstablishNewConnections, CreateWellKnownSockets,
+ * CloseDownConnection, CheckConnections, AddEnabledDevice,
+ * RemoveEnabledDevice, OnlyListToOneClient,
+ * ListenToAllClients,
+ *
+ * (WaitForSomething is in its own file)
+ *
+ * In this implementation, a client socket table is not kept.
+ * Instead, what would be the index into the table is just the
+ * file descriptor of the socket. This won't work for if the
+ * socket ids aren't small nums (0 - 2^8)
+ *
+ *****************************************************************/
+
+#include "misc.h"
+#include <X11/Xtrans.h>
+#include <sys/param.h>
+#include <stdio.h>
+#include <stdlib.h> /* atoi */
+#include <errno.h>
+#ifdef X_NOT_STDC_ENV
+extern int errno;
+#endif
+
+#include <signal.h>
+#include <setjmp.h>
+
+#include <sys/socket.h>
+
+#ifdef hpux
+#include <sys/utsname.h>
+#include <sys/ioctl.h>
+#endif
+
+#ifdef AIXV3
+#include <sys/ioctl.h>
+#endif
+
+#if defined (TCPCONN) || defined(STREAMSCONN)
+# include <netinet/in.h>
+# ifndef hpux
+# ifdef apollo
+# ifndef NO_TCP_H
+# include <netinet/tcp.h>
+# endif
+# else
+# include <netinet/tcp.h>
+# endif
+# endif
+#endif
+
+#include <sys/uio.h>
+#include <X11/Xpoll.h>
+#include "osdep.h"
+#include "os.h"
+#include "lbx.h"
+#include "util.h"
+#include "pm.h"
+#include "wire.h"
+
+#ifdef X_NOT_POSIX
+#define Pid_t int
+#else
+#define Pid_t pid_t
+#endif
+
+#ifdef DNETCONN
+#include <netdnet/dn.h>
+#endif /* DNETCONN */
+
+int lastfdesc; /* maximum file descriptor */
+
+fd_set WellKnownConnections; /* Listener mask */
+fd_set AllSockets; /* select on this */
+fd_set AllClients; /* available clients */
+fd_set LastSelectMask; /* mask returned from last select call */
+fd_set ClientsWithInput; /* clients with FULL requests in buffer */
+fd_set ClientsWriteBlocked; /* clients who cannot receive output */
+fd_set OutputPending; /* clients with reply/event data ready to go */
+int MaxClients = MAXSOCKS;
+Bool NewOutputPending; /* not yet attempted to write some new output */
+Bool AnyClientsWriteBlocked; /* true if some client blocked on write */
+
+Bool RunFromSmartParent; /* send SIGUSR1 to parent process */
+Bool PartialNetwork; /* continue even if unable to bind all addrs */
+static int ParentProcess;
+
+static Bool debug_conns = FALSE;
+
+static fd_set IgnoredClientsWithInput;
+static fd_set GrabImperviousClients;
+static fd_set SavedAllClients;
+static fd_set SavedAllSockets;
+static fd_set SavedClientsWithInput;
+
+static int auditTrailLevel = 1;
+
+int GrabInProgress = 0;
+int ConnectionTranslation[MAXSOCKS];
+int ConnectionOutputTranslation[MAXSOCKS];
+
+static XtransConnInfo *ListenTransConns = NULL;
+static int *ListenTransFds = NULL;
+static int ListenTransCount = 0;
+
+unsigned long raw_stream_out; /* out to server, in from client */
+unsigned long raw_stream_in; /* in from server, out to client */
+extern unsigned long stream_out_plain;
+extern unsigned long stream_in_plain;
+
+static void ErrorConnMax(
+#if NeedFunctionPrototypes
+ XtransConnInfo /* trans_conn */
+#endif
+);
+
+
+static Bool
+PickNewListenDisplay (displayP)
+ char **displayP;
+{
+ static char newDisplay[16];
+ sprintf (newDisplay, "%d", atoi (*displayP) + 1);
+ *displayP = newDisplay;
+
+ if (atoi (*displayP) > 65535)
+ return (FALSE);
+
+ return (TRUE);
+}
+
+static XtransConnInfo
+lookup_trans_conn (fd)
+ int fd;
+{
+ if (ListenTransFds)
+ {
+ int i;
+ for (i = 0; i < ListenTransCount; i++)
+ if (ListenTransFds[i] == fd)
+ return ListenTransConns[i];
+ }
+
+ return (NULL);
+}
+
+
+/*
+ * Create the socket(s) that clients will used for one server.
+ */
+void
+CreateServerSockets(fds)
+ int fds[];
+{
+ int done = 0;
+ int partial;
+ int tmp_trans_count;
+ XtransConnInfo *tmp_trans_conns;
+
+ while (!done)
+ {
+
+ if ((_LBXPROXYTransMakeAllCOTSServerListeners (display, &partial,
+ &tmp_trans_count, &tmp_trans_conns) >= 0) &&
+ (tmp_trans_count >= 1))
+ {
+ if (!PartialNetwork && partial)
+ {
+ (void) fprintf (stderr, "Failed to establish all listening sockets for port number '%s'\n", display);
+ if (PickNewListenDisplay (&display))
+ continue;
+ }
+ else
+ {
+ int i, num_fds;
+
+ /*
+ * Create or Re-create the ListenTransFds array
+ */
+ if (!ListenTransFds) {
+ ListenTransFds = (int *) malloc (tmp_trans_count *
+ sizeof (int));
+ }
+ else {
+ ListenTransFds = (int *)
+ realloc (ListenTransFds,
+ (ListenTransCount + tmp_trans_count) *
+ sizeof (int));
+ }
+ if (!ListenTransFds)
+ FatalError ("Failed to create ListenTransFds");
+
+ /*
+ * Create or Re-create the ListenTransConns array
+ */
+ if (!ListenTransConns)
+ ListenTransConns = tmp_trans_conns;
+ else {
+
+ ListenTransConns = (XtransConnInfo *)
+ realloc (ListenTransConns,
+ (ListenTransCount + tmp_trans_count) *
+ sizeof (XtransConnInfo));
+ if (!ListenTransConns)
+ FatalError ("Failed to create ListenTransFds");
+
+ /*
+ * Add in the new trans' for this server
+ */
+ for (i = 0; i < tmp_trans_count; i++)
+ ListenTransConns[ListenTransCount + i] =
+ tmp_trans_conns[i];
+ }
+
+ for (i = 0, num_fds = 0; i < tmp_trans_count; i++, num_fds++)
+ {
+ int fd;
+
+ fd = _LBXPROXYTransGetConnectionNumber (
+ ListenTransConns[i + ListenTransCount]);
+
+ fds[i] = fd;
+ ListenTransFds[i + ListenTransCount] = fd;
+ FD_SET (fd, &WellKnownConnections);
+ }
+
+ ListenTransCount += tmp_trans_count;
+
+ }
+ } else {
+ if (PickNewListenDisplay (&display))
+ continue;
+ }
+ done = 1;
+ }
+
+ if (!XFD_ANYSET (&WellKnownConnections))
+ FatalError ("Cannot establish any listening sockets");
+
+ /*
+ * If the Proxy Manager isn't being used and the the default port
+ * number isn't available, need to advertise the port number that
+ * clients will use to connect to this server.
+ */
+ if (!proxyMngr && strcmp (display, "63"))
+ (void) fprintf (stderr, "Using port number '%s'\n", display);
+}
+
+/*****************
+ * CreateWellKnownSockets
+ * Initialize the global connection file descriptor arrays
+ * but don't create the listen sockets until a server is
+ * requested.
+ *****************/
+void
+CreateWellKnownSockets()
+{
+ int i;
+
+ FD_ZERO(&AllSockets);
+ FD_ZERO(&AllClients);
+ FD_ZERO(&LastSelectMask);
+ FD_ZERO(&ClientsWithInput);
+
+ for (i=0; i<MAXSOCKS; i++) ConnectionTranslation[i] = 0;
+ for (i=0; i<MAXSOCKS; i++) ConnectionOutputTranslation[i] = 0;
+#ifdef XNO_SYSCONF
+#undef _SC_OPEN_MAX
+#endif
+#ifdef _SC_OPEN_MAX
+ lastfdesc = sysconf(_SC_OPEN_MAX) - 1;
+#else
+#ifdef hpux
+ lastfdesc = _NFILE - 1;
+#else
+ lastfdesc = getdtablesize() - 1;
+#endif
+#endif
+
+ if (lastfdesc > MAXSOCKS)
+ {
+ lastfdesc = MAXSOCKS;
+ if (debug_conns)
+ ErrorF( "GOT TO END OF SOCKETS %d\n", MAXSOCKS);
+ }
+
+ FD_ZERO(&WellKnownConnections);
+
+ OsSignal (SIGPIPE, SIG_IGN);
+ OsSignal (SIGHUP, AutoResetServer);
+ OsSignal (SIGINT, GiveUp);
+ OsSignal (SIGTERM, GiveUp);
+ /*
+ * Magic: If SIGUSR1 was set to SIG_IGN when
+ * the server started, assume that either
+ *
+ * a- The parent process is ignoring SIGUSR1
+ *
+ * or
+ *
+ * b- The parent process is expecting a SIGUSR1
+ * when the server is ready to accept connections
+ *
+ * In the first case, the signal will be harmless,
+ * in the second case, the signal will be quite
+ * useful
+ */
+ if (OsSignal (SIGUSR1, SIG_IGN) == SIG_IGN)
+ RunFromSmartParent = TRUE;
+ ParentProcess = getppid ();
+ if (RunFromSmartParent) {
+ if (ParentProcess > 0) {
+ kill (ParentProcess, SIGUSR1);
+ }
+ }
+}
+
+void
+ListenToProxyManager ()
+{
+ if (proxy_manager_fd >= 0)
+ FD_SET(proxy_manager_fd, &AllSockets);
+}
+
+void
+ListenWellKnownSockets ()
+{
+ XFD_ORSET (&AllSockets, &AllSockets, &WellKnownConnections);
+}
+
+void
+AvailableClientInput (client)
+ ClientPtr client;
+{
+ OsCommPtr oc = (OsCommPtr)client->osPrivate;
+
+ if (FD_ISSET(oc->fd, &AllSockets))
+ FD_SET(oc->fd, &ClientsWithInput);
+}
+
+static int
+ClientRead (fd, buf, len)
+ int fd;
+ char *buf;
+ int len;
+{
+ int n;
+ n = read(fd, buf, len);
+ if (n > 0)
+ raw_stream_out += n;
+ return n;
+}
+
+static int
+ClientWritev(fd, iov, iovcnt)
+ int fd;
+ struct iovec *iov;
+ int iovcnt;
+{
+ int n;
+ n = writev(fd, iov, iovcnt);
+ if (n > 0)
+ raw_stream_in += n;
+ return n;
+}
+
+static int
+ServerRead (fd, buf, len)
+ int fd;
+ char *buf;
+ int len;
+{
+ int n;
+ n = read(fd, buf, len);
+ if (n > 0)
+ stream_in_plain += n;
+ return n;
+}
+
+static int
+ServerWritev(fd, iov, iovcnt)
+ int fd;
+ struct iovec *iov;
+ int iovcnt;
+{
+ int n;
+ n = writev(fd, iov, iovcnt);
+ if (n > 0)
+ stream_out_plain += n;
+ return n;
+}
+
+ClientPtr
+AllocNewConnection (fd, connect_fd, to_server, trans_conn)
+ int fd;
+ int connect_fd;
+ Bool to_server;
+ XtransConnInfo trans_conn;
+{
+ OsCommPtr oc;
+ ClientPtr client;
+
+ if (fd >= lastfdesc)
+ return NullClient;
+ oc = (OsCommPtr)xalloc(sizeof(OsCommRec));
+ if (!oc)
+ return NullClient;
+ oc->fd = fd;
+ oc->trans_conn = trans_conn;
+ oc->input = (ConnectionInputPtr)NULL;
+ oc->output = (ConnectionOutputPtr)NULL;
+ if (to_server) {
+ oc->Read = ServerRead;
+ oc->Writev = ServerWritev;
+ oc->Close = CloseServer;
+ } else {
+ oc->Read = ClientRead;
+ oc->Writev = ClientWritev;
+ oc->Close = CloseDownFileDescriptor;
+ }
+ oc->flushClient = StandardFlushClient;
+ oc->ofirst = (ConnectionOutputPtr) NULL;
+ if (!(client = NextAvailableClient((pointer)oc, connect_fd)))
+ {
+ xfree (oc);
+ return NullClient;
+ }
+ if (!ConnectionTranslation[fd])
+ {
+ ConnectionTranslation[fd] = client->index;
+ ConnectionOutputTranslation[fd] = client->index;
+ if (GrabInProgress)
+ {
+ FD_SET(fd, &SavedAllClients);
+ FD_SET(fd, &SavedAllSockets);
+ }
+ else
+ {
+ FD_SET(fd, &AllClients);
+ FD_SET(fd, &AllSockets);
+ }
+ }
+ client->public.readRequest = StandardReadRequestFromClient;
+ client->public.writeToClient = StandardWriteToClient;
+ client->public.requestLength = StandardRequestLength;
+ return client;
+}
+
+void
+SwitchConnectionFuncs (client, Read, Writev)
+ ClientPtr client;
+ int (*Read)();
+ int (*Writev)();
+{
+ OsCommPtr oc = (OsCommPtr) client->osPrivate;
+
+ oc->Read = Read;
+ oc->Writev = Writev;
+}
+
+void
+StartOutputCompression(client, CompressOn, CompressOff)
+ ClientPtr client;
+ void (*CompressOn)();
+ void (*CompressOff)();
+{
+ OsCommPtr oc = (OsCommPtr) client->osPrivate;
+
+ oc->compressOn = CompressOn;
+ oc->compressOff = CompressOff;
+ oc->flushClient = LbxFlushClient;
+}
+
+/*****************
+ * EstablishNewConnections
+ * If anyone is waiting on listened sockets, accept them.
+ * Returns a mask with indices of new clients. Updates AllClients
+ * and AllSockets.
+ *****************/
+
+/*ARGSUSED*/
+Bool
+EstablishNewConnections(clientUnused, closure)
+ ClientPtr clientUnused;
+ pointer closure;
+{
+ fd_mask readyconnections; /* mask of listeners that are ready */
+ int curconn; /* fd of listener that's ready */
+ register int newconn; /* fd of new client */
+ register ClientPtr client;
+ fd_set tmask;
+
+ XFD_ANDSET (&tmask, (fd_set*)closure, &WellKnownConnections);
+ readyconnections = tmask.fds_bits[0];
+ if (!readyconnections)
+ return TRUE;
+
+ while (readyconnections)
+ {
+ XtransConnInfo trans_conn, new_trans_conn;
+ int status;
+
+ curconn = ffs (readyconnections) - 1;
+ readyconnections &= ~(1 << curconn);
+
+ if ((trans_conn = lookup_trans_conn (curconn)) == NULL)
+ continue;
+
+ if ((new_trans_conn = _LBXPROXYTransAccept (trans_conn, &status)) == NULL)
+ continue;
+
+ newconn = _LBXPROXYTransGetConnectionNumber (new_trans_conn);
+
+ _LBXPROXYTransSetOption(new_trans_conn, TRANS_NONBLOCKING, 1);
+
+ client = AllocNewConnection (newconn, curconn, FALSE, new_trans_conn);
+ if (!client)
+ {
+ ErrorConnMax(new_trans_conn);
+ _LBXPROXYTransClose(new_trans_conn);
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+#define NOROOM "Maximum number of clients reached"
+
+/************
+ * ErrorConnMax
+ * Fail a connection due to lack of client or file descriptor space
+ ************/
+
+static void
+ErrorConnMax(trans_conn)
+XtransConnInfo trans_conn;
+{
+ register int fd = _LBXPROXYTransGetConnectionNumber (trans_conn);
+ xConnSetupPrefix csp;
+ char pad[3];
+ struct iovec iov[3];
+ char byteOrder = 0;
+ int whichbyte = 1;
+ struct timeval waittime;
+ fd_set mask;
+
+ /* if these seems like a lot of trouble to go to, it probably is */
+ waittime.tv_sec = BOTIMEOUT / MILLI_PER_SECOND;
+ waittime.tv_usec = (BOTIMEOUT % MILLI_PER_SECOND) *
+ (1000000 / MILLI_PER_SECOND);
+ FD_ZERO(&mask);
+ FD_SET(fd, &mask);
+ (void)Select(fd + 1, &mask, NULL, NULL, &waittime);
+ /* try to read the byte-order of the connection */
+ (void)_LBXPROXYTransRead(trans_conn, &byteOrder, 1);
+ if ((byteOrder == 'l') || (byteOrder == 'B'))
+ {
+ csp.success = xFalse;
+ csp.lengthReason = sizeof(NOROOM) - 1;
+ csp.length = (sizeof(NOROOM) + 2) >> 2;
+ csp.majorVersion = X_PROTOCOL;
+ csp.minorVersion = X_PROTOCOL_REVISION;
+ if (((*(char *) &whichbyte) && (byteOrder == 'B')) ||
+ (!(*(char *) &whichbyte) && (byteOrder == 'l')))
+ {
+ swaps(&csp.majorVersion, whichbyte);
+ swaps(&csp.minorVersion, whichbyte);
+ swaps(&csp.length, whichbyte);
+ }
+ iov[0].iov_len = sz_xConnSetupPrefix;
+ iov[0].iov_base = (char *) &csp;
+ iov[1].iov_len = csp.lengthReason;
+ iov[1].iov_base = NOROOM;
+ iov[2].iov_len = (4 - (csp.lengthReason & 3)) & 3;
+ iov[2].iov_base = pad;
+ (void)_LBXPROXYTransWritev(trans_conn, iov, 3);
+ }
+}
+
+
+/************
+ * CloseDownFileDescriptor:
+ * Remove this file descriptor and it's I/O buffers, etc.
+ ************/
+
+void
+CloseDownFileDescriptor(client)
+ ClientPtr client;
+{
+ register OsCommPtr oc = (OsCommPtr) client->osPrivate;
+ int connection = oc->fd;
+
+ if (oc->trans_conn) {
+ _LBXPROXYTransDisconnect(oc->trans_conn);
+ _LBXPROXYTransClose(oc->trans_conn);
+ }
+
+ ConnectionTranslation[connection] = 0;
+ ConnectionOutputTranslation[connection] = 0;
+
+ FD_CLR(connection, &AllSockets);
+ FD_CLR(connection, &AllClients);
+ FD_CLR(connection, &ClientsWithInput);
+ FD_CLR(connection, &GrabImperviousClients);
+ if (GrabInProgress)
+ {
+ FD_CLR(connection, &SavedAllSockets);
+ FD_CLR(connection, &SavedAllClients);
+ FD_CLR(connection, &SavedClientsWithInput);
+ }
+ FD_CLR(connection, &ClientsWriteBlocked);
+ if (!XFD_ANYSET(&ClientsWriteBlocked))
+ AnyClientsWriteBlocked = FALSE;
+ FD_CLR(connection, &OutputPending);
+}
+
+/*****************
+ * CheckConections
+ * Some connection has died, go find which one and shut it down
+ * The file descriptor has been closed, but is still in AllClients.
+ * If would truly be wonderful if select() would put the bogus
+ * file descriptors in the exception mask, but nooooo. So we have
+ * to check each and every socket individually.
+ *****************/
+
+void
+CheckConnections()
+{
+ fd_mask mask;
+ fd_set tmask;
+ register int curclient, curoff;
+ int i;
+ struct timeval notime;
+ int r;
+
+ notime.tv_sec = 0;
+ notime.tv_usec = 0;
+
+ for (i=0; i<howmany(XFD_SETSIZE, NFDBITS); i++)
+ {
+ mask = AllClients.fds_bits[i];
+ while (mask)
+ {
+ curoff = ffs (mask) - 1;
+ curclient = curoff + (i << 5);
+ FD_ZERO(&tmask);
+ FD_SET(curclient, &tmask);
+ r = Select (curclient + 1, &tmask, NULL, NULL, &notime);
+ if (r < 0)
+ CloseDownClient(clients[ConnectionTranslation[curclient]]);
+ mask &= ~(1 << curoff);
+ }
+ }
+}
+
+
+/*****************
+ * CloseDownConnection
+ * Delete client from AllClients and free resources
+ *****************/
+
+void
+CloseDownConnection(client)
+ ClientPtr client;
+{
+ OsCommPtr oc = (OsCommPtr)client->osPrivate;
+
+ if (oc->output && oc->output->count)
+ FlushClient(client, oc, (char *)NULL, 0);
+ ConnectionTranslation[oc->fd] = 0;
+ (*oc->Close) (client);
+ FreeOsBuffers(oc);
+ xfree(oc);
+ client->osPrivate = (pointer)NULL;
+ if (auditTrailLevel > 1)
+ AuditF("client %d disconnected\n", client->index);
+}
+
+/*****************
+ * OnlyListenToOneClient:
+ * Only accept requests from one client. Continue to handle new
+ * connections, but don't take any protocol requests from the new
+ * ones. Note that if GrabInProgress is set, EstablishNewConnections
+ * needs to put new clients into SavedAllSockets and SavedAllClients.
+ * Note also that there is no timeout for this in the protocol.
+ * This routine is "undone" by ListenToAllClients()
+ *****************/
+
+void
+OnlyListenToOneClient(client)
+ ClientPtr client;
+{
+ OsCommPtr oc = (OsCommPtr)client->osPrivate;
+ int connection = oc->fd;
+
+ if (! GrabInProgress)
+ {
+ XFD_COPYSET(&ClientsWithInput, &SavedClientsWithInput);
+ XFD_ANDSET(&ClientsWithInput,
+ &ClientsWithInput, &GrabImperviousClients);
+ if (FD_ISSET(connection, &SavedClientsWithInput))
+ {
+ FD_CLR(connection, &SavedClientsWithInput);
+ FD_SET(connection, &ClientsWithInput);
+ }
+ XFD_UNSET(&SavedClientsWithInput, &GrabImperviousClients);
+ FD_CLR(connection, &AllSockets);
+ XFD_COPYSET(&AllSockets, &SavedAllSockets);
+ FD_CLR(connection, &AllClients);
+ XFD_COPYSET(&AllClients, &SavedAllClients);
+ XFD_UNSET(&AllSockets, &AllClients);
+ XFD_ANDSET(&AllClients, &AllClients, &GrabImperviousClients);
+ FD_SET(connection, &AllClients);
+ XFD_ORSET(&AllSockets, &AllSockets, &AllClients);
+ GrabInProgress = client->index;
+ }
+}
+
+/****************
+ * ListenToAllClients:
+ * Undoes OnlyListentToOneClient()
+ ****************/
+
+void
+ListenToAllClients()
+{
+ if (GrabInProgress)
+ {
+ XFD_ORSET(&AllSockets, &AllSockets, &SavedAllSockets);
+ XFD_ORSET(&AllClients, &AllClients, &SavedAllClients);
+ XFD_ORSET(&ClientsWithInput, &ClientsWithInput, &SavedClientsWithInput);
+ GrabInProgress = 0;
+ }
+}
+
+/****************
+ * IgnoreClient
+ * Removes one client from input masks.
+ * Must have cooresponding call to AttendClient.
+ ****************/
+
+void
+IgnoreClient (client)
+ ClientPtr client;
+{
+ OsCommPtr oc = (OsCommPtr)client->osPrivate;
+ int connection = oc->fd;
+
+ if (!GrabInProgress || FD_ISSET (connection, &AllClients))
+ {
+ if (FD_ISSET (connection, &ClientsWithInput))
+ FD_SET(connection, &IgnoredClientsWithInput);
+ else
+ FD_CLR(connection, &IgnoredClientsWithInput);
+ FD_CLR(connection, &ClientsWithInput);
+ FD_CLR(connection, &AllSockets);
+ FD_CLR(connection, &AllClients);
+ FD_CLR(connection, &LastSelectMask);
+ }
+ else
+ {
+ if (FD_ISSET (connection, &SavedClientsWithInput))
+ FD_SET(connection, &IgnoredClientsWithInput);
+ else
+ FD_CLR(connection, &IgnoredClientsWithInput);
+ FD_CLR(connection, &SavedClientsWithInput);
+ FD_CLR(connection, &SavedAllSockets);
+ FD_CLR(connection, &SavedAllClients);
+ }
+ isItTimeToYield = TRUE;
+}
+
+/****************
+ * AttendClient
+ * Adds one client back into the input masks.
+ ****************/
+
+void
+AttendClient (client)
+ ClientPtr client;
+{
+ OsCommPtr oc = (OsCommPtr)client->osPrivate;
+ int connection = oc->fd;
+
+ if (!GrabInProgress || GrabInProgress == client->index ||
+ FD_ISSET(connection, &GrabImperviousClients))
+ {
+ FD_SET(connection, &AllClients);
+ FD_SET(connection, &AllSockets);
+ FD_SET(connection, &LastSelectMask);
+ if (FD_ISSET (connection, &IgnoredClientsWithInput))
+ FD_SET(connection, &ClientsWithInput);
+ }
+ else
+ {
+ FD_SET(connection, &SavedAllClients);
+ FD_SET(connection, &SavedAllSockets);
+ if (FD_ISSET(connection, &IgnoredClientsWithInput))
+ FD_SET(connection, &SavedClientsWithInput);
+ }
+}
+
+/* make client impervious to grabs; assume only executing client calls this */
+
+void
+MakeClientGrabImpervious(client)
+ ClientPtr client;
+{
+ OsCommPtr oc = (OsCommPtr)client->osPrivate;
+ int connection = oc->fd;
+
+ FD_SET(connection, &GrabImperviousClients);
+}
+
+/* make client pervious to grabs; assume only executing client calls this */
+
+void
+MakeClientGrabPervious(client)
+ ClientPtr client;
+{
+ OsCommPtr oc = (OsCommPtr)client->osPrivate;
+ int connection = oc->fd;
+
+ FD_CLR(connection, &GrabImperviousClients);
+ if (GrabInProgress && (GrabInProgress != client->index))
+ {
+ if (FD_ISSET(connection, &ClientsWithInput))
+ {
+ FD_SET(connection, &SavedClientsWithInput);
+ FD_CLR(connection, &ClientsWithInput);
+ }
+ FD_CLR(connection, &AllSockets);
+ FD_CLR(connection, &AllClients);
+ isItTimeToYield = TRUE;
+ }
+}
diff --git a/os/io.c b/os/io.c
new file mode 100644
index 0000000..e87b32f
--- /dev/null
+++ b/os/io.c
@@ -0,0 +1,1240 @@
+/* $Xorg: io.c,v 1.6 2001/02/09 02:05:33 xorgcvs Exp $ */
+/***********************************************************
+
+Copyright 1987, 1989, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+
+Copyright 1987, 1989 by Digital Equipment Corporation, Maynard, Massachusetts.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+******************************************************************/
+/*****************************************************************
+ * i/o functions
+ *
+ * WriteToClient, ReadRequestFromClient
+ * InsertFakeRequest, ResetCurrentRequest
+ *
+ *****************************************************************/
+
+#include <stdio.h>
+#include <X11/Xtrans.h>
+#include "Xos.h"
+#ifdef X_NOT_STDC_ENV
+extern int errno;
+#endif
+#include "misc.h"
+#include <errno.h>
+#include <sys/param.h>
+#include <sys/uio.h>
+#include "os.h"
+#include <X11/Xpoll.h>
+#include "osdep.h"
+#include "lbx.h"
+
+#ifdef BIGREQS
+#include "bigreqstr.h"
+#endif
+
+/* check for both EAGAIN and EWOULDBLOCK, because some supposedly POSIX
+ * systems are broken and return EWOULDBLOCK when they should return EAGAIN
+ */
+#if defined(EAGAIN) && defined(EWOULDBLOCK)
+#define ETEST(err) (err == EAGAIN || err == EWOULDBLOCK)
+#else
+#ifdef EAGAIN
+#define ETEST(err) (err == EAGAIN)
+#else
+#define ETEST(err) (err == EWOULDBLOCK)
+#endif
+#endif
+
+extern void MarkClientException();
+extern int ConnectionTranslation[];
+extern int ConnectionOutputTranslation[];
+
+static int timesThisConnection = 0;
+static ConnectionInputPtr FreeInputs = (ConnectionInputPtr)NULL;
+static ConnectionOutputPtr FreeOutputs = (ConnectionOutputPtr)NULL;
+static OsCommPtr AvailableInput = (OsCommPtr)NULL;
+
+static ConnectionInputPtr AllocateInputBuffer(
+#if NeedFunctionPrototypes
+ void
+#endif
+);
+static ConnectionOutputPtr AllocateOutputBuffer(
+#if NeedFunctionPrototypes
+ void
+#endif
+);
+static ConnectionOutputPtr AllocateUncompBuffer(
+#if NeedFunctionPrototypes
+ int count
+#endif
+);
+
+#define get_req_len(req,cli) (((cli)->swapped ? \
+ lswaps((req)->length) : (req)->length) << 2)
+
+
+unsigned long
+StandardRequestLength(req,client,got,partp)
+ xReq *req;
+ ClientPtr client;
+ int got;
+ Bool *partp;
+{
+ int len;
+
+ if (!req)
+ req = (xReq *) client->requestBuffer;
+ if (got < sizeof (xReq))
+ {
+ *partp = TRUE;
+ return sizeof (xReq);
+ }
+ len = get_req_len(req,client);
+ if (len > MAXBUFSIZE)
+ {
+ *partp = TRUE;
+ return -1;
+ }
+ *partp = FALSE;
+ return len;
+}
+
+#ifdef BIGREQS
+#define get_big_req_len(req,cli) (((cli)->swapped ? \
+ lswapl(((xBigReq *)(req))->length) : \
+ ((xBigReq *)(req))->length) << 2)
+
+#endif
+
+#define MAX_TIMES_PER 10
+
+
+/*
+ * A lot of the code in this file manipulates a ConnectionInputPtr:
+ *
+ * -----------------------------------------------
+ * |------- bufcnt ------->| | |
+ * | |- gotnow ->| | |
+ * | |-------- needed ------>| |
+ * |-----------+--------- size --------+---------->|
+ * -----------------------------------------------
+ * ^ ^
+ * | |
+ * buffer bufptr
+ *
+ * buffer is a pointer to the start of the buffer.
+ * bufptr points to the start of the current request.
+ * bufcnt counts how many bytes are in the buffer.
+ * size is the size of the buffer in bytes.
+ *
+ * In several of the functions, gotnow and needed are local variables
+ * that do the following:
+ *
+ * gotnow is the number of bytes of the request that we're
+ * trying to read that are currently in the buffer.
+ * Typically, gotnow = (buffer + bufcnt) - bufptr
+ *
+ * needed = the length of the request that we're trying to
+ * read in bytes.
+ */
+
+
+/*****************************************************************
+ * ReadRequestFromClient
+ * Returns one request in client->requestBuffer. The request
+ * length will be in client->req_len. Return status is:
+ *
+ * > 0 if successful, specifies length in bytes of the request
+ * = 0 if entire request is not yet available
+ * < 0 if client should be terminated
+ *
+ * The request returned must be contiguous so that it can be
+ * cast in the dispatcher to the correct request type. Because requests
+ * are variable length, ReadRequestFromClient() must look at the first 4
+ * or 8 bytes of a request to determine the length (the request length is
+ * in the 3rd and 4th bytes of the request unless it is a Big Request
+ * (see the Big Request Extension), in which case the 3rd and 4th bytes
+ * are zero and the following 4 bytes are the request length.
+ *
+ * Note: in order to make the server scheduler (WaitForSomething())
+ * "fair", the ClientsWithInput mask is used. This mask tells which
+ * clients have FULL requests left in their buffers. Clients with
+ * partial requests require a read. Basically, client buffers
+ * are drained before select() is called again. But, we can't keep
+ * reading from a client that is sending buckets of data (or has
+ * a partial request) because others clients need to be scheduled.
+ *****************************************************************/
+
+#define YieldControl() \
+ { isItTimeToYield = TRUE; \
+ timesThisConnection = 0; }
+#define YieldControlNoInput() \
+ { YieldControl(); \
+ FD_CLR(fd, &ClientsWithInput); }
+#define YieldControlDeath() \
+ { timesThisConnection = 0; }
+
+int
+StandardReadRequestFromClient(client)
+ ClientPtr client;
+{
+ OsCommPtr oc = (OsCommPtr)client->osPrivate;
+ register ConnectionInputPtr oci = oc->input;
+ int fd = oc->fd;
+ register int gotnow, needed;
+ int result;
+ register xReq *request;
+ int nextneeds;
+ Bool part;
+#ifdef BIGREQS
+ Bool move_header;
+#endif
+
+ /* If an input buffer was empty, either free it if it is too big
+ * or link it into our list of free input buffers. This means that
+ * different clients can share the same input buffer (at different
+ * times). This was done to save memory.
+ */
+
+ if (AvailableInput)
+ {
+ if (AvailableInput != oc)
+ {
+ register ConnectionInputPtr aci = AvailableInput->input;
+ if (aci->size > BUFWATERMARK)
+ {
+ xfree(aci->buffer);
+ xfree(aci);
+ }
+ else
+ {
+ aci->next = FreeInputs;
+ FreeInputs = aci;
+ }
+ AvailableInput->input = (ConnectionInputPtr)NULL;
+ }
+ AvailableInput = (OsCommPtr)NULL;
+ }
+
+ /* make sure we have an input buffer */
+
+ if (!oci)
+ {
+ if ((oci = FreeInputs))
+ {
+ FreeInputs = oci->next;
+ }
+ else if (!(oci = AllocateInputBuffer()))
+ {
+ YieldControlDeath();
+ return -1;
+ }
+ oc->input = oci;
+ }
+
+ /* advance to start of next request */
+
+ oci->bufptr += oci->lenLastReq;
+ oci->lenLastReq = 0;
+
+#ifdef BIGREQS
+ move_header = FALSE;
+#endif
+ gotnow = oci->bufcnt + oci->buffer - oci->bufptr;
+ client->requestBuffer = (pointer)oci->bufptr;
+ needed = RequestLength (NULL, client, gotnow, &part);
+
+#ifdef BIGREQS
+ if (!needed && client->big_requests)
+ {
+ /* It's a Big Request. */
+ move_header = TRUE;
+ if (gotnow < sizeof(xBigReq))
+ {
+ /* Still need more data to tell just how big. */
+ needed = sizeof(xBigReq);
+ part = TRUE;
+ }
+ else
+ needed = get_big_req_len(client->requestBuffer, client);
+ }
+#endif
+
+ client->req_len = needed >> 2;
+ if (gotnow < needed || part)
+ {
+ /* Need to read more data, either so that we can get a
+ * complete xReq (if part is TRUE), a complete
+ * xBigReq (if move_header is TRUE), or the rest of the
+ * request (if part and move_header are both FALSE).
+ */
+
+ if (needed == -1)
+ {
+ YieldControlDeath();
+ return -1;
+ }
+ if ((gotnow == 0) ||
+ ((oci->bufptr - oci->buffer + needed) > oci->size))
+ {
+ /* no data, or the request is too big to fit in the buffer */
+
+ if ((gotnow > 0) && (oci->bufptr != oci->buffer))
+ /* save the data we've already read */
+ memmove(oci->buffer, oci->bufptr, gotnow);
+ if (needed > oci->size)
+ {
+ /* make buffer bigger to accomodate request */
+ char *ibuf;
+
+ ibuf = (char *)xrealloc(oci->buffer, needed);
+ if (!ibuf)
+ {
+ YieldControlDeath();
+ return -1;
+ }
+ oci->size = needed;
+ oci->buffer = ibuf;
+ }
+ oci->bufptr = oci->buffer;
+ oci->bufcnt = gotnow;
+ }
+
+ if (oc->trans_conn)
+ result = _LBXPROXYTransRead(oc->trans_conn,
+ oci->buffer + oci->bufcnt,
+ oci->size - oci->bufcnt);
+ else
+ /*
+ * trans_conn can be NULL if the read is from an X server
+ */
+ result = (*oc->Read)(fd, oci->buffer + oci->bufcnt,
+ oci->size - oci->bufcnt);
+
+ if (result <= 0)
+ {
+ if ((result < 0) && ETEST(errno))
+ {
+ YieldControlNoInput();
+ return 0;
+ }
+ YieldControlDeath();
+ return -1;
+ }
+ oci->bufcnt += result;
+ gotnow += result;
+ /* free up some space after huge requests */
+ if ((oci->size > BUFWATERMARK) &&
+ (oci->bufcnt < BUFSIZE) && (needed < BUFSIZE))
+ {
+ char *ibuf;
+
+ ibuf = (char *)xrealloc(oci->buffer, BUFSIZE);
+ if (ibuf)
+ {
+ oci->size = BUFSIZE;
+ oci->buffer = ibuf;
+ oci->bufptr = ibuf + oci->bufcnt - gotnow;
+ }
+ }
+ client->requestBuffer = (pointer) oci->bufptr;
+ if (part && gotnow >= needed)
+ {
+ /* We wanted an xReq, now we've gotten it. */
+ needed = RequestLength (NULL, client, gotnow, &part);
+#ifdef BIGREQS
+ if (!needed && client->big_requests)
+ {
+ move_header = TRUE;
+ if (gotnow < sizeof(xBigReq))
+ needed = sizeof(xBigReq);
+ else
+ needed = get_big_req_len(client->requestBuffer, client);
+ }
+#endif
+ client->req_len = needed >> 2;
+ }
+ if (gotnow < needed || part)
+ {
+ if (needed == -1)
+ {
+ YieldControlDeath();
+ return -1;
+ }
+ /* Still don't have enough; punt. */
+ YieldControlNoInput();
+ return 0;
+ }
+ }
+
+ if (needed == 0)
+ {
+#ifdef BIGREQS
+ if (client->big_requests)
+ needed = sizeof(xBigReq);
+ else
+#endif
+ needed = sizeof(xReq);
+ }
+
+ oci->lenLastReq = needed;
+
+ /*
+ * Check to see if client has at least one whole request in the
+ * buffer beyond the request we're returning to the caller.
+ * If there is only a partial request, treat like buffer
+ * is empty so that select() will be called again and other clients
+ * can get into the queue.
+ */
+
+ if (gotnow > needed)
+ {
+ request = (xReq *)(oci->bufptr + needed);
+ nextneeds = RequestLength (request, client, gotnow - needed, &part);
+ if (gotnow >= needed + nextneeds && !part
+#ifdef BIGREQS
+ && (nextneeds ||
+ (client->big_requests &&
+ (nextneeds >= sizeof(xBigReq) &&
+ nextneeds >= get_big_req_len(request, client))))
+#endif
+ )
+ FD_SET(fd, &ClientsWithInput);
+ else
+ YieldControlNoInput();
+ }
+ else
+ {
+ AvailableInput = oc;
+ YieldControlNoInput();
+ }
+ if (++timesThisConnection >= MAX_TIMES_PER)
+ YieldControl();
+#ifdef BIGREQS
+ if (move_header)
+ {
+ request = (xReq *)oci->bufptr;
+ oci->bufptr += (sizeof(xBigReq) - sizeof(xReq));
+ *(xReq *)oci->bufptr = *request;
+ oci->lenLastReq -= (sizeof(xBigReq) - sizeof(xReq));
+ client->req_len -= (sizeof(xBigReq) - sizeof(xReq)) >> 2;
+ client->requestBuffer = oci->bufptr;
+ }
+#endif
+ return needed;
+}
+
+int
+PendingClientOutput (client)
+ ClientPtr client;
+{
+ OsCommPtr oc = (OsCommPtr) client->osPrivate;
+ ConnectionOutputPtr oco = oc->output;
+
+ return (oco && oco->count != 0) || oc->ofirst;
+}
+
+int
+CheckPendingClientInput (client)
+ ClientPtr client;
+{
+ OsCommPtr oc = (OsCommPtr)client->osPrivate;
+ register ConnectionInputPtr oci = oc->input;
+ xReq *request;
+ int gotnow;
+ int needed;
+ Bool part;
+
+ if (!oci)
+ return 0;
+ needed = oci->lenLastReq;
+ gotnow = oci->bufcnt + oci->buffer - oci->bufptr;
+ request = (xReq *) (oci->bufptr + needed);
+ if (gotnow >= needed + RequestLength(request, client, gotnow - needed, &part) && !part)
+ {
+ FD_SET(oc->fd, &ClientsWithInput);
+ return 1;
+ }
+ return 0;
+}
+
+void
+MarkConnectionWriteBlocked (client)
+ ClientPtr client;
+{
+ OsCommPtr oc = (OsCommPtr)client->osPrivate;
+
+ FD_SET(oc->fd, &ClientsWriteBlocked);
+ AnyClientsWriteBlocked = TRUE;
+}
+
+int
+BytesInClientBuffer (client)
+ ClientPtr client;
+{
+ OsCommPtr oc = (OsCommPtr)client->osPrivate;
+ register ConnectionInputPtr oci = oc->input;
+
+ if (!oci)
+ return 0;
+ return oci->bufcnt + oci->buffer - (oci->bufptr + oci->lenLastReq);
+}
+
+void
+SkipInClientBuffer (client, nbytes, lenLastReq)
+ ClientPtr client;
+ int nbytes;
+ int lenLastReq;
+{
+ OsCommPtr oc = (OsCommPtr)client->osPrivate;
+ register ConnectionInputPtr oci = oc->input;
+
+ if (!oci)
+ return;
+ oci->bufptr += nbytes;
+ oci->lenLastReq = lenLastReq;
+}
+
+/*****************************************************************
+ * InsertFakeRequest
+ * Splice a consed up (possibly partial) request in as the next request.
+ *
+ **********************/
+
+Bool
+InsertFakeRequest(client, data, count)
+ ClientPtr client;
+ char *data;
+ int count;
+{
+ OsCommPtr oc = (OsCommPtr)client->osPrivate;
+ register ConnectionInputPtr oci = oc->input;
+ int fd = oc->fd;
+ register xReq *request;
+ register int gotnow, moveup;
+ Bool part;
+
+ if (AvailableInput)
+ {
+ if (AvailableInput != oc)
+ {
+ register ConnectionInputPtr aci = AvailableInput->input;
+ if (aci->size > BUFWATERMARK)
+ {
+ xfree(aci->buffer);
+ xfree(aci);
+ }
+ else
+ {
+ aci->next = FreeInputs;
+ FreeInputs = aci;
+ }
+ AvailableInput->input = (ConnectionInputPtr)NULL;
+ }
+ AvailableInput = (OsCommPtr)NULL;
+ }
+ if (!oci)
+ {
+ if ((oci = FreeInputs))
+ FreeInputs = oci->next;
+ else if (!(oci = AllocateInputBuffer()))
+ return FALSE;
+ oc->input = oci;
+ }
+ oci->bufptr += oci->lenLastReq;
+ oci->lenLastReq = 0;
+ gotnow = oci->bufcnt + oci->buffer - oci->bufptr;
+ if ((gotnow + count) > oci->size)
+ {
+ char *ibuf;
+
+ ibuf = (char *)xrealloc(oci->buffer, gotnow + count);
+ if (!ibuf)
+ return(FALSE);
+ oci->size = gotnow + count;
+ oci->buffer = ibuf;
+ oci->bufptr = ibuf + oci->bufcnt - gotnow;
+ }
+ moveup = count - (oci->bufptr - oci->buffer);
+ if (moveup > 0)
+ {
+ if (gotnow > 0)
+ memmove(oci->bufptr + moveup, oci->bufptr, gotnow);
+ oci->bufptr += moveup;
+ oci->bufcnt += moveup;
+ }
+ memmove(oci->bufptr - count, data, count);
+ oci->bufptr -= count;
+ request = (xReq *)oci->bufptr;
+ gotnow += count;
+ if (gotnow >= RequestLength (request, client, gotnow, &part) && !part)
+ FD_SET(fd, &ClientsWithInput);
+ else
+ YieldControlNoInput();
+ return(TRUE);
+}
+
+/*****************************************************************
+ * ResetRequestFromClient
+ * Reset to reexecute the current request, and yield.
+ *
+ **********************/
+
+void
+ResetCurrentRequest(client)
+ ClientPtr client;
+{
+ OsCommPtr oc = (OsCommPtr)client->osPrivate;
+ register ConnectionInputPtr oci = oc->input;
+ int fd = oc->fd;
+ register xReq *request;
+ int gotnow;
+ Bool part;
+
+ if (AvailableInput == oc)
+ AvailableInput = (OsCommPtr)NULL;
+ oci->lenLastReq = 0;
+ gotnow = oci->bufcnt + oci->buffer - oci->bufptr;
+ request = (xReq *)oci->bufptr;
+ if (gotnow >= RequestLength (request, client, gotnow, &part) && !part)
+ {
+ FD_SET(fd, &ClientsWithInput);
+ YieldControl();
+ }
+ else
+ YieldControlNoInput();
+}
+
+ /* lookup table for adding padding bytes to data that is read from
+ or written to the X socket. */
+static int padlength[4] = {0, 3, 2, 1};
+
+ /********************
+ * FlushClient()
+ * If the client isn't keeping up with us, then we try to continue
+ * buffering the data and set the apropriate bit in ClientsWritable
+ * (which is used by WaitFor in the select). If the connection yields
+ * a permanent error, or we can't allocate any more space, we then
+ * close the connection.
+ *
+ **********************/
+
+int
+StandardFlushClient(who, oc, extraBuf, extraCount)
+ ClientPtr who;
+ OsCommPtr oc;
+ char *extraBuf;
+ int extraCount; /* do not modify... returned below */
+{
+ register ConnectionOutputPtr oco = oc->output;
+ int connection = oc->fd;
+ XtransConnInfo trans_conn = oc->trans_conn;
+ struct iovec iov[3];
+ static char padBuffer[3];
+ long written;
+ long padsize;
+ long notWritten;
+ long todo;
+
+ if (!oco)
+ return 0;
+ written = 0;
+ padsize = padlength[extraCount & 3];
+ notWritten = oco->count + extraCount + padsize;
+ todo = notWritten;
+ while (notWritten) {
+ long before = written; /* amount of whole thing written */
+ long remain = todo; /* amount to try this time, <= notWritten */
+ int i = 0;
+ long len;
+
+ /* You could be very general here and have "in" and "out" iovecs
+ * and write a loop without using a macro, but what the heck. This
+ * translates to:
+ *
+ * how much of this piece is new?
+ * if more new then we are trying this time, clamp
+ * if nothing new
+ * then bump down amount already written, for next piece
+ * else put new stuff in iovec, will need all of next piece
+ *
+ * Note that todo had better be at least 1 or else we'll end up
+ * writing 0 iovecs.
+ */
+#define InsertIOV(pointer, length) \
+ len = (length) - before; \
+ if (len > remain) \
+ len = remain; \
+ if (len <= 0) { \
+ before = (-len); \
+ } else { \
+ iov[i].iov_len = len; \
+ iov[i].iov_base = (pointer) + before; \
+ i++; \
+ remain -= len; \
+ before = 0; \
+ }
+
+ InsertIOV ((char *)oco->buf, oco->count)
+ InsertIOV (extraBuf, extraCount)
+ InsertIOV (padBuffer, padsize)
+
+ errno = 0;
+ if (trans_conn)
+ len = _LBXPROXYTransWritev(trans_conn, iov, i);
+ else
+ /*
+ * trans_conn can be NULL if the read is from an X server
+ */
+ len = (*oc->Writev) (connection, iov, i);
+ if (len >= 0)
+ {
+ written += len;
+ notWritten -= len;
+ todo = notWritten;
+ }
+ else if (ETEST(errno)
+#ifdef SUNSYSV /* check for another brain-damaged OS bug */
+ || (errno == 0)
+#endif
+#ifdef EMSGSIZE /* check for another brain-damaged OS bug */
+ || ((errno == EMSGSIZE) && (todo == 1))
+#endif
+ )
+ {
+ /* If we've arrived here, then the client is stuffed to the gills
+ and not ready to accept more. Make a note of it and buffer
+ the rest. */
+ FD_SET(connection, &ClientsWriteBlocked);
+ AnyClientsWriteBlocked = TRUE;
+
+ if (written < oco->count)
+ {
+ if (written > 0)
+ {
+ oco->count -= written;
+ memmove((char *)oco->buf,
+ (char *)oco->buf + written,
+ oco->count);
+ written = 0;
+ }
+ }
+ else
+ {
+ written -= oco->count;
+ oco->count = 0;
+ }
+
+ if (notWritten > oco->size)
+ {
+ unsigned char *obuf;
+
+ obuf = (unsigned char *)xrealloc(oco->buf,
+ notWritten + BUFSIZE);
+ if (!obuf)
+ {
+ _LBXPROXYTransDisconnect(oc->trans_conn);
+ _LBXPROXYTransClose(oc->trans_conn);
+ oc->trans_conn = NULL;
+ MarkClientException(who);
+ oco->count = 0;
+ return(-1);
+ }
+ oco->size = notWritten + BUFSIZE;
+ oco->buf = obuf;
+ }
+
+ /* If the amount written extended into the padBuffer, then the
+ difference "extraCount - written" may be less than 0 */
+ if ((len = extraCount - written) > 0)
+ memmove ((char *)oco->buf + oco->count,
+ extraBuf + written,
+ len);
+
+ oco->count = notWritten; /* this will include the pad */
+ /* return only the amount explicitly requested */
+ return extraCount;
+ }
+#ifdef EMSGSIZE /* check for another brain-damaged OS bug */
+ else if (errno == EMSGSIZE)
+ {
+ todo >>= 1;
+ }
+#endif
+ else
+ {
+ if (oc->trans_conn)
+ {
+ _LBXPROXYTransDisconnect(oc->trans_conn);
+ _LBXPROXYTransClose(oc->trans_conn);
+ oc->trans_conn = NULL;
+ }
+ MarkClientException(who);
+ oco->count = 0;
+ return(-1);
+ }
+ }
+
+ /* everything was flushed out */
+ oco->count = 0;
+ /* check to see if this client was write blocked */
+ if (AnyClientsWriteBlocked)
+ {
+ FD_CLR(oc->fd, &ClientsWriteBlocked);
+ if (! XFD_ANYSET(&ClientsWriteBlocked))
+ AnyClientsWriteBlocked = FALSE;
+ }
+ if (oco->size > BUFWATERMARK)
+ {
+ xfree(oco->buf);
+ xfree(oco);
+ }
+ else
+ {
+ oco->next = FreeOutputs;
+ FreeOutputs = oco;
+ }
+ oc->output = (ConnectionOutputPtr)NULL;
+ return extraCount; /* return only the amount explicitly requested */
+}
+
+static int
+ExpandOutputBuffer(oco, len)
+ ConnectionOutputPtr oco;
+ int len;
+{
+ unsigned char *obuf;
+
+ if (len < BUFSIZE)
+ len = BUFSIZE;
+ obuf = (unsigned char *)xrealloc(oco->buf, len);
+ if (!obuf)
+ {
+ oco->count = 0;
+ return(-1);
+ }
+ oco->size = len;
+ oco->buf = obuf;
+ return 0;
+}
+
+int
+LbxFlushClient(who, oc, extraBuf, extraCount)
+ ClientPtr who;
+ OsCommPtr oc;
+ char *extraBuf;
+ int extraCount; /* do not modify... returned below */
+{
+ ConnectionOutputPtr obuf;
+ register ConnectionOutputPtr oco;
+ int retval;
+
+ if ((oco = oc->ofirst)) {
+ obuf = oc->output;
+ do {
+ Bool nocomp = oco->nocompress;
+ oc->output = oco;
+ oco = (oco != oc->olast) ? oco->next : NULL;
+ if (nocomp)
+ (*oc->compressOff)(oc->fd);
+ retval = StandardFlushClient(who, oc, (char *)NULL, 0);
+ if (nocomp)
+ (*oc->compressOn)(oc->fd);
+ if (retval < 0) {
+ oc->output = obuf;
+ return retval;
+ }
+ if (oc->output) {
+ if (extraCount) {
+ int len = obuf->count + (extraCount + 3) & ~3;
+ if (ExpandOutputBuffer(obuf, len) < 0) {
+ if (oc->trans_conn) {
+ _LBXPROXYTransDisconnect(oc->trans_conn);
+ _LBXPROXYTransClose(oc->trans_conn);
+ oc->trans_conn = NULL;
+ }
+ MarkClientException(who);
+ return(-1);
+ }
+ memmove((char *)obuf->buf + obuf->count,
+ extraBuf, extraCount);
+ obuf->count = len;
+ oc->olast->next = obuf;
+ oc->olast = obuf;
+ obuf = NULL;
+ }
+ oc->output = obuf;
+ return extraCount;
+ }
+ } while ((oc->ofirst = oco));
+ oc->output = obuf;
+ }
+ retval = StandardFlushClient(who, oc, extraBuf, extraCount);
+ if (retval <= 0)
+ return retval;
+ if (oc->output && extraCount) {
+ oc->ofirst = oc->olast = oc->output;
+ oc->output = NULL;
+ }
+ return retval;
+}
+
+ /********************
+ * FlushAllOutput()
+ * Flush all clients with output. However, if some client still
+ * has input in the queue (more requests), then don't flush. This
+ * will prevent the output queue from being flushed every time around
+ * the round robin queue. Now, some say that it SHOULD be flushed
+ * every time around, but...
+ *
+ **********************/
+
+void
+FlushAllOutput()
+{
+ register int index, base, mask;
+ OsCommPtr oc;
+ register ClientPtr client;
+
+ if (! NewOutputPending)
+ return;
+
+ /*
+ * It may be that some client still has critical output pending,
+ * but he is not yet ready to receive it anyway, so we will
+ * simply wait for the select to tell us when he's ready to receive.
+ */
+ NewOutputPending = FALSE;
+
+ for (base = 0; base < howmany(XFD_SETSIZE, NFDBITS); base++)
+ {
+ mask = OutputPending.fds_bits[ base ];
+ OutputPending.fds_bits[ base ] = 0;
+ while (mask)
+ {
+ index = ffs(mask) - 1;
+ mask &= ~lowbit(mask);
+ if ((index = ConnectionOutputTranslation[(base << 5) + index]) == 0)
+ continue;
+ client = clients[index];
+ if (client->clientGone)
+ continue;
+ oc = (OsCommPtr)client->osPrivate;
+ if (FD_ISSET(oc->fd, &ClientsWithInput))
+ {
+ FD_SET(oc->fd, &OutputPending); /* set the bit again */
+ NewOutputPending = TRUE;
+ }
+ else
+ (void)FlushClient(client, oc, (char *)NULL, 0);
+ }
+ }
+
+}
+
+/*****************
+ * WriteToClient
+ * Copies buf into ClientPtr.buf if it fits (with padding), else
+ * flushes ClientPtr.buf and buf to client. As of this writing,
+ * every use of WriteToClient is cast to void, and the result
+ * is ignored. Potentially, this could be used by requests
+ * that are sending several chunks of data and want to break
+ * out of a loop on error. Thus, we will leave the type of
+ * this routine as int.
+ *****************/
+
+int
+StandardWriteToClient (who, count, buf)
+ ClientPtr who;
+ char *buf;
+ int count;
+{
+ OsCommPtr oc = (OsCommPtr)who->osPrivate;
+ register ConnectionOutputPtr oco = oc->output;
+ int padBytes;
+
+ if (!count)
+ return(0);
+
+ if (!oco)
+ {
+ if ((oco = FreeOutputs))
+ {
+ FreeOutputs = oco->next;
+ }
+ else if (!(oco = AllocateOutputBuffer()))
+ {
+ if (oc->trans_conn)
+ {
+ _LBXPROXYTransDisconnect(oc->trans_conn);
+ _LBXPROXYTransClose(oc->trans_conn);
+ oc->trans_conn = NULL;
+ }
+ MarkClientException(who);
+ return -1;
+ }
+ oc->output = oco;
+ }
+
+ padBytes = padlength[count & 3];
+
+ if (oco->count + count + padBytes > oco->size)
+ {
+ FD_CLR(oc->fd, &OutputPending);
+ NewOutputPending = FALSE;
+ return FlushClient(who, oc, buf, count);
+ }
+
+ NewOutputPending = TRUE;
+ FD_SET(oc->fd, &OutputPending);
+ memmove((char *)oco->buf + oco->count, buf, count);
+ oco->count += count;
+
+ if (padBytes)
+ {
+ bzero ((char *)oco->buf + oco->count, padBytes);
+ oco->count += padBytes;
+ }
+ return(count);
+}
+
+int
+UncompressWriteToClient (who, count, buf)
+ ClientPtr who;
+ char *buf;
+ int count;
+{
+ OsCommPtr oc = (OsCommPtr)who->osPrivate;
+ register ConnectionOutputPtr oco;
+ int paddedLen = count + padlength[count & 3];
+
+ if (!count)
+ return(0);
+
+ if ((oco = oc->output)) {
+ /*
+ * we're currently filling a buffer, and it must be compressible,
+ * so put it on the queue
+ */
+ if (oc->ofirst) {
+ oc->olast->next = oco;
+ oc->olast = oco;
+ }
+ else {
+ oc->ofirst = oc->olast = oco;
+ }
+ oco = oc->output = (ConnectionOutputPtr)NULL;
+ }
+ else if (oc->ofirst) {
+ oco = oc->olast;
+ if (!oco->nocompress || ((oco->count + paddedLen) > oco->size))
+ oco = (ConnectionOutputPtr)NULL;
+ }
+
+ if (!oco) {
+ /*
+ * First try to use the FreeOutputs buffer
+ */
+ oco = FreeOutputs;
+ if (oco) {
+ FreeOutputs = oco->next;
+
+ oco->next = 0;
+ oco->count = 0;
+ oco->nocompress = TRUE;
+
+ if (oco->size < paddedLen) {
+ oco->buf = (unsigned char *) xrealloc (oco->buf, paddedLen);
+ if (!oco->buf) {
+ if (oc->trans_conn) {
+ _LBXPROXYTransDisconnect(oc->trans_conn);
+ _LBXPROXYTransClose(oc->trans_conn);
+ oc->trans_conn = NULL;
+ }
+ MarkClientException(who);
+ return -1;
+ }
+ oco->size = paddedLen;
+ }
+ }
+ else if (!(oco = AllocateUncompBuffer(paddedLen))) {
+ if (oc->trans_conn) {
+ _LBXPROXYTransDisconnect(oc->trans_conn);
+ _LBXPROXYTransClose(oc->trans_conn);
+ oc->trans_conn = NULL;
+ }
+ MarkClientException(who);
+ return -1;
+ }
+ }
+ memmove((char *)oco->buf + oco->count, buf, count);
+ oco->count += paddedLen;
+
+ if (oc->ofirst) {
+ oc->olast->next = oco;
+ oc->olast = oco;
+ }
+ else {
+ oc->ofirst = oc->olast = oco;
+ }
+
+ NewOutputPending = TRUE;
+ FD_SET(oc->fd, &OutputPending);
+ return(count);
+}
+
+static ConnectionInputPtr
+AllocateInputBuffer()
+{
+ register ConnectionInputPtr oci;
+
+ oci = (ConnectionInputPtr)xalloc(sizeof(ConnectionInput));
+ if (!oci)
+ return (ConnectionInputPtr)NULL;
+ oci->buffer = (char *)xalloc(BUFSIZE);
+ if (!oci->buffer)
+ {
+ xfree(oci);
+ return (ConnectionInputPtr)NULL;
+ }
+ oci->size = BUFSIZE;
+ oci->bufptr = oci->buffer;
+ oci->bufcnt = 0;
+ oci->lenLastReq = 0;
+ return oci;
+}
+
+static ConnectionOutputPtr
+AllocateOutputBuffer()
+{
+ register ConnectionOutputPtr oco;
+
+ oco = (ConnectionOutputPtr)xalloc(sizeof(ConnectionOutput));
+ if (!oco)
+ return (ConnectionOutputPtr)NULL;
+ oco->buf = (unsigned char *) xalloc(BUFSIZE);
+ if (!oco->buf)
+ {
+ xfree(oco);
+ return (ConnectionOutputPtr)NULL;
+ }
+ oco->size = BUFSIZE;
+ oco->count = 0;
+ oco->nocompress = FALSE;
+ return oco;
+}
+
+static ConnectionOutputPtr
+AllocateUncompBuffer(count)
+ int count;
+{
+ register ConnectionOutputPtr oco;
+ int len = (count > BUFSIZE) ? count : BUFSIZE;
+
+ oco = (ConnectionOutputPtr)xalloc(sizeof(ConnectionOutput));
+ if (!oco)
+ return (ConnectionOutputPtr)NULL;
+ oco->buf = (unsigned char *) xalloc(len);
+ if (!oco->buf)
+ {
+ xfree(oco);
+ return (ConnectionOutputPtr)NULL;
+ }
+ oco->size = len;
+ oco->count = 0;
+ oco->nocompress = TRUE;
+ return oco;
+}
+
+void
+FreeOsBuffers(oc)
+ OsCommPtr oc;
+{
+ register ConnectionInputPtr oci;
+ register ConnectionOutputPtr oco;
+
+ if (AvailableInput == oc)
+ AvailableInput = (OsCommPtr)NULL;
+ if ((oci = oc->input))
+ {
+ if (FreeInputs)
+ {
+ xfree(oci->buffer);
+ xfree(oci);
+ }
+ else
+ {
+ FreeInputs = oci;
+ oci->next = (ConnectionInputPtr)NULL;
+ oci->bufptr = oci->buffer;
+ oci->bufcnt = 0;
+ oci->lenLastReq = 0;
+ }
+ }
+ if ((oco = oc->output))
+ {
+ if (FreeOutputs)
+ {
+ xfree(oco->buf);
+ xfree(oco);
+ }
+ else
+ {
+ FreeOutputs = oco;
+ oco->next = (ConnectionOutputPtr)NULL;
+ oco->count = 0;
+ }
+ }
+ if ((oco = oc->ofirst)) {
+ ConnectionOutputPtr nextoco;
+ do {
+ nextoco = oco->next;
+ xfree(oco->buf);
+ xfree(oco);
+ if (oco == oc->olast)
+ break;
+ oco = nextoco;
+ } while (1);
+ }
+}
diff --git a/os/osdep.h b/os/osdep.h
new file mode 100644
index 0000000..71b3712
--- /dev/null
+++ b/os/osdep.h
@@ -0,0 +1,151 @@
+/* $Xorg: osdep.h,v 1.4 2001/02/09 02:05:33 xorgcvs Exp $ */
+/***********************************************************
+
+Copyright 1987, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+
+Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+******************************************************************/
+
+#define BOTIMEOUT 200 /* in milliseconds */
+#define BUFSIZE 4096
+#define BUFWATERMARK 8192
+#define MAXBUFSIZE (1 << 22)
+
+#include <X11/Xmd.h>
+
+#ifndef sgi /* SGI defines OPEN_MAX in a useless way */
+#ifndef X_NOT_POSIX
+#ifdef _POSIX_SOURCE
+#include <limits.h>
+#else
+#define _POSIX_SOURCE
+#include <limits.h>
+#undef _POSIX_SOURCE
+#endif
+#endif
+#endif
+
+#ifndef OPEN_MAX
+#ifdef SVR4
+#define OPEN_MAX 128
+#else
+#include <sys/param.h>
+#ifndef OPEN_MAX
+#if defined(NOFILE) && !defined(NOFILES_MAX)
+#define OPEN_MAX NOFILE
+#else
+#define OPEN_MAX NOFILES_MAX
+#endif
+#endif
+#endif
+#endif
+
+#if OPEN_MAX <= 128
+#define MAXSOCKS (OPEN_MAX - 1)
+#else
+#define MAXSOCKS 128
+#endif
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+typedef struct _connectionInput {
+ struct _connectionInput *next;
+ char *buffer; /* contains current client input */
+ char *bufptr; /* pointer to current start of data */
+ int bufcnt; /* count of bytes in buffer */
+ int lenLastReq;
+ int size;
+} ConnectionInput, *ConnectionInputPtr;
+
+typedef struct _connectionOutput {
+ struct _connectionOutput *next;
+ int size;
+ unsigned char *buf;
+ int count;
+ Bool nocompress;
+} ConnectionOutput, *ConnectionOutputPtr;
+
+typedef struct _osComm {
+ int fd;
+ ConnectionInputPtr input;
+ ConnectionOutputPtr output;
+ ConnectionOutputPtr ofirst;
+ ConnectionOutputPtr olast;
+ void (*Close) ();
+ int (*Writev) ();
+ int (*Read) ();
+ int (*flushClient) ();
+ void (*compressOff) ();
+ void (*compressOn) ();
+ struct _XtransConnInfo *trans_conn; /* transport connection object */
+} OsCommRec, *OsCommPtr;
+
+#define FlushClient(who, oc, extraBuf, extraCount) \
+ (*((OsCommPtr)((who)->osPrivate))->flushClient)(who, oc, extraBuf, extraCount)
+
+extern void FreeOsBuffers(
+#if NeedFunctionPrototypes
+ OsCommPtr /*oc*/
+#endif
+);
+
+extern int StandardFlushClient(
+#if NeedFunctionPrototypes
+ ClientPtr /*who*/,
+ OsCommPtr /*oc*/,
+ char * /*extraBuf*/,
+ int /*extraCount*/
+#endif
+);
+
+extern int LbxFlushClient(
+#if NeedFunctionPrototypes
+ ClientPtr /*who*/,
+ OsCommPtr /*oc*/,
+ char * /*extraBuf*/,
+ int /*extraCount*/
+#endif
+);
+
diff --git a/os/osinit.c b/os/osinit.c
new file mode 100644
index 0000000..95a98b9
--- /dev/null
+++ b/os/osinit.c
@@ -0,0 +1,64 @@
+/* $Xorg: osinit.c,v 1.4 2001/02/09 02:05:33 xorgcvs Exp $ */
+/***********************************************************
+
+Copyright 1987, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+
+Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+******************************************************************/
+
+#include <stdio.h>
+#include "misc.h"
+#include "util.h"
+
+void
+OsInit()
+{
+ static Bool been_here = FALSE;
+
+ if (!been_here) {
+ fclose(stdin);
+ fclose(stdout);
+ been_here = TRUE;
+ }
+ OsInitAllocator();
+}