diff options
author | Kaleb Keithley <kaleb@freedesktop.org> | 2003-11-14 15:54:53 +0000 |
---|---|---|
committer | Kaleb Keithley <kaleb@freedesktop.org> | 2003-11-14 15:54:53 +0000 |
commit | 83fda9598025b9abcae2ea1a3b47e1d3e9f46d95 (patch) | |
tree | 7bc604da7e547bc2b068dce954f9f116df2d3d73 |
R6.6 is the Xorg base-lineXORG-MAIN
-rw-r--r-- | config/AtomControl | 91 | ||||
-rw-r--r-- | design | 266 | ||||
-rw-r--r-- | di/atomcache.c | 272 | ||||
-rw-r--r-- | di/cache.c | 353 | ||||
-rw-r--r-- | di/cmap.c | 1772 | ||||
-rw-r--r-- | di/cmaputil.c | 981 | ||||
-rw-r--r-- | di/dispatch.c | 638 | ||||
-rw-r--r-- | di/extensions.c | 319 | ||||
-rw-r--r-- | di/gfx.c | 1258 | ||||
-rw-r--r-- | di/globals.c | 56 | ||||
-rw-r--r-- | di/init.c | 270 | ||||
-rw-r--r-- | di/lbxfuncs.c | 1450 | ||||
-rw-r--r-- | di/lbxutil.c | 507 | ||||
-rw-r--r-- | di/main.c | 181 | ||||
-rw-r--r-- | di/options.c | 808 | ||||
-rw-r--r-- | di/pm.c | 491 | ||||
-rw-r--r-- | di/props.c | 410 | ||||
-rw-r--r-- | di/reqtype.c | 312 | ||||
-rw-r--r-- | di/resource.c | 480 | ||||
-rw-r--r-- | di/swaprep.c | 431 | ||||
-rw-r--r-- | di/swapreq.c | 327 | ||||
-rw-r--r-- | di/tables.c | 593 | ||||
-rw-r--r-- | di/tags.c | 192 | ||||
-rw-r--r-- | di/unsquish.c | 123 | ||||
-rw-r--r-- | di/utils.c | 1017 | ||||
-rw-r--r-- | di/wire.c | 1577 | ||||
-rw-r--r-- | di/zeropad.c | 605 | ||||
-rw-r--r-- | include/assert.h | 34 | ||||
-rw-r--r-- | include/atomcache.h | 104 | ||||
-rw-r--r-- | include/cache.h | 128 | ||||
-rw-r--r-- | include/colormap.h | 310 | ||||
-rw-r--r-- | include/init.h | 79 | ||||
-rw-r--r-- | include/lbx.h | 736 | ||||
-rw-r--r-- | include/lbxext.h | 167 | ||||
-rw-r--r-- | include/misc.h | 120 | ||||
-rw-r--r-- | include/os.h | 278 | ||||
-rw-r--r-- | include/pm.h | 60 | ||||
-rw-r--r-- | include/pmP.h | 117 | ||||
-rw-r--r-- | include/proxyopts.h | 144 | ||||
-rw-r--r-- | include/reqtype.h | 71 | ||||
-rw-r--r-- | include/resource.h | 137 | ||||
-rw-r--r-- | include/swap.h | 254 | ||||
-rw-r--r-- | include/tags.h | 134 | ||||
-rw-r--r-- | include/util.h | 227 | ||||
-rw-r--r-- | include/wire.h | 419 | ||||
-rw-r--r-- | lbxproxy.man | 233 | ||||
-rw-r--r-- | os/WaitFor.c | 198 | ||||
-rw-r--r-- | os/connection.c | 886 | ||||
-rw-r--r-- | os/io.c | 1240 | ||||
-rw-r--r-- | os/osdep.h | 151 | ||||
-rw-r--r-- | os/osinit.c | 64 |
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 @@ -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; +} @@ -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, ¬ime); + 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; + } +} @@ -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(); +} |