870 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			870 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			C
		
	
	
	
| /* $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.
 | |
|  *
 | |
|  */
 | |
| /* $XFree86: xc/programs/Xserver/lbx/lbxdix.c,v 1.7 2001/08/23 14:46:57 alanh Exp $ */
 | |
| 
 | |
| /* various bits of DIX-level mangling */
 | |
| 
 | |
| #ifdef HAVE_DIX_CONFIG_H
 | |
| #include <dix-config.h>
 | |
| #endif
 | |
| 
 | |
| #include <sys/types.h>
 | |
| #include <stdio.h>
 | |
| #define NEED_REPLIES
 | |
| #define NEED_EVENTS
 | |
| #include <X11/X.h>
 | |
| #include <X11/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 <X11/extensions/lbxstr.h>
 | |
| #include "lbxserve.h"
 | |
| #include "lbxtags.h"
 | |
| #include "lbxdata.h"
 | |
| #include <X11/Xfuncproto.h>
 | |
| #ifdef XAPPGROUP
 | |
| #include <X11/extensions/Xagsrv.h>
 | |
| #endif
 | |
| #include "swaprep.h"
 | |
| 
 | |
| int         lbx_font_private = -1;
 | |
| 
 | |
| void
 | |
| LbxDixInit(void)
 | |
| {
 | |
|     TagInit();
 | |
|     lbx_font_private = AllocateFontPrivateIndex();
 | |
| }
 | |
| 
 | |
| /* ARGSUSED */
 | |
| void
 | |
| LbxAllowMotion(ClientPtr       	client,
 | |
| 	       int		num)
 | |
| {
 | |
|     LbxProxyPtr proxy = LbxProxy(client);
 | |
|     proxy->motion_allowed_events += num;
 | |
| }
 | |
| 
 | |
| extern xConnSetupPrefix connSetupPrefix;
 | |
| extern char *ConnectionInfo;
 | |
| extern int  connBlockScreenStart;
 | |
| 
 | |
| int
 | |
| LbxSendConnSetup(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;
 | |
| }
 | |
| 
 | |
| static XID modifier_map_tag;
 | |
| 
 | |
| int
 | |
| LbxGetModifierMapping(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(void)
 | |
| {
 | |
| 
 | |
|     if (modifier_map_tag)
 | |
| 	TagDeleteTag(modifier_map_tag);
 | |
| }
 | |
| 
 | |
| static XID keyboard_map_tag;
 | |
| 
 | |
| int
 | |
| LbxGetKeyboardMapping(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 = (ReplySwapPtr)CopySwap32Write;
 | |
| 	WriteSwappedDataToClient(client,
 | |
| 			curKeySyms->mapWidth * stuff->count * sizeof(KeySym),
 | |
| 	    &curKeySyms->map[(stuff->firstKeyCode - curKeySyms->minKeyCode) *
 | |
| 			     curKeySyms->mapWidth]);
 | |
|     }
 | |
|     return client->noClientException;
 | |
| }
 | |
| 
 | |
| void
 | |
| LbxFlushKeyboardMapTag(void)
 | |
| {
 | |
|     if (keyboard_map_tag)
 | |
| 	TagDeleteTag(keyboard_map_tag);
 | |
| }
 | |
| 
 | |
| /* counts number of bits needed to hold value */
 | |
| static int
 | |
| _bitsize(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(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(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(FontPtr     pfont)
 | |
| {
 | |
|     FontTagInfoPtr ftip;
 | |
| 
 | |
|     ftip = (FontTagInfoPtr) FontGetPrivate(pfont, lbx_font_private);
 | |
|     if (ftip)
 | |
| 	TagDeleteTag(ftip->tid);
 | |
| }
 | |
| 
 | |
| int
 | |
| LbxInvalidateTag(ClientPtr   client,
 | |
| 		 XID         tag)
 | |
| {
 | |
|     TagClearProxy(tag, LbxProxyID(client));
 | |
|     return client->noClientException;
 | |
| }
 | |
| 
 | |
| void
 | |
| LbxSendInvalidateTag(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(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(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;
 | |
| }
 | |
| 
 | |
| static SendTagQPtr
 | |
| LbxFindQTag(XID tag)
 | |
| {
 | |
|     SendTagQPtr stqp;
 | |
| 
 | |
|     for (stqp = queried_tags; stqp; stqp = stqp->next) {
 | |
| 	if (stqp->tag == tag)
 | |
| 	    return stqp;
 | |
|     }
 | |
|     return NULL;
 | |
| }
 | |
| 
 | |
| static void
 | |
| LbxFreeQTag(SendTagQPtr stqp)
 | |
| {
 | |
|     xfree(stqp->stalled_clients);
 | |
|     xfree(stqp);
 | |
| }
 | |
| 
 | |
| static void
 | |
| LbxRemoveQTag(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(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(void)
 | |
| {
 | |
|     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(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(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(void)
 | |
| {
 | |
|     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);
 | |
|     }
 | |
| }
 |