/************************************************************ Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts, and the Massachusetts Institute of Technology, Cambridge, Massachusetts. All Rights Reserved Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the names of Digital or MIT not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ********************************************************/ #include "X.h" #define NEED_REPLIES #define NEED_EVENTS #include "Xproto.h" #include "Xprotostr.h" #include "windowstr.h" #include "fontstruct.h" #include "dixfontstr.h" #include "gcstruct.h" #include "osstruct.h" #include "resource.h" #include "selection.h" #include "colormapst.h" #include "dixstruct.h" #include "extension.h" #include "input.h" #include "cursorstr.h" #include "scrnintstr.h" #include "opaque.h" extern WindowRec WindowTable[]; extern xConnSetupPrefix connSetupPrefix; extern char *ConnectionInfo; extern char *SwappedConnInfo; extern void ValidateGC(); extern Selection *CurrentSelections; extern int NumCurrentSelections; extern long ScreenSaverTime; extern long ScreenSaverInterval; extern int ScreenSaverBlanking; extern int ScreenSaverAllowExposures; extern ClientPtr onlyClient; extern Bool grabbingClient; extern long *checkForInput[2]; extern Bool clientsDoomed; extern int (* ProcVector[256]) (); extern int (* SwappedProcVector[256]) (); extern void (* EventSwapVector[128]) (); extern void (* ReplySwapVector[256]) (); void KillAllClients(); /* buffers for clients. legal values below */ extern int nextFreeClientID; /* 0 is for the server */ extern int nClients; /* number active clients */ extern int ProcBadRequest(); #define SAME_SCREENS(a, b) (\ (a.pScreen == b.pScreen)) #define VALIDATE(pGC, pDraw, rt) {\ if (pGC->serialNumber != pDraw->serialNumber)\ {\ ValidateGC(pDraw, pGC);\ } \ } #define LEGAL_NEW_RESOURCE(id)\ if ((LookupID(id, RT_ANY, RC_CORE) != 0) || (id & SERVER_BIT) \ || (client->clientAsMask != CLIENT_BITS(id)))\ return(BadIDChoice) #define LOOKUP_DRAWABLE(did, client)\ ((client->lastDrawableID == did) ? \ (DrawablePtr)client->lastDrawable : (DrawablePtr)LookupDrawable(did, client)) #define VERIFY_GC(pGC, rid, client)\ if (client->lastGCID == rid)\ {\ pGC = (GC *) client->lastGC;\ }\ else\ {\ pGC = (GC *)LookupID(rid, RT_GC, RC_CORE);\ if (!pGC)\ {\ client->errorValue = rid;\ return (BadGC);\ }\ } #define VALIDATE_DRAWABLE_AND_GC(drawID, pDraw, pGC, client)\ if ((client->lastDrawableID != drawID) || (client->lastGCID != stuff->gc))\ {\ if (client->lastDrawableID != drawID)\ {\ pDraw = (DrawablePtr)LookupID(drawID, RT_DRAWABLE, RC_CORE);\ if (!pDraw)\ {\ client->errorValue = drawID; \ return (BadDrawable);\ }\ if ((pDraw->type == DRAWABLE_WINDOW) || \ (pDraw->type == DRAWABLE_PIXMAP))\ {\ client->lastDrawable = (pointer)pDraw;\ client->lastDrawableID = drawID;\ }\ else\ {\ client->errorValue = drawID;\ return (BadDrawable);\ }\ }\ else\ pDraw = (DrawablePtr)client->lastDrawable;\ if (client->lastGCID != stuff->gc)\ {\ pGC = (GC *)LookupID(stuff->gc, RT_GC, RC_CORE);\ if (!pGC)\ {\ client->errorValue = stuff->gc;\ return (BadGC);\ }\ client->lastGC = (pointer)pGC;\ client->lastGCID = stuff->gc;\ }\ else\ pGC = (GC *) client->lastGC;\ if ((pGC->depth != pDraw->depth) || (pGC->pScreen != pDraw->pScreen))\ {\ client->errorValue = stuff->gc;\ client->lastGCID = -1;\ return (BadMatch);\ }\ }\ else\ {\ pGC = (GC *) client->lastGC;\ pDraw = (DrawablePtr)client->lastDrawable;\ }\ if (pGC->serialNumber != pDraw->serialNumber)\ { \ ValidateGC(pDraw, pGC);\ } int ProcFillPoly(client) register ClientPtr client; { int things; register GC *pGC; register DrawablePtr pDraw; REQUEST(xFillPolyReq); REQUEST_AT_LEAST_SIZE(xFillPolyReq); if ((stuff->shape != Complex) && (stuff->shape != Nonconvex) && (stuff->shape != Convex) && (stuff->coordMode != CoordModeOrigin) && (stuff->coordMode != CoordModePrevious)) return BadValue; VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); things = ((stuff->length << 2) - sizeof(xFillPolyReq)) >> 2; if (things) (*pGC->FillPolygon) (pDraw, pGC, stuff->shape, stuff->coordMode, things, (DDXPointPtr) &stuff[1]); return(client->noClientException); } int ProcPolyFillRectangle(client) register ClientPtr client; { int things; register GC *pGC; register DrawablePtr pDraw; REQUEST(xPolyFillRectangleReq); REQUEST_AT_LEAST_SIZE(xPolyFillRectangleReq); VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); things = ((stuff->length << 2) - sizeof(xPolyFillRectangleReq)) >> 3; if (things) (*pGC->PolyFillRect) (pDraw, pGC, things, (xRectangle *) &stuff[1]); return (client->noClientException); } int ProcPolyFillArc (client) register ClientPtr client; { int narcs; register GC *pGC; register DrawablePtr pDraw; REQUEST(xPolyFillArcReq); REQUEST_AT_LEAST_SIZE(xPolyFillArcReq); VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); narcs = ((stuff->length << 2) - sizeof(xPolyFillArcReq)) / sizeof(xArc); if (narcs) (*pGC->PolyFillArc) (pDraw, pGC, narcs, (xArc *) &stuff[1]); return (client->noClientException); } int ProcPutImage(client) register ClientPtr client; { register GC *pGC; register DrawablePtr pDraw; REQUEST(xPutImageReq); REQUEST_AT_LEAST_SIZE(xPutImageReq); VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); if (stuff->format == XYBitmap) { if ((stuff->depth != 1) || (stuff->leftPad > screenInfo.bitmapScanlineUnit)) return BadMatch; } else if (stuff->format == XYPixmap) { if ((pDraw->depth != stuff->depth) || (stuff->leftPad > screenInfo.bitmapScanlineUnit)) return BadMatch; } else if (stuff->format == ZPixmap) { if ((pDraw->depth != stuff->depth) || (stuff->leftPad != 0)) return BadMatch; } else return BadValue; (*pGC->PutImage) (pDraw, pGC, stuff->depth, stuff->dstX, stuff->dstY, stuff->width, stuff->height, stuff->leftPad, stuff->format, (int *) &stuff[1]); return (client->noClientException); } int ProcGetImage(client) register ClientPtr client; { register DrawablePtr pDraw; int nlines, linesDone, widthLine, linesPerBuf, widthBytesLine, height; char *pBuf; xGetImageReply xgi; REQUEST(xGetImageReq); height = stuff->height; REQUEST_SIZE_MATCH(xGetImageReq); if ((stuff->format != XYPixmap) && (stuff->format != ZPixmap)) return(BadValue); if(!(pDraw = LOOKUP_DRAWABLE(stuff->drawable, client) )) return (BadDrawable); if(pDraw->type == DRAWABLE_WINDOW) { if(((WindowPtr) pDraw)->absCorner.x + stuff->x < 0 || ((WindowPtr) pDraw)->absCorner.x + stuff->x + stuff->width > pDraw->pScreen->width || ((WindowPtr) pDraw)->absCorner.y + stuff->y < 0 || ((WindowPtr) pDraw)->absCorner.y + stuff->y + height > pDraw->pScreen->height) return(BadMatch); xgi.visual = ((WindowPtr) pDraw)->visual; } else { xgi.visual = None; } xgi.type = X_Reply; xgi.depth = pDraw->depth; if(stuff->format == ZPixmap) { widthLine = stuff->width; widthBytesLine = widthLine << 2; } else { widthLine = PixmapWidthInPadUnits(stuff->width, pDraw->depth); widthBytesLine = PixmapBytePad(stuff->width, pDraw->depth); } xgi.length = widthLine * height; linesPerBuf = IMAGE_BUFSIZE / widthBytesLine; if(!(pBuf = (char *) ALLOCATE_LOCAL(IMAGE_BUFSIZE))) return (client->noClientException = BadAlloc); WriteReplyToClient(client, sizeof (xGetImageReply), &xgi); linesDone = 0; while (height - linesDone > 0) { nlines = min(linesPerBuf, height - linesDone); (*pDraw->pScreen->GetImage) (pDraw, stuff->x, stuff->y + linesDone, stuff->width, nlines, stuff->format, stuff->planeMask, (int *)pBuf); /* Note that this is NOT a call to WriteReplyToClient, as we do NOT * byte swap */ WriteToClient(client, nlines * widthBytesLine, pBuf); linesDone += nlines; } DEALLOCATE_LOCAL(pBuf); return (client->noClientException); } int ProcPolyText(client) register ClientPtr client; { int xorg; REQUEST(xPolyTextReq); register DrawablePtr pDraw; register GC *pGC; register FontPtr pFont; int (* polyText)(); register unsigned char *pElt; unsigned char *pNextElt; unsigned char *endReq; int itemSize; Bool swapped16; /* True iff we are handling swapped Text16 */ #define TextEltHeader 2 #define FontShiftSize 5 REQUEST_AT_LEAST_SIZE(xPolyTextReq); VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); pElt = (unsigned char *)&stuff[1]; endReq = ((unsigned char *) stuff) + (stuff->length <<2); xorg = stuff->x; if (stuff->reqType == X_PolyText8) { polyText = pGC->PolyText8; itemSize = 1; swapped16 = FALSE; } else { polyText = pGC->PolyText16; itemSize = 2; swapped16 = client->swapped; } while (endReq - pElt > TextEltHeader) { if (*pElt == FontChange) { Font fid; if (endReq - pElt < FontShiftSize) return (BadLength); fid = *(pElt+4) /* big-endian */ | *(pElt+3) << 8 | *(pElt+2) << 16 | *(pElt+1) << 24; pFont = (FontPtr)LookupID(fid, RT_FONT, RC_CORE); if (!pFont) { client->errorValue = fid; return (BadFont); } if (pFont != pGC->font) { ChangeGC( pGC, GCFont, &fid); ValidateGC(pDraw, pGC); } pElt += FontShiftSize; } else /* print a string */ { pNextElt = pElt + TextEltHeader + (*pElt)*itemSize; if ( pNextElt > endReq) return( BadLength); xorg += *((char *)(pElt + 1)); /* must be signed */ if(swapped16) SwapShorts((short *)(*pElt + TextEltHeader), (int)*pElt); xorg = (* polyText)(pDraw, pGC, xorg, stuff->y, *pElt, pElt + TextEltHeader); pElt = pNextElt; } } return (client->noClientException); #undef TextEltHeader #undef FontShiftSize } int ProcCreateGC(client) register ClientPtr client; { int error; GC *pGC; register DrawablePtr pDraw; int len; REQUEST(xCreateGCReq); REQUEST_AT_LEAST_SIZE(xCreateGCReq); client->errorValue = stuff->gc; LEGAL_NEW_RESOURCE(stuff->gc); if (!(pDraw = LOOKUP_DRAWABLE( stuff->drawable, client) )) return (BadDrawable); len = stuff->length - (sizeof(xCreateGCReq) >> 2); if (len != Ones(stuff->mask)) return BadLength; pGC = (GC *)CreateGC(pDraw, stuff->mask, (long *) &stuff[1], (long *)&error); if (error != Success) return error; if (pGC) { AddResource(stuff->gc, RT_GC, (pointer)pGC, FreeGC, RC_CORE); return(client->noClientException); } else return (BadAlloc); } int ProcChangeGC(client) register ClientPtr client; { GC *pGC; REQUEST(xChangeGCReq); int result, len; REQUEST_AT_LEAST_SIZE(xChangeGCReq); VERIFY_GC(pGC, stuff->gc, client); len = stuff->length - (sizeof(xChangeGCReq) >> 2); if (len != Ones(stuff->mask)) return BadLength; result = ChangeGC(pGC, stuff->mask, (long *) &stuff[1]); if (client->noClientException != Success) return(client->noClientException); else return(result); } int ProcCopyGC(client) register ClientPtr client; { register GC *dstGC; register GC *pGC; REQUEST(xCopyGCReq); REQUEST_SIZE_MATCH(xCopyGCReq); VERIFY_GC( pGC, stuff->srcGC, client); VERIFY_GC( dstGC, stuff->dstGC, client); if (dstGC->pScreen != pGC->pScreen) return (BadMatch); CopyGC(pGC, dstGC, stuff->mask); return (client->noClientException); } int ProcSetDashes(client) register ClientPtr client; { register GC *pGC; int result; REQUEST(xSetDashesReq); REQUEST_AT_LEAST_SIZE(xSetDashesReq); if ((sizeof(xSetDashesReq) >> 2) == stuff->length) return BadValue; VERIFY_GC(pGC,stuff->gc, client); result = SetDashes(pGC, (int)stuff->dashOffset, (int)stuff->nDashes, (unsigned char *)&stuff[1]); if (client->noClientException != Success) return(client->noClientException); else return(result); } int ProcSetClipRectangles(client) register ClientPtr client; { int nr; register GC *pGC; REQUEST(xSetClipRectanglesReq); REQUEST_AT_LEAST_SIZE(xSetClipRectanglesReq); if ((stuff->ordering != Unsorted) && (stuff->ordering != YSorted) && (stuff->ordering != YXSorted) && (stuff->ordering != YXBanded)) return BadValue; VERIFY_GC(pGC,stuff->gc, client); pGC->clipOrg.x = stuff->xOrigin; pGC->stateChanges |= GCClipXOrigin; pGC->clipOrg.y = stuff->yOrigin; pGC->stateChanges |= GCClipYOrigin; nr = ((stuff->length << 2) - sizeof(xSetClipRectanglesReq)) >> 3; SetClipRects(pGC, (int)nr, (xRectangle *)&stuff[1], (int)stuff->ordering); pGC->stateChanges |= GCClipMask; pGC->serialNumber = 0; return(client->noClientException); } int ProcFreeGC(client) register ClientPtr client; { register GC *pGC; REQUEST(xResourceReq); REQUEST_SIZE_MATCH(xResourceReq); VERIFY_GC(pGC,stuff->id,client); FreeResource(stuff->id, RC_NONE); return(client->noClientException); } int ProcClearToBackground(client) register ClientPtr client; { REQUEST(xClearAreaReq); register WindowPtr pWin; REQUEST_SIZE_MATCH(xClearAreaReq); pWin = (WindowPtr)LookupWindow( stuff->window, client); if (!pWin) return(BadWindow); if (pWin->class == InputOnly) { client->errorValue = stuff->window; return (BadWindow); } if ((stuff->exposures != xTrue) && (stuff->exposures != xFalse)) return(BadValue); (*pWin->ClearToBackground)(pWin, stuff->x, stuff->y, stuff->width, stuff->height, (Bool)stuff->exposures); return(client->noClientException); } int ProcCopyArea(client) register ClientPtr client; { register DrawablePtr pDst; register DrawablePtr pSrc; register GC *pGC; REQUEST(xCopyAreaReq); REQUEST_SIZE_MATCH(xCopyAreaReq); VALIDATE_DRAWABLE_AND_GC(stuff->dstDrawable, pDst, pGC, client); if (stuff->dstDrawable != stuff->srcDrawable) { if (!(pSrc = LOOKUP_DRAWABLE(stuff->srcDrawable, client))) return(BadDrawable); if ((pDst->pScreen != pSrc->pScreen) || (pDst->depth != pSrc->depth)) { client->errorValue = stuff->dstDrawable; return (BadMatch); } } else pSrc = pDst; (*pGC->CopyArea)(pSrc, pDst, pGC, stuff->srcX, stuff->srcY, stuff->width, stuff->height, stuff->dstX, stuff->dstY); return(client->noClientException); } int ProcCopyPlane(client) register ClientPtr client; { register DrawablePtr psrcDraw, pdstDraw; register GC *pGC; REQUEST(xCopyPlaneReq); REQUEST_SIZE_MATCH(xCopyPlaneReq); /* Check to see if stff->plane only has ONE bit set XXX */ VALIDATE_DRAWABLE_AND_GC(stuff->dstDrawable, pdstDraw, pGC, client); if (stuff->dstDrawable != stuff->srcDrawable) { if (!(psrcDraw = LOOKUP_DRAWABLE(stuff->srcDrawable, client))) return(BadDrawable); if ((pdstDraw->pScreen != psrcDraw->pScreen) || (pdstDraw->depth != psrcDraw->depth)) { client->errorValue = stuff->dstDrawable; return (BadMatch); } } else psrcDraw = pdstDraw; (*pGC->CopyPlane)(psrcDraw, pdstDraw, pGC, stuff->srcX, stuff->srcY, stuff->width, stuff->height, stuff->dstX, stuff->dstY, stuff->bitPlane); return(client->noClientException); } int ProcPolyPoint(client) register ClientPtr client; { int npoint; register GC *pGC; register DrawablePtr pDraw; REQUEST(xPolyPointReq); REQUEST_AT_LEAST_SIZE(xPolyPointReq); if ((stuff->coordMode != CoordModeOrigin) && (stuff->coordMode != CoordModePrevious)) return BadValue; VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); npoint = ((stuff->length << 2) - sizeof(xPolyPointReq)) >> 2; if (npoint) (*pGC->PolyPoint)(pDraw, pGC, stuff->coordMode, npoint, (xPoint *) &stuff[1]); return (client->noClientException); } int ProcPolyLine(client) register ClientPtr client; { int npoint; register GC *pGC; register DrawablePtr pDraw; REQUEST(xPolyLineReq); REQUEST_AT_LEAST_SIZE(xPolyLineReq); if ((stuff->coordMode != CoordModeOrigin) && (stuff->coordMode != CoordModePrevious)) return BadValue; VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); npoint = ((stuff->length << 2) - sizeof(xPolyLineReq)); if(npoint % sizeof(xPoint) != 0) return(BadLength); npoint >>= 2; if (npoint < 1) return(BadLength); (*pGC->Polylines)(pDraw, pGC, stuff->coordMode, npoint, (xPoint *) &stuff[1]); return(client->noClientException); } int ProcPolySegment(client) register ClientPtr client; { int nsegs; register GC *pGC; register DrawablePtr pDraw; REQUEST(xPolySegmentReq); REQUEST_AT_LEAST_SIZE(xPolySegmentReq); VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); nsegs = (stuff->length << 2) - sizeof(xPolySegmentReq); if(nsegs % sizeof(xSegment) != 0) return(BadLength); nsegs >>= 3; if (nsegs) (*pGC->PolySegment)(pDraw, pGC, nsegs, (xSegment *) &stuff[1]); return (client->noClientException); } int ProcPolyRectangle (client) register ClientPtr client; { int nrects; register GC *pGC; register DrawablePtr pDraw; REQUEST(xPolyRectangleReq); REQUEST_AT_LEAST_SIZE(xPolyRectangleReq); VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); nrects = ((stuff->length << 2) - sizeof(xPolyRectangleReq)) >> 3; if (nrects) (*pGC->PolyRectangle)(pDraw, pGC, nrects, (xRectangle *) &stuff[1]); return(client->noClientException); } int ProcPolyArc(client) register ClientPtr client; { int narcs; register GC *pGC; register DrawablePtr pDraw; REQUEST(xPolyArcReq); REQUEST_AT_LEAST_SIZE(xPolyArcReq); VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); narcs = ((stuff->length << 2) - sizeof(xPolyArcReq)) / sizeof(xArc); if (narcs) (*pGC->PolyArc)(pDraw, pGC, narcs, (xArc *) &stuff[1]); return (client->noClientException); }