home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / X / mit / extensions / server / shape.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-06-17  |  26.1 KB  |  1,038 lines

  1. /************************************************************
  2. Copyright 1989 by The Massachusetts Institute of Technology
  3.  
  4. Permission to use, copy, modify, and distribute this
  5. software and its documentation for any purpose and without
  6. fee is hereby granted, provided that the above copyright
  7. no- tice appear in all copies and that both that copyright
  8. no- tice and this permission notice appear in supporting
  9. docu- mentation, and that the name of MIT not be used in
  10. advertising or publicity pertaining to distribution of the
  11. software without specific prior written permission.
  12. M.I.T. makes no representation about the suitability of
  13. this software for any purpose. It is provided "as is"
  14. without any express or implied warranty.
  15.  
  16. MIT DISCLAIMS ALL WARRANTIES WITH REGARD TO  THIS  SOFTWARE,
  17. INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT-
  18. NESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MIT BE  LI-
  19. ABLE  FOR  ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  20. ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,  DATA  OR
  21. PROFITS,  WHETHER  IN  AN  ACTION OF CONTRACT, NEGLIGENCE OR
  22. OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
  23. THE USE OR PERFORMANCE OF THIS SOFTWARE.
  24.  
  25. ********************************************************/
  26.  
  27. /* $XConsortium: shape.c,v 5.16 91/06/17 11:36:52 rws Exp $ */
  28. #define NEED_REPLIES
  29. #define NEED_EVENTS
  30. #include <stdio.h>
  31. #include "X.h"
  32. #include "Xproto.h"
  33. #include "misc.h"
  34. #include "os.h"
  35. #include "windowstr.h"
  36. #include "scrnintstr.h"
  37. #include "pixmapstr.h"
  38. #include "extnsionst.h"
  39. #include "dixstruct.h"
  40. #include "resource.h"
  41. #include "opaque.h"
  42. #define _SHAPE_SERVER_    /* don't want Xlib structures */
  43. #include "shapestr.h"
  44. #include "regionstr.h"
  45. #include "gcstruct.h"
  46.  
  47. static int ShapeFreeClient(), ShapeFreeEvents();
  48. static void SendShapeNotify();
  49. static int ProcShapeDispatch(), SProcShapeDispatch();
  50. static void ShapeResetProc(), SShapeNotifyEvent();
  51.  
  52. static unsigned char ShapeReqCode = 0;
  53. static int ShapeEventBase = 0;
  54. static RESTYPE ClientType, EventType; /* resource types for event masks */
  55.  
  56. /*
  57.  * each window has a list of clients requesting
  58.  * ShapeNotify events.  Each client has a resource
  59.  * for each window it selects ShapeNotify input for,
  60.  * this resource is used to delete the ShapeNotifyRec
  61.  * entry from the per-window queue.
  62.  */
  63.  
  64. typedef struct _ShapeEvent *ShapeEventPtr;
  65.  
  66. typedef struct _ShapeEvent {
  67.     ShapeEventPtr   next;
  68.     ClientPtr        client;
  69.     WindowPtr        window;
  70.     XID            clientResource;
  71. } ShapeEventRec;
  72.  
  73. /****************
  74.  * ShapeExtensionInit
  75.  *
  76.  * Called from InitExtensions in main() or from QueryExtension() if the
  77.  * extension is dynamically loaded.
  78.  *
  79.  ****************/
  80.  
  81. void
  82. ShapeExtensionInit()
  83. {
  84.     ExtensionEntry *extEntry, *AddExtension();
  85.  
  86.     ClientType = CreateNewResourceType(ShapeFreeClient);
  87.     EventType = CreateNewResourceType(ShapeFreeEvents);
  88.     if (ClientType && EventType &&
  89.     (extEntry = AddExtension(SHAPENAME, ShapeNumberEvents, 0,
  90.                  ProcShapeDispatch, SProcShapeDispatch,
  91.                  ShapeResetProc, StandardMinorOpcode)))
  92.     {
  93.     ShapeReqCode = (unsigned char)extEntry->base;
  94.     ShapeEventBase = extEntry->eventBase;
  95.     EventSwapVector[ShapeEventBase] = SShapeNotifyEvent;
  96.     }
  97. }
  98.  
  99. /*ARGSUSED*/
  100. static void
  101. ShapeResetProc (extEntry)
  102. ExtensionEntry    *extEntry;
  103. {
  104. }
  105.  
  106. static
  107. RegionOperate (client, pWin, kind, destRgnp, srcRgn, op, xoff, yoff, create)
  108.     ClientPtr    client;
  109.     WindowPtr    pWin;
  110.     int        kind;
  111.     RegionPtr    *destRgnp, srcRgn;
  112.     int        op;
  113.     int        xoff, yoff;
  114.     RegionPtr    (*create)();    /* creates a reasonable *destRgnp */
  115. {
  116.     ScreenPtr    pScreen = pWin->drawable.pScreen;
  117.  
  118.     if (srcRgn && (xoff || yoff))
  119.     (*pScreen->TranslateRegion) (srcRgn, xoff, yoff);
  120.     if (!pWin->parent)
  121.     {
  122.     if (srcRgn)
  123.         (*pScreen->RegionDestroy) (srcRgn);
  124.     return Success;
  125.     }
  126.     switch (op) {
  127.     case ShapeSet:
  128.     if (*destRgnp)
  129.         (*pScreen->RegionDestroy) (*destRgnp);
  130.     *destRgnp = srcRgn;
  131.     srcRgn = 0;
  132.     break;
  133.     case ShapeUnion:
  134.     if (*destRgnp)
  135.         (*pScreen->Union) (*destRgnp, *destRgnp, srcRgn);
  136.     break;
  137.     case ShapeIntersect:
  138.     if (*destRgnp)
  139.         (*pScreen->Intersect) (*destRgnp, *destRgnp, srcRgn);
  140.     else {
  141.         *destRgnp = srcRgn;
  142.         srcRgn = 0;
  143.     }
  144.     break;
  145.     case ShapeSubtract:
  146.     if (!*destRgnp)
  147.         *destRgnp = (*create)(pWin);
  148.     (*pScreen->Subtract) (*destRgnp, *destRgnp, srcRgn);
  149.     break;
  150.     case ShapeInvert:
  151.     if (!*destRgnp)
  152.         *destRgnp = (*pScreen->RegionCreate) ((BoxPtr) 0, 0);
  153.     else
  154.         (*pScreen->Subtract) (*destRgnp, srcRgn, *destRgnp);
  155.     break;
  156.     default:
  157.     client->errorValue = op;
  158.     return BadValue;
  159.     }
  160.     if (srcRgn)
  161.     (*pScreen->RegionDestroy) (srcRgn);
  162.     SetShape (pWin);
  163.     SendShapeNotify (pWin, kind);
  164.     return Success;
  165. }
  166.  
  167. static RegionPtr
  168. CreateBoundingShape (pWin)
  169.     WindowPtr    pWin;
  170. {
  171.     BoxRec    extents;
  172.  
  173.     extents.x1 = -wBorderWidth (pWin);
  174.     extents.y1 = -wBorderWidth (pWin);
  175.     extents.x2 = pWin->drawable.width + wBorderWidth (pWin);
  176.     extents.y2 = pWin->drawable.height + wBorderWidth (pWin);
  177.     return (*pWin->drawable.pScreen->RegionCreate) (&extents, 1);
  178. }
  179.  
  180. static RegionPtr
  181. CreateClipShape (pWin)
  182.     WindowPtr    pWin;
  183. {
  184.     BoxRec    extents;
  185.  
  186.     extents.x1 = 0;
  187.     extents.y1 = 0;
  188.     extents.x2 = pWin->drawable.width;
  189.     extents.y2 = pWin->drawable.height;
  190.     return (*pWin->drawable.pScreen->RegionCreate) (&extents, 1);
  191. }
  192.  
  193. static int
  194. ProcShapeQueryVersion (client)
  195.     register ClientPtr    client;
  196. {
  197.     REQUEST(xShapeQueryVersionReq);
  198.     xShapeQueryVersionReply    rep;
  199.     register int        n;
  200.  
  201.     REQUEST_SIZE_MATCH (xShapeQueryVersionReq);
  202.     rep.type = X_Reply;
  203.     rep.length = 0;
  204.     rep.sequenceNumber = client->sequence;
  205.     rep.majorVersion = SHAPE_MAJOR_VERSION;
  206.     rep.minorVersion = SHAPE_MINOR_VERSION;
  207.     if (client->swapped) {
  208.         swaps(&rep.sequenceNumber, n);
  209.         swapl(&rep.length, n);
  210.     swaps(&rep.majorVersion, n);
  211.     swaps(&rep.minorVersion, n);
  212.     }
  213.     WriteToClient(client, sizeof (xShapeQueryVersionReply), (char *)&rep);
  214.     return (client->noClientException);
  215. }
  216.  
  217. /*****************
  218.  * ProcShapeRectangles
  219.  *
  220.  *****************/
  221.  
  222. static int
  223. ProcShapeRectangles (client)
  224.     register ClientPtr client;
  225. {
  226.     WindowPtr        pWin;
  227.     ScreenPtr        pScreen;
  228.     REQUEST(xShapeRectanglesReq);
  229.     xRectangle        *prects;
  230.     int                nrects, ctype;
  231.     RegionPtr        srcRgn;
  232.     RegionPtr        *destRgn;
  233.     RegionPtr        (*createDefault)();
  234.     int            destBounding;
  235.  
  236.     REQUEST_AT_LEAST_SIZE (xShapeRectanglesReq);
  237.     UpdateCurrentTime();
  238.     pWin = LookupWindow (stuff->dest, client);
  239.     if (!pWin)
  240.     return BadWindow;
  241.     switch (stuff->destKind) {
  242.     case ShapeBounding:
  243.     destBounding = 1;
  244.     createDefault = CreateBoundingShape;
  245.     break;
  246.     case ShapeClip:
  247.     destBounding = 0;
  248.     createDefault = CreateClipShape;
  249.     break;
  250.     default:
  251.     client->errorValue = stuff->destKind;
  252.     return BadValue;
  253.     }
  254.     if ((stuff->ordering != Unsorted) && (stuff->ordering != YSorted) &&
  255.     (stuff->ordering != YXSorted) && (stuff->ordering != YXBanded))
  256.     {
  257.     client->errorValue = stuff->ordering;
  258.         return BadValue;
  259.     }
  260.     pScreen = pWin->drawable.pScreen;
  261.     nrects = ((stuff->length  << 2) - sizeof(xShapeRectanglesReq));
  262.     if (nrects & 4)
  263.     return BadLength;
  264.     nrects >>= 3;
  265.     prects = (xRectangle *) &stuff[1];
  266.     ctype = VerifyRectOrder(nrects, prects, (int)stuff->ordering);
  267.     if (ctype < 0)
  268.     return BadMatch;
  269.     srcRgn = (*pScreen->RectsToRegion)(nrects, prects, ctype);
  270.  
  271.     if (!pWin->optional)
  272.     MakeWindowOptional (pWin);
  273.     if (destBounding)
  274.     destRgn = &pWin->optional->boundingShape;
  275.     else
  276.     destRgn = &pWin->optional->clipShape;
  277.  
  278.     return RegionOperate (client, pWin, (int)stuff->destKind,
  279.               destRgn, srcRgn, (int)stuff->op,
  280.               stuff->xOff, stuff->yOff, createDefault);
  281. }
  282.  
  283. /**************
  284.  * ProcShapeMask
  285.  **************/
  286.  
  287. static int
  288. ProcShapeMask (client)
  289.     register ClientPtr client;
  290. {
  291.     WindowPtr        pWin;
  292.     ScreenPtr        pScreen;
  293.     REQUEST(xShapeMaskReq);
  294.     RegionPtr        srcRgn;
  295.     RegionPtr        *destRgn;
  296.     PixmapPtr        pPixmap;
  297.     RegionPtr        (*createDefault)();
  298.     int            destBounding;
  299.  
  300.     REQUEST_SIZE_MATCH (xShapeMaskReq);
  301.     UpdateCurrentTime();
  302.     pWin = LookupWindow (stuff->dest, client);
  303.     if (!pWin)
  304.     return BadWindow;
  305.     switch (stuff->destKind) {
  306.     case ShapeBounding:
  307.     destBounding = 1;
  308.     createDefault = CreateBoundingShape;
  309.     break;
  310.     case ShapeClip:
  311.     destBounding = 0;
  312.     createDefault = CreateClipShape;
  313.     break;
  314.     default:
  315.     client->errorValue = stuff->destKind;
  316.     return BadValue;
  317.     }
  318.     pScreen = pWin->drawable.pScreen;
  319.     if (stuff->src == None)
  320.     srcRgn = 0;
  321.     else {
  322.         pPixmap = (PixmapPtr) LookupIDByType(stuff->src, RT_PIXMAP);
  323.         if (!pPixmap)
  324.         return BadPixmap;
  325.     if (pPixmap->drawable.pScreen != pScreen ||
  326.         pPixmap->drawable.depth != 1)
  327.         return BadMatch;
  328.     srcRgn = (*pScreen->BitmapToRegion)(pPixmap);
  329.     if (!srcRgn)
  330.         return BadAlloc;
  331.     }
  332.  
  333.     if (!pWin->optional)
  334.     MakeWindowOptional (pWin);
  335.     if (destBounding)
  336.     destRgn = &pWin->optional->boundingShape;
  337.     else
  338.     destRgn = &pWin->optional->clipShape;
  339.  
  340.     return RegionOperate (client, pWin, (int)stuff->destKind,
  341.               destRgn, srcRgn, (int)stuff->op,
  342.               stuff->xOff, stuff->yOff, createDefault);
  343. }
  344.  
  345. /************
  346.  * ProcShapeCombine
  347.  ************/
  348.  
  349. static int
  350. ProcShapeCombine (client)
  351.     register ClientPtr client;
  352. {
  353.     WindowPtr        pSrcWin, pDestWin;
  354.     ScreenPtr        pScreen;
  355.     REQUEST(xShapeCombineReq);
  356.     RegionPtr        srcRgn;
  357.     RegionPtr        *destRgn;
  358.     RegionPtr        (*createDefault)();
  359.     RegionPtr        (*createSrc)();
  360.     RegionPtr        tmp;
  361.     int            destBounding;
  362.  
  363.     REQUEST_SIZE_MATCH (xShapeCombineReq);
  364.     UpdateCurrentTime();
  365.     pDestWin = LookupWindow (stuff->dest, client);
  366.     if (!pDestWin)
  367.     return BadWindow;
  368.     if (!pDestWin->optional)
  369.     MakeWindowOptional (pDestWin);
  370.     switch (stuff->destKind) {
  371.     case ShapeBounding:
  372.     destBounding = 1;
  373.     createDefault = CreateBoundingShape;
  374.     break;
  375.     case ShapeClip:
  376.     destBounding = 0;
  377.     createDefault = CreateClipShape;
  378.     break;
  379.     default:
  380.     client->errorValue = stuff->destKind;
  381.     return BadValue;
  382.     }
  383.     pScreen = pDestWin->drawable.pScreen;
  384.  
  385.     pSrcWin = LookupWindow (stuff->src, client);
  386.     if (!pSrcWin)
  387.     return BadWindow;
  388.     switch (stuff->srcKind) {
  389.     case ShapeBounding:
  390.     srcRgn = wBoundingShape (pSrcWin);
  391.     createSrc = CreateBoundingShape;
  392.     break;
  393.     case ShapeClip:
  394.     srcRgn = wClipShape (pSrcWin);
  395.     createSrc = CreateClipShape;
  396.     break;
  397.     default:
  398.     client->errorValue = stuff->srcKind;
  399.     return BadValue;
  400.     }
  401.     if (pSrcWin->drawable.pScreen != pScreen)
  402.     {
  403.     return BadMatch;
  404.     }
  405.  
  406.     if (srcRgn) {
  407.         tmp = (*pScreen->RegionCreate) ((BoxPtr) 0, 0);
  408.         (*pScreen->RegionCopy) (tmp, srcRgn);
  409.         srcRgn = tmp;
  410.     } else
  411.     srcRgn = (*createSrc) (pSrcWin);
  412.  
  413.     if (!pDestWin->optional)
  414.     MakeWindowOptional (pDestWin);
  415.     if (destBounding)
  416.     destRgn = &pDestWin->optional->boundingShape;
  417.     else
  418.     destRgn = &pDestWin->optional->clipShape;
  419.  
  420.     return RegionOperate (client, pDestWin, (int)stuff->destKind,
  421.               destRgn, srcRgn, (int)stuff->op,
  422.               stuff->xOff, stuff->yOff, createDefault);
  423. }
  424.  
  425. /*************
  426.  * ProcShapeOffset
  427.  *************/
  428.  
  429. static int
  430. ProcShapeOffset (client)
  431.     register ClientPtr client;
  432. {
  433.     WindowPtr        pWin;
  434.     ScreenPtr        pScreen;
  435.     REQUEST(xShapeOffsetReq);
  436.     RegionPtr        srcRgn;
  437.  
  438.     REQUEST_SIZE_MATCH (xShapeOffsetReq);
  439.     UpdateCurrentTime();
  440.     pWin = LookupWindow (stuff->dest, client);
  441.     if (!pWin)
  442.     return BadWindow;
  443.     switch (stuff->destKind) {
  444.     case ShapeBounding:
  445.     srcRgn = wBoundingShape (pWin);
  446.     break;
  447.     case ShapeClip:
  448.     srcRgn = wClipShape(pWin);
  449.     break;
  450.     default:
  451.     client->errorValue = stuff->destKind;
  452.     return BadValue;
  453.     }
  454.     pScreen = pWin->drawable.pScreen;
  455.     if (srcRgn)
  456.     {
  457.         (*pScreen->TranslateRegion) (srcRgn, stuff->xOff, stuff->yOff);
  458.         SetShape (pWin);
  459.     }
  460.     SendShapeNotify (pWin, (int)stuff->destKind);
  461.     return Success;
  462. }
  463.  
  464. static int
  465. ProcShapeQueryExtents (client)
  466.     register ClientPtr    client;
  467. {
  468.     REQUEST(xShapeQueryExtentsReq);
  469.     WindowPtr        pWin;
  470.     xShapeQueryExtentsReply    rep;
  471.     BoxRec        extents;
  472.     register int    n;
  473.  
  474.     REQUEST_SIZE_MATCH (xShapeQueryExtentsReq);
  475.     pWin = LookupWindow (stuff->window, client);
  476.     if (!pWin)
  477.     return BadWindow;
  478.     rep.type = X_Reply;
  479.     rep.length = 0;
  480.     rep.sequenceNumber = client->sequence;
  481.     rep.boundingShaped = (wBoundingShape(pWin) != 0);
  482.     rep.clipShaped = (wClipShape(pWin) != 0);
  483.     if (wBoundingShape(pWin)) {
  484.     extents = *(pWin->drawable.pScreen->RegionExtents) (wBoundingShape(pWin));
  485.     } else {
  486.     extents.x1 = -wBorderWidth (pWin);
  487.     extents.y1 = -wBorderWidth (pWin);
  488.     extents.x2 = pWin->drawable.width + wBorderWidth (pWin);
  489.     extents.y2 = pWin->drawable.height + wBorderWidth (pWin);
  490.     }
  491.     rep.xBoundingShape = extents.x1;
  492.     rep.yBoundingShape = extents.y1;
  493.     rep.widthBoundingShape = extents.x2 - extents.x1;
  494.     rep.heightBoundingShape = extents.y2 - extents.y1;
  495.     if (wClipShape(pWin)) {
  496.     extents = *(pWin->drawable.pScreen->RegionExtents) (wClipShape(pWin));
  497.     } else {
  498.     extents.x1 = 0;
  499.     extents.y1 = 0;
  500.     extents.x2 = pWin->drawable.width;
  501.     extents.y2 = pWin->drawable.height;
  502.     }
  503.     rep.xClipShape = extents.x1;
  504.     rep.yClipShape = extents.y1;
  505.     rep.widthClipShape = extents.x2 - extents.x1;
  506.     rep.heightClipShape = extents.y2 - extents.y1;
  507.     if (client->swapped) {
  508.         swaps(&rep.sequenceNumber, n);
  509.         swapl(&rep.length, n);
  510.     swaps(&rep.xBoundingShape, n);
  511.     swaps(&rep.yBoundingShape, n);
  512.     swaps(&rep.widthBoundingShape, n);
  513.     swaps(&rep.heightBoundingShape, n);
  514.     swaps(&rep.xClipShape, n);
  515.     swaps(&rep.yClipShape, n);
  516.     swaps(&rep.widthClipShape, n);
  517.     swaps(&rep.heightClipShape, n);
  518.     }
  519.     WriteToClient(client, sizeof (xShapeQueryExtentsReply), (char *)&rep);
  520.     return (client->noClientException);
  521. }
  522.  
  523. /*ARGSUSED*/
  524. static int
  525. ShapeFreeClient (data, id)
  526.     pointer        data;
  527.     XID            id;
  528. {
  529.     ShapeEventPtr   pShapeEvent;
  530.     WindowPtr        pWin;
  531.     ShapeEventPtr   *pHead, pCur, pPrev;
  532.  
  533.     pShapeEvent = (ShapeEventPtr) data;
  534.     pWin = pShapeEvent->window;
  535.     pHead = (ShapeEventPtr *) LookupIDByType(pWin->drawable.id, EventType);
  536.     if (pHead) {
  537.     pPrev = 0;
  538.     for (pCur = *pHead; pCur && pCur != pShapeEvent; pCur=pCur->next)
  539.         pPrev = pCur;
  540.     if (pPrev)
  541.         pPrev->next = pShapeEvent->next;
  542.     else
  543.         *pHead = pShapeEvent->next;
  544.     }
  545.     xfree ((pointer) pShapeEvent);
  546. }
  547.  
  548. /*ARGSUSED*/
  549. static int
  550. ShapeFreeEvents (data, id)
  551.     pointer        data;
  552.     XID            id;
  553. {
  554.     ShapeEventPtr   *pHead, pCur, pNext;
  555.  
  556.     pHead = (ShapeEventPtr *) data;
  557.     for (pCur = *pHead; pCur; pCur = pNext) {
  558.     pNext = pCur->next;
  559.     FreeResource (pCur->clientResource, ClientType);
  560.     xfree ((pointer) pCur);
  561.     }
  562.     xfree ((pointer) pHead);
  563. }
  564.  
  565. static int
  566. ProcShapeSelectInput (client)
  567.     register ClientPtr    client;
  568. {
  569.     REQUEST(xShapeSelectInputReq);
  570.     WindowPtr        pWin;
  571.     ShapeEventPtr    pShapeEvent, pNewShapeEvent, *pHead;
  572.     XID            clientResource;
  573.  
  574.     REQUEST_SIZE_MATCH (xShapeSelectInputReq);
  575.     pWin = LookupWindow (stuff->window, client);
  576.     if (!pWin)
  577.     return BadWindow;
  578.     pHead = (ShapeEventPtr *) LookupIDByType(pWin->drawable.id, EventType);
  579.     switch (stuff->enable) {
  580.     case xTrue:
  581.     if (pHead) {
  582.  
  583.         /* check for existing entry. */
  584.         for (pShapeEvent = *pHead;
  585.          pShapeEvent;
  586.           pShapeEvent = pShapeEvent->next)
  587.         {
  588.         if (pShapeEvent->client == client)
  589.             return Success;
  590.         }
  591.     }
  592.  
  593.     /* build the entry */
  594.         pNewShapeEvent = (ShapeEventPtr)
  595.                 xalloc (sizeof (ShapeEventRec));
  596.         if (!pNewShapeEvent)
  597.         return BadAlloc;
  598.         pNewShapeEvent->next = 0;
  599.         pNewShapeEvent->client = client;
  600.         pNewShapeEvent->window = pWin;
  601.         /*
  602.       * add a resource that will be deleted when
  603.           * the client goes away
  604.           */
  605.        clientResource = FakeClientID (client->index);
  606.         pNewShapeEvent->clientResource = clientResource;
  607.         if (!AddResource (clientResource, ClientType, (pointer)pNewShapeEvent))
  608.         {
  609.         xfree (pNewShapeEvent);
  610.         return BadAlloc;
  611.         }
  612.         /*
  613.           * create a resource to contain a pointer to the list
  614.           * of clients selecting input.  This must be indirect as
  615.           * the list may be arbitrarily rearranged which cannot be
  616.           * done through the resource database.
  617.           */
  618.         if (!pHead)
  619.         {
  620.         pHead = (ShapeEventPtr *) xalloc (sizeof (ShapeEventPtr));
  621.         if (!pHead ||
  622.             !AddResource (pWin->drawable.id, EventType, (pointer)pHead))
  623.         {
  624.             FreeResource (clientResource, ClientType);
  625.             xfree (pHead);
  626.             xfree (pNewShapeEvent);
  627.             return BadAlloc;
  628.         }
  629.         *pHead = 0;
  630.         }
  631.         pNewShapeEvent->next = *pHead;
  632.         *pHead = pNewShapeEvent;
  633.     break;
  634.     case xFalse:
  635.     /* delete the interest */
  636.     if (pHead) {
  637.         pNewShapeEvent = 0;
  638.         for (pShapeEvent = *pHead; pShapeEvent; pShapeEvent = pShapeEvent->next) {
  639.         if (pShapeEvent->client == client)
  640.             break;
  641.         pNewShapeEvent = 0;
  642.         }
  643.         if (pShapeEvent) {
  644.         FreeResource (pShapeEvent->clientResource, ClientType);
  645.         if (pNewShapeEvent)
  646.             pNewShapeEvent->next = pShapeEvent->next;
  647.         else
  648.             *pHead = pShapeEvent->next;
  649.         xfree (pShapeEvent);
  650.         }
  651.     }
  652.     break;
  653.     default:
  654.     client->errorValue = stuff->enable;
  655.     return BadValue;
  656.     }
  657.     return Success;
  658. }
  659.  
  660. /*
  661.  * deliver the event
  662.  */
  663.  
  664. static void
  665. SendShapeNotify (pWin, which)
  666.     WindowPtr    pWin;
  667.     int        which;
  668. {
  669.     ShapeEventPtr    *pHead, pShapeEvent;
  670.     ClientPtr        client;
  671.     xShapeNotifyEvent    se;
  672.     BoxRec        extents;
  673.     RegionPtr        region;
  674.     BYTE        shaped;
  675.  
  676.     pHead = (ShapeEventPtr *) LookupIDByType(pWin->drawable.id, EventType);
  677.     if (!pHead)
  678.     return;
  679.     if (which == ShapeBounding) {
  680.     region = wBoundingShape(pWin);
  681.     if (region) {
  682.         extents = *(pWin->drawable.pScreen->RegionExtents) (region);
  683.         shaped = xTrue;
  684.     } else {
  685.         extents.x1 = -wBorderWidth (pWin);
  686.         extents.y1 = -wBorderWidth (pWin);
  687.         extents.x2 = pWin->drawable.width + wBorderWidth (pWin);
  688.         extents.y2 = pWin->drawable.height + wBorderWidth (pWin);
  689.         shaped = xFalse;
  690.     }
  691.     } else {
  692.     region = wClipShape(pWin);
  693.     if (region) {
  694.         extents = *(pWin->drawable.pScreen->RegionExtents) (region);
  695.         shaped = xTrue;
  696.     } else {
  697.         extents.x1 = 0;
  698.         extents.y1 = 0;
  699.         extents.x2 = pWin->drawable.width;
  700.         extents.y2 = pWin->drawable.height;
  701.         shaped = xFalse;
  702.     }
  703.     }
  704.     for (pShapeEvent = *pHead; pShapeEvent; pShapeEvent = pShapeEvent->next) {
  705.     client = pShapeEvent->client;
  706.     if (client == serverClient || client->clientGone)
  707.         continue;
  708.     se.type = ShapeNotify + ShapeEventBase;
  709.     se.kind = which;
  710.     se.window = pWin->drawable.id;
  711.     se.sequenceNumber = client->sequence;
  712.     se.x = extents.x1;
  713.     se.y = extents.y1;
  714.     se.width = extents.x2 - extents.x1;
  715.     se.height = extents.y2 - extents.y1;
  716.     se.time = currentTime.milliseconds;
  717.     se.shaped = shaped;
  718.     WriteEventsToClient (client, 1, (xEvent *) &se);
  719.     }
  720. }
  721.  
  722. static int
  723. ProcShapeInputSelected (client)
  724.     register ClientPtr    client;
  725. {
  726.     REQUEST(xShapeInputSelectedReq);
  727.     WindowPtr        pWin;
  728.     ShapeEventPtr    pShapeEvent, *pHead;
  729.     int            enabled;
  730.     xShapeInputSelectedReply    rep;
  731.     register int        n;
  732.  
  733.     REQUEST_SIZE_MATCH (xShapeInputSelectedReq);
  734.     pWin = LookupWindow (stuff->window, client);
  735.     if (!pWin)
  736.     return BadWindow;
  737.     pHead = (ShapeEventPtr *) LookupIDByType(pWin->drawable.id, EventType);
  738.     enabled = xFalse;
  739.     if (pHead) {
  740.         for (pShapeEvent = *pHead;
  741.          pShapeEvent;
  742.          pShapeEvent = pShapeEvent->next)
  743.         {
  744.         if (pShapeEvent->client == client) {
  745.             enabled = xTrue;
  746.         break;
  747.         }
  748.         }
  749.     }
  750.     rep.type = X_Reply;
  751.     rep.length = 0;
  752.     rep.sequenceNumber = client->sequence;
  753.     rep.enabled = enabled;
  754.     if (client->swapped) {
  755.     swaps (&rep.sequenceNumber, n);
  756.     swapl (&rep.length, n);
  757.     }
  758.     WriteToClient (client, sizeof (xShapeInputSelectedReply), (char *) &rep);
  759.     return (client->noClientException);
  760. }
  761.  
  762. static int
  763. ProcShapeGetRectangles (client)
  764.     register ClientPtr    client;
  765. {
  766.     REQUEST(xShapeGetRectanglesReq);
  767.     WindowPtr            pWin;
  768.     xShapeGetRectanglesReply    rep;
  769.     xRectangle            *rects;
  770.     int                nrects, i;
  771.     RegionPtr            region;
  772.     register int        n;
  773.  
  774.     REQUEST_SIZE_MATCH(xShapeGetRectanglesReq);
  775.     pWin = LookupWindow (stuff->window, client);
  776.     if (!pWin)
  777.     return BadWindow;
  778.     switch (stuff->kind) {
  779.     case ShapeBounding:
  780.     region = wBoundingShape(pWin);
  781.     break;
  782.     case ShapeClip:
  783.     region = wClipShape(pWin);
  784.     break;
  785.     default:
  786.     client->errorValue = stuff->kind;
  787.     return BadValue;
  788.     }
  789.     if (!region) {
  790.     nrects = 1;
  791.     rects = (xRectangle *) ALLOCATE_LOCAL (sizeof (xRectangle));
  792.     if (!rects)
  793.         return BadAlloc;
  794.     switch (stuff->kind) {
  795.     case ShapeBounding:
  796.         rects->x = - (int) wBorderWidth (pWin);
  797.         rects->y = - (int) wBorderWidth (pWin);
  798.         rects->width = pWin->drawable.width + wBorderWidth (pWin);
  799.         rects->height = pWin->drawable.height + wBorderWidth (pWin);
  800.         break;
  801.     case ShapeClip:
  802.         rects->x = 0;
  803.         rects->y = 0;
  804.         rects->width = pWin->drawable.width;
  805.         rects->height = pWin->drawable.height;
  806.         break;
  807.     }
  808.     } else {
  809.     BoxPtr box;
  810.     nrects = REGION_NUM_RECTS(region);
  811.     box = REGION_RECTS(region);
  812.     rects = (xRectangle *) ALLOCATE_LOCAL (nrects * sizeof (xRectangle));
  813.     if (!rects && nrects)
  814.         return BadAlloc;
  815.     for (i = 0; i < nrects; i++, box++) {
  816.         rects[i].x = box->x1;
  817.         rects[i].y = box->y1;
  818.         rects[i].width = box->x2 - box->x1;
  819.         rects[i].height = box->y2 - box->y1;
  820.     }
  821.     }
  822.     rep.type = X_Reply;
  823.     rep.sequenceNumber = client->sequence;
  824.     rep.length = (nrects * sizeof (xRectangle)) >> 2;
  825.     rep.ordering = YXBanded;
  826.     rep.nrects = nrects;
  827.     if (client->swapped) {
  828.     swaps (&rep.sequenceNumber, n);
  829.     swapl (&rep.length, n);
  830.     swapl (&rep.nrects, n);
  831.     SwapShorts ((short *)rects, (unsigned long)nrects * 4);
  832.     }
  833.     WriteToClient (client, sizeof (rep), (char *) &rep);
  834.     WriteToClient (client, nrects * sizeof (xRectangle), (char *) rects);
  835.     DEALLOCATE_LOCAL (rects);
  836.     return client->noClientException;
  837. }
  838.  
  839. static int
  840. ProcShapeDispatch (client)
  841.     register ClientPtr    client;
  842. {
  843.     REQUEST(xReq);
  844.     switch (stuff->data) {
  845.     case X_ShapeQueryVersion:
  846.     return ProcShapeQueryVersion (client);
  847.     case X_ShapeRectangles:
  848.     return ProcShapeRectangles (client);
  849.     case X_ShapeMask:
  850.     return ProcShapeMask (client);
  851.     case X_ShapeCombine:
  852.     return ProcShapeCombine (client);
  853.     case X_ShapeOffset:
  854.     return ProcShapeOffset (client);
  855.     case X_ShapeQueryExtents:
  856.     return ProcShapeQueryExtents (client);
  857.     case X_ShapeSelectInput:
  858.     return ProcShapeSelectInput (client);
  859.     case X_ShapeInputSelected:
  860.     return ProcShapeInputSelected (client);
  861.     case X_ShapeGetRectangles:
  862.     return ProcShapeGetRectangles (client);
  863.     default:
  864.     return BadRequest;
  865.     }
  866. }
  867.  
  868. static void
  869. SShapeNotifyEvent(from, to)
  870.     xShapeNotifyEvent *from, *to;
  871. {
  872.     to->type = from->type;
  873.     to->kind = from->kind;
  874.     cpswapl (from->window, to->window);
  875.     cpswaps (from->sequenceNumber, to->sequenceNumber);
  876.     cpswaps (from->x, to->x);
  877.     cpswaps (from->y, to->y);
  878.     cpswaps (from->width, to->width);
  879.     cpswaps (from->height, to->height);
  880.     cpswapl (from->time, to->time);
  881.     to->shaped = from->shaped;
  882. }
  883.  
  884. static int
  885. SProcShapeQueryVersion (client)
  886.     register ClientPtr    client;
  887. {
  888.     register int    n;
  889.     REQUEST (xShapeQueryVersionReq);
  890.  
  891.     swaps (&stuff->length, n);
  892.     return ProcShapeQueryVersion (client);
  893. }
  894.  
  895. static int
  896. SProcShapeRectangles (client)
  897.     register ClientPtr    client;
  898. {
  899.     register char   n;
  900.     REQUEST (xShapeRectanglesReq);
  901.  
  902.     swaps (&stuff->length, n);
  903.     REQUEST_AT_LEAST_SIZE (xShapeRectanglesReq);
  904.     swapl (&stuff->dest, n);
  905.     swaps (&stuff->xOff, n);
  906.     swaps (&stuff->yOff, n);
  907.     SwapRestS(stuff);
  908.     return ProcShapeRectangles (client);
  909. }
  910.  
  911. static int
  912. SProcShapeMask (client)
  913.     register ClientPtr    client;
  914. {
  915.     register char   n;
  916.     REQUEST (xShapeMaskReq);
  917.  
  918.     swaps (&stuff->length, n);
  919.     REQUEST_SIZE_MATCH (xShapeMaskReq);
  920.     swapl (&stuff->dest, n);
  921.     swaps (&stuff->xOff, n);
  922.     swaps (&stuff->yOff, n);
  923.     swapl (&stuff->src, n);
  924.     return ProcShapeMask (client);
  925. }
  926.  
  927. static int
  928. SProcShapeCombine (client)
  929.     register ClientPtr    client;
  930. {
  931.     register char   n;
  932.     REQUEST (xShapeCombineReq);
  933.  
  934.     swaps (&stuff->length, n);
  935.     REQUEST_SIZE_MATCH (xShapeCombineReq);
  936.     swapl (&stuff->dest, n);
  937.     swaps (&stuff->xOff, n);
  938.     swaps (&stuff->yOff, n);
  939.     swapl (&stuff->src, n);
  940.     return ProcShapeCombine (client);
  941. }
  942.  
  943. static int
  944. SProcShapeOffset (client)
  945.     register ClientPtr    client;
  946. {
  947.     register char   n;
  948.     REQUEST (xShapeOffsetReq);
  949.  
  950.     swaps (&stuff->length, n);
  951.     REQUEST_SIZE_MATCH (xShapeOffsetReq);
  952.     swapl (&stuff->dest, n);
  953.     swaps (&stuff->xOff, n);
  954.     swaps (&stuff->yOff, n);
  955.     return ProcShapeOffset (client);
  956. }
  957.  
  958. static int
  959. SProcShapeQueryExtents (client)
  960.     register ClientPtr    client;
  961. {
  962.     register char   n;
  963.     REQUEST (xShapeQueryExtentsReq);
  964.  
  965.     swaps (&stuff->length, n);
  966.     REQUEST_SIZE_MATCH (xShapeQueryExtentsReq);
  967.     swapl (&stuff->window, n);
  968.     return ProcShapeQueryExtents (client);
  969. }
  970.  
  971. static int
  972. SProcShapeSelectInput (client)
  973.     register ClientPtr    client;
  974. {
  975.     register char   n;
  976.     REQUEST (xShapeSelectInputReq);
  977.  
  978.     swaps (&stuff->length, n);
  979.     REQUEST_SIZE_MATCH (xShapeSelectInputReq);
  980.     swapl (&stuff->window, n);
  981.     return ProcShapeSelectInput (client);
  982. }
  983.  
  984. static int
  985. SProcShapeInputSelected (client)
  986.     register ClientPtr    client;
  987. {
  988.     register int    n;
  989.     REQUEST (xShapeInputSelectedReq);
  990.  
  991.     swaps (&stuff->length, n);
  992.     REQUEST_SIZE_MATCH (xShapeInputSelectedReq);
  993.     swapl (&stuff->window, n);
  994.     return ProcShapeInputSelected (client);
  995. }
  996.  
  997. static int
  998. SProcShapeGetRectangles (client)
  999.     register ClientPtr    client;
  1000. {
  1001.     REQUEST(xShapeGetRectanglesReq);
  1002.     register char   n;
  1003.  
  1004.     swaps (&stuff->length, n);
  1005.     REQUEST_SIZE_MATCH(xShapeGetRectanglesReq);
  1006.     swapl (&stuff->window, n);
  1007.     return ProcShapeGetRectangles (client);
  1008. }
  1009.  
  1010. static int
  1011. SProcShapeDispatch (client)
  1012.     register ClientPtr    client;
  1013. {
  1014.     REQUEST(xReq);
  1015.     switch (stuff->data) {
  1016.     case X_ShapeQueryVersion:
  1017.     return SProcShapeQueryVersion (client);
  1018.     case X_ShapeRectangles:
  1019.     return SProcShapeRectangles (client);
  1020.     case X_ShapeMask:
  1021.     return SProcShapeMask (client);
  1022.     case X_ShapeCombine:
  1023.     return SProcShapeCombine (client);
  1024.     case X_ShapeOffset:
  1025.     return SProcShapeOffset (client);
  1026.     case X_ShapeQueryExtents:
  1027.     return SProcShapeQueryExtents (client);
  1028.     case X_ShapeSelectInput:
  1029.     return SProcShapeSelectInput (client);
  1030.     case X_ShapeInputSelected:
  1031.     return SProcShapeInputSelected (client);
  1032.     case X_ShapeGetRectangles:
  1033.     return SProcShapeGetRectangles (client);
  1034.     default:
  1035.     return BadRequest;
  1036.     }
  1037. }
  1038.