diff options
Diffstat (limited to 'lbx')
-rw-r--r-- | lbx/lbxcmap.c | 1148 | ||||
-rw-r--r-- | lbx/lbxdata.h | 44 | ||||
-rw-r--r-- | lbx/lbxdix.c | 887 | ||||
-rw-r--r-- | lbx/lbxexts.c | 270 | ||||
-rw-r--r-- | lbx/lbxgfx.c | 867 | ||||
-rw-r--r-- | lbx/lbxmain.c | 1819 | ||||
-rw-r--r-- | lbx/lbxopts.c | 817 | ||||
-rw-r--r-- | lbx/lbxprop.c | 552 | ||||
-rw-r--r-- | lbx/lbxserve.h | 173 | ||||
-rw-r--r-- | lbx/lbxsquish.c | 152 | ||||
-rw-r--r-- | lbx/lbxsrvopts.h | 78 | ||||
-rw-r--r-- | lbx/lbxswap.c | 858 | ||||
-rw-r--r-- | lbx/lbxtables.c | 33 | ||||
-rw-r--r-- | lbx/lbxtags.c | 238 | ||||
-rw-r--r-- | lbx/lbxtags.h | 119 | ||||
-rw-r--r-- | lbx/lbxzerorep.c | 416 |
16 files changed, 8471 insertions, 0 deletions
diff --git a/lbx/lbxcmap.c b/lbx/lbxcmap.c new file mode 100644 index 000000000..6af20b03b --- /dev/null +++ b/lbx/lbxcmap.c @@ -0,0 +1,1148 @@ +/* $Xorg: lbxcmap.c,v 1.4 2001/02/09 02:05:16 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 <sys/types.h> +#define NEED_REPLIES +#define NEED_EVENTS +#include "X.h" +#include "Xproto.h" +#include "Xos.h" +#include "misc.h" +#include "os.h" +#include "dixstruct.h" +#include "resource.h" +#include "scrnintstr.h" +#include "colormapst.h" +#define _XLBX_SERVER_ +#include "lbxstr.h" +#include "lbxserve.h" +#include "Xfuncproto.h" +#include <stdio.h> + +static int lbxScreenPrivIndex; /* lbx screen private index */ +static int lbxColormapPrivIndex; /* lbx colormap private index */ + +typedef struct { /* lbx screen private */ + CreateColormapProcPtr CreateColormap; + DestroyColormapProcPtr DestroyColormap; +} LbxScreenPriv; + +typedef struct _LbxStalled { + XID id; + struct _LbxStalled *next; +} LbxStalled; + +typedef struct _LbxColormapPriv { /* lbx colormap private */ + char grab_status; + char smart_grab; + LbxProxyPtr grabber; + int last_grabber; /* uid, not pid */ + LbxStalled *stalled_clients; + ColormapPtr next; /* proxy chain */ +} LbxColormapPriv; + +#define CMAP_NOT_GRABBED 0 +#define CMAP_GRABBED 1 +#define CMAP_WAITING_FOR_UNGRAB 2 + +static int LbxUnstallClient(); +void LbxReleaseCmap(); + +static RESTYPE StalledResType; + +/* + * Initialize the fields in the colormap private allocated for LBX. + */ + +static LbxColormapPriv * +LbxColormapPrivInit (pmap) + ColormapPtr pmap; +{ + LbxColormapPriv *cmapPriv; + + cmapPriv = (LbxColormapPriv *) xalloc (sizeof (LbxColormapPriv)); + if (!cmapPriv) + return cmapPriv; + + pmap->devPrivates[lbxColormapPrivIndex].ptr = (pointer) cmapPriv; + + cmapPriv->grab_status = CMAP_NOT_GRABBED; + cmapPriv->grabber = NULL; + cmapPriv->last_grabber = 0; + cmapPriv->smart_grab = FALSE; + cmapPriv->stalled_clients = NULL; + cmapPriv->next = NULL; + + return cmapPriv; +} + + +static int +LbxDefCmapPrivInit (pmap) + ColormapPtr pmap; +{ + pmap->devPrivates[lbxColormapPrivIndex].ptr = NULL; + return 1; +} + +static Bool +LbxCreateColormap (pmap) + ColormapPtr pmap; +{ + ScreenPtr pScreen = pmap->pScreen; + Bool ret; + + pScreen->CreateColormap = ((LbxScreenPriv *) (pScreen->devPrivates[ + lbxScreenPrivIndex].ptr))->CreateColormap; + + pmap->devPrivates[lbxColormapPrivIndex].ptr = NULL; + ret = (*pScreen->CreateColormap) (pmap); + + pScreen->CreateColormap = LbxCreateColormap; + + return ret; +} + +static void +LbxDestroyColormap (pmap) + ColormapPtr pmap; +{ + ScreenPtr pScreen = pmap->pScreen; + + LbxReleaseCmap(pmap, FALSE); + pScreen->DestroyColormap = ((LbxScreenPriv *) (pScreen->devPrivates[ + lbxScreenPrivIndex].ptr))->DestroyColormap; + (*pScreen->DestroyColormap) (pmap); + if (pmap->devPrivates && pmap->devPrivates[lbxColormapPrivIndex].ptr) + xfree(pmap->devPrivates[lbxColormapPrivIndex].ptr); + pScreen->DestroyColormap = LbxDestroyColormap; +} + +/* + * Initialize LBX colormap private. + */ + +int +LbxCmapInit () + +{ + LbxScreenPriv *pScreenPriv; + ScreenPtr pScreen; + int i; + + StalledResType = CreateNewResourceType(LbxUnstallClient); + + lbxScreenPrivIndex = AllocateScreenPrivateIndex (); + if (lbxScreenPrivIndex < 0) + return 0; + + lbxColormapPrivIndex = AllocateColormapPrivateIndex (LbxDefCmapPrivInit); + if (lbxColormapPrivIndex < 0) + return 0; + + for (i = 0; i < screenInfo.numScreens; i++) + { + pScreen = screenInfo.screens[i]; + + pScreenPriv = (LbxScreenPriv *) xalloc (sizeof (LbxScreenPriv)); + if (!pScreenPriv) + return 0; + + pScreenPriv->CreateColormap = pScreen->CreateColormap; + pScreen->CreateColormap = LbxCreateColormap; + pScreenPriv->DestroyColormap = pScreen->DestroyColormap; + pScreen->DestroyColormap = LbxDestroyColormap; + pScreen->devPrivates[lbxScreenPrivIndex].ptr = (pointer) pScreenPriv; + } + + return 1; +} + + +/* + * Return the number of allocated cells in the PSEUDO colormap. + */ + +static int +NumAllocatedCells (pent, size) + EntryPtr pent; + int size; +{ + Pixel pixel; + int count = 0; + + for (pixel = 0; pixel < size; pixel++) + { + if (pent[pixel].refcnt != 0 && pent[pixel].refcnt != AllocTemporary) + count++; + } + + return count; +} + +#define NUMRED(vis) ((vis->redMask >> vis->offsetRed) + 1) +#define NUMGREEN(vis) ((vis->greenMask >> vis->offsetGreen) + 1) +#define NUMBLUE(vis) ((vis->blueMask >> vis->offsetBlue) + 1) + +#define PIX_OUT(ptr,is2,val) \ + if (is2) *ptr++ = (val) >> 8; \ + *ptr++ = (val) +#define RGB_OUT(ptr,is2,shift,val) \ + *ptr++ = (val) >> shift; \ + if (is2) *ptr++ = (val) + +/* + * Return the list of allocated cells in the channel in + * the format required by LbxGrabCmapReply. + */ + +static CARD8 * +OutputChannel(pmap, chan, size, ptr, flags, channels) + ColormapPtr pmap; + EntryPtr chan; + int size; + CARD8 *ptr; + CARD8 flags; + CARD8 channels; +{ + Bool px2; + Bool rgb2; + int shift; + int rgb_sz; + Pixel pixel; + EntryPtr pent; + CARD8 *pixel_private_range_ptr = NULL; + CARD8 *pixel_shared_range_ptr = NULL; + int allocpriv; + + px2 = (flags & LBX_2BYTE_PIXELS) != 0; + rgb2 = (flags & LBX_RGB_BITS_MASK) > 7; + if (rgb2) + shift = 8; + else + shift = 15 - (flags & LBX_RGB_BITS_MASK); + rgb_sz = rgb2 + 1; + if (channels == DoRed|DoGreen|DoBlue) + rgb_sz *= 3; + /* kinda gross, but ddxen use AllocAll on static maps */ + allocpriv = (pmap->pVisual->class & DynamicClass) ? AllocPrivate : 0; + for (pixel = 0; pixel < size; pixel++) + { + pent = (EntryPtr) &chan[pixel]; + + if (pent->refcnt == 0 || pent->refcnt == AllocTemporary) + { + /* + * A free pixel. This disrupts all ranges. + */ + + pixel_private_range_ptr = pixel_shared_range_ptr = NULL; + + continue; + } + else if (pent->refcnt == allocpriv) + { + /* + * A private pixel. This disrupts any PIXEL_SHARED_RANGE. + */ + + pixel_shared_range_ptr = NULL; + + if (!pixel_private_range_ptr) + { + pixel_private_range_ptr = ptr; + + *ptr++ = LBX_PIXEL_PRIVATE; + PIX_OUT(ptr, px2, pixel); + } + else + { + CARD8 *pos = pixel_private_range_ptr + 2 + px2; + if (*pixel_private_range_ptr == LBX_PIXEL_PRIVATE) { + *pixel_private_range_ptr = LBX_PIXEL_RANGE_PRIVATE; + ptr += 1 + px2; + } + PIX_OUT(pos, px2, pixel); + } + } + else + { + /* + * A shared pixel. This disrupts any PIXEL_PRIVATE_RANGE. + */ + + pixel_private_range_ptr = NULL; + + if (!pixel_shared_range_ptr) + { + pixel_shared_range_ptr = ptr; + + *ptr++ = LBX_PIXEL_SHARED; + PIX_OUT(ptr, px2, pixel); + } + else + { + CARD8 *pos = pixel_shared_range_ptr + 2 + px2; + if (*pixel_shared_range_ptr == LBX_PIXEL_SHARED) + { + *pixel_shared_range_ptr = LBX_PIXEL_RANGE_SHARED; + memmove (pos + 1 + px2, pos, rgb_sz); + ptr += 1 + px2; + } + PIX_OUT(pos, px2, pixel); + } + + if (channels & DoRed) { + RGB_OUT(ptr, rgb2, shift, pent->co.local.red); + } + if (channels & DoGreen) { + RGB_OUT(ptr, rgb2, shift, pent->co.local.green); + } + if (channels & DoBlue) { + RGB_OUT(ptr, rgb2, shift, pent->co.local.blue); + } + } + } + return ptr; +} + +static void +GetAllocatedCells (pmap, flags, buf, bytes) + ColormapPtr pmap; + CARD8 *flags; + CARD8 *buf; + int *bytes; +{ + CARD8 *ptr; + + *flags = pmap->pVisual->bitsPerRGBValue - 1; + if (pmap->pVisual->ColormapEntries > 256) + *flags |= LBX_2BYTE_PIXELS; + if (!(pmap->pVisual->class & DynamicClass)) + *flags |= LBX_AUTO_RELEASE; + if ((pmap->pVisual->class | DynamicClass) == DirectColor) { + *flags |= LBX_3CHANNELS; + ptr = OutputChannel(pmap, pmap->red, NUMRED(pmap->pVisual), + buf, *flags, DoRed); + *ptr++ = LBX_NEXT_CHANNEL; + ptr = OutputChannel(pmap, pmap->green, NUMGREEN(pmap->pVisual), + ptr, *flags, DoGreen); + *ptr++ = LBX_NEXT_CHANNEL; + ptr = OutputChannel(pmap, pmap->blue, NUMBLUE(pmap->pVisual), + ptr, *flags, DoBlue); + } else + ptr = OutputChannel(pmap, pmap->red, pmap->pVisual->ColormapEntries, + buf, *flags, DoRed|DoGreen|DoBlue); + *ptr++ = LBX_LIST_END; + *bytes = ptr - buf; +} + + +/* + * Send an LbxReleaseCmapEvent to a proxy. + */ + +static void +SendReleaseCmapEvent (proxy, cmap) + LbxProxyPtr proxy; + Colormap cmap; +{ + xLbxReleaseCmapEvent ev; + ClientPtr client; + LbxClientPtr lbxcp; + int n; + + lbxcp = proxy->lbxClients[0]; + + if (lbxcp && (client = lbxcp->client)) + { + ev.type = LbxEventCode; + ev.lbxType = LbxReleaseCmapEvent; + ev.sequenceNumber = client->sequence; + ev.colormap = cmap; + ev.pad1 = ev.pad2 = ev.pad3 = ev.pad4 = ev.pad5 = ev.pad6 = 0; + + if (client->swapped) + { + swaps(&ev.sequenceNumber, n); + swapl(&ev.colormap, n); + } + + WriteToClient(client, sz_xLbxReleaseCmapEvent, (char *) &ev); + LbxForceOutput(proxy); + +#ifdef COLOR_DEBUG + fprintf (stderr, + "Sent LbxReleaseCmapEvent to proxy %d, seq = 0x%x, cmap = 0x%x\n", + proxy->pid, client->sequence, cmap); +#endif + } +} + + +/* + * WaitForServerCmapControl checks if the colormap is grabbed by a proxy, + * and if so, sends an LbxReleaseCmapEvent to the proxy. It then suspends + * the current request until the server gets the ReleaseCmap message from + * the proxy. + */ + +static Bool +WaitForServerCmapControl (client, pmap) + register ClientPtr client; + register ColormapPtr pmap; +{ + LbxColormapPriv *cmapPriv = (LbxColormapPriv *) + (pmap->devPrivates[lbxColormapPrivIndex].ptr); + LbxStalled *stalled; + + if (cmapPriv->grab_status == CMAP_GRABBED) + { + /* + * Send an LbxReleaseCmapEvent to the proxy that has the grab. + */ + + SendReleaseCmapEvent (cmapPriv->grabber, pmap->mid); + cmapPriv->grab_status = CMAP_WAITING_FOR_UNGRAB; + } + + stalled = (LbxStalled *)xalloc(sizeof(LbxStalled)); + if (!stalled) + return FALSE; + stalled->id = FakeClientID(client->index); + stalled->next = cmapPriv->stalled_clients; + cmapPriv->stalled_clients = stalled; + return AddResource(stalled->id, StalledResType, (pointer)cmapPriv); +} + + +/* + * When the X server gets any of the requests that allocate color cells, + * it calls LbxCheckColorRequest on the request. This function will check + * if the colormap is grabbed by a proxy, and if so, will suspend the + * current request and wait for the proxy to release the colormap. + */ + +Bool +LbxCheckColorRequest (client, pmap, req) + ClientPtr client; + ColormapPtr pmap; + xReq *req; +{ + LbxColormapPriv *cmapPriv = (LbxColormapPriv *) + (pmap->devPrivates[lbxColormapPrivIndex].ptr); + + if (!cmapPriv) + return FALSE; + + if (cmapPriv->grab_status != CMAP_NOT_GRABBED) + { + /* + * The colormap is grabbed by a proxy. Reset this request, and + * process it after the server gets back control of the colormap. + * Before we reset the request, we must put it back in the + * client's byte order. + */ + + if (!WaitForServerCmapControl (client, pmap)) + return FALSE; + + if (client->swapped) + { + register int n; + + switch (req->reqType) + { + case X_AllocColor: + { + xAllocColorReq *stuff = (xAllocColorReq *) req; + swaps(&stuff->length, n); + swapl(&stuff->cmap, n); + swaps(&stuff->red, n); + swaps(&stuff->green, n); + swaps(&stuff->blue, n); + break; + } + case X_AllocNamedColor: + { + xAllocNamedColorReq *stuff = (xAllocNamedColorReq *) req; + swaps(&stuff->length, n); + swapl(&stuff->cmap, n); + swaps(&stuff->nbytes, n); + break; + } + case X_AllocColorCells: + { + xAllocColorCellsReq *stuff = (xAllocColorCellsReq *) req; + swaps(&stuff->length, n); + swapl(&stuff->cmap, n); + swaps(&stuff->colors, n); + swaps(&stuff->planes, n); + break; + } + case X_AllocColorPlanes: + { + xAllocColorPlanesReq *stuff = (xAllocColorPlanesReq *) req; + swaps(&stuff->length, n); + swapl(&stuff->cmap, n); + swaps(&stuff->colors, n); + swaps(&stuff->red, n); + swaps(&stuff->green, n); + swaps(&stuff->blue, n); + break; + } + default: + break; + } + } + + ResetCurrentRequest(client); + client->sequence--; + IgnoreClient(client); + + return TRUE; + } + + if (!LbxClient(client) || + LbxProxy(client)->uid != cmapPriv->last_grabber) + { + /* + * Next time the proxy for this client does a colormap grab, it + * will have to get the colormap state (a non-smart grab). + */ + + cmapPriv->smart_grab = FALSE; + } + + return FALSE; +} + +static Bool +LbxGrabbedByClient (client, pmap) + ClientPtr client; + ColormapPtr pmap; +{ + LbxColormapPriv *cmapPriv = (LbxColormapPriv *) + (pmap->devPrivates[lbxColormapPrivIndex].ptr); + return (cmapPriv && + (cmapPriv->grab_status != CMAP_NOT_GRABBED) && + (cmapPriv->grabber == LbxProxy(client))); +} + +/* + * Check if a colormap is grabbed by a proxy. + */ + +int +LbxCheckCmapGrabbed (pmap) + ColormapPtr pmap; +{ + LbxColormapPriv *cmapPriv = (LbxColormapPriv *) + (pmap->devPrivates[lbxColormapPrivIndex].ptr); + + return (cmapPriv && (cmapPriv->grab_status == CMAP_GRABBED)); +} + + +/* + * Disable a smart grab on the specified colormap. + */ + +void +LbxDisableSmartGrab (pmap) + ColormapPtr pmap; +{ + LbxColormapPriv *cmapPriv = (LbxColormapPriv *) + (pmap->devPrivates[lbxColormapPrivIndex].ptr); + + if (cmapPriv) + cmapPriv->smart_grab = FALSE; +} + + +/* + * Send an LbxFreeCellsEvent to the specified proxy. + */ + +static void +SendFreeCellsEvent (proxy, cmap, pixel_start, pixel_end) + LbxProxyPtr proxy; + Colormap cmap; + Pixel pixel_start; + Pixel pixel_end; +{ + xLbxFreeCellsEvent ev; + ClientPtr client; + LbxClientPtr lbxcp; + int n; + + lbxcp = proxy->lbxClients[0]; + + if (lbxcp && (client = lbxcp->client)) + { + ev.type = LbxEventCode; + ev.lbxType = LbxFreeCellsEvent; + ev.sequenceNumber = client->sequence; + ev.colormap = cmap; + ev.pixelStart = pixel_start; + ev.pixelEnd = pixel_end; + ev.pad1 = ev.pad2 = ev.pad3 = ev.pad4 = 0; + + if (client->swapped) + { + swaps(&ev.sequenceNumber, n); + swapl(&ev.colormap, n); + swapl(&ev.pixelStart, n); + swapl(&ev.pixelEnd, n); + } + + WriteToClient(client, sz_xLbxFreeCellsEvent, (char *) &ev); + LbxForceOutput(proxy); +#ifdef COLOR_DEBUG + fprintf (stderr, "Sent LbxFreeCellsEvent to proxy %d, seq = 0x%x\n", + proxy->pid, client->sequence); + fprintf (stderr, " cmap = 0x%x, pixelStart = %d, pixelEnd = %d\n", + cmap, pixel_start, pixel_end); +#endif + } +} + +/* XXX use of globals like this is gross */ +static long pixel_start; +static long pixel_end; + + +/* + * LbxFreeCellsEvent generation functions. + */ + +/*ARGSUSED*/ +void +LbxBeginFreeCellsEvent (pmap) + ColormapPtr pmap; +{ + pixel_start = -1; + pixel_end = -1; +} + + +void +LbxAddFreeCellToEvent (pmap, pixel) + ColormapPtr pmap; + Pixel pixel; +{ + /* + * We must notify the proxy that has this colormap + * grabbed which cells are being freed (their refcount + * has reached zero). + */ + + if (pixel_start == -1) + pixel_start = pixel; + else + { + if (pixel_end == -1) + pixel_end = pixel; + else + { + if (pixel_end + 1 == pixel) + pixel_end = pixel; + else if (pixel > pixel_end + 1) + { + LbxColormapPriv *cmapPriv = (LbxColormapPriv *) + (pmap->devPrivates[lbxColormapPrivIndex].ptr); + + SendFreeCellsEvent (cmapPriv->grabber, + pmap->mid, pixel_start, pixel_end); + + pixel_start = pixel; + pixel_end = -1; + } + } + } +} + +void +LbxEndFreeCellsEvent (pmap) + ColormapPtr pmap; +{ + /* + * Check if there is an LbxFreeCellEvent we need to write. + */ + + if (pixel_start != -1) + { + LbxColormapPriv *cmapPriv = (LbxColormapPriv *) + (pmap->devPrivates[lbxColormapPrivIndex].ptr); + + SendFreeCellsEvent (cmapPriv->grabber, + pmap->mid, pixel_start, + pixel_end == -1 ? pixel_start : pixel_end); + } +} + + +/* + * Sort the specified pixel list. This optimizes generation + * of LbxFreeCellsEvent. + */ + +void +LbxSortPixelList (pixels, count) + Pixel *pixels; + int count; +{ + int i, j; + + for (i = 0; i <= count - 2; i++) + for (j = count - 1; j > i; j--) + if (pixels[j - 1] > pixels[j]) + { + Pixel temp = pixels[j - 1]; + pixels[j - 1] = pixels[j]; + pixels[j] = temp; + } +} + + +/* + * Handle a colormap grab request from a proxy. + */ + +int +ProcLbxGrabCmap(client) + register ClientPtr client; +{ + REQUEST(xLbxGrabCmapReq); + xLbxGrabCmapReply *reply; + Bool smartGrab; + LbxColormapPriv *cmapPriv; + ColormapPtr pmap; + int bytes, n; + LbxProxyPtr proxy = LbxProxy(client); + + client->sequence--; /* not a counted request */ + + pmap = (ColormapPtr) SecurityLookupIDByType (client, stuff->cmap, + RT_COLORMAP, + SecurityWriteAccess); + + if (!pmap) + { + client->errorValue = stuff->cmap; + return BadColor; + } + + cmapPriv = (LbxColormapPriv *) + (pmap->devPrivates[lbxColormapPrivIndex].ptr); + if (!cmapPriv) + { + cmapPriv = LbxColormapPrivInit (pmap); + if (!cmapPriv) + return BadAlloc; + } + + + /* + * We have a SMART GRAB if 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. + */ + + /* if proxy is this confused, give it full info */ + if (cmapPriv->grab_status == CMAP_GRABBED && cmapPriv->grabber == proxy) + LbxReleaseCmap(pmap, FALSE); + + if (proxy->uid != cmapPriv->last_grabber) + cmapPriv->smart_grab = FALSE; + smartGrab = cmapPriv->smart_grab; + +#ifdef COLOR_DEBUG + fprintf (stderr, "\nGot colormap grab request, "); + fprintf (stderr, "seq = 0x%x, proxy = %d, client = %d, cmap = 0x%x\n", + client->sequence, proxy->pid, client->index, stuff->cmap); + + if (cmapPriv->grab_status == CMAP_NOT_GRABBED) + { + fprintf (stderr, "cmap 0x%x is not grabbed by any proxy\n", + stuff->cmap); + if (smartGrab) + fprintf (stderr, "This is a smart grab\n"); + } + else if (cmapPriv->grab_status == CMAP_GRABBED) + { + if (cmapPriv->grabber == proxy) + { + fprintf (stderr, "cmap 0x%x is already grabbed by proxy %d\n", + stuff->cmap, proxy->pid); + } + else + { + fprintf (stderr, "cmap 0x%x is currently grabbed by proxy %d\n", + stuff->cmap, cmapPriv->grabber->pid); + } + } + else if (cmapPriv->grab_status == CMAP_WAITING_FOR_UNGRAB) + { + fprintf (stderr, + "Already waiting for cmap 0x%x to be ungrabbed by proxy %d\n", + stuff->cmap, cmapPriv->grabber->pid); + } +#endif + + if (cmapPriv->grab_status != CMAP_NOT_GRABBED && + cmapPriv->grabber != proxy) + { + /* + * The colormap is grabbed by a proxy other than the one that + * is requesting this grab. Reset this grab request, and process + * it after the server gets back control of the colormap. Before + * we reset the request, we must put it back in the client's byte + * order. + */ + + if (!WaitForServerCmapControl (client, pmap)) + return BadAlloc; + + if (client->swapped) + { + swaps(&stuff->length, n); + swapl(&stuff->cmap, n); + } + + ResetCurrentRequest(client); + IgnoreClient(client); + + return Success; + } + + if (pmap->pVisual->class & DynamicClass) { + cmapPriv->grabber = proxy; + cmapPriv->grab_status = CMAP_GRABBED; + cmapPriv->next = proxy->grabbedCmaps; + proxy->grabbedCmaps = pmap; + } else + smartGrab = FALSE; + + /* + * For an smart grab (see comments above), there is no information + * sent about the colormap cells because the proxy is all up to date. + * Otherwise, the server sends the proxy the state of all allocated + * cells in the colormap. All cells not specified are assumed free. + */ + + bytes = 0; + if (!smartGrab) { + if ((pmap->pVisual->class | DynamicClass) == DirectColor) { + bytes = NumAllocatedCells(pmap->red, + NUMRED(pmap->pVisual)) * 9; + bytes += NumAllocatedCells(pmap->green, + NUMGREEN(pmap->pVisual)) * 9; + bytes += NumAllocatedCells(pmap->blue, + NUMBLUE(pmap->pVisual)) * 9; + bytes += 2; + } else + bytes = NumAllocatedCells(pmap->red, + pmap->pVisual->ColormapEntries) * 9; + } + bytes += sz_xLbxGrabCmapReply + 1; + reply = (xLbxGrabCmapReply *) xalloc (bytes); + bzero (reply, sz_xLbxGrabCmapReply); + + if (smartGrab) + { + reply->flags = LBX_SMART_GRAB; + reply->length = 0; + } + else + { + GetAllocatedCells (pmap, &reply->flags, + (CARD8 *) reply + sz_xLbxGrabCmapReplyHdr, &bytes); + if (bytes <= (sz_xLbxGrabCmapReply - sz_xLbxGrabCmapReplyHdr)) + reply->length = 0; + else + reply->length = (sz_xLbxGrabCmapReplyHdr + + bytes - sz_xLbxGrabCmapReply + 3) >> 2; + } + + reply->type = X_Reply; + reply->sequenceNumber = client->sequence; + + bytes = sz_xLbxGrabCmapReply + (reply->length << 2); + + if (client->swapped) + { + register char n; + + swaps (&reply->sequenceNumber, n); + swapl (&reply->length, n); + } + + WriteToClient (client, bytes, (char *)reply); + + xfree (reply); + + return (client->noClientException); +} + +static int +LbxUnstallClient(data, id) + pointer data; + XID id; +{ + LbxColormapPriv *cmapPriv = (LbxColormapPriv *)data; + LbxStalled **prev; + ClientPtr client; + + for (prev = &cmapPriv->stalled_clients; *prev && (*prev)->id != id; ) + prev = &(*prev)->next; + *prev = (*prev)->next; + client = clients[CLIENT_ID(id)]; + if (!client->clientGone) + AttendClient(client); + return 0; +} + +void +LbxReleaseCmap(pmap, smart) + ColormapPtr pmap; + Bool smart; +{ + LbxColormapPriv *cmapPriv; + ColormapPtr *prev; + + if (!pmap->devPrivates) + return; + cmapPriv = (LbxColormapPriv *) + (pmap->devPrivates[lbxColormapPrivIndex].ptr); + if (!cmapPriv || (cmapPriv->grab_status == CMAP_NOT_GRABBED)) + return; + + for (prev = &cmapPriv->grabber->grabbedCmaps; *prev && *prev != pmap; ) + prev = &((LbxColormapPriv *) + (*prev)->devPrivates[lbxColormapPrivIndex].ptr)->next; + if (*prev == pmap) + *prev = cmapPriv->next; + + while (cmapPriv->stalled_clients) + FreeResource(cmapPriv->stalled_clients->id, 0); + + cmapPriv->grab_status = CMAP_NOT_GRABBED; + cmapPriv->last_grabber = smart ? cmapPriv->grabber->uid : 0; + cmapPriv->grabber = NULL; + cmapPriv->smart_grab = smart; +} + +/* + * Handle a colormap release request from a proxy. + */ + +int +ProcLbxReleaseCmap(client) + register ClientPtr client; +{ + REQUEST(xLbxReleaseCmapReq); + ColormapPtr pmap; + +#ifdef COLOR_DEBUG + fprintf (stderr, "Got colormap release request, "); + fprintf (stderr, "seq = 0x%x, proxy = %d, client = %d, cmap = 0x%x\n", + client->sequence, LbxProxyID(client), client->index, stuff->cmap); +#endif + + pmap = (ColormapPtr) SecurityLookupIDByType (client, stuff->cmap, + RT_COLORMAP, + SecurityWriteAccess); + + if (!pmap) + { + client->errorValue = stuff->cmap; + return BadColor; + } + + if (LbxGrabbedByClient(client, pmap)) + LbxReleaseCmap(pmap, TRUE); + return Success; +} + + +/* + * Handle an LbxAllocColor request. The proxy did the alloc and + * is telling the server what rgb and pixel value to use. + */ + +int +ProcLbxAllocColor(client) + register ClientPtr client; +{ + REQUEST(xLbxAllocColorReq); + ColormapPtr pmap; + CARD32 pixel = stuff->pixel; + + REQUEST_SIZE_MATCH (xLbxAllocColorReq); + pmap = (ColormapPtr) SecurityLookupIDByType (client, stuff->cmap, + RT_COLORMAP, + SecurityWriteAccess); + +#ifdef COLOR_DEBUG + fprintf (stderr, + "Got LBX alloc color: seq = 0x%x, proxy = %d, client = %d\n", + client->sequence, LbxProxyID(client), client->index); + fprintf (stderr, " cmap = 0x%x, pixel = %d, rgb = (%d,%d,%d)\n", + stuff->cmap, stuff->pixel, stuff->red, stuff->green, stuff->blue); +#endif + + if (pmap) + { + int status; + if (!LbxGrabbedByClient(client, pmap)) + return BadAccess; + + status = AllocColor (pmap, + &stuff->red, &stuff->green, &stuff->blue, + &pixel, client->index); + + if (status == Success && pixel != stuff->pixel) + { + /* + * Internal error - Proxy allocated different pixel from server + */ +#ifdef COLOR_DEBUG + fprintf(stderr, "got pixel %d (%d, %d, %d), expected %d\n", + pixel, stuff->red, stuff->green, stuff->blue, stuff->pixel); +#endif + FreeColors (pmap, client->index, 1, &pixel, 0L); + return BadAlloc; + } + + return status; + } + else + { + client->errorValue = stuff->cmap; + return (BadColor); + } +} + + +/* + * The proxy sends an LbxIncrementPixel request when it short circuits + * an AllocColor. The server must bump up the reference count the + * specified amount. + */ + +int +ProcLbxIncrementPixel(client) + register ClientPtr client; +{ + REQUEST(xLbxIncrementPixelReq); + ColormapPtr pmap; + EntryPtr pent; + Pixel pixel; + unsigned short red, green, blue; + VisualPtr pVisual; + int status; + +#ifdef COLOR_DEBUG + fprintf (stderr, + "Got LBX increment pixel: seq = 0x%x, proxy = %d, client = %d\n", + client->sequence, LbxProxyID(client), client->index); + fprintf (stderr, " cmap = 0x%x, pixel = %d\n", + stuff->cmap, stuff->pixel); +#endif + + /* + * Looks up the color associated with the pixel, and then call + * AllocColor() - a bit round-about, but it should work. + */ + + pmap = (ColormapPtr) SecurityLookupIDByType(client, stuff->cmap, + RT_COLORMAP, + SecurityWriteAccess); + if (!pmap) { + client->errorValue = stuff->cmap; + return BadColor; + } + + pixel = stuff->pixel; + + switch (pmap->class) { + case StaticColor: + case StaticGray: + red = pmap->red[pixel].co.local.red; + green = pmap->red[pixel].co.local.green; + blue = pmap->red[pixel].co.local.blue; + break; + case GrayScale: + case PseudoColor: + pent = pmap->red + pixel; + red = pent->co.local.red; + green = pent->co.local.green; + blue = pent->co.local.blue; + break; + default: + pVisual = pmap->pVisual; + red = pmap->red[(pixel & pVisual->redMask) >> pVisual->offsetRed].co.local.red; + green = pmap->green[(pixel & pVisual->greenMask) >> pVisual->offsetGreen].co.local.green; + blue = pmap->blue[(pixel & pVisual->blueMask) >> pVisual->offsetBlue].co.local.blue; + break; + } + + status = AllocColor(pmap, &red, &green, &blue, &pixel, client->index); + + if (status == Success && pixel != stuff->pixel) + { + /* + * Internal error - Proxy allocated different pixel from server + */ +#ifdef COLOR_DEBUG + fprintf(stderr, "got pixel %d, expected %d\n", pixel, stuff->pixel); +#endif + FreeColors (pmap, client->index, 1, &pixel, 0L); + return BadAlloc; + } + + return status; +} diff --git a/lbx/lbxdata.h b/lbx/lbxdata.h new file mode 100644 index 000000000..d5240f7ea --- /dev/null +++ b/lbx/lbxdata.h @@ -0,0 +1,44 @@ +/* $Xorg: lbxdata.h,v 1.3 2000/08/17 19:53:31 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 _LBXDATA_H_ +#define _LBXDATA_H_ +#define NEED_REPLIES +#include "X.h" +#include "Xproto.h" +#define _XLBX_SERVER_ +#include "lbxstr.h" +#include "dixfontstr.h" + +extern int lbx_font_private; + +typedef struct _fonttaginfo { + XID tid; + FontPtr pfont; + unsigned long size; + int compression; + xLbxFontInfo *fontinfo; +} FontTagInfoRec, *FontTagInfoPtr; + +#endif /* _LBXDATA_H_ */ diff --git a/lbx/lbxdix.c b/lbx/lbxdix.c new file mode 100644 index 000000000..e4822f190 --- /dev/null +++ b/lbx/lbxdix.c @@ -0,0 +1,887 @@ +/* $Xorg: lbxdix.c,v 1.4 2001/02/09 02:05:16 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. + * + */ + +/* various bits of DIX-level mangling */ + +#include <sys/types.h> +#include <stdio.h> +#define NEED_REPLIES +#define NEED_EVENTS +#include "X.h" +#include "Xproto.h" +#include "misc.h" +#include "os.h" +#include "dixstruct.h" +#include "resource.h" +#include "inputstr.h" +#include "servermd.h" +#include "dixfontstr.h" +#include "gcstruct.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "propertyst.h" +#define _XLBX_SERVER_ +#include "lbxstr.h" +#include "lbxserve.h" +#include "lbxtags.h" +#include "lbxdata.h" +#include "Xfuncproto.h" + +extern void CopySwap32Write(); +extern int (*ProcVector[256]) (); +extern int (*SwappedProcVector[256]) (); +extern void (*ReplySwapVector[256]) (); + +extern void LbxWriteSConnSetupPrefix(); + +int lbx_font_private; + +void +LbxDixInit() +{ + TagInit(); + lbx_font_private = AllocateFontPrivateIndex(); +} + +/* ARGSUSED */ +void +LbxAllowMotion(client, num) + ClientPtr client; + int num; +{ + LbxProxyPtr proxy = LbxProxy(client); + proxy->motion_allowed_events += num; +} + +extern WindowPtr *WindowTable; +extern xConnSetupPrefix connSetupPrefix; +extern char *ConnectionInfo; +extern int connBlockScreenStart; + +int +LbxSendConnSetup(client, reason) + ClientPtr client; + char *reason; +{ + int dlength; + int i, ndex, lim, wndex; + CARD32 dataBuf[16]; + xLbxConnSetupPrefix csp; + NewClientInfoRec nci; + LbxProxyPtr proxy = LbxProxy(client); + + if (reason) { + SendConnSetup(client, reason); + LbxForceOutput(proxy); /* expedient to avoid another state variable */ + return (client->noClientException); + } + + IncrementClientCount(); + + client->requestVector = client->swapped ? SwappedProcVector : ProcVector; + client->sequence = 0; + dataBuf[0] = client->clientAsMask; + + csp.success = TRUE; + csp.majorVersion = connSetupPrefix.majorVersion; + csp.minorVersion = connSetupPrefix.minorVersion; + csp.tag = 0; +#ifdef XAPPGROUP + if (!client->appgroup) { +#endif + csp.changeType = 1; /* LbxNormalDeltas */ + csp.length = 2 + /* tag + resource-id-base */ + screenInfo.numScreens; /* input-mask per screen */ + wndex = 0; ndex = 1; lim = screenInfo.numScreens; +#ifdef XAPPGROUP + } else { + csp.changeType = 2; /* LbxAppGroupDeltas */ + csp.length = 7 + /* tag, res-id-base, root, visual, colormap, b&w-pix */ + 1 + screenInfo.numScreens - screenInfo.numVideoScreens; + XagGetDeltaInfo (client, &dataBuf[1]); + for (i = 0; i < MAXSCREENS; i++) { + if ((CARD32) WindowTable[i]->drawable.id == dataBuf[1]) { + dataBuf[6] = WindowTable[i]->eventMask | wOtherEventMasks(WindowTable[i]); + break; + } + } + wndex = screenInfo.numVideoScreens; + ndex = 7; + lim = screenInfo.numScreens - screenInfo.numVideoScreens; + } +#endif + for (i = 0; i < lim; i++, ndex++, wndex++) { + dataBuf[ndex] = + WindowTable[wndex]->eventMask | wOtherEventMasks(WindowTable[wndex]); + } + dlength = (csp.length - 1) << 2; + + if (LbxProxyClient(proxy)->swapped) { + swaps(&csp.length, i); + } + + if (client->swapped) { + LbxWriteSConnSetupPrefix(client, &csp); + SwapLongs(dataBuf, (1 + screenInfo.numScreens)); + WriteToClient(client, dlength, (pointer) dataBuf); + } else { + WriteToClient(client, sizeof(xLbxConnSetupPrefix), (char *) &csp); + WriteToClient(client, dlength, (pointer) dataBuf); + } + + LbxForceOutput(proxy); /* expedient to avoid another state variable */ + client->clientState = ClientStateRunning; + if (ClientStateCallback) { + if (LbxProxyClient(proxy)->swapped != client->swapped) { + swaps(&csp.length, i); + } + nci.client = client; + nci.prefix = (xConnSetupPrefix*) &csp; + nci.setup = (xConnSetup *) ConnectionInfo; + CallCallbacks(&ClientStateCallback, (pointer) &nci); + } + + return client->noClientException; +} + +extern InputInfo inputInfo; + +static XID modifier_map_tag; + +int +LbxGetModifierMapping(client) + ClientPtr client; +{ + TagData td; + pointer tagdata; + xLbxGetModifierMappingReply rep; + register KeyClassPtr keyc = inputInfo.keyboard->key; + int dlength = keyc->maxKeysPerModifier << 3; + Bool tag_known = FALSE, + send_data; + int n; + + if (!modifier_map_tag) { + tagdata = (pointer) keyc->modifierKeyMap; + TagSaveTag(LbxTagTypeModmap, dlength, tagdata, &modifier_map_tag); + } else { + td = TagGetTag(modifier_map_tag); + tagdata = td->tdata; + tag_known = TagProxyMarked(modifier_map_tag, LbxProxyID(client)); + } + if (modifier_map_tag) + TagMarkProxy(modifier_map_tag, LbxProxyID(client)); + + send_data = (!modifier_map_tag || !tag_known); + + rep.type = X_Reply; + rep.keyspermod = keyc->maxKeysPerModifier; + rep.sequenceNumber = client->sequence; + rep.tag = modifier_map_tag; + rep.pad0 = rep.pad1 = rep.pad2 = rep.pad3 = rep.pad4 = 0; + + if (send_data) + rep.length = dlength >> 2; + else + rep.length = 0; + + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.tag, n); + } + WriteToClient(client, sizeof(xLbxGetModifierMappingReply), (char *)&rep); + + if (send_data) + WriteToClient(client, dlength, (char *) tagdata); + + return client->noClientException; +} + +void +LbxFlushModifierMapTag() +{ + + if (modifier_map_tag) + TagDeleteTag(modifier_map_tag); +} + +static XID keyboard_map_tag; + +int +LbxGetKeyboardMapping(client) + ClientPtr client; +{ + TagData td; + pointer tagdata; + xLbxGetKeyboardMappingReply rep; + + REQUEST(xLbxGetKeyboardMappingReq); + KeySymsPtr curKeySyms = &inputInfo.keyboard->key->curKeySyms; + int dlength; + Bool tag_known = FALSE, + send_data; + int n; + + REQUEST_SIZE_MATCH(xLbxGetKeyboardMappingReq); + + if ((stuff->firstKeyCode < curKeySyms->minKeyCode) || + (stuff->firstKeyCode > curKeySyms->maxKeyCode)) { + client->errorValue = stuff->firstKeyCode; + return BadValue; + } + if (stuff->firstKeyCode + stuff->count > curKeySyms->maxKeyCode + 1) { + client->errorValue = stuff->count; + return BadValue; + } + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.keysperkeycode = curKeySyms->mapWidth; + /* length is a count of 4 byte quantities and KeySyms are 4 bytes */ + + if (!keyboard_map_tag) { + tagdata = (pointer) &curKeySyms->map[(stuff->firstKeyCode - + curKeySyms->minKeyCode) * curKeySyms->mapWidth]; + dlength = (curKeySyms->mapWidth * stuff->count); + TagSaveTag(LbxTagTypeKeymap, dlength, tagdata, &keyboard_map_tag); + } else { + td = TagGetTag(keyboard_map_tag); + tagdata = td->tdata; + tag_known = TagProxyMarked(keyboard_map_tag, LbxProxyID(client)); + } + if (keyboard_map_tag) + TagMarkProxy(keyboard_map_tag, LbxProxyID(client)); + + send_data = (!keyboard_map_tag || !tag_known); + rep.type = X_Reply; + rep.keysperkeycode = curKeySyms->mapWidth; + rep.sequenceNumber = client->sequence; + rep.tag = keyboard_map_tag; + rep.pad0 = rep.pad1 = rep.pad2 = rep.pad3 = rep.pad4 = 0; + + if (send_data) + rep.length = (curKeySyms->mapWidth * stuff->count); + else + rep.length = 0; + + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.tag, n); + } + WriteToClient(client, sizeof(xLbxGetKeyboardMappingReply), (char *)&rep); + + if (send_data) { + client->pSwapReplyFunc = CopySwap32Write; + WriteSwappedDataToClient(client, + curKeySyms->mapWidth * stuff->count * sizeof(KeySym), + &curKeySyms->map[(stuff->firstKeyCode - curKeySyms->minKeyCode) * + curKeySyms->mapWidth]); + } + return client->noClientException; +} + +void +LbxFlushKeyboardMapTag() +{ + if (keyboard_map_tag) + TagDeleteTag(keyboard_map_tag); +} + +/* counts number of bits needed to hold value */ +static int +_bitsize(val) + int val; +{ + int bits = 1; /* always need one for sign bit */ + + if (val == 0) + return (bits); + + if (val < 0) { + val = -val; + } + while (val) { + bits++; + val >>= 1; + } + + return bits; + +} + +/* + * squashes the font (if possible), returning the new length and + * a pointer to the new data (which has been allocated). if it can't + * squish, it just returns a 0 and the data is sent in raw form. + */ +int _lbx_fi_junklen = sizeof(BYTE) * 2 + sizeof(CARD16) + sizeof(CARD32); + +static int +squish_font_info(qfr, rlen, sqrep) + xQueryFontReply *qfr; + int rlen; + xLbxFontInfo **sqrep; +{ + int len, + hlen; + xLbxFontInfo *new; + xCharInfo *minb, + *maxb, + *ci, + bbox; + int i; + char *t; + xLbxCharInfo *chars; + int num_chars; + + num_chars = qfr->nCharInfos; + + if (num_chars == 0) + return 0; + + minb = &qfr->minBounds; + maxb = &qfr->maxBounds; + /* + * first do the quick check -- if the attribute fields aren't all the + * same, punt + */ + + if (minb->attributes != maxb->attributes) + return 0; + +#define compute(field) \ + bbox.field = max(_bitsize(minb->field), _bitsize(maxb->field)) + + compute(characterWidth); + compute(leftSideBearing); + compute(rightSideBearing); + compute(ascent); + compute(descent); + +#undef compute + + /* make sure it fits */ + if (!((bbox.characterWidth <= LBX_WIDTH_BITS) && + (bbox.leftSideBearing <= LBX_LEFT_BITS) && + (bbox.rightSideBearing <= LBX_RIGHT_BITS) && + (bbox.ascent <= LBX_ASCENT_BITS) && + (bbox.descent <= LBX_DESCENT_BITS))) { + return 0; + } + + hlen = sizeof(xLbxFontInfo) + qfr->nFontProps * sizeof(xFontProp); + + len = hlen + (num_chars * sizeof(xLbxCharInfo)); + + new = (xLbxFontInfo *) xalloc(len); + if (!new) + return 0; + + /* gross hack to avoid copying all the fields */ + t = (char *) qfr; + t += _lbx_fi_junklen; + + /* copy all but the char infos */ + memcpy((char *) new, (char *) t, hlen); + + t = (char *) new; + t += hlen; + chars = (xLbxCharInfo *) t; + + t = (char *) qfr; + t += sizeof(xQueryFontReply) + qfr->nFontProps * sizeof(xFontProp); + ci = (xCharInfo *) t; + + /* now copy & pack the charinfos */ + for (i = 0; i < num_chars; i++, chars++, ci++) { + chars->metrics = 0; + chars->metrics |= (LBX_MASK_BITS(ci->characterWidth, LBX_WIDTH_BITS) + << LBX_WIDTH_SHIFT); + chars->metrics |= (LBX_MASK_BITS(ci->leftSideBearing, LBX_LEFT_BITS) + << LBX_LEFT_SHIFT); + chars->metrics |= (LBX_MASK_BITS(ci->rightSideBearing, LBX_RIGHT_BITS) + << LBX_RIGHT_SHIFT); + chars->metrics |= (LBX_MASK_BITS(ci->ascent, LBX_ASCENT_BITS) + << LBX_ASCENT_SHIFT); + chars->metrics |= (LBX_MASK_BITS(ci->descent, LBX_DESCENT_BITS) + << LBX_DESCENT_SHIFT); + } + + *sqrep = new; + return len; +} + +int +LbxQueryFont(client) + ClientPtr client; +{ + xQueryFontReply *reply; + xLbxQueryFontReply lbxrep; + FontPtr pFont; + register GC *pGC; + Bool send_data = FALSE; + Bool free_data = FALSE; + int rlength = 0; + FontTagInfoPtr ftip; + int sqlen = 0; + xLbxFontInfo *sqrep, + *sreply = NULL; + + REQUEST(xLbxQueryFontReq); + + REQUEST_SIZE_MATCH(xLbxQueryFontReq); + + client->errorValue = stuff->fid; /* EITHER font or gc */ + pFont = (FontPtr) SecurityLookupIDByType(client, stuff->fid, RT_FONT, + SecurityReadAccess); + if (!pFont) { + /* can't use VERIFY_GC because it might return BadGC */ + pGC = (GC *) SecurityLookupIDByType(client, stuff->fid, RT_GC, + SecurityReadAccess); + if (!pGC || !pGC->font) { /* catch a non-existent builtin font */ + client->errorValue = stuff->fid; + return (BadFont); /* procotol spec says only error is BadFont */ + } + pFont = pGC->font; + } + + /* get tag (if any) */ + ftip = (FontTagInfoPtr) FontGetPrivate(pFont, lbx_font_private); + + if (!ftip) { + xCharInfo *pmax = FONTINKMAX(pFont); + xCharInfo *pmin = FONTINKMIN(pFont); + int nprotoxcistructs; + + nprotoxcistructs = ( + pmax->rightSideBearing == pmin->rightSideBearing && + pmax->leftSideBearing == pmin->leftSideBearing && + pmax->descent == pmin->descent && + pmax->ascent == pmin->ascent && + pmax->characterWidth == pmin->characterWidth) ? + 0 : N2dChars(pFont); + + rlength = sizeof(xQueryFontReply) + + FONTINFONPROPS(FONTCHARSET(pFont)) * sizeof(xFontProp) + + nprotoxcistructs * sizeof(xCharInfo); + reply = (xQueryFontReply *) xalloc(rlength); + if (!reply) { + return (BadAlloc); + } + free_data = TRUE; + send_data = TRUE; + QueryFont(pFont, reply, nprotoxcistructs); + + sqlen = squish_font_info(reply, rlength, &sqrep); + if (!sqlen) { /* if it failed to squish, send it raw */ + char *t; + + lbxrep.compression = 0; + + sqlen = rlength - _lbx_fi_junklen; + t = (char *) reply; + sqrep = (xLbxFontInfo *) (t + _lbx_fi_junklen); + } else { + lbxrep.compression = 1; + xfree(reply); /* no longer needed */ + } + } else { /* just get data from tag */ + sqrep = ftip->fontinfo; + sqlen = ftip->size; + lbxrep.compression = ftip->compression; + } + + if (!ftip) { + /* data allocation is done when font is first queried */ + ftip = (FontTagInfoPtr) xalloc(sizeof(FontTagInfoRec)); + if (ftip && + TagSaveTag(LbxTagTypeFont, sqlen, (pointer) ftip, &ftip->tid)) { + FontSetPrivate(pFont, lbx_font_private, (pointer) ftip); + ftip->pfont = pFont; + ftip->size = sqlen; + ftip->fontinfo = sqrep; + ftip->compression = lbxrep.compression; + free_data = FALSE; + } else { + xfree(ftip); + } + } + if (ftip) { + if (!TagProxyMarked(ftip->tid, LbxProxyID(client))) + send_data = TRUE; + TagMarkProxy(ftip->tid, LbxProxyID(client)); + lbxrep.tag = ftip->tid; + } else { + lbxrep.tag = 0; + send_data = TRUE; + } + + lbxrep.type = X_Reply; + lbxrep.sequenceNumber = client->sequence; + lbxrep.pad0 = lbxrep.pad1 = lbxrep.pad2 = lbxrep.pad3 = lbxrep.pad4 = 0; + + if (send_data) + lbxrep.length = sqlen >> 2; + else + lbxrep.length = 0; + + if (client->swapped) { + int n; + + swaps(&lbxrep.sequenceNumber, n); + swapl(&lbxrep.length, n); + swapl(&lbxrep.tag, n); + sreply = (xLbxFontInfo *) ALLOCATE_LOCAL(sqlen); + if (!sreply) + return BadAlloc; + memcpy((char *) sreply, (char *) sqrep, sqlen); + LbxSwapFontInfo(sreply, lbxrep.compression); + sqrep = sreply; + } + WriteToClient(client, sizeof(xLbxQueryFontReply), (char *) &lbxrep); + if (send_data) + WriteToClient(client, sqlen, (char *)sqrep); + if (free_data) + xfree(sqrep); + if (sreply) + DEALLOCATE_LOCAL(sreply); + return (client->noClientException); +} + +void +LbxFreeFontTag(pfont) + FontPtr pfont; +{ + FontTagInfoPtr ftip; + + ftip = (FontTagInfoPtr) FontGetPrivate(pfont, lbx_font_private); + if (ftip) + TagDeleteTag(ftip->tid); +} + +LbxInvalidateTag(client, tag) + ClientPtr client; + XID tag; +{ + TagClearProxy(tag, LbxProxyID(client)); + return client->noClientException; +} + +void +LbxSendInvalidateTag(client, tag, tagtype) + ClientPtr client; + XID tag; + int tagtype; +{ + xLbxInvalidateTagEvent ev; + int n; + + ev.type = LbxEventCode; + ev.lbxType = LbxInvalidateTagEvent; + ev.sequenceNumber = client->sequence; + ev.tag = tag; + ev.tagType = tagtype; + ev.pad1 = ev.pad2 = ev.pad3 = ev.pad4 = ev.pad5 = 0; + + if (client->swapped) { + swaps(&ev.sequenceNumber, n); + swapl(&ev.tag, n); + swapl(&ev.tagType, n); + } + DBG(DBG_CLIENT, (stderr, "Invalidating tag %d\n", tag)); + WriteToClient(client, sizeof(xLbxInvalidateTagEvent), (char *) &ev); + LbxForceOutput(LbxProxy(client)); +} + +static void +LbxSendSendTagData(pid, tag, tagtype) + int pid; + XID tag; + int tagtype; +{ + xLbxSendTagDataEvent ev; + int n; + LbxProxyPtr proxy; + ClientPtr client; + LbxClientPtr lbxcp; + + proxy = LbxPidToProxy(pid); + lbxcp = (proxy != NULL) ? proxy->lbxClients[0] : NULL; + if (lbxcp && (client = lbxcp->client)) { + ev.type = LbxEventCode; + ev.lbxType = LbxSendTagDataEvent; + ev.sequenceNumber = client->sequence; + ev.tag = tag; + ev.tagType = tagtype; + ev.pad1 = ev.pad2 = ev.pad3 = ev.pad4 = ev.pad5 = 0; + + if (client->swapped) { + swaps(&ev.sequenceNumber, n); + swapl(&ev.tag, n); + swapl(&ev.tagType, n); + } + DBG(DBG_CLIENT, (stderr, "Requesting tag %d\n", tag)); + WriteToClient(client, sizeof(xLbxSendTagDataEvent), (char *) &ev); + LbxForceOutput(proxy); + } +} + +/* + * keep track of clients stalled waiting for tags to come back from + * a proxy. since multiple clinets can be waiting for the same tag, + * we have to keep a list of all of them. + */ + +typedef struct _sendtagq { + XID tag; + int num_stalled; + ClientPtr *stalled_clients; + struct _sendtagq *next; +} SendTagQRec, *SendTagQPtr; + +static SendTagQPtr queried_tags = NULL; + +#define LbxSendTagFailed -1 +#define LbxSendTagSendIt 0 +#define LbxSendTagAlreadySent 1 + +static Bool +LbxQueueSendTag(client, tag) + ClientPtr client; + XID tag; +{ + SendTagQPtr stqp, *prev, new; + ClientPtr *newlist; + + + /* see if we're asking for one already in the pipeline */ + for (prev = &queried_tags; stqp = *prev; prev = &stqp->next) { + if (stqp->tag == tag) { + /* add new client to list */ + newlist = (ClientPtr *) xrealloc(stqp->stalled_clients, + (sizeof(ClientPtr) * (stqp->num_stalled + 1))); + if (!newlist) + return LbxSendTagFailed; + newlist[stqp->num_stalled++] = client; + stqp->stalled_clients = newlist; + DBG(DBG_CLIENT, (stderr, "Additional client requesting tag %d\n", tag)); + return LbxSendTagAlreadySent; + } + } + + /* make new one */ + new = (SendTagQPtr) xalloc(sizeof(SendTagQRec)); + newlist = (ClientPtr *) xalloc(sizeof(ClientPtr)); + if (!new || !newlist) { + xfree(new); + xfree(newlist); + return LbxSendTagFailed; + } + *newlist = client; + new->stalled_clients = newlist; + new->num_stalled = 1; + new->tag = tag; + new->next = NULL; + + /* stick on end of list */ + *prev = new; + return LbxSendTagSendIt; +} + +SendTagQPtr +LbxFindQTag(tag) + XID tag; +{ + SendTagQPtr stqp; + + for (stqp = queried_tags; stqp; stqp = stqp->next) { + if (stqp->tag == tag) + return stqp; + } + return NULL; +} + +static void +LbxFreeQTag(stqp) + SendTagQPtr stqp; +{ + xfree(stqp->stalled_clients); + xfree(stqp); +} + +static void +LbxRemoveQTag(tag) + XID tag; +{ + SendTagQPtr stqp, *prev; + + for (prev = &queried_tags; stqp = *prev; prev = &stqp->next) { + if (stqp->tag == tag) { + *prev = stqp->next; + LbxFreeQTag(stqp); + return; + } + } +} + +Bool +LbxFlushQTag(tag) + XID tag; +{ + SendTagQPtr stqp; + ClientPtr *cp; + + stqp = LbxFindQTag(tag); + if (!stqp) + return FALSE; + for (cp = stqp->stalled_clients; --stqp->num_stalled >= 0; cp++) + AttendClient(*cp); + LbxRemoveQTag(tag); + return TRUE; +} + +void +ProcessQTagZombies() +{ + SendTagQPtr stqp; + ClientPtr *out, *in; + int i; + + for (stqp = queried_tags; stqp; stqp = stqp->next) { + out = stqp->stalled_clients; + for (in = out, i = stqp->num_stalled; --i >= 0; in++) { + if ((*in)->clientGone) + --stqp->num_stalled; + else + *out++ = *in; + } + } +} + +/* + * server sends this + */ + +void +LbxQueryTagData(client, owner_pid, tag, tagtype) + ClientPtr client; + int owner_pid; + XID tag; + int tagtype; +{ + /* save the info and the client being stalled */ + if (LbxQueueSendTag(client, tag) == LbxSendTagSendIt) + LbxSendSendTagData(owner_pid, tag, tagtype); +} + +/* + * server recieves this + */ +int +LbxTagData(client, tag, len, data) + ClientPtr client; + XID tag; + unsigned long len; + pointer data; +{ + TagData td; + PropertyPtr pProp; + + td = TagGetTag(tag); + if (!td || td->data_type != LbxTagTypeProperty) + return Success; + if (!td->global) { + /* somebody changed contents while we were querying */ + TagDeleteTag(tag); + return Success; + } + LbxFlushQTag(tag); + pProp = (PropertyPtr) td->tdata; + if (pProp->tag_id != tag || pProp->owner_pid != LbxProxyID(client)) + return Success; + pProp->owner_pid = 0; + if (len != td->size) + pProp->size = len / (pProp->format >> 3); + pProp->data = xrealloc(pProp->data, len); + if (!pProp->data) { + pProp->size = 0; + return Success; + } + if (client->swapped) { + switch (pProp->format) { + case 32: + SwapLongs((CARD32 *) data, len >> 2); + break; + case 16: + SwapShorts((short *) data, len >> 1); + break; + default: + break; + } + } + memmove((char *) pProp->data, (char *) data, len); + return Success; +} + +/* when server resets, need to reset global tags */ +void +LbxResetTags() +{ + SendTagQPtr stqp; + + modifier_map_tag = 0; + keyboard_map_tag = 0; + + /* clean out any pending tag requests */ + while (stqp = queried_tags) { + queried_tags = stqp->next; + LbxFreeQTag(stqp); + } +} diff --git a/lbx/lbxexts.c b/lbx/lbxexts.c new file mode 100644 index 000000000..4ee5f87c6 --- /dev/null +++ b/lbx/lbxexts.c @@ -0,0 +1,270 @@ +/* $Xorg: lbxexts.c,v 1.3 2000/08/17 19:53:31 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. + * + */ + +#include "X.h" +#include "Xproto.h" +#include "misc.h" +#include "dixstruct.h" +#define _XLBX_SERVER_ +#include "lbxstr.h" +#ifdef XCSECURITY +#define _SECURITY_SERVER +#include "extensions/security.h" +#endif + +typedef struct _lbxext { + char *name; + char **aliases; + int num_aliases; + int idx; + int opcode; + int ev_base; + int err_base; + int num_reqs; + CARD8 *rep_mask; + CARD8 *ev_mask; +#ifdef XCSECURITY + Bool secure; +#endif +} LbxExtensionEntry; + +static LbxExtensionEntry **lbx_extensions = NULL; +static int num_exts = 0; + + +Bool +LbxAddExtension(name, opcode, ev_base, err_base) + char *name; + int opcode; + int ev_base, + err_base; +{ + int i; + register LbxExtensionEntry *ext, + **newexts; + + ext = (LbxExtensionEntry *) xalloc(sizeof(LbxExtensionEntry)); + if (!ext) + return FALSE; + ext->name = (char *) xalloc(strlen(name) + 1); + ext->num_aliases = 0; + ext->aliases = (char **) NULL; + if (!ext->name) { + xfree(ext); + return FALSE; + } + strcpy(ext->name, name); + i = num_exts; + newexts = (LbxExtensionEntry **) xrealloc(lbx_extensions, + (i + 1) * sizeof(LbxExtensionEntry *)); + if (!newexts) { + xfree(ext->name); + xfree(ext); + return FALSE; + } + num_exts++; + lbx_extensions = newexts; + lbx_extensions[i] = ext; + ext->idx = i; + + ext->opcode = opcode;; + ext->ev_base = ev_base;; + ext->err_base = err_base; + ext->ev_mask = NULL; + ext->rep_mask = NULL; + ext->num_reqs = 0; +#ifdef XCSECURITY + ext->secure = FALSE; +#endif + + return TRUE; +} + +Bool +LbxAddExtensionAlias(idx, alias) + int idx; + char *alias; +{ + char *name; + char **aliases; + LbxExtensionEntry *ext = lbx_extensions[idx]; + + aliases = (char **) xrealloc(ext->aliases, + (ext->num_aliases + 1) * sizeof(char *)); + if (!aliases) + return FALSE; + ext->aliases = aliases; + name = (char *) xalloc(strlen(alias) + 1); + if (!name) + return FALSE; + strcpy(name, alias); + ext->aliases[ext->num_aliases] = name; + ext->num_aliases++; + return TRUE; +} + +static int +LbxFindExtension(extname, len) + char *extname; + int len; +{ + int i, j; + + for (i = 0; i < num_exts; i++) { + if ((strlen(lbx_extensions[i]->name) == len) && + (strncmp(lbx_extensions[i]->name, extname, len) == 0)) + return i; + for (j = lbx_extensions[i]->num_aliases; --j >= 0;) { + if ((strlen(lbx_extensions[i]->aliases[j]) == len) && + (strncmp(lbx_extensions[i]->aliases[j], extname, len) == 0)) + return i; + } + } + return -1; +} + +void +LbxDeclareExtensionSecurity(extname, secure) + char *extname; + Bool secure; +{ +#ifdef XCSECURITY + int i = LbxFindExtension(extname, strlen(extname)); + if (i >= 0) + lbx_extensions[i]->secure = secure; +#endif +} + +Bool +LbxRegisterExtensionGenerationMasks(idx, num_reqs, rep_mask, ev_mask) + int idx; + int num_reqs; + char *rep_mask, + *ev_mask; +{ + LbxExtensionEntry *ext = lbx_extensions[idx]; + CARD8 *nrm, + *nem; + int mlen = mlen = num_reqs / (8 * sizeof(CARD8)) + 1; + + nrm = (CARD8 *) xalloc(sizeof(CARD8) * mlen); + nem = (CARD8 *) xalloc(sizeof(CARD8) * mlen); + + if (!nrm || !nem) { + xfree(nrm); + xfree(nem); + return FALSE; + } + memcpy((char *) nrm, (char *) rep_mask, mlen); + memcpy((char *) nem, (char *) ev_mask, mlen); + ext->rep_mask = nrm; + ext->ev_mask = nem; + ext->num_reqs = num_reqs; + + return TRUE; +} + +int +LbxQueryExtension(client, ename, nlen) + ClientPtr client; + char *ename; + int nlen; +{ + xLbxQueryExtensionReply rep; + int i; + int mlen = 0; + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.major_opcode = 0; + rep.present = FALSE; + rep.length = 0; + rep.pad0 = rep.pad1 = rep.pad2 = rep.pad3 = rep.pad4 = 0; + + i = LbxFindExtension(ename, nlen); + + if (i < 0 +#ifdef XCSECURITY + /* don't show insecure extensions to untrusted clients */ + || (client->trustLevel == XSecurityClientUntrusted && + !lbx_extensions[i]->secure) +#endif + ) + rep.present = FALSE; + else { + rep.present = TRUE; + rep.major_opcode = lbx_extensions[i]->opcode; + rep.first_event = lbx_extensions[i]->ev_base; + rep.first_error = lbx_extensions[i]->err_base; + rep.numReqs = lbx_extensions[i]->num_reqs; + if (lbx_extensions[i]->rep_mask) { + mlen = (lbx_extensions[i]->num_reqs + 7) >> 3; + rep.length = ((mlen + 3) >> 2) * 2; + } + } + if (client->swapped) { + char n; + + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + } + WriteToClient(client, sizeof(xLbxQueryExtensionReply), (char *)&rep); + if (mlen) { + WriteToClient(client, mlen, (char *)lbx_extensions[i]->rep_mask); + WriteToClient(client, mlen, (char *)lbx_extensions[i]->ev_mask); + } + return Success; +} + +LbxCloseDownExtensions() +{ + int i; + + for (i = 0; i < num_exts; i++) { + xfree(lbx_extensions[i]->name); + xfree(lbx_extensions[i]->aliases); + xfree(lbx_extensions[i]->rep_mask); + xfree(lbx_extensions[i]->ev_mask); + xfree(lbx_extensions[i]); + } + xfree(lbx_extensions); + lbx_extensions = NULL; + num_exts = 0; +} + +void +LbxSetReqMask(mask, req, on) + CARD8 *mask; + int req; + Bool on; +{ + int mword = req / (8 * sizeof(CARD8)); + + req = req % (8 * sizeof(CARD8)); + if (on) { + mask[mword] |= (1 << req); + } else { + mask[mword] &= ~(1 << req); + } +} diff --git a/lbx/lbxgfx.c b/lbx/lbxgfx.c new file mode 100644 index 000000000..25e87cc63 --- /dev/null +++ b/lbx/lbxgfx.c @@ -0,0 +1,867 @@ +/* $Xorg: lbxgfx.c,v 1.3 2000/08/17 19:53:31 cpqbld Exp $ */ +/* + * 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. + * + */ + +/* various bits of DIX-level mangling */ + +#include <sys/types.h> +#include <stdio.h> +#define NEED_REPLIES +#define NEED_EVENTS +#include "X.h" +#include "Xproto.h" +#include "misc.h" +#include "os.h" +#include "dixstruct.h" +#include "resource.h" +#include "servermd.h" +#include "windowstr.h" +#include "scrnintstr.h" +#define _XLBX_SERVER_ +#include "lbxstr.h" +#include "lbxserve.h" +#include "lbxtags.h" +#include "Xfuncproto.h" +#include "lbximage.h" +#include "lbxsrvopts.h" + +#define DrawableCache(client) (LbxClient(client)->drawableCache) +#define GContextCache(client) (LbxClient(client)->gcontextCache) + +extern int (*ProcVector[256])(); + +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 XID +use (cache, i) + XID cache[GFX_CACHE_SIZE]; + int i; +{ + XID tmp; + + tmp = cache[i]; + if (i != 0) + { + memmove (cache + 1, cache, i * sizeof (cache[0])); + cache[0] = tmp; + } + return tmp; +} + +extern char *ConnectionInfo; + +int +LbxDecodeGFXCache(client, cacheEnts, after, drawp, gcp) + ClientPtr client; + CARD8 cacheEnts; + char *after; + Drawable *drawp; + GContext *gcp; +{ + int skip; + int dcache, gcache; + + dcache = GFXdCacheEnt (cacheEnts); + gcache = GFXgCacheEnt (cacheEnts); + skip = 0; + if (dcache == GFXCacheNone) + { + memcpy (drawp, after, sizeof (Drawable)); + push (DrawableCache(client), *drawp); + after += sizeof (Drawable); + skip += sizeof (Drawable); + } + else + *drawp = use (DrawableCache(client), dcache); + if (gcache == GFXCacheNone) + { + memcpy (gcp, after, sizeof (GContext)); + push (GContextCache(client), *gcp); + skip += sizeof (GContext); + } + else + *gcp = use (GContextCache(client), gcache); + return skip; +} + +int +LbxDecodeDrawableCache(client, cacheEnts, after, drawp) + ClientPtr client; + CARD8 cacheEnts; + char *after; + Drawable *drawp; +{ + int skip; + int dcache; + + dcache = GFXdCacheEnt (cacheEnts); + skip = 0; + if (dcache == GFXCacheNone) + { + memcpy (drawp, after, sizeof (Drawable)); + push (DrawableCache(client), *drawp); + after += sizeof (Drawable); + skip += sizeof (Drawable); + } + else + *drawp = use (DrawableCache(client), dcache); + return skip; +} + +int +LbxDecodeGCCache(client, cacheEnts, after, gcp) + ClientPtr client; + CARD8 cacheEnts; + char *after; + GContext *gcp; +{ + int skip; + int gcache; + + gcache = GFXgCacheEnt (cacheEnts); + skip = 0; + if (gcache == GFXCacheNone) + { + memcpy (gcp, after, sizeof (GContext)); + push (GContextCache(client), *gcp); + after += sizeof (GContext); + skip += sizeof (GContext); + } + else + *gcp = use (GContextCache(client), gcache); + return skip; +} + +#define GFX_GET_DRAWABLE_AND_GC(type,in,len) {\ + int skip; \ + len = (client->req_len << 2) - SIZEOF(type); \ + in = ((char *) stuff) + SIZEOF(type);\ + skip = LbxDecodeGFXCache(client, stuff->cacheEnts, in, \ + &drawable, &gc); \ + in += skip; \ + len -= skip; \ +} + +#define GFX_GET_DST_DRAWABLE_AND_GC(type,in,len) {\ + int skip; \ + len = (client->req_len << 2) - SIZEOF(type); \ + in = ((char *) stuff) + SIZEOF(type);\ + skip = LbxDecodeGFXCache(client, stuff->cacheEnts, in, \ + &dstDrawable, &gc); \ + in += skip; \ + len -= skip; \ +} + +#define GFX_GET_SRC_DST_DRAWABLE_AND_GC(type, in, len) { \ + int skip; \ + len = (client->req_len << 2) - SIZEOF(type); \ + in = ((char *) stuff) + SIZEOF(type); \ + skip = LbxDecodeDrawableCache(client, stuff->srcCache, in, \ + &srcDrawable); \ + in += skip; \ + len -= skip; \ + skip = LbxDecodeGFXCache(client, stuff->cacheEnts, in, \ + &dstDrawable, &gc); \ + in += skip; \ + len -= skip; \ +} + +#define GFX_GET_GC(type, in, len) { \ + int skip; \ + len = (client->req_len << 2) - SIZEOF(type); \ + in = ((char *) stuff) + SIZEOF(type); \ + skip = LbxDecodeGCCache(client, stuff->gcCache, in, &gc); \ + in += skip; \ + len -= skip; \ +} + +int +LbxDecodePoly(client, xreqtype, decode_rtn) + register ClientPtr client; + CARD8 xreqtype; + int (*decode_rtn)(); +{ + REQUEST(xLbxPolyPointReq); + char *in; + xPolyPointReq *xreq; + int len; + int retval; + Drawable drawable; + GContext gc; + + GFX_GET_DRAWABLE_AND_GC(xLbxPolyPointReq, in, len); + if ((xreq = (xPolyPointReq *) + xalloc(sizeof(xPolyPointReq) + (len << 1))) == NULL) + return BadAlloc; + len = (*decode_rtn)(in, in + len - stuff->padBytes, &xreq[1]); + xreq->reqType = xreqtype; + xreq->coordMode = 1; + xreq->drawable = drawable; + xreq->gc = gc; + xreq->length = client->req_len = (sizeof(xPolyPointReq) + len) >> 2; + client->requestBuffer = (pointer)xreq; + + retval = (*ProcVector[xreqtype])(client); + xfree(xreq); + return retval; +} + +int +LbxDecodeFillPoly(client) + register ClientPtr client; +{ + REQUEST(xLbxFillPolyReq); + char *in; + xFillPolyReq *xreq; + int len; + int retval; + Drawable drawable; + GContext gc; + + GFX_GET_DRAWABLE_AND_GC(xLbxFillPolyReq, in, len); + if ((xreq = (xFillPolyReq *) + xalloc(sizeof(xFillPolyReq) + (len << 1))) == NULL) + return BadAlloc; + len = LbxDecodePoints(in, in + len - stuff->padBytes, (short *) &xreq[1]); + xreq->reqType = X_FillPoly; + xreq->drawable = drawable; + xreq->gc = gc; + xreq->shape = stuff->shape; + xreq->coordMode = 1; + xreq->length = client->req_len = (sizeof(xFillPolyReq) + len) >> 2; + client->requestBuffer = (pointer)xreq; + + retval = (*ProcVector[X_FillPoly])(client); + xfree(xreq); + return retval; +} + +/* + * Routines for decoding line drawing requests + */ + +#define DECODE_PSHORT(in, val) \ + if ((*(in) & 0xf0) != 0xf0) \ + (val) = *(CARD8 *)(in)++; \ + else { \ + (val) = ((*(CARD8 *)(in) & 0x0f) << 8) | *(CARD8 *)((in) + 1); \ + if ((val) >= 0xe00) \ + (val) -= 0x1000; \ + else \ + (val) += 0xf0; \ + (in) += 2; \ + } + +#define DECODE_SHORT(in, val) \ + if ((*(in) & 0xf0) != 0x80) \ + (val) = *(INT8 *)(in)++; \ + else { \ + (val) = ((*(CARD8 *)(in) & 0x0f) << 8) | *(CARD8 *)((in) + 1); \ + if ((val) & 0x0800) \ + (val) = ((val) | 0xf000) - 0x70; \ + else \ + (val) += 0x80; \ + (in) += 2; \ + } + +#define DECODE_USHORT(in, val) \ + if ((*(in) & 0xf0) != 0xf0) \ + (val) = *(CARD8 *)(in)++; \ + else { \ + (val) = (((*(CARD8 *)(in) & 0x0f) << 8) | *(CARD8 *)((in) + 1)) + 0xf0; \ + (in) += 2; \ + } + +#define DECODE_ANGLE(in, val) \ + if (*(INT8 *)(in) >= 0x6e) \ + (val) = (*(INT8 *)(in)++ - 0x67) * (15 << 6); \ + else if (*(INT8 *)(in) >= 0x5a) \ + (val) = (*(INT8 *)(in)++ - 0x5a) * (5 << 6); \ + else if (*(INT8 *)(in) <= (INT8)0x91) \ + (val) = (*(INT8 *)(in)++ - (INT8)0x98) * (15 << 6); \ + else if (*(INT8 *)(in) <= (INT8)0xa5) \ + (val) = (*(INT8 *)(in)++ - (INT8)0xa6) * (5 << 6); \ + else { \ + (val) = (*(CARD8 *)(in) << 8) | *(CARD8 *)((in) + 1); \ + (in) += 2; \ + } + +int +LbxDecodePoints(in, inend, out) + register char *in; + char *inend; + register short *out; +{ + char *start_out = (char *)out; + + while (in < inend) { + DECODE_SHORT(in, *out); + out++; + DECODE_SHORT(in, *out); + out++; + } + return ((char *)out - start_out); +} + +int +LbxDecodeSegment(in, inend, out) + register char *in; + char *inend; + register short *out; +{ + register short diff; + short last_x = 0; + short last_y = 0; + char *start_out = (char *)out; + + while (in < inend) { + DECODE_SHORT(in, diff); + *out = last_x + diff; + last_x += diff; + out++; + DECODE_SHORT(in, diff); + *out = last_y + diff; + last_y += diff; + out++; + + DECODE_SHORT(in, diff); + *out = last_x + diff; + out++; + DECODE_SHORT(in, diff); + *out = last_y + diff; + out++; + } + return ((char *)out - start_out); +} + +int +LbxDecodeRectangle(in, inend, out) + register char *in; + char *inend; + register short *out; +{ + register short diff; + short last_x = 0; + short last_y = 0; + char *start_out = (char *)out; + + while (in < inend) { + DECODE_SHORT(in, diff); + *out = last_x + diff; + last_x += diff; + out++; + DECODE_SHORT(in, diff); + *out = last_y + diff; + last_y += diff; + out++; + + DECODE_USHORT(in, *(unsigned short *)out); + out++; + DECODE_USHORT(in, *(unsigned short *)out); + out++; + } + return ((char *)out - start_out); +} + +int +LbxDecodeArc(in, inend, out) + register char *in; + char *inend; + register short *out; +{ + register short diff; + short last_x = 0; + short last_y = 0; + char *start_out = (char *)out; + + while (in < inend) { + DECODE_SHORT(in, diff); + *out = last_x + diff; + last_x += diff; + out++; + DECODE_SHORT(in, diff); + *out = last_y + diff; + last_y += diff; + out++; + + DECODE_USHORT(in, *(unsigned short *)out); + out++; + DECODE_USHORT(in, *(unsigned short *)out); + out++; + + DECODE_ANGLE(in, *out); + out++; + DECODE_ANGLE(in, *out); + out++; + } + return ((char *)out - start_out); +} + +int +LbxDecodeCopyArea (client) + ClientPtr client; +{ + REQUEST(xLbxCopyAreaReq); + char *in; + xCopyAreaReq req; + int len; + Drawable srcDrawable, dstDrawable; + GContext gc; + + GFX_GET_SRC_DST_DRAWABLE_AND_GC(xLbxCopyAreaReq, in, len); + req.reqType = X_CopyArea; + req.length = client->req_len = SIZEOF(xCopyAreaReq) >> 2; + req.srcDrawable = srcDrawable; + req.dstDrawable = dstDrawable; + req.gc = gc; + DECODE_PSHORT (in, req.srcX); + DECODE_PSHORT (in, req.srcY); + DECODE_PSHORT (in, req.dstX); + DECODE_PSHORT (in, req.dstY); + DECODE_USHORT (in, req.width); + DECODE_USHORT (in, req.height); + client->requestBuffer = (pointer) &req; + return (*ProcVector[X_CopyArea])(client); +} + +int +LbxDecodeCopyPlane (client) + ClientPtr client; +{ + REQUEST(xLbxCopyPlaneReq); + char *in; + xCopyPlaneReq req; + int len; + Drawable srcDrawable, dstDrawable; + GContext gc; + + GFX_GET_SRC_DST_DRAWABLE_AND_GC(xLbxCopyPlaneReq, in, len); + req.reqType = X_CopyPlane; + req.length = client->req_len = SIZEOF(xCopyPlaneReq) >> 2; + req.srcDrawable = srcDrawable; + req.dstDrawable = dstDrawable; + req.gc = gc; + DECODE_PSHORT (in, req.srcX); + DECODE_PSHORT (in, req.srcY); + DECODE_PSHORT (in, req.dstX); + DECODE_PSHORT (in, req.dstY); + DECODE_USHORT (in, req.width); + DECODE_USHORT (in, req.height); + req.bitPlane = stuff->bitPlane; + client->requestBuffer = (pointer) &req; + return (*ProcVector[X_CopyPlane])(client); +} + +static pointer +get_gfx_buffer(client, len) + ClientPtr client; + int len; +{ + LbxClientPtr lbxClient = LbxClient(client); + pointer tmp; + + /* XXX should probably shrink this sucker too */ + if (len > lbxClient->gb_size) { + tmp = (pointer) xrealloc(lbxClient->gfx_buffer, len); + if (!tmp) + return (pointer) NULL; + lbxClient->gfx_buffer = tmp; + lbxClient->gb_size = len; + } + return lbxClient->gfx_buffer; +} + +int +LbxDecodePolyText (client) + ClientPtr client; +{ + REQUEST(xLbxPolyTextReq); + char *in, *pos; + xPolyTextReq *xreq; + int len; + Drawable drawable; + GContext gc; + + GFX_GET_DRAWABLE_AND_GC(xLbxPolyTextReq, in, len); + xreq = (xPolyTextReq *) get_gfx_buffer(client, sizeof (xPolyTextReq) + len); + if (!xreq) + return BadAlloc; + xreq->reqType = stuff->lbxReqType == X_LbxPolyText8? X_PolyText8 : X_PolyText16; + xreq->drawable = drawable; + xreq->gc = gc; + pos = in; + DECODE_PSHORT(in, xreq->x); + DECODE_PSHORT(in, xreq->y); + len -= (in - pos); + memmove ((char *) (xreq + 1), in, len); + xreq->length = client->req_len = (sizeof (xPolyTextReq) + len) >> 2; + client->requestBuffer = (pointer) xreq; + return (*ProcVector[xreq->reqType])(client); +} + +int +LbxDecodeImageText (client) + ClientPtr client; +{ + REQUEST(xLbxImageTextReq); + char *in, *pos; + xImageTextReq *xreq; + int len; + Drawable drawable; + GContext gc; + + GFX_GET_DRAWABLE_AND_GC(xLbxImageTextReq, in, len); + xreq = (xImageTextReq *) get_gfx_buffer(client, sizeof (xImageTextReq) + len); + if (!xreq) + return BadAlloc; + xreq->reqType = stuff->lbxReqType == X_LbxImageText8? X_ImageText8 : X_ImageText16; + xreq->drawable = drawable; + xreq->gc = gc; + xreq->nChars = stuff->nChars; + pos = in; + DECODE_PSHORT(in, xreq->x); + DECODE_PSHORT(in, xreq->y); + len -= (in - pos); + memmove ((char *) (xreq + 1), in, len); + xreq->length = client->req_len = (sizeof (xImageTextReq) + len) >> 2; + client->requestBuffer = (pointer) xreq; + return (*ProcVector[xreq->reqType])(client); +} + +int +LbxDecodePutImage (client) + register ClientPtr client; +{ + REQUEST (xLbxPutImageReq); + char *in, *data; + xPutImageReq xreq; + int ppl, bpl, nbytes; + int retval; + int n; + + xreq.reqType = X_PutImage; + + in = (char *) stuff + sz_xLbxPutImageReq; + + if (stuff->bitPacked & 0x80) { + xreq.format = (stuff->bitPacked >> 5) & 0x3; + xreq.depth = ((stuff->bitPacked >> 2) & 0x7) + 1; + xreq.leftPad = 0; + } else { + xreq.depth = (stuff->bitPacked >> 2) + 1; + xreq.format = (*in >> 5) & 0x3; + xreq.leftPad = *in++ & 0x1f; + } + DECODE_USHORT(in, xreq.width); + DECODE_USHORT(in, xreq.height); + DECODE_PSHORT(in, xreq.dstX); + DECODE_PSHORT(in, xreq.dstY); + if (client->swapped) { + if (GFXdCacheEnt (stuff->cacheEnts) == GFXCacheNone || + GFXgCacheEnt (stuff->cacheEnts) == GFXCacheNone) + { + swapl (in, n); + if (GFXdCacheEnt (stuff->cacheEnts) == GFXCacheNone && + GFXgCacheEnt (stuff->cacheEnts) == GFXCacheNone) + swapl (in + 4, n); + } + } + in += LbxDecodeGFXCache(client, stuff->cacheEnts, in, + &xreq.drawable, &xreq.gc); + + ppl = xreq.width + xreq.leftPad; + if (xreq.format != ZPixmap || + (xreq.depth == 1 && screenInfo.formats->bitsPerPixel == 1)) { +#ifdef INTERNAL_VS_EXTERNAL_PADDING + bpl = BitmapBytePadProto(ppl); +#else + bpl = BitmapBytePad(ppl); +#endif + nbytes = bpl; + if (xreq.format == XYPixmap) + nbytes *= xreq.depth; + } else { +#ifdef INTERNAL_VS_EXTERNAL_PADDING + bpl = PixmapBytePadProto(ppl, xreq.depth); +#else + bpl = PixmapBytePad(ppl, xreq.depth); +#endif + nbytes = bpl; + } + nbytes *= xreq.height; + xreq.length = ((nbytes + 3) >> 2) + (sz_xPutImageReq >> 2); + /* +1 is because fillspan in DecodeFaxG42D seems to go 1 byte too far, + * and I don't want to mess with that code */ + if ((data = (char *) xalloc ((xreq.length << 2) + 1)) == NULL) + return BadAlloc; + + *((xPutImageReq *)data) = xreq; + + if (!stuff->compressionMethod) + { + memcpy(data + sz_xPutImageReq, in, nbytes); + } + else if (xreq.format != ZPixmap || + (xreq.depth == 1 && screenInfo.formats->bitsPerPixel == 1)) + { + LbxBitmapCompMethod *compMethod; + + compMethod = LbxSrvrLookupBitmapCompMethod (LbxProxy(client), + stuff->compressionMethod); + + if (!compMethod) + { + xfree (data); + return (BadValue); + } + else + { + if (!compMethod->inited) + { + if (compMethod->compInit) + (*compMethod->compInit)(); + compMethod->inited = 1; + } + + (*compMethod->decompFunc) ( + (unsigned char *) in, (unsigned char *) data + sz_xPutImageReq, + nbytes, +#if BITMAP_BIT_ORDER != IMAGE_BYTE_ORDER + (ppl + BITMAP_SCANLINE_UNIT - 1) & ~BITMAP_SCANLINE_UNIT, +#else + ppl, +#endif + bpl, + ((xConnSetup *) ConnectionInfo)->bitmapBitOrder == LSBFirst); + } + } + else + { + LbxPixmapCompMethod *compMethod; + + compMethod = LbxSrvrLookupPixmapCompMethod (LbxProxy(client), + stuff->compressionMethod); + + if (!compMethod) + { + xfree (data); + return (BadValue); + } + else + { + if (!compMethod->inited) + { + if (compMethod->compInit) + (*compMethod->compInit)(); + compMethod->inited = 1; + } + + (*compMethod->decompFunc) ( + in, (char *) data + sz_xPutImageReq, + (int) xreq.height, bpl); + } + } + + client->req_len = xreq.length; + client->requestBuffer = (pointer) data; + + retval = (*ProcVector[X_PutImage])(client); + xfree(data); + return retval; +} + +int +LbxDecodeGetImage (client) + register ClientPtr client; +{ + REQUEST (xLbxGetImageReq); + xLbxGetImageReply *reply = NULL; + int lbxLen, xLen, n; + int method, bytes, status; + xGetImageReply *theImage; + + REQUEST_SIZE_MATCH(xLbxGetImageReq); + + status = DoGetImage(client, stuff->format, stuff->drawable, + stuff->x, stuff->y, + (int)stuff->width, (int)stuff->height, + stuff->planeMask, &theImage); + + if (status != Success) + return (status); + + if ((reply = (xLbxGetImageReply *) xalloc ( + sz_xLbxGetImageReply + theImage->length)) == NULL) + { + xfree(theImage); + return (BadAlloc); + } + + if (stuff->format != ZPixmap || + (theImage->depth == 1 && screenInfo.formats->bitsPerPixel == 1)) + { + LbxBitmapCompMethod *compMethod; + + compMethod = LbxSrvrFindPreferredBitmapCompMethod (LbxProxy(client)); + + if (!compMethod) + status = LBX_IMAGE_COMPRESS_NO_SUPPORT; + else + { + if (!compMethod->inited) + { + if (compMethod->compInit) + (*compMethod->compInit)(); + compMethod->inited = 1; + } + + status = (*compMethod->compFunc) ( + (unsigned char *) &theImage[1], + (unsigned char *) &reply[1], + theImage->length, + theImage->length, +#if BITMAP_BIT_ORDER != IMAGE_BYTE_ORDER + (int) (stuff->width + BITMAP_SCANLINE_UNIT - 1) & + ~BITMAP_SCANLINE_UNIT, +#else + (int) stuff->width, +#endif +#ifdef INTERNAL_VS_EXTERNAL_PADDING + BitmapBytePadProto(stuff->width), +#else + BitmapBytePad(stuff->width), +#endif + ((xConnSetup *) ConnectionInfo)->bitmapBitOrder == LSBFirst, + &bytes); + + method = compMethod->methodOpCode; + } + } + else + { + LbxPixmapCompMethod *compMethod; + + compMethod = LbxSrvrFindPreferredPixmapCompMethod ( + LbxProxy(client), (int) stuff->format, theImage->depth); + + if (!compMethod) + status = LBX_IMAGE_COMPRESS_NO_SUPPORT; + else + { + if (!compMethod->inited) + { + if (compMethod->compInit) + (*compMethod->compInit)(); + compMethod->inited = 1; + } + + status = (*compMethod->compFunc) ( + (char *) &theImage[1], + (char *) &reply[1], + theImage->length, + (int) stuff->format, + theImage->depth, + (int) stuff->height, +#ifdef INTERNAL_VS_EXTERNAL_PADDING + PixmapBytePadProto(stuff->width, theImage->depth), +#else + PixmapBytePad(stuff->width, theImage->depth), +#endif + &bytes); + + method = compMethod->methodOpCode; + } + } + + reply->type = X_Reply; + reply->depth = theImage->depth; + reply->sequenceNumber = client->sequence; + reply->visual = theImage->visual; + reply->pad1 = reply->pad2 = reply->pad3 = reply->pad4 = reply->pad5 = 0; + + if (status != LBX_IMAGE_COMPRESS_SUCCESS) + { + reply->compressionMethod = LbxImageCompressNone; + reply->lbxLength = reply->xLength = (theImage->length + 3) >> 2; + } + else + { + reply->compressionMethod = method; + reply->lbxLength = (bytes + 3) >> 2; + reply->xLength = (theImage->length + 3) >> 2; + } + + lbxLen = reply->lbxLength; + xLen = reply->xLength; + + if (client->swapped) + { + swaps (&reply->sequenceNumber, n); + swapl (&reply->lbxLength, n); + swapl (&reply->xLength, n); + swapl (&reply->visual, n); + } + + if (reply->compressionMethod != LbxImageCompressNone) + { + /* + * If the compressed image is greater that 25% of the original + * image, run the GetImage reply through the regular stream + * compressor. Otherwise, just write the compressed image. + */ + + if (lbxLen > (xLen / 4)) + { + WriteToClient (client, + sz_xLbxGetImageReply + (lbxLen << 2), (char *)reply); + } + else + { + UncompressedWriteToClient (client, + sz_xLbxGetImageReply + (lbxLen << 2), (char *)reply); + } + } + else + { + /* + * Write back the original uncompressed image. + */ + + WriteToClient (client, sz_xLbxGetImageReply, (char *)reply); + WriteToClient (client, lbxLen << 2, (char *)&theImage[1]); + } + + xfree (theImage); + + if (reply) + xfree ((char *) reply); + + return (Success); +} diff --git a/lbx/lbxmain.c b/lbx/lbxmain.c new file mode 100644 index 000000000..3fa565fef --- /dev/null +++ b/lbx/lbxmain.c @@ -0,0 +1,1819 @@ +/* $Xorg: lbxmain.c,v 1.4 2001/02/09 02:05:16 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. + * + */ + +#include <sys/types.h> +#define NEED_REPLIES +#define NEED_EVENTS +#include "X.h" +#include "Xproto.h" +#include "Xos.h" +#include "misc.h" +#include "os.h" +#include "dixstruct.h" +#include "resource.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "pixmapstr.h" +#include "gcstruct.h" +#include "extnsionst.h" +#include "servermd.h" +#include "lbxdeltastr.h" +#define _XLBX_SERVER_ +#include "lbxstr.h" +#include "lbxserve.h" +#include "lbximage.h" +#include "lbxsrvopts.h" +#include "Xfuncproto.h" +#include <errno.h> +#ifdef X_NOT_STDC_ENV +extern int errno; +#endif +#include <sys/uio.h> +#include <stdio.h> + +#ifndef X_NOT_POSIX +#include <unistd.h> +#endif + +#define CloseLbxClient 0xff + +#define MAXBYTESDIFF 8 + +extern void LbxAllowMotion(); +extern int LbxDecodePoints(); +extern int LbxDecodeSegment(); +extern int LbxDecodeRectangle(); +extern int LbxDecodeArc(); + +extern int GrabInProgress; + +int LbxWhoAmI = 1; /* + * for lbx zlib library to know who we are + * server = 1 + * proxy = 0 + */ + +int ProcLbxDispatch(); +extern int SProcLbxDispatch(); +static void LbxResetProc(); +static int DecodeLbxDelta(); +static void LbxFreeClient (); +static void LbxShutdownProxy (); + +static LbxProxyPtr proxyList; +unsigned char LbxReqCode; +int LbxEventCode; +static int BadLbxClientCode; +static int uid_seed; + +static int lbxCompressWorkProcCount; + +LbxClientPtr lbxClients[MAXCLIENTS]; + +extern xConnSetupPrefix connSetupPrefix; +extern char *ConnectionInfo; +extern int (*LbxInitialVector[3])(); + +#ifdef DEBUG +int lbxDebug = 0; +#endif + + +void +LbxExtensionInit() +{ + ExtensionEntry *extEntry; + + lbxCompressWorkProcCount = 0; + proxyList = NULL; + uid_seed = 0; + if ((extEntry = AddExtension(LBXNAME, LbxNumberEvents, LbxNumberErrors, + ProcLbxDispatch, SProcLbxDispatch, + LbxResetProc, StandardMinorOpcode))) + { + LbxReqCode = (unsigned char)extEntry->base; + LbxEventCode = extEntry->eventBase; + BadLbxClientCode = extEntry->errorBase + BadLbxClient; + LbxDixInit(); + + LbxCmapInit (); + DeclareExtensionSecurity(LBXNAME, TRUE); + } +} + +/*ARGSUSED*/ +static void +LbxResetProc (extEntry) +ExtensionEntry *extEntry; +{ + LbxResetTags(); + uid_seed = 0; +} + +void +LbxCloseClient (client) + ClientPtr client; +{ + xLbxCloseEvent closeEvent; + ClientPtr master; + LbxProxyPtr proxy; + LbxClientPtr lbxClient = LbxClient(client); + CARD32 id; + + if (!lbxClient) + return; + id = lbxClient->id; + proxy = lbxClient->proxy; + + DBG (DBG_CLIENT, (stderr, "Close client %d\n", client->index)); + LbxFreeClient (client); + if (!id) + { + isItTimeToYield = TRUE; + CloseDownFileDescriptor (client); + LbxShutdownProxy (proxy); + } + else + { + master = NULL; + if (proxy->lbxClients[0]) + master = LbxProxyClient(proxy); + if (master && !master->clientGone) + { + closeEvent.type = LbxEventCode; + closeEvent.lbxType = LbxCloseEvent; + closeEvent.client = id; + closeEvent.sequenceNumber = master->sequence; + closeEvent.pad1 = closeEvent.pad2 = closeEvent.pad3 = + closeEvent.pad4 = closeEvent.pad5 = closeEvent.pad6 = 0; + if (master->swapped) { + int n; + + swaps(&closeEvent.sequenceNumber, n); + swapl(&closeEvent.client, n); + } + WriteToClient(master, sizeof (closeEvent), (char *)&closeEvent); + LbxForceOutput(proxy); + } + } +} + +static int +LbxReencodeEvent(client, proxy, buf) + ClientPtr client; + LbxProxyPtr proxy; + char *buf; +{ + xEvent *ev = (xEvent *)buf; + int n; + lbxMotionCache *motionCache = &proxy->motionCache; + int motionDelta = 0; + Bool swapCache; + xEvent tev, *sev; + + if (ev->u.u.type != MotionNotify) { + if (proxy->dosquishing) + return LbxSquishEvent(buf); + return 0; + } + + /* + * Check if we can generate a motion delta event. + * + * The motion cache contains the last motion event the server sent. + * + * The following are always stored in the cache in the server's + * byte order: + * sequenceNumber, time, rootX, rootY, eventX, eventY + * This is because when determining if we can do a delta, all + * arithmetic must be done using the server'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 + * These fields do not need to be stored in the server's byte order + * because we only use the '==' operator on them. + */ + + if (!proxy->motion_allowed_events) { + DBG(DBG_CLIENT, (stderr, "throttling motion event for client %d\n", client->index)); + return sz_xEvent; + } + proxy->motion_allowed_events--; + + motionCache = &proxy->motionCache; + + if (!client->swapped) + { + swapCache = motionCache->swapped; + sev = ev; + } + else + { + swapCache = !motionCache->swapped; + sev = &tev; + cpswaps (ev->u.keyButtonPointer.rootX, + sev->u.keyButtonPointer.rootX); + cpswaps (ev->u.keyButtonPointer.rootY, + sev->u.keyButtonPointer.rootY); + cpswaps (ev->u.keyButtonPointer.eventX, + sev->u.keyButtonPointer.eventX); + cpswaps (ev->u.keyButtonPointer.eventY, + sev->u.keyButtonPointer.eventY); + cpswaps (ev->u.u.sequenceNumber, + sev->u.u.sequenceNumber); + cpswapl (ev->u.keyButtonPointer.time, + sev->u.keyButtonPointer.time); + } + + if (swapCache) + { + swapl (&motionCache->root, n); + swapl (&motionCache->event, n); + swapl (&motionCache->child, n); + swaps (&motionCache->state, n); + + motionCache->swapped = !motionCache->swapped; + } + + motionDelta = 0; + + if (ev->u.u.detail == motionCache->detail && + 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) { + + int root_delta_x = + sev->u.keyButtonPointer.rootX - motionCache->rootX; + int root_delta_y = + sev->u.keyButtonPointer.rootY - motionCache->rootY; + int event_delta_x = + sev->u.keyButtonPointer.eventX - motionCache->eventX; + int event_delta_y = + sev->u.keyButtonPointer.eventY - motionCache->eventY; + unsigned long sequence_delta = + sev->u.u.sequenceNumber - motionCache->sequenceNumber; + unsigned long time_delta = + sev->u.keyButtonPointer.time - motionCache->time; + + if (root_delta_x == event_delta_x && + event_delta_x >= -128 && event_delta_x < 128 && + root_delta_y == event_delta_y && + event_delta_y >= -128 && event_delta_y < 128) { + + if (sequence_delta == 0 && time_delta < 256) { + + lbxQuickMotionDeltaEvent *mev = + (lbxQuickMotionDeltaEvent *)(buf + sz_xEvent - + sz_lbxQuickMotionDeltaEvent); + + mev->type = LbxEventCode + LbxQuickMotionDeltaEvent; + mev->deltaTime = time_delta; + mev->deltaX = event_delta_x; + mev->deltaY = event_delta_y; + + motionDelta = sz_xEvent - sz_lbxQuickMotionDeltaEvent; + + } else if (sequence_delta < 65536 && time_delta < 65536) { + + lbxMotionDeltaEvent *mev = + (lbxMotionDeltaEvent *)(buf + sz_xEvent - + sz_lbxMotionDeltaEvent); + + mev->type = LbxEventCode; + mev->lbxType = LbxMotionDeltaEvent; + mev->deltaTime = time_delta; + mev->deltaSequence = sequence_delta; + mev->deltaX = event_delta_x; + mev->deltaY = event_delta_y; + + if (LbxProxyClient(proxy)->swapped) + { + swaps (&mev->deltaTime, n); + swaps (&mev->deltaSequence, n); + } + + motionDelta = sz_xEvent - sz_lbxMotionDeltaEvent; + } + } + } + + motionCache->sequenceNumber = sev->u.u.sequenceNumber; + motionCache->time = sev->u.keyButtonPointer.time; + motionCache->rootX = sev->u.keyButtonPointer.rootX; + motionCache->rootY = sev->u.keyButtonPointer.rootY; + motionCache->eventX = sev->u.keyButtonPointer.eventX; + motionCache->eventY = sev->u.keyButtonPointer.eventY; + + if (motionDelta) + return motionDelta; + + ev->u.keyButtonPointer.pad1 = 0; + motionCache->detail = ev->u.u.detail; + motionCache->root = ev->u.keyButtonPointer.root; + motionCache->event = ev->u.keyButtonPointer.event; + motionCache->child = ev->u.keyButtonPointer.child; + motionCache->state = ev->u.keyButtonPointer.state; + motionCache->sameScreen = ev->u.keyButtonPointer.sameScreen; + return 0; +} + +static int +LbxComposeDelta(proxy, reply, len, buf) + LbxProxyPtr proxy; + char *reply; + int len; + char *buf; +{ + int diffs; + int cindex; + int n; + xLbxDeltaReq *p = (xLbxDeltaReq *)buf; + + diffs = LBXDeltaMinDiffs(&proxy->outdeltas, reply, len, + min(MAXBYTESDIFF, (len - sz_xLbxDeltaReq) >> 1), + &cindex); + if (diffs < 0) { + LBXAddDeltaOut(&proxy->outdeltas, reply, len); + return 0; + } + LBXEncodeDelta(&proxy->outdeltas, reply, diffs, cindex, + &buf[sz_xLbxDeltaReq]); + LBXAddDeltaOut(&proxy->outdeltas, reply, len); + p->reqType = LbxEventCode; + p->lbxReqType = LbxDeltaEvent; + p->diffs = diffs; + p->cindex = cindex; + len = (sz_xLbxDeltaReq + sz_xLbxDiffItem * diffs + 3) & ~3; + p->length = len >> 2; + if (LbxProxyClient(proxy)->swapped) { + swaps(&p->length, n); + } + return len; +} + +void +LbxReencodeOutput(client, pbuf, pcount, cbuf, ccount) + ClientPtr client; + char *pbuf; + int *pcount; + char *cbuf; + int *ccount; +{ + LbxClientPtr lbxClient = LbxClient(client); + LbxProxyPtr proxy = lbxClient->proxy; + CARD32 len; + int n; + int count = *ccount; + char *obuf = cbuf; + + if (client->clientState != ClientStateRunning) { + if (DELTA_CACHEABLE(&proxy->outdeltas, count) && + (n = LbxComposeDelta(proxy, cbuf, count, proxy->oDeltaBuf))) { + memcpy(obuf, proxy->oDeltaBuf, n); + *ccount -= (count - n); + } + return; + } + if (lbxClient->bytes_remaining) { + if (count < lbxClient->bytes_remaining) { + lbxClient->bytes_remaining -= count; + return; + } + if (DELTA_CACHEABLE(&proxy->outdeltas, lbxClient->bytes_in_reply)) { + len = lbxClient->bytes_in_reply - lbxClient->bytes_remaining; + pbuf += (*pcount - len); + memcpy(proxy->replyBuf, pbuf, len); + memcpy(proxy->replyBuf + len, cbuf, lbxClient->bytes_remaining); + n = LbxComposeDelta(proxy, proxy->replyBuf, + lbxClient->bytes_in_reply, proxy->oDeltaBuf); + if (!n) + obuf += lbxClient->bytes_remaining; + else if (n <= len) { + memcpy(pbuf, proxy->oDeltaBuf, n); + *pcount -= (len - n); + *ccount -= lbxClient->bytes_remaining; + } else { + memcpy(pbuf, proxy->oDeltaBuf, len); + memcpy(obuf, proxy->oDeltaBuf + len, n - len); + *ccount -= lbxClient->bytes_remaining - (n - len); + obuf += n - len; + } + } else + obuf += lbxClient->bytes_remaining; + cbuf += lbxClient->bytes_remaining; + count -= lbxClient->bytes_remaining; + lbxClient->bytes_remaining = 0; + } + while (count) { + lbxClient->bytes_in_reply = sz_xEvent; + if (((xGenericReply *)cbuf)->type == X_Reply) { + len = ((xGenericReply *)cbuf)->length; + if (client->swapped) { + swapl(&len, n); + } + lbxClient->bytes_in_reply += (len << 2); + if (LbxProxyClient(proxy)->swapped != client->swapped) { + swapl(&((xGenericReply *)cbuf)->length, n); + } + if (count < lbxClient->bytes_in_reply) { + lbxClient->bytes_remaining = lbxClient->bytes_in_reply - count; + if (obuf != cbuf) + memmove(obuf, cbuf, count); + return; + } + } else if (((xGenericReply *)cbuf)->type > X_Reply && + ((xGenericReply *)cbuf)->type < LASTEvent && + (n = LbxReencodeEvent(client, proxy, cbuf))) { + cbuf += n; + *ccount -= n; + count -= n; + if (n == sz_xEvent) + continue; + lbxClient->bytes_in_reply -= n; + } + if (DELTA_CACHEABLE(&proxy->outdeltas, lbxClient->bytes_in_reply) && + (n = LbxComposeDelta(proxy, cbuf, lbxClient->bytes_in_reply, + proxy->oDeltaBuf))) { + memcpy(obuf, proxy->oDeltaBuf, n); + obuf += n; + *ccount -= (lbxClient->bytes_in_reply - n); + } else { + if (obuf != cbuf) + memmove(obuf, cbuf, lbxClient->bytes_in_reply); + obuf += lbxClient->bytes_in_reply; + } + cbuf += lbxClient->bytes_in_reply; + count -= lbxClient->bytes_in_reply; + } +} + +/*ARGSUSED*/ +static void +LbxReplyCallback(pcbl, nulldata, calldata) + CallbackListPtr *pcbl; + pointer nulldata; + pointer calldata; +{ + ReplyInfoRec *pri = (ReplyInfoRec *)calldata; + ClientPtr client = pri->client; + LbxClientPtr lbxClient; + REQUEST(xReq); + + if (!pri->startOfReply || stuff->reqType > 127) + return; + lbxClient = LbxClient(client); + if (lbxClient) + ZeroReplyPadBytes(pri->replyData, stuff->reqType); +} + +/* + * XXX If you think this is moronic, you're in good company, + * but things definitely hang if we don't have this. + */ +/* ARGSUSED */ +static Bool +LbxCheckCompressInput (dummy1, dummy2) + ClientPtr dummy1; + pointer dummy2; +{ + LbxProxyPtr proxy; + + if (!lbxCompressWorkProcCount) + return TRUE; + + for (proxy = proxyList; proxy; proxy = proxy->next) { + if (proxy->compHandle && + proxy->streamOpts.streamCompInputAvail(proxy->fd)) + AvailableClientInput (LbxProxyClient(proxy)); + } + return FALSE; +} + +static Bool +LbxIsClientBlocked (lbxClient) + LbxClientPtr lbxClient; +{ + LbxProxyPtr proxy = lbxClient->proxy; + + return (lbxClient->ignored || + (GrabInProgress && lbxClient->client->index != GrabInProgress && + lbxClient != proxy->lbxClients[0])); +} + +static void +LbxSwitchRecv (proxy, lbxClient) + LbxProxyPtr proxy; + LbxClientPtr lbxClient; +{ + ClientPtr client; + + proxy->curRecv = lbxClient; + if (!lbxClient || lbxClient->client->clientGone) + { + DBG(DBG_CLIENT, (stderr, "switching to dispose input\n")); + lbxClient = proxy->lbxClients[0]; + if (!lbxClient) + return; + } + client = lbxClient->client; + DBG (DBG_SWITCH, (stderr, "switching input to client %d\n", client->index)); + + SwitchClientInput (client, FALSE); + proxy->curDix = lbxClient; +} + +/* ARGSUSED */ +static Bool +LbxWaitForUnblocked (client, closure) + ClientPtr client; + pointer closure; +{ + LbxClientPtr lbxClient; + LbxProxyPtr proxy; + + if (client->clientGone) + return TRUE; + lbxClient = LbxClient(client); + if (!lbxClient) + return TRUE; + proxy = lbxClient->proxy; + if (LbxIsClientBlocked (lbxClient) || + ((lbxClient != proxy->curDix) && proxy->curDix->reqs_pending && + !LbxIsClientBlocked(proxy->curDix))) + return FALSE; + lbxClient->input_blocked = FALSE; + DBG (DBG_BLOCK, (stderr, "client %d no longer blocked, switching\n", + client->index)); + SwitchClientInput (client, TRUE); + proxy->curDix = lbxClient; + return TRUE; +} + +void +LbxSetForBlock(lbxClient) + LbxClientPtr lbxClient; +{ + lbxClient->reqs_pending++; + if (!lbxClient->input_blocked) + { + lbxClient->input_blocked = TRUE; + QueueWorkProc(LbxWaitForUnblocked, lbxClient->client, NULL); + } +} + +/* ARGSUSED */ +static int +LbxWaitForUngrab (client, closure) + ClientPtr client; + pointer closure; +{ + LbxClientPtr lbxClient = LbxClient(client); + LbxProxyPtr proxy; + xLbxListenToAllEvent ungrabEvent; + + if (client->clientGone || !lbxClient) + return TRUE; + if (GrabInProgress) + return FALSE; + proxy = lbxClient->proxy; + proxy->grabClient = 0; + ungrabEvent.type = LbxEventCode; + ungrabEvent.lbxType = LbxListenToAll; + ungrabEvent.pad1 = ungrabEvent.pad2 = ungrabEvent.pad3 = + ungrabEvent.pad4 = ungrabEvent.pad5 = ungrabEvent.pad6 = + ungrabEvent.pad7 = 0; + WriteToClient (client, + sizeof(xLbxListenToAllEvent), (char *)&ungrabEvent); + LbxForceOutput(proxy); + return TRUE; +} + +static void +LbxServerGrab(proxy) + LbxProxyPtr proxy; +{ + LbxClientPtr grabbingLbxClient; + xLbxListenToOneEvent grabEvent; + + /* + * If the current grabbing client has changed, then we need + * to send a message to update the proxy. + */ + + grabEvent.type = LbxEventCode; + grabEvent.lbxType = LbxListenToOne; + if (!(grabbingLbxClient = lbxClients[GrabInProgress]) || + grabbingLbxClient->proxy != proxy) + grabEvent.client = 0xffffffff; /* client other than a proxy client */ + else + grabEvent.client = grabbingLbxClient->id; + grabEvent.pad1 = grabEvent.pad2 = grabEvent.pad3 = + grabEvent.pad4 = grabEvent.pad5 = grabEvent.pad6 = 0; + if (LbxProxyClient(proxy)->swapped) { + int n; + swapl(&grabEvent.client, n); + } + WriteToClient(LbxProxyClient(proxy), + sizeof(xLbxListenToOneEvent), (char *)&grabEvent); + LbxForceOutput(proxy); + if (!proxy->grabClient) + QueueWorkProc(LbxWaitForUngrab, LbxProxyClient(proxy), NULL); + proxy->grabClient = GrabInProgress; +} + +#define MAJOROP(client) ((xReq *)client->requestBuffer)->reqType +#define MINOROP(client) ((xReq *)client->requestBuffer)->data + +static Bool lbxCacheable[] = { + FALSE, /* LbxQueryVersion 0 */ + FALSE, /* LbxStartProxy 1 */ + TRUE, /* LbxStopProxy 2 */ + FALSE, /* LbxSwitch 3 */ + FALSE, /* LbxNewClient 4 */ + TRUE, /* LbxCloseClient 5 */ + TRUE, /* LbxModifySequence 6 */ + FALSE, /* LbxAllowMotion 7 */ + TRUE, /* LbxIncrementPixel 8 */ + FALSE, /* LbxDelta 9 */ + TRUE, /* LbxGetModifierMapping 10 */ + FALSE, /* nothing 11 */ + TRUE, /* LbxInvalidateTag 12 */ + TRUE, /* LbxPolyPoint 13 */ + TRUE, /* LbxPolyLine 14 */ + TRUE, /* LbxPolySegment 15 */ + TRUE, /* LbxPolyRectangle 16 */ + TRUE, /* LbxPolyArc 17 */ + TRUE, /* LbxFillPoly 18 */ + TRUE, /* LbxPolyFillRectangle 19 */ + TRUE, /* LbxPolyFillArc 20 */ + TRUE, /* LbxGetKeyboardMapping 21 */ + TRUE, /* LbxQueryFont 22 */ + TRUE, /* LbxChangeProperty 23 */ + TRUE, /* LbxGetProperty 24 */ + TRUE, /* LbxTagData 25 */ + TRUE, /* LbxCopyArea 26 */ + TRUE, /* LbxCopyPlane 27 */ + TRUE, /* LbxPolyText8 28 */ + TRUE, /* LbxPolyText16 29 */ + TRUE, /* LbxImageText8 30 */ + TRUE, /* LbxImageText16 31 */ + FALSE, /* LbxQueryExtension 32 */ + TRUE, /* LbxPutImage 33 */ + TRUE, /* LbxGetImage 34 */ + FALSE, /* LbxBeginLargeRequest 35 */ + FALSE, /* LbxLargeRequestData 36 */ + FALSE, /* LbxEndLargeRequest 37 */ + FALSE, /* LbxInternAtoms 38 */ + TRUE, /* LbxGetWinAttrAndGeom 39 */ + TRUE, /* LbxGrabCmap 40 */ + TRUE, /* LbxReleaseCmap 41 */ + TRUE, /* LbxAllocColor 42 */ + TRUE, /* LbxSync 43 */ +}; + +#define NUM(a) (sizeof (a) / sizeof (a[0])) + +static int +LbxReadRequestFromClient (client) + ClientPtr client; +{ + int ret; + LbxClientPtr lbxClient = LbxClient(client); + LbxProxyPtr proxy = lbxClient->proxy; + ClientPtr masterClient = LbxProxyClient(proxy); + Bool isblocked; + Bool cacheable; + + DBG (DBG_READ_REQ, (stderr, "Reading request from client %d\n", client->index)); + + if (GrabInProgress && (proxy->grabClient != GrabInProgress)) + LbxServerGrab(proxy); + isblocked = LbxIsClientBlocked(lbxClient); + + if (lbxClient->reqs_pending && !isblocked) { + ret = StandardReadRequestFromClient(client); + if (ret > 0 && (MAJOROP(client) == LbxReqCode) && + (MINOROP(client) == X_LbxEndLargeRequest)) + ret = PrepareLargeReqBuffer(client); + if (!--lbxClient->reqs_pending && (lbxClient != proxy->curRecv)) + LbxSwitchRecv (proxy, proxy->curRecv); + return ret; + } + while (1) { + ret = StandardReadRequestFromClient(masterClient); + if (ret <= 0) + return ret; + client->requestBuffer = masterClient->requestBuffer; + client->req_len = masterClient->req_len; + cacheable = client->clientState == ClientStateRunning; + if (cacheable && (MAJOROP(client) == LbxReqCode)) { + /* Check to see if this request is delta cached */ + if (MINOROP(client) < NUM(lbxCacheable)) + cacheable = lbxCacheable[MINOROP(client)]; + switch (MINOROP(client)) { + case X_LbxSwitch: + /* Switch is sent by proxy */ + if (masterClient->swapped) + SProcLbxSwitch (client); + else + ProcLbxSwitch (client); + return 0; + case X_LbxDelta: + ret = DecodeLbxDelta (client); + DBG(DBG_DELTA, + (stderr,"delta decompressed msg %d, len = %d\n", + (unsigned)((unsigned char *)client->requestBuffer)[0], + ret)); + break; + case X_LbxEndLargeRequest: + if (!isblocked) + ret = PrepareLargeReqBuffer(client); + break; + } + } + if (cacheable && DELTA_CACHEABLE(&proxy->indeltas, ret)) { + DBG(DBG_DELTA, + (stderr, "caching msg %d, len = %d, index = %d\n", + (unsigned)((unsigned char *)client->requestBuffer)[0], + ret, proxy->indeltas.nextDelta)); + LBXAddDeltaIn(&proxy->indeltas, client->requestBuffer, ret); + } + if (client->swapped != masterClient->swapped) { + char n; + /* put length in client order */ + swaps(&((xReq *)client->requestBuffer)->length, n); + } + if (!isblocked) + return ret; + DBG (DBG_BLOCK, (stderr, "Stashing %d bytes for %d\n", + ret, client->index)); + AppendFakeRequest (client, client->requestBuffer, ret); + LbxSetForBlock(lbxClient); + } +} + +static LbxClientPtr +LbxInitClient (proxy, client, id) + LbxProxyPtr proxy; + ClientPtr client; + CARD32 id; +{ + LbxClientPtr lbxClient; + int i; + + lbxClient = (LbxClientPtr) xalloc (sizeof (LbxClientRec)); + if (!lbxClient) + return NULL; + lbxClient->id = id; + lbxClient->client = client; + lbxClient->proxy = proxy; + lbxClient->ignored = FALSE; + lbxClient->input_blocked = FALSE; + lbxClient->reqs_pending = 0; + lbxClient->bytes_in_reply = 0; + lbxClient->bytes_remaining = 0; + client->readRequest = LbxReadRequestFromClient; + bzero (lbxClient->drawableCache, sizeof (lbxClient->drawableCache)); + bzero (lbxClient->gcontextCache, sizeof (lbxClient->gcontextCache)); + lbxClients[client->index] = lbxClient; + for (i = 0; proxy->lbxClients[i]; i++) + ; + if (i > proxy->maxIndex) + proxy->maxIndex = i; + proxy->lbxClients[i] = lbxClient; + proxy->numClients++; + lbxClient->gfx_buffer = (pointer) NULL; + lbxClient->gb_size = 0; + return lbxClient; +} + +static void +LbxFreeClient (client) + ClientPtr client; +{ + LbxClientPtr lbxClient = LbxClient(client); + LbxProxyPtr proxy = lbxClient->proxy; + int i; + + if (lbxClient != proxy->lbxClients[0]) { + if (lbxClient == proxy->curRecv) + LbxSwitchRecv(proxy, NULL); + else if (lbxClient == proxy->curDix) + LbxSwitchRecv(proxy, proxy->curRecv); + } + + --proxy->numClients; + lbxClients[client->index] = NULL; + for (i = 0; i <= proxy->maxIndex; i++) { + if (proxy->lbxClients[i] == lbxClient) { + proxy->lbxClients[i] = NULL; + break; + } + } + while (proxy->maxIndex >= 0 && !proxy->lbxClients[proxy->maxIndex]) + --proxy->maxIndex; + xfree(lbxClient->gfx_buffer); + client->readRequest = StandardReadRequestFromClient; + xfree (lbxClient); +} + +static void +LbxFreeProxy (proxy) + LbxProxyPtr proxy; +{ + LbxProxyPtr *p; + + LBXFreeDeltaCache(&proxy->indeltas); + LBXFreeDeltaCache(&proxy->outdeltas); + LbxFreeOsBuffers(proxy); + if (proxy->iDeltaBuf) + xfree(proxy->iDeltaBuf); + if (proxy->replyBuf) + xfree(proxy->replyBuf); + if (proxy->oDeltaBuf) + xfree(proxy->oDeltaBuf); + if (proxy->compHandle) + proxy->streamOpts.streamCompFreeHandle(proxy->compHandle); + if (proxy->bitmapCompMethods) + xfree (proxy->bitmapCompMethods); + if (proxy->pixmapCompMethods) + xfree (proxy->pixmapCompMethods); + if (proxy->pixmapCompDepths) + { + int i; + for (i = 0; i < proxy->numPixmapCompMethods; i++) + xfree (proxy->pixmapCompDepths[i]); + xfree (proxy->pixmapCompDepths); + } + + for (p = &proxyList; *p; p = &(*p)->next) { + if (*p == proxy) { + *p = proxy->next; + break; + } + } + if (!proxyList) + DeleteCallback(&ReplyCallback, LbxReplyCallback, NULL); + + xfree (proxy); +} + +LbxProxyPtr +LbxPidToProxy(pid) + int pid; +{ + LbxProxyPtr proxy; + + for (proxy = proxyList; proxy; proxy = proxy->next) { + if (proxy->pid == pid) + return proxy; + } + return NULL; +} + +static void +LbxShutdownProxy (proxy) + LbxProxyPtr proxy; +{ + int i; + ClientPtr client; + + if (proxy->compHandle) + --lbxCompressWorkProcCount; + while (proxy->grabbedCmaps) + LbxReleaseCmap(proxy->grabbedCmaps, FALSE); + for (i = 0; i <= proxy->maxIndex; i++) + { + if (proxy->lbxClients[i]) + { + client = proxy->lbxClients[i]->client; + if (!client->clientGone) + CloseDownClient (client); + } + } + LbxFlushTags(proxy); + LbxFreeProxy(proxy); +} + + +int +ProcLbxQueryVersion(client) + register ClientPtr client; +{ + REQUEST(xLbxQueryVersionReq); + xLbxQueryVersionReply rep; + register int n; + + REQUEST_SIZE_MATCH(xLbxQueryVersionReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.majorVersion = LBX_MAJOR_VERSION; + rep.minorVersion = LBX_MINOR_VERSION; + rep.pad0 = rep.pad1 = rep.pad2 = rep.pad3 = rep.pad4 = 0; + + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swaps(&rep.majorVersion, n); + swaps(&rep.minorVersion, n); + } + WriteToClient(client, sizeof(xLbxQueryVersionReply), (char *)&rep); + return (client->noClientException); +} + +static int +NextProxyID() +{ + LbxProxyPtr proxy; + int id; + + for (id = 1; id < MAX_NUM_PROXIES; id++) { + for (proxy = proxyList; proxy && proxy->pid != id; proxy = proxy->next) + ; + if (!proxy) + return id; + } + return -1; +} + +int +ProcLbxStartProxy(client) + register ClientPtr client; +{ + REQUEST(xLbxStartProxyReq); + LbxProxyPtr proxy; + LbxClientPtr lbxClient; + int reqlen; + int replylen; + xLbxStartReply *replybuf; + LbxNegOptsRec negopt; + register int n; + pointer compHandle = NULL; + + REQUEST_AT_LEAST_SIZE(xLbxStartProxyReq); + if (lbxClients[client->index]) + return BadLbxClientCode; + proxy = (LbxProxyPtr) xalloc (sizeof (LbxProxyRec)); + if (!proxy) + return BadAlloc; + bzero(proxy, sizeof (LbxProxyRec)); + proxy->pid = NextProxyID(); + if (proxy->pid < 0) { /* too many proxies */ + xfree(proxy); + return BadAlloc; + } + proxy->uid = ++uid_seed; + if (!proxyList) + AddCallback(&ReplyCallback, LbxReplyCallback, NULL); + + if(!proxyList) + proxyList = proxy; + else{ + proxy->next = proxyList; + proxyList = proxy; + } + + /* + * Don't know exactly how big the reply will be, but it won't be + * bigger than the request + */ + reqlen = client->req_len << 2; + replybuf = (xLbxStartReply *) xalloc(max(reqlen, sz_xLbxStartReply)); + if (!replybuf) { + LbxFreeProxy(proxy); + return BadAlloc; + } + + LbxOptionInit(&negopt); + + replylen = LbxOptionParse(&negopt, + &stuff[1], + reqlen - sz_xLbxStartProxyReq, + &replybuf->optDataStart); + if (replylen < 0) { + /* + * Didn't understand option format, so we'll just end up + * using the defaults. Set nopts so that the proxy will + * be informed that we rejected the options because of + * decoding problems. + */ + LbxOptionInit(&negopt); + negopt.nopts = 0xff; + replylen = 0; + } + + if (LBXInitDeltaCache(&proxy->indeltas, negopt.proxyDeltaN, + negopt.proxyDeltaMaxLen) < 0 + || + LBXInitDeltaCache(&proxy->outdeltas, negopt.serverDeltaN, + negopt.serverDeltaMaxLen) < 0) { + LbxFreeProxy(proxy); + xfree(replybuf); + return BadAlloc; + } + + n = 0; + if (negopt.proxyDeltaN) + n = negopt.proxyDeltaMaxLen; + if (negopt.serverDeltaN && negopt.serverDeltaMaxLen > n) + n = negopt.serverDeltaMaxLen; + if (n && + (!(proxy->iDeltaBuf = (char *)xalloc (n)) || + !(proxy->replyBuf = (char *)xalloc (n)) || + !(proxy->oDeltaBuf = (char *)xalloc (n)))) { + LbxFreeProxy(proxy); + xfree(replybuf); + return BadAlloc; + } + + MakeClientGrabImpervious(client); /* proxy needs to be grab-proof */ + proxy->fd = ClientConnectionNumber(client); + if (negopt.streamOpts.streamCompInit) { + compHandle = + (*negopt.streamOpts.streamCompInit)(proxy->fd, negopt.streamOpts.streamCompArg); + if (!compHandle) { + LbxFreeProxy(proxy); + xfree(replybuf); + return BadAlloc; + } + } + proxy->ofirst = NULL; + proxy->olast = NULL; + if (!LbxInitClient (proxy, client, 0)) + { + LbxFreeProxy(proxy); + xfree(replybuf); + return BadAlloc; + } + proxy->dosquishing = negopt.squish; + proxy->numBitmapCompMethods = negopt.numBitmapCompMethods; + proxy->bitmapCompMethods = negopt.bitmapCompMethods; + proxy->numPixmapCompMethods = negopt.numPixmapCompMethods; + proxy->pixmapCompMethods = negopt.pixmapCompMethods; + proxy->pixmapCompDepths = negopt.pixmapCompDepths; + + proxy->streamOpts = negopt.streamOpts; + proxy->useTags = negopt.useTags; + + proxy->grabbedCmaps = NULL; + + /* send reply */ + replybuf->type = X_Reply; + replybuf->nOpts = negopt.nopts; + replybuf->sequenceNumber = client->sequence; + + replylen += sz_xLbxStartReplyHdr; + if (replylen < sz_xLbxStartReply) + replylen = sz_xLbxStartReply; + replybuf->length = (replylen - sz_xLbxStartReply + 3) >> 2; + if (client->swapped) { + swaps(&replybuf->sequenceNumber, n); + swapl(&replybuf->length, n); + } + lbxClient = LbxClient(client); + WriteToClient(client, replylen, (char *)replybuf); + + LbxProxyConnection(client, proxy); + lbxClient = proxy->lbxClients[0]; + proxy->curDix = lbxClient; + proxy->curRecv = lbxClient; + proxy->compHandle = compHandle; + + if (proxy->compHandle && !lbxCompressWorkProcCount++) + QueueWorkProc(LbxCheckCompressInput, NULL, NULL); + + xfree(replybuf); + return Success; +} + +int +ProcLbxStopProxy(client) + register ClientPtr client; +{ + REQUEST(xLbxStopProxyReq); + LbxProxyPtr proxy; + LbxClientPtr lbxClient = LbxClient(client); + + REQUEST_SIZE_MATCH(xLbxStopProxyReq); + + if (!lbxClient) + return BadLbxClientCode; + if (lbxClient->id) + return BadLbxClientCode; + + proxy = lbxClient->proxy; + LbxFreeClient (client); + LbxShutdownProxy (proxy); + return Success; +} + +int +ProcLbxSwitch(client) + register ClientPtr client; +{ + REQUEST(xLbxSwitchReq); + LbxProxyPtr proxy = LbxMaybeProxy(client); + LbxClientPtr lbxClient; + int i; + + REQUEST_SIZE_MATCH(xLbxSwitchReq); + if (!proxy) + return BadLbxClientCode; + for (i = 0; i <= proxy->maxIndex; i++) { + lbxClient = proxy->lbxClients[i]; + if (lbxClient && lbxClient->id == stuff->client) { + LbxSwitchRecv (proxy, lbxClient); + return Success; + } + } + LbxSwitchRecv (proxy, NULL); + return BadLbxClientCode; +} + +int +ProcLbxBeginLargeRequest(client) + register ClientPtr client; +{ + REQUEST(xLbxBeginLargeRequestReq); + + client->sequence--; + REQUEST_SIZE_MATCH(xLbxBeginLargeRequestReq); + if (!AllocateLargeReqBuffer(client, stuff->largeReqLength << 2)) + return BadAlloc; + return Success; +} + + +int +ProcLbxLargeRequestData(client) + register ClientPtr client; +{ + REQUEST(xLbxLargeRequestDataReq); + + client->sequence--; + REQUEST_AT_LEAST_SIZE(xLbxLargeRequestDataReq); + if (!AddToLargeReqBuffer(client, (char *) (stuff + 1), + (client->req_len - 1) << 2)) + return BadAlloc; + return Success; +} + + +int +ProcLbxEndLargeRequest(client) + register ClientPtr client; +{ + REQUEST(xReq); + + client->sequence--; + REQUEST_SIZE_MATCH(xReq); + return BadAlloc; +} + + +int +ProcLbxInternAtoms(client) + register ClientPtr client; +{ + REQUEST(xLbxInternAtomsReq); + LbxClientPtr lbxClient = LbxClient(client); + xLbxInternAtomsReply *replyRet; + char *ptr = (char *) stuff + sz_xLbxInternAtomsReq; + Atom *atomsRet; + int replyLen, i; + char lenbuf[2]; + CARD16 len; + char n; + + REQUEST_AT_LEAST_SIZE(xLbxInternAtomsReq); + + if (!lbxClient) + return BadLbxClientCode; + if (lbxClient->id) + return BadLbxClientCode; + + replyLen = sz_xLbxInternAtomsReplyHdr + stuff->num * sizeof (Atom); + if (replyLen < sz_xLbxInternAtomsReply) + replyLen = sz_xLbxInternAtomsReply; + + if (!(replyRet = (xLbxInternAtomsReply *) xalloc (replyLen))) + return BadAlloc; + + atomsRet = (Atom *) ((char *) replyRet + sz_xLbxInternAtomsReplyHdr); + + for (i = 0; i < stuff->num; i++) + { + lenbuf[0] = ptr[0]; + lenbuf[1] = ptr[1]; + len = *((CARD16 *) lenbuf); + ptr += 2; + + if ((atomsRet[i] = MakeAtom (ptr, len, TRUE)) == BAD_RESOURCE) + { + xfree (replyRet); + return BadAlloc; + } + + ptr += len; + } + + if (client->swapped) + for (i = 0; i < stuff->num; i++) + swapl (&atomsRet[i], n); + + replyRet->type = X_Reply; + replyRet->sequenceNumber = client->sequence; + replyRet->length = (replyLen - sz_xLbxInternAtomsReply + 3) >> 2; + + if (client->swapped) { + swaps(&replyRet->sequenceNumber, n); + swapl(&replyRet->length, n); + } + + WriteToClient (client, replyLen, (char *) replyRet); + + xfree (replyRet); + + return Success; +} + + +int +ProcLbxGetWinAttrAndGeom(client) + register ClientPtr client; +{ + REQUEST(xLbxGetWinAttrAndGeomReq); + xGetWindowAttributesReply wa; + xGetGeometryReply wg; + xLbxGetWinAttrAndGeomReply reply; + WindowPtr pWin; + int status; + + REQUEST_SIZE_MATCH(xLbxGetWinAttrAndGeomReq); + pWin = (WindowPtr)SecurityLookupWindow(stuff->id, client, + SecurityReadAccess); + if (!pWin) + return(BadWindow); + GetWindowAttributes(pWin, client, &wa); + + if ((status = GetGeometry(client, &wg)) != Success) + return status; + + reply.type = X_Reply; + reply.length = (sz_xLbxGetWinAttrAndGeomReply - 32) >> 2; + reply.sequenceNumber = client->sequence; + + reply.backingStore = wa.backingStore; + reply.visualID = wa.visualID; +#if defined(__cplusplus) || defined(c_plusplus) + reply.c_class = wa.c_class; +#else + reply.class = wa.class; +#endif + reply.bitGravity = wa.bitGravity; + reply.winGravity = wa.winGravity; + reply.backingBitPlanes = wa.backingBitPlanes; + reply.backingPixel = wa.backingPixel; + reply.saveUnder = wa.saveUnder; + reply.mapInstalled = wa.mapInstalled; + reply.mapState = wa.mapState; + reply.override = wa.override; + reply.colormap = wa.colormap; + reply.allEventMasks = wa.allEventMasks; + reply.yourEventMask = wa.yourEventMask; + reply.doNotPropagateMask = wa.doNotPropagateMask; + reply.pad1 = 0; + reply.root = wg.root; + reply.x = wg.x; + reply.y = wg.y; + reply.width = wg.width; + reply.height = wg.height; + reply.borderWidth = wg.borderWidth; + reply.depth = wg.depth; + reply.pad2 = 0; + + if (client->swapped) + { + register char n; + + swaps(&reply.sequenceNumber, n); + swapl(&reply.length, n); + swapl(&reply.visualID, n); + swaps(&reply.class, n); + swapl(&reply.backingBitPlanes, n); + swapl(&reply.backingPixel, n); + swapl(&reply.colormap, n); + swapl(&reply.allEventMasks, n); + swapl(&reply.yourEventMask, n); + swaps(&reply.doNotPropagateMask, n); + swapl(&reply.root, n); + swaps(&reply.x, n); + swaps(&reply.y, n); + swaps(&reply.width, n); + swaps(&reply.height, n); + swaps(&reply.borderWidth, n); + } + + WriteToClient(client, sizeof(xLbxGetWinAttrAndGeomReply), (char *)&reply); + return(client->noClientException); +} + +int +ProcLbxNewClient(client) + register ClientPtr client; +{ + REQUEST(xLbxNewClientReq); + ClientPtr newClient; + LbxProxyPtr proxy = LbxMaybeProxy(client); + CARD32 id; + int len, i; + char *setupbuf; + LbxClientPtr lbxClient; + + REQUEST_AT_LEAST_SIZE(xLbxNewClientReq); + + /* save info before our request disappears */ + id = stuff->client; + if (!proxy || !id) + return BadLbxClientCode; + if (proxy->numClients == MAX_LBX_CLIENTS) + return BadAlloc; + for (i = 1; i <= proxy->maxIndex; i++) { + if (proxy->lbxClients[i] && proxy->lbxClients[i]->id == id) + return BadLbxClientCode; + } + len = (client->req_len << 2) - sizeof(xLbxNewClientReq); + setupbuf = (char *)xalloc (len); + if (!setupbuf) + return BadAlloc; + memcpy (setupbuf, (char *)&stuff[1], len); + + newClient = AllocLbxClientConnection (client, proxy); + if (!newClient) + return BadAlloc; + newClient->requestVector = LbxInitialVector; + lbxClient = LbxInitClient (proxy, newClient, id); + if (!lbxClient) + { + CloseDownClient (newClient); + return BadAlloc; + } + + AppendFakeRequest (newClient, setupbuf, len); + xfree (setupbuf); + LbxSetForBlock(lbxClient); + + DBG (DBG_CLIENT, (stderr, "lbxNewClient X %d\n", newClient->index)); + return Success; +} + +int +ProcLbxEstablishConnection(client) + register ClientPtr client; +{ + char *reason = NULL; + char *auth_proto, *auth_string; + register xConnClientPrefix *prefix; + REQUEST(xReq); + + prefix = (xConnClientPrefix *)((char *)stuff + sz_xReq); + auth_proto = (char *)prefix + sz_xConnClientPrefix; + auth_string = auth_proto + ((prefix->nbytesAuthProto + 3) & ~3); + if ((prefix->majorVersion != X_PROTOCOL) || + (prefix->minorVersion != X_PROTOCOL_REVISION)) + reason = "Protocol version mismatch"; + else + reason = ClientAuthorized(client, + prefix->nbytesAuthProto, + auth_proto, + prefix->nbytesAuthString, + auth_string); + + if (client->clientState == ClientStateCheckingSecurity || + client->clientState == ClientStateAuthenticating) + return (client->noClientException = -1); /* XXX some day */ + return(LbxSendConnSetup(client, reason)); +} + +int +ProcLbxCloseClient (client) + register ClientPtr client; +{ + REQUEST(xLbxCloseClientReq); + LbxClientPtr lbxClient = LbxClient(client); + + REQUEST_SIZE_MATCH(xLbxCloseClientReq); + if (!lbxClient || lbxClient->id != stuff->client) + return BadLbxClientCode; + + /* this will cause the client to be closed down back in Dispatch() */ + return(client->noClientException = CloseLbxClient); +} + +int +ProcLbxModifySequence (client) + register ClientPtr client; +{ + REQUEST(xLbxModifySequenceReq); + + REQUEST_SIZE_MATCH(xLbxModifySequenceReq); + client->sequence += (stuff->adjust - 1); /* Dispatch() adds 1 */ + return Success; +} + +int +ProcLbxAllowMotion (client) + register ClientPtr client; +{ + REQUEST(xLbxAllowMotionReq); + + client->sequence--; + REQUEST_SIZE_MATCH(xLbxAllowMotionReq); + LbxAllowMotion(client, stuff->num); + return Success; +} + + +static int +DecodeLbxDelta(client) + register ClientPtr client; +{ + REQUEST(xLbxDeltaReq); + LbxClientPtr lbxClient = LbxClient(client); + LbxProxyPtr proxy = lbxClient->proxy; + int len; + char *buf; + + /* Note that LBXDecodeDelta decodes and adds current msg to the cache */ + len = LBXDecodeDelta(&proxy->indeltas, ((char *)stuff) + sz_xLbxDeltaReq, + stuff->diffs, stuff->cindex, &buf); + /* + * Some requests, such as FillPoly, result in the protocol input + * buffer being modified. So we need to copy the request + * into a temporary buffer where a write would be harmless. + * Maybe some day do this copying on a case by case basis, + * since not all requests are guilty of this. + */ + memcpy(proxy->iDeltaBuf, buf, len); + + client->requestBuffer = proxy->iDeltaBuf; + client->req_len = len >> 2; + return len; +} + +int +ProcLbxGetModifierMapping(client) + ClientPtr client; +{ + REQUEST(xLbxGetModifierMappingReq); + + REQUEST_SIZE_MATCH(xLbxGetModifierMappingReq); + return LbxGetModifierMapping(client); +} + +int +ProcLbxGetKeyboardMapping(client) + ClientPtr client; +{ + REQUEST(xLbxGetKeyboardMappingReq); + + REQUEST_SIZE_MATCH(xLbxGetKeyboardMappingReq); + return LbxGetKeyboardMapping(client); +} + +int +ProcLbxQueryFont(client) + ClientPtr client; +{ + REQUEST(xLbxQueryFontReq); + + REQUEST_SIZE_MATCH(xLbxQueryFontReq); + return LbxQueryFont(client); +} + +int +ProcLbxChangeProperty(client) + ClientPtr client; +{ + REQUEST(xLbxChangePropertyReq); + + REQUEST_SIZE_MATCH(xLbxChangePropertyReq); + return LbxChangeProperty(client); +} + +int +ProcLbxGetProperty(client) + ClientPtr client; +{ + REQUEST(xLbxGetPropertyReq); + + REQUEST_SIZE_MATCH(xLbxGetPropertyReq); + return LbxGetProperty(client); +} + +int +ProcLbxTagData(client) + ClientPtr client; +{ + REQUEST(xLbxTagDataReq); + + client->sequence--; /* not a counted request */ + REQUEST_AT_LEAST_SIZE(xLbxTagDataReq); + + return LbxTagData(client, stuff->tag, stuff->real_length, + (pointer)&stuff[1]); /* better not give any errors */ +} + +int +ProcLbxInvalidateTag(client) + ClientPtr client; +{ + REQUEST(xLbxInvalidateTagReq); + + client->sequence--; + REQUEST_SIZE_MATCH(xLbxInvalidateTagReq); + return LbxInvalidateTag(client, stuff->tag); +} + +int +ProcLbxPolyPoint(client) + register ClientPtr client; +{ + return LbxDecodePoly(client, X_PolyPoint, LbxDecodePoints); +} + +int +ProcLbxPolyLine(client) + register ClientPtr client; +{ + return LbxDecodePoly(client, X_PolyLine, LbxDecodePoints); +} + +int +ProcLbxPolySegment(client) + register ClientPtr client; +{ + return LbxDecodePoly(client, X_PolySegment, LbxDecodeSegment); +} + +int +ProcLbxPolyRectangle(client) + register ClientPtr client; +{ + return LbxDecodePoly(client, X_PolyRectangle, LbxDecodeRectangle); +} + +int +ProcLbxPolyArc(client) + register ClientPtr client; +{ + return LbxDecodePoly(client, X_PolyArc, LbxDecodeArc); +} + +int +ProcLbxFillPoly(client) + register ClientPtr client; +{ + return LbxDecodeFillPoly(client); +} + +int +ProcLbxPolyFillRectangle(client) + register ClientPtr client; +{ + return LbxDecodePoly(client, X_PolyFillRectangle, LbxDecodeRectangle); +} + +int +ProcLbxPolyFillArc(client) + register ClientPtr client; +{ + return LbxDecodePoly(client, X_PolyFillArc, LbxDecodeArc); +} + +int +ProcLbxCopyArea (client) + register ClientPtr client; +{ + return LbxDecodeCopyArea(client); +} + +int +ProcLbxCopyPlane (client) + register ClientPtr client; +{ + return LbxDecodeCopyPlane(client); +} + + +int +ProcLbxPolyText (client) + register ClientPtr client; +{ + return LbxDecodePolyText(client); +} + +int +ProcLbxImageText (client) + register ClientPtr client; +{ + return LbxDecodeImageText(client); +} + +int +ProcLbxQueryExtension(client) + ClientPtr client; +{ + REQUEST(xLbxQueryExtensionReq); + char *ename; + + REQUEST_AT_LEAST_SIZE(xLbxQueryExtensionReq); + ename = (char *) &stuff[1]; + return LbxQueryExtension(client, ename, stuff->nbytes); +} + +int +ProcLbxPutImage(client) + register ClientPtr client; +{ + return LbxDecodePutImage(client); +} + +int +ProcLbxGetImage(client) + register ClientPtr client; +{ + return LbxDecodeGetImage(client); +} + + +int +ProcLbxSync(client) + register ClientPtr client; +{ + xLbxSyncReply reply; + + client->sequence--; /* not a counted request */ + +#ifdef COLOR_DEBUG + fprintf (stderr, "Got LBX sync, seq = 0x%x\n", client->sequence); +#endif + + reply.type = X_Reply; + reply.length = 0; + reply.sequenceNumber = client->sequence; + reply.pad0 = reply.pad1 = reply.pad2 = reply.pad3 = reply.pad4 = + reply.pad5 = reply.pad6 = 0; + + if (client->swapped) + { + register char n; + swaps (&reply.sequenceNumber, n); + } + + WriteToClient (client, sz_xLbxSyncReply, (char *)&reply); + + return (client->noClientException); +} + + +int +ProcLbxDispatch (client) + register ClientPtr client; +{ + REQUEST(xReq); + switch (stuff->data) + { + case X_LbxQueryVersion: + return ProcLbxQueryVersion(client); + case X_LbxStartProxy: + return ProcLbxStartProxy(client); + case X_LbxStopProxy: + return ProcLbxStopProxy(client); + case X_LbxNewClient: + return ProcLbxNewClient(client); + case X_LbxCloseClient: + return ProcLbxCloseClient(client); + case X_LbxModifySequence: + return ProcLbxModifySequence(client); + case X_LbxAllowMotion: + return ProcLbxAllowMotion(client); + case X_LbxIncrementPixel: + return ProcLbxIncrementPixel(client); + case X_LbxGrabCmap: + return ProcLbxGrabCmap(client); + case X_LbxReleaseCmap: + return ProcLbxReleaseCmap(client); + case X_LbxAllocColor: + return ProcLbxAllocColor(client); + case X_LbxGetModifierMapping: + return ProcLbxGetModifierMapping(client); + case X_LbxGetKeyboardMapping: + return ProcLbxGetKeyboardMapping(client); + case X_LbxInvalidateTag: + return ProcLbxInvalidateTag(client); + case X_LbxPolyPoint: + return ProcLbxPolyPoint (client); + case X_LbxPolyLine: + return ProcLbxPolyLine (client); + case X_LbxPolySegment: + return ProcLbxPolySegment (client); + case X_LbxPolyRectangle: + return ProcLbxPolyRectangle (client); + case X_LbxPolyArc: + return ProcLbxPolyArc (client); + case X_LbxFillPoly: + return ProcLbxFillPoly (client); + case X_LbxPolyFillRectangle: + return ProcLbxPolyFillRectangle (client); + case X_LbxPolyFillArc: + return ProcLbxPolyFillArc (client); + case X_LbxQueryFont: + return ProcLbxQueryFont (client); + case X_LbxChangeProperty: + return ProcLbxChangeProperty (client); + case X_LbxGetProperty: + return ProcLbxGetProperty (client); + case X_LbxTagData: + return ProcLbxTagData (client); + case X_LbxCopyArea: + return ProcLbxCopyArea (client); + case X_LbxCopyPlane: + return ProcLbxCopyPlane (client); + case X_LbxPolyText8: + case X_LbxPolyText16: + return ProcLbxPolyText (client); + case X_LbxImageText8: + case X_LbxImageText16: + return ProcLbxImageText (client); + case X_LbxQueryExtension: + return ProcLbxQueryExtension (client); + case X_LbxPutImage: + return ProcLbxPutImage (client); + case X_LbxGetImage: + return ProcLbxGetImage (client); + case X_LbxInternAtoms: + return ProcLbxInternAtoms(client); + case X_LbxGetWinAttrAndGeom: + return ProcLbxGetWinAttrAndGeom(client); + case X_LbxSync: + return ProcLbxSync(client); + case X_LbxBeginLargeRequest: + return ProcLbxBeginLargeRequest(client); + case X_LbxLargeRequestData: + return ProcLbxLargeRequestData(client); + case X_LbxEndLargeRequest: + return ProcLbxLargeRequestData(client); + default: + return BadRequest; + } +} diff --git a/lbx/lbxopts.c b/lbx/lbxopts.c new file mode 100644 index 000000000..fe9af687e --- /dev/null +++ b/lbx/lbxopts.c @@ -0,0 +1,817 @@ +/* $Xorg: lbxopts.c,v 1.3 2000/08/17 19:53:31 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. + * + */ + +#ifdef OPTDEBUG +#include <stdio.h> +#endif +#include "X.h" +#include "Xproto.h" +#include "misc.h" +#include "lbxserve.h" +#include "lbxstr.h" +#include "lbximage.h" +#include "lbxopts.h" +#include "lbxsrvopts.h" +#ifndef NO_ZLIB +#include "lbxzlib.h" +#endif /* NO_ZLIB */ + +static int LbxDeltaOpt(); +static int LbxProxyDeltaOpt(); +static int LbxServerDeltaOpt(); +static int LbxStreamCompOpt(); +static int LbxBitmapCompOpt(); +static int LbxPixmapCompOpt(); +static int LbxMessageCompOpt(); +static int LbxUseTagsOpt(); +static int LbxCmapAllOpt(); + +/* + * List of LBX options we recognize and are willing to negotiate + */ +static struct _LbxOptionParser { + CARD8 optcode; + int (*parser)(); +} LbxOptions[] = { + { LBX_OPT_DELTA_PROXY, LbxProxyDeltaOpt }, + { LBX_OPT_DELTA_SERVER, LbxServerDeltaOpt }, + { LBX_OPT_STREAM_COMP, LbxStreamCompOpt }, + { LBX_OPT_BITMAP_COMP, LbxBitmapCompOpt }, + { LBX_OPT_PIXMAP_COMP, LbxPixmapCompOpt }, + { LBX_OPT_MSG_COMP, LbxMessageCompOpt }, + { LBX_OPT_USE_TAGS, LbxUseTagsOpt }, + { LBX_OPT_CMAP_ALL, LbxCmapAllOpt } +}; + +#define LBX_N_OPTS (sizeof(LbxOptions) / sizeof(struct _LbxOptionParser)) + +/* + * Set option defaults + */ +LbxOptionInit(pno) + LbxNegOptsPtr pno; +{ + bzero(pno, sizeof(LbxNegOptsRec)); + pno->proxyDeltaN = pno->serverDeltaN = LBX_OPT_DELTA_NCACHE_DFLT; + pno->proxyDeltaMaxLen = pno->serverDeltaMaxLen = LBX_OPT_DELTA_MSGLEN_DFLT; + pno->squish = TRUE; + pno->numBitmapCompMethods = 0; + pno->bitmapCompMethods = NULL; + pno->numPixmapCompMethods = 0; + pno->pixmapCompMethods = NULL; + pno->pixmapCompDepths = NULL; + pno->useTags = TRUE; +} + +int +LbxOptionParse(pno, popt, optlen, preply) + LbxNegOptsPtr pno; + unsigned char *popt; + int optlen; + unsigned char *preply; +{ + int i; + int nopts = *popt++; + unsigned char *pout = preply; + + for (i = 0; i < nopts; i++) { + int j; + int len; + int hdrlen; + int replylen; + + LBX_OPT_DECODE_LEN(popt + 1, len, hdrlen); + if (len < ++hdrlen || len > optlen) { +#ifdef OPTDEBUG + fprintf(stderr, "bad option length, len = %d, hdrlen = %d, optlen = %d\n", len, hdrlen, optlen); +#endif + return -1; + } + + for (j = 0; j < LBX_N_OPTS; j++) { + if (popt[0] == LbxOptions[j].optcode) { + replylen = (*LbxOptions[j].parser)(pno, + popt + hdrlen, + len - hdrlen, + pout + LBX_OPT_SMALLHDR_LEN); + if (replylen < 0) + return -1; + else if (replylen > 0) { + /* + * None of the current options require big headers, + * so this works for now. + */ + *pout++ = i; + *pout++ = LBX_OPT_SMALLHDR_LEN + replylen; + pout += replylen; + pno->nopts++; + } + break; + } + } + + optlen -= len; + popt += len; + } + + return (pout - preply); +} + +static int +LbxProxyDeltaOpt(pno, popt, optlen, preply) + LbxNegOptsPtr pno; + unsigned char *popt; + int optlen; + unsigned char *preply; +{ + return LbxDeltaOpt(popt, optlen, preply, + &pno->proxyDeltaN, &pno->proxyDeltaMaxLen); +} + +static int +LbxServerDeltaOpt(pno, popt, optlen, preply) + LbxNegOptsPtr pno; + unsigned char *popt; + int optlen; + unsigned char *preply; +{ + return LbxDeltaOpt(popt, optlen, preply, + &pno->serverDeltaN, &pno->serverDeltaMaxLen); +} + +static int +LbxDeltaOpt(popt, optlen, preply, pn, pmaxlen) + unsigned char *popt; + int optlen; + unsigned char *preply; + short *pn; + short *pmaxlen; +{ + short n; + short maxlen; + + /* + * If there's more data than we expect, we just ignore it. + */ + if (optlen < LBX_OPT_DELTA_REQLEN) { +#ifdef OPTDEBUG + fprintf(stderr, "bad delta option length = %d\n", optlen); +#endif + return -1; + } + + /* + * Accept whatever value the proxy prefers, so skip the + * min/max offerings. Note that the max message len value is + * encoded as the number of 4-byte values. + */ + popt += 2; + n = *popt++; + popt += 2; + maxlen = *popt++; + if ((maxlen <<= 2) == 0) + n = 0; + else if (maxlen < 32) { +#ifdef OPTDEBUG + fprintf(stderr, "bad delta max msg length %d\n", maxlen); +#endif + return -1; + } + + /* + * Put the response in the reply buffer + */ + *preply++ = n; + *preply++ = maxlen >> 2; + + *pn = n; + *pmaxlen = maxlen; + + return LBX_OPT_DELTA_REPLYLEN; +} + +static int ZlibParse(); + +static struct _LbxStreamCompParser { + int typelen; + char *type; + int (*parser)(); +} LbxStreamComp[] = { +#ifndef NO_ZLIB + { ZLIB_STRCOMP_OPT_LEN, ZLIB_STRCOMP_OPT, ZlibParse }, +#endif /* NO_ZLIB */ +}; + +#define LBX_N_STRCOMP \ + (sizeof(LbxStreamComp) / sizeof(struct _LbxStreamCompParser)) + +static int +LbxStreamCompOpt(pno, popt, optlen, preply) + LbxNegOptsPtr pno; + unsigned char *popt; + int optlen; + unsigned char *preply; +{ + int i; + int typelen; + int nopts = *popt++; + + for (i = 0; i < nopts; i++) { + int j; + int len; + int lensize; + int replylen; + + typelen = popt[0]; + for (j = 0; j < LBX_N_STRCOMP; j++) { + if (typelen == LbxStreamComp[j].typelen && + !strncmp((char *) popt + 1, LbxStreamComp[j].type, typelen)) + break; + } + + popt += 1 + typelen; + optlen -= 1 + typelen; + LBX_OPT_DECODE_LEN(popt, len, lensize); + + if (j < LBX_N_STRCOMP) { + if (len > optlen) + return -1; + replylen = (*LbxStreamComp[j].parser)(pno, + popt + lensize, + len - lensize, + preply + 1); + if (replylen == -1) + return -1; + else if (replylen >= 0) { + *preply = i; + return replylen + 1; + } + } + + optlen -= len; + popt += len; + } + + return 0; +} + + +extern LbxStreamCompHandle ZlibInit(); +extern int ZlibStuffInput(), ZlibInputAvail(), ZlibFlush(), + ZlibRead(), ZlibWriteV(); +extern void ZlibCompressOn(), ZlibCompressOff(), ZlibFree(); + + +static int +ZlibParse(pno, popt, optlen, preply) + LbxNegOptsPtr pno; + unsigned char *popt; + int optlen; + unsigned char *preply; +{ + int level; /* compression level */ + + if (*popt++ != 1) /* length should be 1 */ + return (-1); + + level = *popt; + if (level < 1 || level > 9) + return (-1); + + pno->streamOpts.streamCompInit = ZlibInit; + pno->streamOpts.streamCompArg = (pointer) level; + pno->streamOpts.streamCompStuffInput = ZlibStuffInput; + pno->streamOpts.streamCompInputAvail = ZlibInputAvail; + pno->streamOpts.streamCompFlush = ZlibFlush; + pno->streamOpts.streamCompRead = ZlibRead; + pno->streamOpts.streamCompWriteV = ZlibWriteV; + pno->streamOpts.streamCompOn = ZlibCompressOn; + pno->streamOpts.streamCompOff = ZlibCompressOff; + pno->streamOpts.streamCompFreeHandle = ZlibFree; + + return (0); +} + +static int +LbxMessageCompOpt(pno, popt, optlen, preply) + LbxNegOptsPtr pno; + unsigned char *popt; + int optlen; + unsigned char *preply; +{ + + if (optlen == 0) { +#ifdef OPTDEBUG + fprintf(stderr, "bad message-comp option length specified %d\n", optlen); +#endif + return -1; + } + + pno->squish = *preply = *popt; + return 1; +} + + +static int +LbxUseTagsOpt(pno, popt, optlen, preply) + LbxNegOptsPtr pno; + unsigned char *popt; + int optlen; + unsigned char *preply; +{ + + if (optlen == 0) { +#ifdef OPTDEBUG + fprintf(stderr, "bad use-tags option length specified %d\n", optlen); +#endif + return -1; + } + + pno->useTags = *preply = *popt; + return 1; +} + + +/* + * Option negotiation for image compression + */ + +LbxBitmapCompMethod +LbxBitmapCompMethods [] = { + { + "XC-FaxG42D", /* compression method name */ + 0, /* inited */ + 2, /* method opcode */ + NULL, /* init function */ + LbxImageEncodeFaxG42D, /* encode function */ + LbxImageDecodeFaxG42D /* decode function */ + } +}; + +#define NUM_BITMAP_METHODS \ + (sizeof (LbxBitmapCompMethods) / sizeof (LbxBitmapCompMethod)) + + +#if 1 +/* + * 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 +LbxPixmapCompMethod LbxPixmapCompMethods [1]; /* dummy */ + +#else + +LbxPixmapCompMethod +LbxPixmapCompMethods [] = { + { + "XC-PackBits", /* compression method name */ + 1 << ZPixmap, /* formats supported */ + 1, {8}, /* depths supported */ + 0, /* inited */ + 1, /* method opcode */ + NULL, /* init function */ + LbxImageEncodePackBits, /* encode function */ + LbxImageDecodePackBits /* decode function */ + } +}; + +#define NUM_PIXMAP_METHODS \ + (sizeof (LbxPixmapCompMethods) / sizeof (LbxPixmapCompMethod)) +#endif + +static int MergeDepths (); + + +static int +LbxImageCompOpt (pixmap, pno, popt, optlen, preply) + +Bool pixmap; +LbxNegOptsPtr pno; +unsigned char *popt; +int optlen; +unsigned char *preply; + +{ + unsigned char *preplyStart = preply; + int numMethods = *popt++; + char *myIndices, *hisIndices; + unsigned *retFormats; + int **retDepths; + int replyCount = 0; + int status, i, j; + + if (numMethods == 0) + { + if (pixmap) + pno->numPixmapCompMethods = 0; + else + pno->numBitmapCompMethods = 0; + + *preply++ = 0; + return (1); + } + + myIndices = (char *) xalloc (numMethods); + hisIndices = (char *) xalloc (numMethods); + + if (!myIndices || !hisIndices) + { + if (myIndices) + xfree (myIndices); + if (hisIndices) + xfree (hisIndices); + return -1; + } + + if (pixmap) + { + retFormats = (unsigned *) xalloc (numMethods); + retDepths = (int **) xalloc (numMethods * sizeof (int *)); + + if (!retFormats || !retDepths) + { + if (retFormats) + xfree (retFormats); + if (retDepths) + xfree (retDepths); + xfree (myIndices); + xfree (hisIndices); + return -1; + } + } + + /* + * For each method in the list sent by the proxy, see if the server + * supports this method. If YES, update the following lists: + * + * myIndices[] is a list of indices into the server's + * LbxBit[Pix]mapCompMethods table. + * + * hisIndices[] is a list of indices into the list of + * method names sent by the proxy. + * + * retFormats[] indicates for each pixmap compression method, + * the pixmap formats supported. + * + * retDepths[] indicates for each pixmap compression method, + * the pixmap depths supported. + */ + + for (i = 0; i < numMethods; i++) + { + unsigned formatMask, newFormatMask; + int depthCount, *depths, len; + int freeDepths; + char *methodName; + + freeDepths = 0; + len = *popt++; + methodName = (char *) popt; + popt += len; + + if (pixmap) + { + formatMask = *popt++; + depthCount = *popt++; + depths = (int *) xalloc ((depthCount + 1) * sizeof (int)); + freeDepths = 1; + depths[0] = depthCount; + for (j = 1; j <= depthCount; j++) + depths[j] = *popt++; + } + + for (j = 0; + j < (pixmap ? NUM_PIXMAP_METHODS : NUM_BITMAP_METHODS); j++) + { + + status = strncmp (methodName, + (pixmap ? LbxPixmapCompMethods[j].methodName : + LbxBitmapCompMethods[j].methodName), + len); + + if (status == 0 && pixmap) + { + newFormatMask = + formatMask & LbxPixmapCompMethods[j].formatMask; + + depthCount = MergeDepths (depths, &LbxPixmapCompMethods[j]); + + if (newFormatMask == 0 || depthCount == 0) + status = 1; + } + + if (status == 0) + { + myIndices[replyCount] = j; + hisIndices[replyCount] = i; + + if (pixmap) + { + retFormats[replyCount] = newFormatMask; + retDepths[replyCount] = depths; + freeDepths = 0; + } + + replyCount++; + break; + } + } + + if (freeDepths) + xfree (depths); + } + + *preply++ = replyCount; + + /* + * Sort the lists by LBX server preference (increasing myIndices[] vals) + */ + + for (i = 0; i <= replyCount - 2; i++) + for (j = replyCount - 1; j >= i; j--) + if (myIndices[j - 1] > myIndices[j]) + { + char temp1 = myIndices[j - 1]; + char temp2 = hisIndices[j - 1]; + + myIndices[j - 1] = myIndices[j]; + myIndices[j] = temp1; + + hisIndices[j - 1] = hisIndices[j]; + hisIndices[j] = temp2; + + if (pixmap) + { + unsigned temp3 = retFormats[j - 1]; + int *temp4 = retDepths[j - 1]; + + retFormats[j - 1] = retFormats[j]; + retFormats[j] = temp3; + + retDepths[j - 1] = retDepths[j]; + retDepths[j] = temp4; + } + } + + /* + * For each method supported, return to the proxy an index into + * the list sent by the proxy, the opcode to be used for the method, + * the pixmap formats supported, and the list of depths supported. + */ + + for (i = 0; i < replyCount; i++) + { + *preply++ = hisIndices[i]; + + if (pixmap) + { + int left; + *preply++ = LbxPixmapCompMethods[myIndices[i]].methodOpCode; + *preply++ = retFormats[i]; + *preply++ = left = retDepths[i][0]; + j = 1; + while (left > 0) + { + *preply++ = retDepths[i][j]; + left--; + } + } + else + { + *preply++ = LbxBitmapCompMethods[myIndices[i]].methodOpCode; + } + } + + if (pixmap) + { + pno->numPixmapCompMethods = replyCount; + pno->pixmapCompMethods = myIndices; + pno->pixmapCompDepths = retDepths; + } + else + { + pno->numBitmapCompMethods = replyCount; + pno->bitmapCompMethods = myIndices; + } + + if (hisIndices) + xfree (hisIndices); + + if (pixmap) + { + if (retFormats) + xfree (retFormats); + } + + return (preply - preplyStart); +} + + + +static int +LbxBitmapCompOpt (pno, popt, optlen, preply) + +LbxNegOptsPtr pno; +unsigned char *popt; +int optlen; +unsigned char *preply; + +{ + return (LbxImageCompOpt (0 /* bitmap */, pno, popt, optlen, preply)); +} + + +static int +LbxPixmapCompOpt (pno, popt, optlen, preply) + +LbxNegOptsPtr pno; +unsigned char *popt; +int optlen; +unsigned char *preply; + +{ + return (LbxImageCompOpt (1 /* Pixmap */, pno, popt, optlen, preply)); +} + + +LbxBitmapCompMethod * +LbxSrvrLookupBitmapCompMethod (proxy, methodOpCode) + +LbxProxyPtr proxy; +int methodOpCode; + +{ + int i; + + for (i = 0; i < proxy->numBitmapCompMethods; i++) + { + LbxBitmapCompMethod *method; + + method = &LbxBitmapCompMethods[proxy->bitmapCompMethods[i]]; + + if (method->methodOpCode == methodOpCode) + return (method); + } + + return (NULL); +} + + +LbxPixmapCompMethod * +LbxSrvrLookupPixmapCompMethod (proxy, methodOpCode) + +LbxProxyPtr proxy; +int methodOpCode; + +{ + int i; + + for (i = 0; i < proxy->numPixmapCompMethods; i++) + { + LbxPixmapCompMethod *method; + + method = &LbxPixmapCompMethods[proxy->pixmapCompMethods[i]]; + + if (method->methodOpCode == methodOpCode) + return (method); + } + + return (NULL); +} + + +LbxBitmapCompMethod * +LbxSrvrFindPreferredBitmapCompMethod (proxy) + +LbxProxyPtr proxy; + +{ + if (proxy->numBitmapCompMethods == 0) + return NULL; + else + return (&LbxBitmapCompMethods[proxy->bitmapCompMethods[0]]); +} + + + +LbxPixmapCompMethod * +LbxSrvrFindPreferredPixmapCompMethod (proxy, format, depth) + +LbxProxyPtr proxy; +int format; +int depth; + +{ + if (proxy->numPixmapCompMethods == 0) + return NULL; + else + { + LbxPixmapCompMethod *method; + int i, j; + + for (i = 0; i < proxy->numPixmapCompMethods; i++) + { + method = &LbxPixmapCompMethods[proxy->pixmapCompMethods[i]]; + + if ((method->formatMask & (1 << format))) + { + int n = proxy->pixmapCompDepths[i][0]; + j = 1; + while (n > 0) + { + if (depth == proxy->pixmapCompDepths[i][j]) + return method; + else + n--; + } + } + } + + return NULL; + } +} + + +static int MergeDepths (depths, method) + +int *depths; +LbxPixmapCompMethod *method; + +{ + int i, j, count; + int temp[LBX_MAX_DEPTHS + 1]; + + temp[0] = count = 0; + + for (i = 1; i <= depths[0]; i++) + { + for (j = 0; j < method->depthCount; j++) + if (method->depths[j] == depths[i]) + { + temp[0]++; + temp[++count] = depths[i]; + break; + } + } + + memcpy (depths, temp, (count + 1) * sizeof (int)); + + return (count); +} + + +#define LbxCmapAllMethod "XC-CMAP" + +static int +LbxCmapAllOpt (pno, popt, optlen, preply) + +LbxNegOptsPtr pno; +unsigned char *popt; +int optlen; +unsigned char *preply; + +{ + int numMethods = *popt++; + int i; + + for (i = 0; i < numMethods; i++) + { + int len; + char *methodName; + + len = *popt++; + methodName = (char *) popt; + popt += len; + if (!strncmp(methodName, LbxCmapAllMethod, len)) + break; + } + if (i >= numMethods) + i = 0; /* assume first one is proxy's favorite */ + *preply = i; + return 1; +} diff --git a/lbx/lbxprop.c b/lbx/lbxprop.c new file mode 100644 index 000000000..b70fade72 --- /dev/null +++ b/lbx/lbxprop.c @@ -0,0 +1,552 @@ +/* $Xorg: lbxprop.c,v 1.4 2001/02/09 02:05:17 xorgcvs Exp $ */ +/* + +Copyright 1986, 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. + * + */ + +/* various bits of DIX-level mangling */ + +#include <sys/types.h> +#include <stdio.h> +#define NEED_REPLIES +#define NEED_EVENTS +#include "X.h" +#include "Xproto.h" +#include "misc.h" +#include "os.h" +#include "dixstruct.h" +#include "resource.h" +#include "servermd.h" +#include "propertyst.h" +#include "windowstr.h" +#define _XLBX_SERVER_ +#include "lbxstr.h" +#include "lbxserve.h" +#include "lbxtags.h" +#include "Xfuncproto.h" +#ifdef XCSECURITY +#define _SECURITY_SERVER +#include "extensions/security.h" +#endif + +extern int (*ProcVector[256]) (); +extern void (*ReplySwapVector[256]) (); +extern void CopySwap16Write(), CopySwap32Write(), Swap32Write(); + +void +LbxStallPropRequest(client, pProp) + ClientPtr client; + PropertyPtr pProp; +{ + xReq *req = (xReq *) client->requestBuffer; + register char n; + + LbxQueryTagData(client, pProp->owner_pid, + pProp->tag_id, LbxTagTypeProperty); + + /* + * Before we reset the request, we must make sure + * it is in the client's byte order. + */ + + if (client->swapped) { + if (req->reqType == X_ChangeProperty) { + xChangePropertyReq *stuff = (xChangePropertyReq *) req; + swaps(&stuff->length, n); + swapl(&stuff->window, n); + swapl(&stuff->property, n); + swapl(&stuff->type, n); + swapl(&stuff->nUnits, n); + switch ( stuff->format ) { + case 16: + SwapRestS(stuff); + break; + case 32: + SwapRestL(stuff); + break; + } + } else if (req->reqType == X_GetProperty) { + xGetPropertyReq *stuff = (xGetPropertyReq *) req; + swaps(&stuff->length, n); + swapl(&stuff->window, n); + swapl(&stuff->property, n); + swapl(&stuff->type, n); + swapl(&stuff->longOffset, n); + swapl(&stuff->longLength, n); + } else if (req->data == X_LbxChangeProperty) { + xLbxChangePropertyReq *stuff = (xLbxChangePropertyReq *) req; + swaps(&stuff->length, n); + swapl(&stuff->window, n); + swapl(&stuff->property, n); + swapl(&stuff->type, n); + swapl(&stuff->nUnits, n); + } else if (req->data == X_LbxGetProperty) { + xLbxGetPropertyReq *stuff = (xLbxGetPropertyReq *) req; + swaps(&stuff->length, n); + swapl(&stuff->window, n); + swapl(&stuff->property, n); + swapl(&stuff->type, n); + swapl(&stuff->longOffset, n); + swapl(&stuff->longLength, n); + } + } + ResetCurrentRequest(client); + client->sequence--; + IgnoreClient(client); +} + +int +LbxChangeWindowProperty(client, pWin, property, type, format, mode, len, + have_data, value, sendevent, tag) + ClientPtr client; + WindowPtr pWin; + Atom property, + type; + int format, + mode; + unsigned long len; + Bool have_data; + pointer value; + Bool sendevent; + XID *tag; +{ + PropertyPtr pProp; + xEvent event; + int sizeInBytes; + int totalSize; + pointer data; + + sizeInBytes = format >> 3; + totalSize = len * sizeInBytes; + + /* first see if property already exists */ + + pProp = wUserProps(pWin); + while (pProp) { + if (pProp->propertyName == property) + break; + pProp = pProp->next; + } + if (!pProp) { /* just add to list */ + if (!pWin->optional && !MakeWindowOptional(pWin)) + return (BadAlloc); + pProp = (PropertyPtr) xalloc(sizeof(PropertyRec)); + if (!pProp) + return (BadAlloc); + data = (pointer) xalloc(totalSize); + if (!data && len) { + xfree(pProp); + return (BadAlloc); + } + pProp->propertyName = property; + pProp->type = type; + pProp->format = format; + pProp->data = data; + if (have_data) { + if (len) + memmove((char *) data, (char *) value, totalSize); + pProp->tag_id = 0; + pProp->owner_pid = 0; + } else { + if (!TagSaveTag(LbxTagTypeProperty, totalSize, + (pointer)pProp, &pProp->tag_id)) { + xfree(pProp); + xfree(pProp->data); + return BadAlloc; + } + pProp->owner_pid = LbxProxyID(client); + TagMarkProxy(pProp->tag_id, pProp->owner_pid); + } + pProp->size = len; + pProp->next = pWin->optional->userProps; + pWin->optional->userProps = pProp; + } else { + /* + * To append or prepend to a property the request format and type must + * match those of the already defined property. The existing format + * and type are irrelevant when using the mode "PropModeReplace" since + * they will be written over. + */ + + if ((format != pProp->format) && (mode != PropModeReplace)) + return (BadMatch); + if ((pProp->type != type) && (mode != PropModeReplace)) + return (BadMatch); + + /* + * if its a modify instead of replace, make sure we have the current + * value + */ + if ((mode != PropModeReplace) && pProp->tag_id && pProp->owner_pid) { + LbxStallPropRequest(client, pProp); + return (client->noClientException); + } + /* make sure any old tag is flushed first */ + if (pProp->tag_id) + TagDeleteTag(pProp->tag_id); + if (mode == PropModeReplace) { + if (totalSize != pProp->size * (pProp->format >> 3)) { + data = (pointer) xrealloc(pProp->data, totalSize); + if (!data && len) + return (BadAlloc); + pProp->data = data; + } + if (have_data) { + if (len) + memmove((char *) pProp->data, (char *) value, totalSize); + } else { + if (!TagSaveTag(LbxTagTypeProperty, totalSize, + (pointer)pProp, &pProp->tag_id)) { + xfree(pProp); + xfree(pProp->data); + return BadAlloc; + } + pProp->owner_pid = LbxProxyID(client); + TagMarkProxy(pProp->tag_id, pProp->owner_pid); + } + pProp->size = len; + pProp->type = type; + pProp->format = format; + } else if (len == 0) { + /* do nothing */ + } else if (mode == PropModeAppend) { + data = (pointer) xrealloc(pProp->data, + sizeInBytes * (len + pProp->size)); + if (!data) + return (BadAlloc); + pProp->data = data; + memmove(&((char *) data)[pProp->size * sizeInBytes], + (char *) value, + totalSize); + pProp->size += len; + } else if (mode == PropModePrepend) { + data = (pointer) xalloc(sizeInBytes * (len + pProp->size)); + if (!data) + return (BadAlloc); + memmove(&((char *) data)[totalSize], (char *) pProp->data, + (int) (pProp->size * sizeInBytes)); + memmove((char *) data, (char *) value, totalSize); + xfree(pProp->data); + pProp->data = data; + pProp->size += len; + } + } + if (sendevent) { + event.u.u.type = PropertyNotify; + event.u.property.window = pWin->drawable.id; + event.u.property.state = PropertyNewValue; + event.u.property.atom = pProp->propertyName; + event.u.property.time = currentTime.milliseconds; + DeliverEvents(pWin, &event, 1, (WindowPtr) NULL); + } + if (pProp->tag_id) + *tag = pProp->tag_id; + return (Success); +} + +int +LbxChangeProperty(client) + ClientPtr client; +{ + WindowPtr pWin; + char format, + mode; + unsigned long len; + int err; + int n; + XID newtag; + xLbxChangePropertyReply rep; + REQUEST(xLbxChangePropertyReq); + + REQUEST_SIZE_MATCH(xLbxChangePropertyReq); + UpdateCurrentTime(); + format = stuff->format; + mode = stuff->mode; + if ((mode != PropModeReplace) && (mode != PropModeAppend) && + (mode != PropModePrepend)) { + client->errorValue = mode; + return BadValue; + } + if ((format != 8) && (format != 16) && (format != 32)) { + client->errorValue = format; + return BadValue; + } + len = stuff->nUnits; + if (len > ((0xffffffff - sizeof(xChangePropertyReq)) >> 2)) + return BadLength; + + pWin = (WindowPtr) SecurityLookupWindow(stuff->window, client, + SecurityWriteAccess); + if (!pWin) + return (BadWindow); + if (!ValidAtom(stuff->property)) { + client->errorValue = stuff->property; + return (BadAtom); + } + if (!ValidAtom(stuff->type)) { + client->errorValue = stuff->type; + return (BadAtom); + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.pad = rep.pad0 = rep.pad1 = rep.pad2 = rep.pad3 = rep.pad4 = 0; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + } + +#ifdef XCSECURITY + switch (SecurityCheckPropertyAccess(client, pWin, stuff->property, + SecurityWriteAccess)) + { + case SecurityErrorOperation: + client->errorValue = stuff->property; + return BadAtom; + case SecurityIgnoreOperation: + rep.tag = 0; + WriteToClient(client, sizeof(xLbxChangePropertyReply), (char *)&rep); + return client->noClientException; + } +#endif + + err = LbxChangeWindowProperty(client, pWin, stuff->property, stuff->type, + (int) format, (int) mode, len, FALSE, (pointer) &stuff[1], + TRUE, &newtag); + if (err) + return err; + + rep.tag = newtag; + + if (client->swapped) { + swapl(&rep.tag, n); + } + WriteToClient(client, sizeof(xLbxChangePropertyReply), (char *)&rep); + + return client->noClientException; +} + +static void +LbxWriteGetpropReply(client, rep) + ClientPtr client; + xLbxGetPropertyReply *rep; +{ + int n; + + if (client->swapped) { + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + swapl(&rep->propertyType, n); + swapl(&rep->bytesAfter, n); + swapl(&rep->nItems, n); + swapl(&rep->tag, n); + } + WriteToClient(client, sizeof(xLbxGetPropertyReply), (char *)rep); +} + +int +LbxGetProperty(client) + ClientPtr client; +{ + PropertyPtr pProp, + prevProp; + unsigned long n, + len, + ind; + WindowPtr pWin; + xLbxGetPropertyReply reply; + Bool send_data = FALSE; + + REQUEST(xLbxGetPropertyReq); + + REQUEST_SIZE_MATCH(xLbxGetPropertyReq); + + reply.pad1 = 0; + reply.pad2 = 0; + + if (stuff->delete) + UpdateCurrentTime(); + pWin = (WindowPtr) SecurityLookupWindow(stuff->window, client, + SecurityReadAccess); + if (!pWin) + return (BadWindow); + + if (!ValidAtom(stuff->property)) { + client->errorValue = stuff->property; + return (BadAtom); + } + if ((stuff->delete != xTrue) && (stuff->delete != xFalse)) { + client->errorValue = stuff->delete; + return (BadValue); + } + if ((stuff->type != AnyPropertyType) && !ValidAtom(stuff->type)) + { + client->errorValue = stuff->type; + return(BadAtom); + } + pProp = wUserProps(pWin); + prevProp = (PropertyPtr) NULL; + while (pProp) { + if (pProp->propertyName == stuff->property) + break; + prevProp = pProp; + pProp = pProp->next; + } + reply.type = X_Reply; + reply.sequenceNumber = client->sequence; + if (!pProp) { + reply.nItems = 0; + reply.length = 0; + reply.bytesAfter = 0; + reply.propertyType = None; + reply.format = 0; + reply.tag = 0; + LbxWriteGetpropReply(client, &reply); + return client->noClientException; + } + /* + * If the request type and actual type don't match. Return the + * property information, but not the data. + */ + if ((stuff->type != pProp->type) && + (stuff->type != AnyPropertyType)) { + reply.bytesAfter = pProp->size; + reply.format = pProp->format; + reply.length = 0; + reply.nItems = 0; + reply.propertyType = pProp->type; + reply.tag = 0; + LbxWriteGetpropReply(client, &reply); + return client->noClientException; + } + /* + * Return type, format, value to client + */ + n = (pProp->format >> 3) * pProp->size; /* size (bytes) of prop */ + ind = stuff->longOffset << 2; + + /* + * If longOffset is invalid such that it causes "len" to be + * negative, it's a value error. + */ + + if (n < ind) { + client->errorValue = stuff->longOffset; + return BadValue; + } + + /* make sure we have the current value */ + if (pProp->tag_id && pProp->owner_pid) { + LbxStallPropRequest(client, pProp); + return client->noClientException; + } + + len = min(n - ind, stuff->longLength << 2); + + reply.bytesAfter = n - (ind + len); + reply.format = pProp->format; + reply.propertyType = pProp->type; + + if (!pProp->tag_id) { + if (n && (!stuff->delete || reply.bytesAfter)) { + TagSaveTag(LbxTagTypeProperty, n, (pointer)pProp, &pProp->tag_id); + pProp->owner_pid = 0; + } + send_data = TRUE; + } else + send_data = !TagProxyMarked(pProp->tag_id, LbxProxyID(client)); + if (pProp->tag_id && send_data) + TagMarkProxy(pProp->tag_id, LbxProxyID(client)); + reply.tag = pProp->tag_id; + + if (!send_data) + len = 0; + else if (reply.tag) { + len = n; + ind = 0; + } + reply.nItems = len / (pProp->format >> 3); + reply.length = (len + 3) >> 2; + + if (stuff->delete && (reply.bytesAfter == 0)) { + xEvent event; + + event.u.u.type = PropertyNotify; + event.u.property.window = pWin->drawable.id; + event.u.property.state = PropertyDelete; + event.u.property.atom = pProp->propertyName; + event.u.property.time = currentTime.milliseconds; + DeliverEvents(pWin, &event, 1, (WindowPtr) NULL); + } + LbxWriteGetpropReply(client, &reply); + if (len) { + switch (reply.format) { + case 32: + client->pSwapReplyFunc = CopySwap32Write; + break; + case 16: + client->pSwapReplyFunc = CopySwap16Write; + break; + default: + client->pSwapReplyFunc = (void (*) ()) WriteToClient; + break; + } + WriteSwappedDataToClient(client, len, + (char *) pProp->data + ind); + } + if (stuff->delete && (reply.bytesAfter == 0)) { + if (pProp->tag_id) + TagDeleteTag(pProp->tag_id); + if (prevProp == (PropertyPtr) NULL) { + if (!(pWin->optional->userProps = pProp->next)) + CheckWindowOptionalNeed(pWin); + } else + prevProp->next = pProp->next; + xfree(pProp->data); + xfree(pProp); + } + return client->noClientException; +} diff --git a/lbx/lbxserve.h b/lbx/lbxserve.h new file mode 100644 index 000000000..3151207be --- /dev/null +++ b/lbx/lbxserve.h @@ -0,0 +1,173 @@ +/* $Xorg: lbxserve.h,v 1.4 2001/02/09 02:05:17 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 _LBXSERVE_H_ +#define _LBXSERVE_H_ +#include "lbxdeltastr.h" +#define _XLBX_SERVER_ +#include "lbxstr.h" +#include "lbxopts.h" + +#define MAX_LBX_CLIENTS MAXCLIENTS +#define MAX_NUM_PROXIES (MAXCLIENTS >> 1) + +typedef struct _LbxClient *LbxClientPtr; +typedef struct _LbxProxy *LbxProxyPtr; + +typedef struct _LbxClient { + CARD32 id; + ClientPtr client; + LbxProxyPtr proxy; + Bool ignored; + Bool input_blocked; + int reqs_pending; + long bytes_in_reply; + long bytes_remaining; + Drawable drawableCache[GFX_CACHE_SIZE]; + GContext gcontextCache[GFX_CACHE_SIZE]; + pointer gfx_buffer; /* tmp buffer for unpacking gfx requests */ + unsigned long gb_size; +} LbxClientRec; + +typedef struct _connectionOutput *OSBufPtr; + +typedef struct _LbxProxy { + LbxProxyPtr next; + /* this array is indexed by lbx proxy index */ + LbxClientPtr lbxClients[MAX_LBX_CLIENTS]; + LbxClientPtr curRecv, + curDix; + int fd; + int pid; /* proxy ID */ + int uid; + int numClients; + int maxIndex; + Bool aborted; + int grabClient; + pointer compHandle; + Bool dosquishing; + Bool useTags; + LBXDeltasRec indeltas; + LBXDeltasRec outdeltas; + char *iDeltaBuf; + char *replyBuf; + char *oDeltaBuf; + OSBufPtr ofirst; + OSBufPtr olast; + CARD32 cur_send_id; + + LbxStreamOpts streamOpts; + + int numBitmapCompMethods; + char *bitmapCompMethods; /* array of indices */ + int numPixmapCompMethods; + char *pixmapCompMethods; /* array of indices */ + int **pixmapCompDepths; /* depths supported from each method */ + + struct _ColormapRec *grabbedCmaps; /* chained via lbx private */ + int motion_allowed_events; + lbxMotionCache motionCache; +} LbxProxyRec; + +/* This array is indexed by server client index, not lbx proxy index */ + +extern LbxClientPtr lbxClients[MAXCLIENTS]; + +#define LbxClient(client) (lbxClients[(client)->index]) +#define LbxProxy(client) (LbxClient(client)->proxy) +#define LbxMaybeProxy(client) (LbxClient(client) ? LbxProxy(client) : 0) +#define LbxProxyID(client) (LbxProxy(client)->pid) +#define LbxProxyClient(proxy) ((proxy)->lbxClients[0]->client) + +extern int LbxEventCode; + +extern void LbxDixInit( +#if NeedFunctionPrototypes + void +#endif +); + +extern LbxProxyPtr LbxPidToProxy( +#if NeedFunctionPrototypes + int /* pid */ +#endif +); + +extern void LbxReencodeOutput( +#if NeedFunctionPrototypes + ClientPtr /*client*/, + char* /*pbuf*/, + int* /*pcount*/, + char* /*cbuf*/, + int* /*ccount*/ +#endif +); + +extern int UncompressedWriteToClient( +#if NeedFunctionPrototypes + ClientPtr /*who*/, + int /*count*/, + char* /*buf*/ +#endif +); + +extern ClientPtr AllocLbxClientConnection( +#if NeedFunctionPrototypes + ClientPtr /* client */, + LbxProxyPtr /* proxy */ +#endif +); + +extern void LbxProxyConnection( +#if NeedFunctionPrototypes + ClientPtr /* client */, + LbxProxyPtr /* proxy */ +#endif +); + +#endif /* _LBXSERVE_H_ */ diff --git a/lbx/lbxsquish.c b/lbx/lbxsquish.c new file mode 100644 index 000000000..6d3eddbfc --- /dev/null +++ b/lbx/lbxsquish.c @@ -0,0 +1,152 @@ +/* $Xorg: lbxsquish.c,v 1.4 2001/02/09 02:05:17 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. + * + */ +#define NEED_REPLIES +#define NEED_EVENTS +#include "X.h" +#include "Xproto.h" +#include "Xos.h" +#include "misc.h" +#include "lbxserve.h" +#define _XLBX_SERVER_ +#include "lbxstr.h" + +/* handles server-side protocol squishing */ + +static char lbxevdelta[] = { + 0, + 0, + sz_xEvent - lbxsz_KeyButtonEvent, + sz_xEvent - lbxsz_KeyButtonEvent, + sz_xEvent - lbxsz_KeyButtonEvent, + sz_xEvent - lbxsz_KeyButtonEvent, + sz_xEvent - lbxsz_KeyButtonEvent, + sz_xEvent - lbxsz_EnterLeaveEvent, + sz_xEvent - lbxsz_EnterLeaveEvent, + sz_xEvent - lbxsz_FocusEvent, + sz_xEvent - lbxsz_FocusEvent, + sz_xEvent - lbxsz_KeymapEvent, + sz_xEvent - lbxsz_ExposeEvent, + sz_xEvent - lbxsz_GfxExposeEvent, + sz_xEvent - lbxsz_NoExposeEvent, + sz_xEvent - lbxsz_VisibilityEvent, + sz_xEvent - lbxsz_CreateNotifyEvent, + sz_xEvent - lbxsz_DestroyNotifyEvent, + sz_xEvent - lbxsz_UnmapNotifyEvent, + sz_xEvent - lbxsz_MapNotifyEvent, + sz_xEvent - lbxsz_MapRequestEvent, + sz_xEvent - lbxsz_ReparentEvent, + sz_xEvent - lbxsz_ConfigureNotifyEvent, + sz_xEvent - lbxsz_ConfigureRequestEvent, + sz_xEvent - lbxsz_GravityEvent, + sz_xEvent - lbxsz_ResizeRequestEvent, + sz_xEvent - lbxsz_CirculateEvent, + sz_xEvent - lbxsz_CirculateEvent, + sz_xEvent - lbxsz_PropertyEvent, + sz_xEvent - lbxsz_SelectionClearEvent, + sz_xEvent - lbxsz_SelectionRequestEvent, + sz_xEvent - lbxsz_SelectionNotifyEvent, + sz_xEvent - lbxsz_ColormapEvent, + sz_xEvent - lbxsz_ClientMessageEvent, + sz_xEvent - lbxsz_MappingNotifyEvent +}; + +static char lbxevpad[] = { + 0, + 0, + lbxsz_KeyButtonEvent - lbxupsz_KeyButtonEvent, + lbxsz_KeyButtonEvent - lbxupsz_KeyButtonEvent, + lbxsz_KeyButtonEvent - lbxupsz_KeyButtonEvent, + lbxsz_KeyButtonEvent - lbxupsz_KeyButtonEvent, + lbxsz_KeyButtonEvent - lbxupsz_KeyButtonEvent, + lbxsz_EnterLeaveEvent - lbxupsz_EnterLeaveEvent, + lbxsz_EnterLeaveEvent - lbxupsz_EnterLeaveEvent, + lbxsz_FocusEvent - lbxupsz_FocusEvent, + lbxsz_FocusEvent - lbxupsz_FocusEvent, + lbxsz_KeymapEvent - lbxupsz_KeymapEvent, + lbxsz_ExposeEvent - lbxupsz_ExposeEvent, + lbxsz_GfxExposeEvent - lbxupsz_GfxExposeEvent, + lbxsz_NoExposeEvent - lbxupsz_NoExposeEvent, + lbxsz_VisibilityEvent - lbxupsz_VisibilityEvent, + lbxsz_CreateNotifyEvent - lbxupsz_CreateNotifyEvent, + lbxsz_DestroyNotifyEvent - lbxupsz_DestroyNotifyEvent, + lbxsz_UnmapNotifyEvent - lbxupsz_UnmapNotifyEvent, + lbxsz_MapNotifyEvent - lbxupsz_MapNotifyEvent, + lbxsz_MapRequestEvent - lbxupsz_MapRequestEvent, + lbxsz_ReparentEvent - lbxupsz_ReparentEvent, + lbxsz_ConfigureNotifyEvent - lbxupsz_ConfigureNotifyEvent, + lbxsz_ConfigureRequestEvent - lbxupsz_ConfigureRequestEvent, + lbxsz_GravityEvent - lbxupsz_GravityEvent, + lbxsz_ResizeRequestEvent - lbxupsz_ResizeRequestEvent, + lbxsz_CirculateEvent - lbxupsz_CirculateEvent, + lbxsz_CirculateEvent - lbxupsz_CirculateEvent, + lbxsz_PropertyEvent - lbxupsz_PropertyEvent, + lbxsz_SelectionClearEvent - lbxupsz_SelectionClearEvent, + lbxsz_SelectionRequestEvent - lbxupsz_SelectionRequestEvent, + lbxsz_SelectionNotifyEvent - lbxupsz_SelectionNotifyEvent, + lbxsz_ColormapEvent - lbxupsz_ColormapEvent, + lbxsz_ClientMessageEvent - lbxupsz_ClientMessageEvent, + lbxsz_MappingNotifyEvent - lbxupsz_MappingNotifyEvent +}; + +int +LbxSquishEvent(buf) + char *buf; +{ + int delta = lbxevdelta[((xEvent *)buf)->u.u.type]; + int pad = lbxevpad[((xEvent *)buf)->u.u.type]; + + if (delta) + memmove(buf + delta, buf, sz_xEvent - delta); + if (pad) { + buf += sz_xEvent; + while (--pad >= 0) + *--buf = 0; + } + return delta; +} diff --git a/lbx/lbxsrvopts.h b/lbx/lbxsrvopts.h new file mode 100644 index 000000000..a08f1fec8 --- /dev/null +++ b/lbx/lbxsrvopts.h @@ -0,0 +1,78 @@ +/* $Xorg: lbxsrvopts.h,v 1.3 2000/08/17 19:53:31 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 _LBX_SRVOPTS_H_ +#define _LBX_SRVOPTS_H_ + +#include "lbxopts.h" + +typedef struct _LbxNegOpts { + int nopts; + short proxyDeltaN; + short proxyDeltaMaxLen; + short serverDeltaN; + short serverDeltaMaxLen; + LbxStreamOpts streamOpts; + int numBitmapCompMethods; + char *bitmapCompMethods; /* array of indices */ + int numPixmapCompMethods; + char *pixmapCompMethods; /* array of indices */ + int **pixmapCompDepths; /* depths supported from each method */ + Bool squish; + Bool useTags; +} LbxNegOptsRec; + +typedef LbxNegOptsRec *LbxNegOptsPtr; + + +extern LbxBitmapCompMethod *LbxSrvrLookupBitmapCompMethod ( +#if NeedFunctionPrototypes + LbxProxyPtr, /* proxy */ + int /* methodOpCode */ +#endif +); + +extern LbxPixmapCompMethod *LbxSrvrLookupPixmapCompMethod ( +#if NeedFunctionPrototypes + LbxProxyPtr, /* proxy */ + int /* methodOpCode */ +#endif +); + +extern LbxBitmapCompMethod *LbxSrvrFindPreferredBitmapCompMethod ( +#if NeedFunctionPrototypes + LbxProxyPtr /* proxy */ +#endif +); + +extern LbxPixmapCompMethod *LbxSrvrFindPreferredPixmapCompMethod ( +#if NeedFunctionPrototypes + LbxProxyPtr, /* proxy */ + int, /* format */ + int /* depth */ +#endif +); + + +#endif /* _LBX_SRVOPTS_H_ */ diff --git a/lbx/lbxswap.c b/lbx/lbxswap.c new file mode 100644 index 000000000..38ba66b70 --- /dev/null +++ b/lbx/lbxswap.c @@ -0,0 +1,858 @@ +/* $Xorg: lbxswap.c,v 1.4 2001/02/09 02:05:17 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. + * + */ + +#include <sys/types.h> +#define NEED_REPLIES +#define NEED_EVENTS +#include "X.h" +#include "Xproto.h" +#include "Xos.h" +#include "misc.h" +#include "os.h" +#include "dixstruct.h" +#include "pixmapstr.h" +#include "scrnintstr.h" +#include "servermd.h" +#define _XLBX_SERVER_ +#include "lbxstr.h" +#include "lbxserve.h" +#include "Xfuncproto.h" + +#include <stdio.h> + +static int +SProcLbxQueryVersion(client) + register ClientPtr client; +{ + register int n; + + REQUEST(xLbxQueryVersionReq); + + swaps(&stuff->length, n); + return ProcLbxQueryVersion(client); +} + +static int +SProcLbxStartProxy(client) + register ClientPtr client; +{ + register int n; + + REQUEST(xLbxStartProxyReq); + + swaps(&stuff->length, n); + return ProcLbxStartProxy(client); +} + +static int +SProcLbxStopProxy(client) + register ClientPtr client; +{ + register int n; + + REQUEST(xLbxStopProxyReq); + + swaps(&stuff->length, n); + return ProcLbxStopProxy(client); +} + +int +SProcLbxSwitch(client) + register ClientPtr client; +{ + register int n; + + REQUEST(xLbxSwitchReq); + + swaps(&stuff->length, n); + swapl(&stuff->client, n); + return ProcLbxSwitch(client); +} + +int +SProcLbxBeginLargeRequest (client) + register ClientPtr client; +{ + register int n; + + REQUEST(xLbxBeginLargeRequestReq); + + swaps(&stuff->length, n); + swapl(&stuff->largeReqLength, n); + return ProcLbxBeginLargeRequest(client); +} + +int +SProcLbxLargeRequestData (client) + register ClientPtr client; +{ + register int n; + + REQUEST(xLbxLargeRequestDataReq); + + swaps(&stuff->length, n); + return ProcLbxLargeRequestData(client); +} + +int +SProcLbxEndLargeRequest (client) + register ClientPtr client; +{ + register int n; + + REQUEST(xLbxEndLargeRequestReq); + + swaps(&stuff->length, n); + return ProcLbxEndLargeRequest(client); +} + +static int +SProcLbxNewClient(client) + register ClientPtr client; +{ + register int n; + + REQUEST(xLbxNewClientReq); + + swaps(&stuff->length, n); + swapl(&stuff->client, n); + return ProcLbxNewClient(client); +} + +static int +SProcLbxCloseClient(client) + register ClientPtr client; +{ + register int n; + + REQUEST(xLbxCloseClientReq); + + swaps(&stuff->length, n); + swapl(&stuff->client, n); + return ProcLbxCloseClient(client); +} + +static int +SProcLbxModifySequence(client) + register ClientPtr client; +{ + register int n; + + REQUEST(xLbxModifySequenceReq); + + swaps(&stuff->length, n); + swapl(&stuff->adjust, n); + return ProcLbxModifySequence(client); +} + +static int +SProcLbxAllowMotion(client) + register ClientPtr client; +{ + register int n; + + REQUEST(xLbxAllowMotionReq); + + swaps(&stuff->length, n); + swapl(&stuff->num, n); + return ProcLbxAllowMotion(client); +} + +static int +SProcLbxIncrementPixel(client) + register ClientPtr client; +{ + register int n; + + REQUEST(xLbxIncrementPixelReq); + + swaps(&stuff->length, n); + swapl(&stuff->cmap, n); + swapl(&stuff->pixel, n); + return ProcLbxIncrementPixel(client); +} + +static int +SProcLbxGrabCmap(client) + register ClientPtr client; +{ + register int n; + + REQUEST(xLbxGrabCmapReq); + + swaps(&stuff->length, n); + swapl(&stuff->cmap, n); + + return ProcLbxGrabCmap(client); +} + +static int +SProcLbxReleaseCmap(client) + register ClientPtr client; +{ + register int n; + + REQUEST(xLbxReleaseCmapReq); + + swaps(&stuff->length, n); + swapl(&stuff->cmap, n); + + return ProcLbxReleaseCmap(client); +} + +static int +SProcLbxAllocColor(client) + register ClientPtr client; +{ + register int n; + + REQUEST(xLbxAllocColorReq); + + swaps(&stuff->length, n); + swapl(&stuff->cmap, n); + swapl(&stuff->pixel, n); + swaps(&stuff->red, n); + swaps(&stuff->green, n); + swaps(&stuff->blue, n); + + return ProcLbxAllocColor(client); +} + +static int +SProcLbxGetModifierMapping(client) + register ClientPtr client; +{ + register int n; + + REQUEST(xLbxGetModifierMappingReq); + + swaps(&stuff->length, n); + return ProcLbxGetModifierMapping(client); +} + +static int +SProcLbxGetKeyboardMapping(client) + register ClientPtr client; +{ + register int n; + + REQUEST(xLbxGetKeyboardMappingReq); + + swaps(&stuff->length, n); + return ProcLbxGetKeyboardMapping(client); +} + +static int +SProcLbxQueryFont(client) + register ClientPtr client; +{ + register int n; + + REQUEST(xLbxQueryFontReq); + + swaps(&stuff->length, n); + swapl(&stuff->fid, n); + return ProcLbxQueryFont(client); +} + +static int +SProcLbxChangeProperty(client) + register ClientPtr client; +{ + register int n; + + REQUEST(xLbxChangePropertyReq); + + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xLbxChangePropertyReq); + swapl(&stuff->window, n); + swapl(&stuff->property, n); + swapl(&stuff->type, n); + swapl(&stuff->nUnits, n); + switch (stuff->format) { + case 8: + break; + case 16: + SwapRestS(stuff); + break; + case 32: + SwapRestL(stuff); + break; + } + return ProcLbxChangeProperty(client); +} + +static int +SProcLbxGetProperty(client) + register ClientPtr client; +{ + register int n; + + REQUEST(xLbxGetPropertyReq); + + swaps(&stuff->length, n); + swapl(&stuff->window, n); + swapl(&stuff->property, n); + swapl(&stuff->type, n); + swapl(&stuff->longOffset, n); + swapl(&stuff->longLength, n); + return ProcLbxGetProperty(client); +} + +static int +SProcLbxTagData(client) + register ClientPtr client; +{ + register int n; + + REQUEST(xLbxTagDataReq); + + swaps(&stuff->length, n); + swapl(&stuff->tag, n); + swapl(&stuff->real_length, n); + return ProcLbxTagData(client); +} + +static int +SProcLbxInvalidateTag(client) + register ClientPtr client; +{ + register int n; + + REQUEST(xLbxInvalidateTagReq); + + swaps(&stuff->length, n); + swapl(&stuff->tag, n); + return ProcLbxInvalidateTag(client); +} + +static int +SProcLbxPoly(client) + register ClientPtr client; +{ + register int n; + + REQUEST(xLbxPolyPointReq); + char *after; + + swaps(&stuff->length, n); + after = ((char *) stuff) + SIZEOF(xLbxPolyPointReq); + if (GFXdCacheEnt (stuff->cacheEnts) == GFXCacheNone) + { + swapl (((Drawable *) after), n); + after += sizeof (Drawable); + } + if (GFXgCacheEnt (stuff->cacheEnts) == GFXCacheNone) + swapl (((GContext *) after), n); + return ProcLbxDispatch(client); +} + +static int +SProcLbxFillPoly(client) + register ClientPtr client; +{ + register int n; + + REQUEST(xLbxFillPolyReq); + char *after; + + swaps(&stuff->length, n); + after = ((char *) stuff) + SIZEOF(xLbxFillPolyReq); + if (GFXdCacheEnt (stuff->cacheEnts) == GFXCacheNone) + { + swapl (((Drawable *) after), n); + after += sizeof (Drawable); + } + if (GFXgCacheEnt (stuff->cacheEnts) == GFXCacheNone) + swapl (((GContext *) after), n); + return ProcLbxFillPoly(client); +} + +static int +SProcLbxCopyArea (client) + register ClientPtr client; +{ + register int n; + + REQUEST(xLbxCopyAreaReq); + char *after; + + swaps(&stuff->length, n); + after = ((char *) stuff) + SIZEOF(xLbxCopyAreaReq); + if (GFXdCacheEnt (stuff->srcCache) == GFXCacheNone) + { + swapl (((Drawable *) after), n); + after += sizeof (Drawable); + } + if (GFXdCacheEnt (stuff->cacheEnts) == GFXCacheNone) + { + swapl (((Drawable *) after), n); + after += sizeof (Drawable); + } + if (GFXgCacheEnt (stuff->cacheEnts) == GFXCacheNone) + swapl (((GContext *) after), n); + return ProcLbxCopyArea(client); +} + +static int +SProcLbxCopyPlane (client) + register ClientPtr client; +{ + register int n; + + REQUEST(xLbxCopyPlaneReq); + char *after; + + swaps(&stuff->length, n); + swapl(&stuff->bitPlane, n); + after = ((char *) stuff) + SIZEOF(xLbxCopyPlaneReq); + if (GFXdCacheEnt (stuff->srcCache) == GFXCacheNone) + { + swapl (((Drawable *) after), n); + after += sizeof (Drawable); + } + if (GFXdCacheEnt (stuff->cacheEnts) == GFXCacheNone) + { + swapl (((Drawable *) after), n); + after += sizeof (Drawable); + } + if (GFXgCacheEnt (stuff->cacheEnts) == GFXCacheNone) + swapl (((GContext *) after), n); + return ProcLbxCopyPlane(client); +} + +static int +SProcLbxPolyText(client) + register ClientPtr client; +{ + register int n; + + REQUEST(xLbxPolyTextReq); + char *after; + + swaps(&stuff->length, n); + after = ((char *) stuff) + SIZEOF(xLbxPolyTextReq); + if (GFXdCacheEnt (stuff->cacheEnts) == GFXCacheNone) + { + swapl (((Drawable *) after), n); + after += sizeof (Drawable); + } + if (GFXgCacheEnt (stuff->cacheEnts) == GFXCacheNone) + swapl (((GContext *) after), n); + return ProcLbxDispatch(client); +} + +static int +SProcLbxImageText(client) + register ClientPtr client; +{ + register int n; + + REQUEST(xLbxImageTextReq); + char *after; + + swaps(&stuff->length, n); + after = ((char *) stuff) + SIZEOF(xLbxImageTextReq); + if (GFXdCacheEnt (stuff->cacheEnts) == GFXCacheNone) + { + swapl (((Drawable *) after), n); + after += sizeof (Drawable); + } + if (GFXgCacheEnt (stuff->cacheEnts) == GFXCacheNone) + swapl (((GContext *) after), n); + return ProcLbxDispatch(client); +} + + +static int +SProcLbxPutImage(client) + register ClientPtr client; +{ + register int n; + + REQUEST(xLbxPutImageReq); + + swaps (&stuff->length, n); + return ProcLbxPutImage(client); +} + +static int +SProcLbxGetImage(client) + register ClientPtr client; +{ + register int n; + + REQUEST(xLbxGetImageReq); + + swaps (&stuff->length, 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); + return ProcLbxGetImage(client); +} + +static int +SProcLbxInternAtoms(client) + register ClientPtr client; +{ + register int n; + char *ptr; + char lenbuf[2]; + CARD16 len; + int i; + + REQUEST(xLbxInternAtomsReq); + + swaps (&stuff->length, n); + swaps (&stuff->num, n); + + ptr = (char *) stuff + sz_xLbxInternAtomsReq; + for (i = 0; i < stuff->num; i++) + { + swaps (ptr, n); + lenbuf[0] = ptr[0]; + lenbuf[1] = ptr[1]; + len = *((CARD16 *) lenbuf); + ptr += (len + 2); + } + + return ProcLbxInternAtoms(client); +} + + +static int +SProcLbxGetWinAttrAndGeom(client) + ClientPtr client; +{ + int n; + + REQUEST(xLbxGetWinAttrAndGeomReq); + + swaps(&stuff->length, n); + swapl(&stuff->id, n); + + return ProcLbxGetWinAttrAndGeom(client); +} + + + +static int +SProcLbxQueryExtension(client) + ClientPtr client; +{ + int n; + + REQUEST(xLbxQueryExtensionReq); + + swaps(&stuff->length, n); + swapl(&stuff->nbytes, n); + return ProcLbxQueryExtension(client); +} + +int +SProcLbxDispatch(client) + register ClientPtr client; +{ + REQUEST(xReq); + switch (stuff->data) { + case X_LbxQueryVersion: + return SProcLbxQueryVersion(client); + case X_LbxStartProxy: + return SProcLbxStartProxy(client); + case X_LbxStopProxy: + return SProcLbxStopProxy(client); + case X_LbxNewClient: + return SProcLbxNewClient(client); + case X_LbxCloseClient: + return SProcLbxCloseClient(client); + case X_LbxModifySequence: + return SProcLbxModifySequence(client); + case X_LbxAllowMotion: + return SProcLbxAllowMotion(client); + case X_LbxIncrementPixel: + return SProcLbxIncrementPixel(client); + case X_LbxGrabCmap: + return SProcLbxGrabCmap(client); + case X_LbxReleaseCmap: + return SProcLbxReleaseCmap(client); + case X_LbxAllocColor: + return SProcLbxAllocColor(client); + case X_LbxGetModifierMapping: + return SProcLbxGetModifierMapping(client); + case X_LbxGetKeyboardMapping: + return SProcLbxGetKeyboardMapping(client); + case X_LbxInvalidateTag: + return SProcLbxInvalidateTag(client); + case X_LbxPolyPoint: + case X_LbxPolyLine: + case X_LbxPolySegment: + case X_LbxPolyRectangle: + case X_LbxPolyArc: + case X_LbxPolyFillRectangle: + case X_LbxPolyFillArc: + return SProcLbxPoly(client); + case X_LbxFillPoly: + return SProcLbxFillPoly(client); + case X_LbxQueryFont: + return SProcLbxQueryFont(client); + case X_LbxChangeProperty: + return SProcLbxChangeProperty(client); + case X_LbxGetProperty: + return SProcLbxGetProperty(client); + case X_LbxTagData: + return SProcLbxTagData(client); + case X_LbxCopyArea: + return SProcLbxCopyArea(client); + case X_LbxCopyPlane: + return SProcLbxCopyPlane(client); + case X_LbxPolyText8: + case X_LbxPolyText16: + return SProcLbxPolyText(client); + case X_LbxImageText8: + case X_LbxImageText16: + return SProcLbxImageText (client); + case X_LbxQueryExtension: + return SProcLbxQueryExtension(client); + case X_LbxPutImage: + return SProcLbxPutImage(client); + case X_LbxGetImage: + return SProcLbxGetImage(client); + case X_LbxInternAtoms: + return SProcLbxInternAtoms(client); + case X_LbxGetWinAttrAndGeom: + return SProcLbxGetWinAttrAndGeom(client); + case X_LbxSync: + return ProcLbxSync(client); /* nothing to swap */ + case X_LbxBeginLargeRequest: + return SProcLbxBeginLargeRequest(client); + case X_LbxLargeRequestData: + return SProcLbxLargeRequestData(client); + default: + return BadRequest; + } +} + +#ifdef notyet +void +LbxWriteSConnectionInfo(pClient, size, pInfo) + ClientPtr pClient; + unsigned long size; + char *pInfo; +{ + int i, j, k; + ScreenPtr pScreen; + DepthPtr pDepth; + 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) * screenInfo.numPixmapFormats; + memmove(pInfoT, pInfo, i); + pInfo += i; + pInfoT += i; + + for(i = 0; i < screenInfo.numScreens; i++) + { + pScreen = screenInfo.screens[i]; + SwapWinRoot((xWindowRoot *)pInfo, (xWindowRoot *)pInfoT); + pInfo += sizeof(xWindowRoot); + pInfoT += sizeof(xWindowRoot); + pDepth = pScreen->allowedDepths; + for(j = 0; j < pScreen->numDepths; j++, pDepth++) + { + ((xDepth *)pInfoT)->depth = ((xDepth *)pInfo)->depth; + cpswaps(((xDepth *)pInfo)->nVisuals, ((xDepth *)pInfoT)->nVisuals); + pInfo += sizeof(xDepth); + pInfoT += sizeof(xDepth); + for(k = 0; k < pDepth->numVids; k++) + { + SwapVisual((xVisualType *)pInfo, (xVisualType *)pInfoT); + pInfo += sizeof(xVisualType); + pInfoT += sizeof(xVisualType); + } + } + } + (void)WriteToClient(pClient, (int)size, (char *) pInfoTBase); + DEALLOCATE_LOCAL(pInfoTBase); +} + +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); +} +#endif + +void +LbxWriteSConnSetupPrefix(pClient, pcsp) + ClientPtr pClient; + xLbxConnSetupPrefix *pcsp; +{ + xLbxConnSetupPrefix cspT; + + cspT.success = pcsp->success; + cspT.changeType = pcsp->changeType; + cspT.length = pcsp->length; + cpswaps(pcsp->majorVersion, cspT.majorVersion); + cpswaps(pcsp->minorVersion, cspT.minorVersion); + cpswapl(pcsp->tag, cspT.tag); + + (void)WriteToClient(pClient, sizeof(cspT), (char *) &cspT); +} + +void +LbxSwapFontInfo(pr, compressed) + xLbxFontInfo *pr; + Bool compressed; +{ + unsigned i; + xCharInfo *pxci; + unsigned nchars, + nprops; + char *pby; + register char n; + + nchars = pr->nCharInfos; + nprops = pr->nFontProps; + 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); + + 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; + } + if (!compressed) { + pxci = (xCharInfo *) pby; + for (i = 0; i < nchars; i++, pxci++) + SwapCharInfo(pxci); + } else { + SwapLongs((CARD32 *) pby, nchars); + } +} diff --git a/lbx/lbxtables.c b/lbx/lbxtables.c new file mode 100644 index 000000000..c3d4f1270 --- /dev/null +++ b/lbx/lbxtables.c @@ -0,0 +1,33 @@ +/* $Xorg: lbxtables.c,v 1.3 2000/08/17 19:53:32 cpqbld Exp $ */ +/* + * 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. + * + */ + +extern int ProcInitialConnection(); +extern int ProcLbxEstablishConnection(); + +int (* LbxInitialVector[3]) () = +{ + 0, + ProcInitialConnection, + ProcLbxEstablishConnection +}; diff --git a/lbx/lbxtags.c b/lbx/lbxtags.c new file mode 100644 index 000000000..b2bc40ade --- /dev/null +++ b/lbx/lbxtags.c @@ -0,0 +1,238 @@ +/* $Xorg: lbxtags.c,v 1.4 2001/02/09 02:05:17 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 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 "X.h" +#include "misc.h" +#include "lbxdata.h" +#include "resource.h" +#include "lbxtags.h" +#define _XLBX_SERVER_ +#include "lbxstr.h" +#include "propertyst.h" + +static int tag_free(); + +static RESTYPE TagResType; + +/* ARGSUSED */ +static int +tag_free(data, id) + pointer data; + XID id; +{ + TagData td = (TagData) data; + FontTagInfoPtr ftip; + char *t; + extern int _lbx_fi_junklen; + + if (td->global) + *(td->global) = 0; + /* some types need to be freed, others are shared */ + if (td->data_type == LbxTagTypeFont) { + /* remove any back links */ + ftip = (FontTagInfoPtr) td->tdata; + FontSetPrivate(ftip->pfont, lbx_font_private, NULL); + t = (char *) ftip->fontinfo; + if (!ftip->compression) /* points to xQueryFont, so back up to it */ + t -= _lbx_fi_junklen; + xfree(t); + xfree(ftip); + } + xfree(data); + return 0; +} + +TagInit() +{ + TagResType = CreateNewResourceType(tag_free); +} + +XID +TagNewTag() +{ + return FakeClientID(0); +} + +void +TagClearProxy(tid, pid) + XID tid; + int pid; +{ + TagData td; + + td = (TagData) LookupIDByType(tid, TagResType); + if (td) + td->sent_to_proxy[pid >> 3] &= ~(1 << (pid & 7)); +} + +void +TagMarkProxy(tid, pid) + XID tid; + int pid; +{ + TagData td; + + td = (TagData) LookupIDByType(tid, TagResType); + td->sent_to_proxy[pid >> 3] |= 1 << (pid & 7); +} + +Bool +TagProxyMarked(tid, pid) + XID tid; + int pid; +{ + TagData td; + + td = (TagData) LookupIDByType(tid, TagResType); + return (td->sent_to_proxy[pid >> 3] & (1 << (pid & 7))) != 0; +} + +XID +TagSaveTag(dtype, size, data, global) + int dtype; + int size; + pointer data; + XID *global; +{ + TagData td; + + td = (TagData) xalloc(sizeof(TagDataRec)); + if (!td) { + if (global) + *global = 0; + return 0; + } + bzero((char *) td->sent_to_proxy, (MAX_NUM_PROXIES + 7) / 8); + td->tid = TagNewTag(); + td->data_type = dtype; + td->tdata = data; + td->size = size; + td->global = global; + if (!AddResource(td->tid, TagResType, (pointer) td)) + return 0; + if (global) + *global = td->tid; + return td->tid; +} + +void +TagDeleteTag(tid) + XID tid; +{ + int pid; + TagData td; + LbxProxyPtr proxy; + ClientPtr client; + LbxClientPtr lbxcp; + + td = (TagData) LookupIDByType(tid, TagResType); + if (!td) /* shouldn't happen, but play it safe */ + return; + for (pid = 1; pid < MAX_NUM_PROXIES; pid++) { + if (td->sent_to_proxy[pid >> 3] & (1 << (pid & 7))) { + proxy = LbxPidToProxy(pid); + lbxcp = (proxy != NULL) ? proxy->lbxClients[0] : NULL; + if (lbxcp && (client = lbxcp->client)) + LbxSendInvalidateTag(client, tid, td->data_type); + td->sent_to_proxy[pid >> 3] &= ~(1 << (pid & 7)); + } + } + if (td->data_type != LbxTagTypeProperty || !LbxFlushQTag(tid)) + FreeResource(tid, 0); + else if (td->global) { + *(td->global) = 0; + td->global = NULL; + } +} + +TagData +TagGetTag(tid) + XID tid; +{ + TagData td; + + td = (TagData) LookupIDByType(tid, TagResType); + return td; +} + +static void +LbxFlushTag(value, tid, cdata) + pointer value; + XID tid; + pointer cdata; +{ + TagData td = (TagData)value; + LbxProxyPtr proxy = (LbxProxyPtr)cdata; + int i; + + if ((td->data_type == LbxTagTypeProperty) && td->global) { + PropertyPtr pProp = (PropertyPtr)td->tdata; + if ((pProp->tag_id == tid) && (pProp->owner_pid == proxy->pid)) { + LbxFlushQTag(tid); + pProp->size = 0; + FreeResource(tid, 0); + return; + } + } + td->sent_to_proxy[proxy->pid >> 3] &= ~(1 << (proxy->pid & 7)); + for (i = 0; i < (MAX_NUM_PROXIES + 7) / 8; i++) { + if (td->sent_to_proxy[i]) + return; + } + FreeResource(tid, 0); +} + +/* + * clear out markers for proxies + */ +LbxFlushTags(proxy) + LbxProxyPtr proxy; +{ + FindClientResourcesByType(NULL, TagResType, LbxFlushTag, (pointer)proxy); +} diff --git a/lbx/lbxtags.h b/lbx/lbxtags.h new file mode 100644 index 000000000..3b6ab731a --- /dev/null +++ b/lbx/lbxtags.h @@ -0,0 +1,119 @@ +/* $Xorg: lbxtags.h,v 1.4 2001/02/09 02:05:17 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 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 _LBXTAGS_H_ +#define _LBXTAGS_H_ +#include "lbxserve.h" + +#include "os.h" +#include "opaque.h" +#include "resource.h" +#include "X.h" +#include "Xproto.h" + +typedef struct _tagdata { + XID tid; + short data_type; + unsigned char sent_to_proxy[(MAX_NUM_PROXIES + 7) / 8]; + int size; + pointer tdata; + XID *global; +} TagDataRec; + +typedef struct _tagdata *TagData; + +extern TagData TagGetTag( +#if NeedFunctionPrototypes + XID /*tid*/ +#endif +); + +extern XID TagNewTag( +#if NeedFunctionPrototypes + void +#endif +); + +extern void TagClearProxy( +#if NeedFunctionPrototypes + XID /*tid*/, + int /*pid*/ +#endif +); + +extern void TagMarkProxy( +#if NeedFunctionPrototypes + XID /*tid*/, + int /*pid*/ +#endif +); + +extern Bool TagProxyMarked( +#if NeedFunctionPrototypes + XID /*tid*/, + int /*pid*/ +#endif +); + +extern void TagDeleteTag( +#if NeedFunctionPrototypes + XID /*tid*/ +#endif +); + +extern XID TagSaveTag( +#if NeedFunctionPrototypes + int /*dtype*/, + int /*size*/, + pointer /*data*/, + XID* /*global*/ +#endif +); + +#endif /* _LBXTAGS_H_ */ diff --git a/lbx/lbxzerorep.c b/lbx/lbxzerorep.c new file mode 100644 index 000000000..350d7f0f9 --- /dev/null +++ b/lbx/lbxzerorep.c @@ -0,0 +1,416 @@ +/* $Xorg: lbxzerorep.c,v 1.4 2001/02/09 02:05:17 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 core X replies. + * This will hopefully improve both stream and delta compression, + * since we are removing the random values in pad bytes. + */ + +#define NEED_REPLIES +#include "X.h" +#include <X11/Xproto.h> + + +ZeroReplyPadBytes (buf, reqType) + char *buf; + int reqType; +{ + switch (reqType) { + case X_GetWindowAttributes: + { + xGetWindowAttributesReply *reply = (xGetWindowAttributesReply *) buf; + reply->pad = 0; + break; + } + case X_GetGeometry: + { + xGetGeometryReply *reply = (xGetGeometryReply *) buf; + reply->pad1 = 0; + reply->pad2 = 0; + reply->pad3 = 0; + break; + } + case X_QueryTree: + { + xQueryTreeReply *reply = (xQueryTreeReply *) buf; + reply->pad1 = 0; + reply->pad2 = 0; + reply->pad3 = 0; + reply->pad4 = 0; + reply->pad5 = 0; + break; + } + case X_InternAtom: + { + xInternAtomReply *reply = (xInternAtomReply *) buf; + reply->pad1 = 0; + reply->pad2 = 0; + reply->pad3 = 0; + reply->pad4 = 0; + reply->pad5 = 0; + reply->pad6 = 0; + break; + } + case X_GetAtomName: + { + xGetAtomNameReply *reply = (xGetAtomNameReply *) buf; + reply->pad1 = 0; + reply->pad2 = 0; + reply->pad3 = 0; + reply->pad4 = 0; + reply->pad5 = 0; + reply->pad6 = 0; + reply->pad7 = 0; + break; + } + case X_GetProperty: + { + xGetPropertyReply *reply = (xGetPropertyReply *) buf; + reply->pad1 = 0; + reply->pad2 = 0; + reply->pad3 = 0; + break; + } + case X_ListProperties: + { + xListPropertiesReply *reply = (xListPropertiesReply *) buf; + reply->pad1 = 0; + reply->pad2 = 0; + reply->pad3 = 0; + reply->pad4 = 0; + reply->pad5 = 0; + reply->pad6 = 0; + reply->pad7 = 0; + break; + } + case X_GetSelectionOwner: + { + xGetSelectionOwnerReply *reply = (xGetSelectionOwnerReply *) buf; + reply->pad1 = 0; + reply->pad2 = 0; + reply->pad3 = 0; + reply->pad4 = 0; + reply->pad5 = 0; + reply->pad6 = 0; + break; + } + case X_GrabKeyboard: + case X_GrabPointer: + { + xGrabKeyboardReply *reply = (xGrabKeyboardReply *) buf; + reply->pad1 = 0; + reply->pad2 = 0; + reply->pad3 = 0; + reply->pad4 = 0; + reply->pad5 = 0; + reply->pad6 = 0; + break; + } + case X_QueryPointer: + { + xQueryPointerReply *reply = (xQueryPointerReply *) buf; + reply->pad1 = 0; + reply->pad = 0; + break; + } + case X_GetMotionEvents: + { + xGetMotionEventsReply *reply = (xGetMotionEventsReply *) buf; + reply->pad1 = 0; + reply->pad2 = 0; + reply->pad3 = 0; + reply->pad4 = 0; + reply->pad5 = 0; + reply->pad6 = 0; + break; + } + case X_TranslateCoords: + { + xTranslateCoordsReply *reply = (xTranslateCoordsReply *) buf; + reply->pad2 = 0; + reply->pad3 = 0; + reply->pad4 = 0; + reply->pad5 = 0; + break; + } + case X_GetInputFocus: + { + xGetInputFocusReply *reply = (xGetInputFocusReply *) buf; + reply->pad1 = 0; + reply->pad2 = 0; + reply->pad3 = 0; + reply->pad4 = 0; + reply->pad5 = 0; + break; + } + case X_QueryKeymap: + { + xQueryKeymapReply *reply = (xQueryKeymapReply *) buf; + reply->pad1 = 0; + break; + } + case X_QueryFont: + { + xQueryFontReply *reply = (xQueryFontReply *) buf; + reply->pad1 = 0; + break; + } + case X_QueryTextExtents: + { + xQueryTextExtentsReply *reply = (xQueryTextExtentsReply *) buf; + reply->pad = 0; + break; + } + case X_ListFonts: + { + xListFontsReply *reply = (xListFontsReply *) buf; + reply->pad1 = 0; + reply->pad2 = 0; + reply->pad3 = 0; + reply->pad4 = 0; + reply->pad5 = 0; + reply->pad6 = 0; + reply->pad7 = 0; + break; + } + case X_GetFontPath: + { + xGetFontPathReply *reply = (xGetFontPathReply *) buf; + reply->pad1 = 0; + reply->pad2 = 0; + reply->pad3 = 0; + reply->pad4 = 0; + reply->pad5 = 0; + reply->pad6 = 0; + reply->pad7 = 0; + break; + } + case X_GetImage: + { + xGetImageReply *reply = (xGetImageReply *) buf; + reply->pad3 = 0; + reply->pad4 = 0; + reply->pad5 = 0; + reply->pad6 = 0; + reply->pad7 = 0; + break; + } + case X_ListInstalledColormaps: + { + xListInstalledColormapsReply *reply = + (xListInstalledColormapsReply *) buf; + reply->pad1 = 0; + reply->pad2 = 0; + reply->pad3 = 0; + reply->pad4 = 0; + reply->pad5 = 0; + reply->pad6 = 0; + reply->pad7 = 0; + break; + } + case X_AllocColor: + { + xAllocColorReply *reply = (xAllocColorReply *) buf; + reply->pad1 = 0; + reply->pad2 = 0; + reply->pad3 = 0; + reply->pad4 = 0; + reply->pad5 = 0; + break; + } + case X_AllocNamedColor: + { + xAllocNamedColorReply *reply = (xAllocNamedColorReply *) buf; + reply->pad1 = 0; + reply->pad2 = 0; + reply->pad3 = 0; + break; + } + case X_AllocColorCells: + { + xAllocColorCellsReply *reply = (xAllocColorCellsReply *) buf; + reply->pad1 = 0; + reply->pad3 = 0; + reply->pad4 = 0; + reply->pad5 = 0; + reply->pad6 = 0; + reply->pad7 = 0; + break; + } + case X_AllocColorPlanes: + { + xAllocColorPlanesReply *reply = (xAllocColorPlanesReply *) buf; + reply->pad1 = 0; + reply->pad2 = 0; + reply->pad3 = 0; + reply->pad4 = 0; + break; + } + case X_QueryColors: + { + xQueryColorsReply *reply = (xQueryColorsReply *) buf; + reply->pad1 = 0; + reply->pad2 = 0; + reply->pad3 = 0; + reply->pad4 = 0; + reply->pad5 = 0; + reply->pad6 = 0; + reply->pad7 = 0; + break; + } + case X_LookupColor: + { + xLookupColorReply *reply = (xLookupColorReply *) buf; + reply->pad1 = 0; + reply->pad3 = 0; + reply->pad4 = 0; + reply->pad5 = 0; + break; + } + case X_QueryBestSize: + { + xQueryBestSizeReply *reply = (xQueryBestSizeReply *) buf; + reply->pad1 = 0; + reply->pad3 = 0; + reply->pad4 = 0; + reply->pad5 = 0; + reply->pad6 = 0; + reply->pad7 = 0; + break; + } + case X_QueryExtension: + { + xQueryExtensionReply *reply = (xQueryExtensionReply *) buf; + reply->pad1 = 0; + reply->pad3 = 0; + reply->pad4 = 0; + reply->pad5 = 0; + reply->pad6 = 0; + reply->pad7 = 0; + break; + } + case X_ListExtensions: + { + xListExtensionsReply *reply = (xListExtensionsReply *) buf; + reply->pad2 = 0; + reply->pad3 = 0; + reply->pad4 = 0; + reply->pad5 = 0; + reply->pad6 = 0; + reply->pad7 = 0; + break; + } + case X_SetPointerMapping: + case X_SetModifierMapping: + { + xSetMappingReply *reply = (xSetMappingReply *) buf; + reply->pad2 = 0; + reply->pad3 = 0; + reply->pad4 = 0; + reply->pad5 = 0; + reply->pad6 = 0; + reply->pad7 = 0; + break; + } + case X_GetPointerMapping: + { + xGetPointerMappingReply *reply = (xGetPointerMappingReply *) buf; + reply->pad2 = 0; + reply->pad3 = 0; + reply->pad4 = 0; + reply->pad5 = 0; + reply->pad6 = 0; + reply->pad7 = 0; + break; + } + case X_GetKeyboardMapping: + { + xGetKeyboardMappingReply *reply = (xGetKeyboardMappingReply *) buf; + reply->pad2 = 0; + reply->pad3 = 0; + reply->pad4 = 0; + reply->pad5 = 0; + reply->pad6 = 0; + reply->pad7 = 0; + break; + } + case X_GetModifierMapping: + { + xGetModifierMappingReply *reply = (xGetModifierMappingReply *) buf; + reply->pad1 = 0; + reply->pad2 = 0; + reply->pad3 = 0; + reply->pad4 = 0; + reply->pad5 = 0; + reply->pad6 = 0; + break; + } + case X_GetKeyboardControl: + { + xGetKeyboardControlReply *reply = (xGetKeyboardControlReply *) buf; + reply->pad = 0; + break; + } + case X_GetPointerControl: + { + xGetPointerControlReply *reply = (xGetPointerControlReply *) buf; + reply->pad1 = 0; + reply->pad2 = 0; + reply->pad3 = 0; + reply->pad4 = 0; + reply->pad5 = 0; + reply->pad6 = 0; + break; + } + case X_GetScreenSaver: + { + xGetScreenSaverReply *reply = (xGetScreenSaverReply *) buf; + reply->pad1 = 0; + reply->pad2 = 0; + reply->pad3 = 0; + reply->pad4 = 0; + reply->pad5 = 0; + reply->pad6 = 0; + break; + } + case X_ListHosts: + { + xListHostsReply *reply = (xListHostsReply *) buf; + reply->pad1 = 0; + reply->pad3 = 0; + reply->pad4 = 0; + reply->pad5 = 0; + reply->pad6 = 0; + reply->pad7 = 0; + break; + } + } +} |