home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / X / mit / extensions / lib / PEXlib / pl_pick.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-26  |  23.5 KB  |  1,092 lines

  1. /* $XConsortium: pl_pick.c,v 1.7 92/08/26 13:06:19 mor Exp $ */
  2.  
  3. /******************************************************************************
  4. Copyright 1987,1991 by Digital Equipment Corporation, Maynard, Massachusetts
  5. Copyright 1992 by ShoGraphics, Inc., Mountain View, California
  6. Copyright 1992 by the Massachusetts Institute of Technology
  7.  
  8.                         All Rights Reserved
  9.  
  10. Permission to use, copy, modify, distribute, and sell this software and its
  11. documentation for any purpose is hereby granted without fee, provided that
  12. the above copyright notice appear in all copies and that both that copyright
  13. notice and this permission notice appear in supporting documentation, and that
  14. the name of Digital, ShowGraphics, or M.I.T. not be used in advertising or
  15. publicity pertaining to distribution of the software without specific, written
  16. prior permission.  Digital, ShowGraphics, and M.I.T. make no representations
  17. about the suitability of this software for any purpose.  It is provided "as is"
  18. without express or implied warranty.
  19.  
  20. DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  21. ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  22. DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  23. ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  24. WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  25. ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  26. SOFTWARE.
  27.  
  28. SHOGRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  29. ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  30. SHOGRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  31. ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  32. WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  33. ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  34. SOFTWARE.
  35. *************************************************************************/
  36.  
  37. /*
  38.  *  NEED EVENTS needs to be defined when including Xproto.h so xEvent can be
  39.  *  sucked in.  Turn it on here in case Xproto.h is grabbed earlier
  40.  */ 
  41.  
  42. #define NEED_EVENTS
  43.  
  44. #include <X11/Xlib.h>      /* for XEvent */
  45. #include <X11/Xproto.h>    /* for xEvent */
  46.  
  47. #undef NEED_EVENTS
  48.  
  49. #include "PEXlib.h"
  50. #include "PEXlibint.h"
  51.  
  52.  
  53. PEXPickMeasure
  54. PEXCreatePickMeasure (display, wks, devType)
  55.  
  56. INPUT Display        *display;
  57. INPUT PEXWorkstation    wks;
  58. INPUT int        devType;
  59.  
  60. {
  61.     pexCreatePickMeasureReq    *req;
  62.     PEXPickMeasure        pm;
  63.  
  64.  
  65.     /*
  66.      * Get a Pick Measure resource id from X.
  67.      */
  68.  
  69.     pm = XAllocID (display);
  70.  
  71.  
  72.     /*
  73.      * Lock around the critical section, for multithreading.
  74.      */
  75.  
  76.     LockDisplay (display);
  77.  
  78.  
  79.     /*
  80.      * Put the request in the X request buffer.
  81.      */
  82.  
  83.     PEXGetReq (CreatePickMeasure, req);
  84.     req->wks = wks;
  85.     req->pm = pm;
  86.     req->devType = devType;
  87.  
  88.  
  89.     /*
  90.      * Done, so unlock and check for synchronous-ness.
  91.      */
  92.  
  93.     UnlockDisplay (display);
  94.     PEXSyncHandle (display);
  95.  
  96.     return (pm);
  97. }
  98.  
  99.  
  100. void
  101. PEXFreePickMeasure (display, pm)
  102.  
  103. INPUT Display        *display;
  104. INPUT PEXPickMeasure    pm;
  105.  
  106. {
  107.     pexFreePickMeasureReq    *req;
  108.  
  109.  
  110.     /*
  111.      * Lock around the critical section, for multithreading.
  112.      */
  113.  
  114.     LockDisplay (display);
  115.  
  116.  
  117.     /*
  118.      * Put the request in the X request buffer.
  119.      */
  120.  
  121.     PEXGetReq (FreePickMeasure, req);
  122.     req->id = pm;
  123.  
  124.  
  125.     /*
  126.      * Done, so unlock and check for synchronous-ness.
  127.      */
  128.  
  129.     UnlockDisplay (display);
  130.     PEXSyncHandle (display);
  131. }
  132.  
  133.  
  134. PEXPMAttributes *
  135. PEXGetPickMeasure (display, pm, valueMask)
  136.  
  137. INPUT Display            *display;
  138. INPUT PEXPickMeasure        pm;
  139. INPUT unsigned long        valueMask;
  140.  
  141. {
  142.     pexGetPickMeasureReq    *req;
  143.     pexGetPickMeasureReply    rep;
  144.     PEXPMAttributes        *ppmi;
  145.     unsigned long        *pv;
  146.     unsigned long        f;
  147.     int                i, tmp;
  148.  
  149.  
  150.     /*
  151.      * Lock around the critical section, for multithreading.
  152.      */
  153.  
  154.     LockDisplay (display);
  155.  
  156.  
  157.     /*
  158.      * Put the request in the X request buffer and get a reply.
  159.      */
  160.  
  161.     PEXGetReq (GetPickMeasure, req);
  162.     req->pm = pm;
  163.     req->itemMask = valueMask;
  164.  
  165.     if (_XReply (display, &rep, 0, xFalse) == 0)
  166.     {
  167.     UnlockDisplay (display);
  168.     PEXSyncHandle (display);
  169.     return (NULL);          /* return an error */
  170.     }
  171.  
  172.  
  173.     /*
  174.      * Allocate a scratch buffer and copy the reply data to the buffer.
  175.      */
  176.  
  177.     pv = (unsigned long *) _XAllocScratch (display,
  178.     (unsigned long) (rep.length << 2));
  179.  
  180.     _XRead (display, (char *) pv, (long) (rep.length << 2));
  181.  
  182.  
  183.     /*
  184.      * Allocate a buffer for the replies to pass back to the client.
  185.      */
  186.  
  187.     ppmi = (PEXPMAttributes *)
  188.     PEXAllocBuf ((unsigned) (sizeof (PEXPMAttributes)));
  189.  
  190.     ppmi->pick_path.count = 0;
  191.     ppmi->pick_path.elements = NULL;
  192.  
  193.     for (i = 0; i < (PEXPMMaxShift + 1); i++)
  194.     {
  195.     f = (1L << i);
  196.     if (valueMask & f)
  197.     {
  198.         switch (f)
  199.         {
  200.         case PEXPMStatus:
  201.         ppmi->status = *pv;
  202.         pv++;
  203.         break;
  204.         case PEXPMPath:
  205.         tmp = *(int *) pv;
  206.         pv++;
  207.         ppmi->pick_path.count = tmp;
  208.         tmp *= sizeof (PEXPickElementRef);
  209.         ppmi->pick_path.elements =
  210.             (PEXPickElementRef *) PEXAllocBuf ((unsigned) tmp);
  211.         COPY_AREA ((char *) pv,
  212.             (char *) (ppmi->pick_path.elements), tmp);
  213.         pv += NUMWORDS (tmp);
  214.         break;
  215.         }
  216.     }
  217.     }
  218.  
  219.  
  220.     /*
  221.      * Done, so unlock and check for synchronous-ness.
  222.      */
  223.  
  224.     UnlockDisplay (display);
  225.     PEXSyncHandle (display);
  226.  
  227.     return (ppmi);
  228. }
  229.  
  230.  
  231. void
  232. PEXUpdatePickMeasure (display, pick_measure, pick_device_type, pick_record)
  233.  
  234. INPUT Display        *display;
  235. INPUT PEXPickMeasure    pick_measure;
  236. INPUT int        pick_device_type;
  237. INPUT PEXPickRecord    *pick_record;
  238.  
  239. {
  240.     pexUpdatePickMeasureReq    *req;
  241.     int                numBytes;
  242.  
  243.  
  244.     /*
  245.      * Lock around the critical section, for multithreading.
  246.      */
  247.  
  248.     LockDisplay (display);
  249.  
  250.  
  251.     /*
  252.      * Put the request in the X request buffer.
  253.      */
  254.  
  255.     numBytes = (pick_device_type == PEXPickDeviceDCHitBox) ?
  256.     sizeof (PEXPDDCHitBox) : sizeof (PEXPDNPCHitVolume);
  257.  
  258.     PEXGetReqExtra (UpdatePickMeasure, numBytes, req);
  259.     req->pm = pick_measure;
  260.     req->numBytes = numBytes;
  261.  
  262.     COPY_AREA (pick_record, ((char *) &req[1]), numBytes);
  263.  
  264.  
  265.     /*
  266.      * Done, so unlock and check for synchronous-ness.
  267.      */
  268.  
  269.     UnlockDisplay (display);
  270.     PEXSyncHandle (display);
  271. }
  272.  
  273.  
  274. PEXPDAttributes *
  275. PEXGetPickDevice (display, wks, devType, valueMask)
  276.  
  277. INPUT Display            *display;
  278. INPUT PEXWorkstation        wks;
  279. INPUT int            devType;
  280. INPUT unsigned long        valueMask;
  281.  
  282. {
  283.     pexGetPickDeviceReq        *req;
  284.     pexGetPickDeviceReply    rep;
  285.     PEXPDAttributes        *ppdi;
  286.     unsigned long        *pv;
  287.     unsigned long        f;
  288.     int                i, tmp;
  289.     int                convertFP;
  290.  
  291.  
  292.     /*
  293.      * Lock around the critical section, for multithreading.
  294.      */
  295.  
  296.     LockDisplay (display);
  297.  
  298.  
  299.     /*
  300.      * Put the request in the X request buffer and get a reply.
  301.      */
  302.  
  303.     PEXGetFPReq (GetPickDevice, req, convertFP);
  304.     req->wks = wks;
  305.     req->itemMask = valueMask;
  306.     req->devType = devType;
  307.  
  308.     if (_XReply (display, &rep, 0, xFalse) == 0)
  309.     {
  310.     UnlockDisplay (display);
  311.     PEXSyncHandle (display);
  312.     return (NULL);          /* return an error */
  313.     }
  314.  
  315.     /*
  316.      * Allocate a scratch buffer and copy the reply data to the buffer.
  317.      */
  318.  
  319.     pv = (unsigned long *) _XAllocScratch (display,
  320.     (unsigned long) (rep.length << 2));
  321.  
  322.     _XRead (display, (char *) pv, (long) (rep.length << 2));
  323.  
  324.  
  325.     /*
  326.      * Allocate a buffer for the replies to pass back to the client.
  327.      */
  328.  
  329.     ppdi = (PEXPDAttributes *)
  330.     PEXAllocBuf ((unsigned) (sizeof (PEXPDAttributes)));
  331.  
  332.     ppdi->path.count = 0;
  333.     ppdi->path.elements = NULL;
  334.  
  335.     for (i = 0; i < (PEXPDMaxShift + 1); i++)
  336.     {
  337.     f = (1L << i);
  338.     if (valueMask & f)
  339.     {
  340.         switch (f)
  341.         {
  342.         case PEXPDPickStatus:
  343.         ppdi->status = *pv;
  344.         pv++;
  345.         break;
  346.         case PEXPDPickPath:
  347.         tmp = *(int *) pv;
  348.         pv++;
  349.         ppdi->path.count = tmp;
  350.         tmp *= sizeof (PEXPickElementRef);
  351.         ppdi->path.elements = (PEXPickElementRef *)
  352.             PEXAllocBuf ((unsigned) tmp);
  353.         COPY_AREA ((char *) pv, (char *) (ppdi->path.elements), tmp);
  354.         pv += NUMWORDS (tmp);
  355.         break;
  356.         case PEXPDPickPathOrder:
  357.         ppdi->path_order = *pv;
  358.         pv++;
  359.         break;
  360.         case PEXPDPickIncl:
  361.         ppdi->inclusion = *((PEXNameSet *) pv);
  362.         pv++;
  363.         break;
  364.         case PEXPDPickExcl:
  365.         ppdi->exclusion = *((PEXNameSet *) pv);
  366.         pv++;
  367.         break;
  368.         case PEXPDPickDataRec:
  369.         tmp = *(int *) pv;
  370.         pv++;
  371.         COPY_AREA ((char *) pv, (char *) &(ppdi->pick_record), tmp);
  372.         pv += NUMWORDS (tmp);
  373.         break;
  374.         case PEXPDPromptEchoType:
  375.         ppdi->prompt_echo_type = *pv;
  376.         pv++;
  377.         break;
  378.         case PEXPDEchoVolume:
  379.         ppdi->echo_volume = *((PEXViewport *) pv);
  380.         pv += LENOF (PEXViewport);
  381.         break;
  382.         case PEXPDEchoSwitch:
  383.         ppdi->echo_switch = *pv;
  384.         pv++;
  385.         break;
  386.         }
  387.     }
  388.     }
  389.  
  390.  
  391.     /*
  392.      * Done, so unlock and check for synchronous-ness.
  393.      */
  394.  
  395.     UnlockDisplay (display);
  396.     PEXSyncHandle (display);
  397.  
  398.     return (ppdi);
  399. }
  400.  
  401.  
  402. void
  403. PEXChangePickDevice (display, wks, devType, valueMask, values)
  404.  
  405. INPUT Display        *display;
  406. INPUT PEXWorkstation    wks;
  407. INPUT int        devType;
  408. INPUT unsigned long    valueMask;
  409. INPUT PEXPDAttributes    *values;
  410.  
  411. {
  412.     pexChangePickDeviceReq    *req;
  413.     unsigned long        *pv, *pvSend;
  414.     unsigned long        f, size;
  415.     int                i, tmp, length;
  416.     int                convertFP;
  417.  
  418.  
  419.     /*
  420.      * Lock around the critical section, for multithreading.
  421.      */
  422.  
  423.     LockDisplay (display);
  424.  
  425.  
  426.     /*
  427.      * Put the request in the X request buffer.
  428.      */
  429.  
  430.     PEXGetFPReq (ChangePickDevice, req, convertFP);
  431.     req->wks = wks;
  432.     req->itemMask = valueMask;
  433.     req->devType = devType;
  434.  
  435.  
  436.     /*
  437.      * Allocate a scratch buffer used to pack the attributes.  It's not
  438.      * worth computing the exact amount of memory needed, so assume the
  439.      * worse case.
  440.      */
  441.  
  442.     size = 6 * sizeof (CARD32) +
  443.     (sizeof (PEXPickElementRef) * ((valueMask & PEXPDPickPath) ?
  444.         values->path.count : 0)) +
  445.     sizeof (PEXNameSet) * 2 +
  446.     sizeof (PEXPickRecord) +
  447.     sizeof (PEXViewport);
  448.  
  449.     pv = pvSend = (CARD32 *) _XAllocScratch (display, (unsigned long) size);
  450.  
  451.     for (i = 0; i < (PEXPDMaxShift + 1); i++)
  452.     {
  453.     f = (1L << i);
  454.     if (valueMask & f)
  455.     {
  456.         switch (f)
  457.         {
  458.         case PEXPDPickStatus:
  459.         *pv = values->status;
  460.         pv++;
  461.         break;
  462.         case PEXPDPickPath:
  463.         tmp = *((unsigned long *) pv) = values->path.count;
  464.         pv++;
  465.         tmp *= sizeof (PEXPickElementRef);
  466.         COPY_AREA ((char *) (values->path.elements), (char *) pv, tmp);
  467.         pv += NUMWORDS (tmp);
  468.         break;
  469.         case PEXPDPickPathOrder:
  470.         *pv = values->path_order;
  471.         pv++;
  472.         break;
  473.         case PEXPDPickIncl:
  474.         *((PEXNameSet *) pv) = values->inclusion;
  475.         pv += LENOF (PEXNameSet);
  476.         break;
  477.         case PEXPDPickExcl:
  478.         *((PEXNameSet *) pv) = values->exclusion;
  479.         pv += LENOF (PEXNameSet);
  480.         break;
  481.         case PEXPDPickDataRec:
  482.         tmp = *((unsigned long *) pv) =
  483.             (devType == PEXPickDeviceDCHitBox) ?
  484.             sizeof (PEXPDDCHitBox) : sizeof (PEXPDNPCHitVolume);
  485.         pv++;
  486.         COPY_AREA ((char *) &(values->pick_record), (char *) pv, tmp);
  487.         pv += NUMWORDS (tmp);
  488.         break;
  489.         case PEXPDPromptEchoType:
  490.         *pv = values->prompt_echo_type;
  491.         pv++;
  492.         break;
  493.         case PEXPDEchoVolume:
  494.         *((PEXViewport *) pv) = values->echo_volume;
  495.         pv += LENOF (PEXViewport);
  496.         break;
  497.         case PEXPDEchoSwitch:
  498.         *pv = values->echo_switch;
  499.         pv++;
  500.         break;
  501.         }
  502.     }
  503.     }
  504.  
  505.     length = pv - pvSend;
  506.     req->length += length;
  507.  
  508.     Data (display, (char *) pvSend, (length << 2));
  509.  
  510.  
  511.     /*
  512.      * Done, so unlock and check for synchronous-ness.
  513.      */
  514.  
  515.     UnlockDisplay (display);
  516.     PEXSyncHandle (display);
  517. }
  518.  
  519.  
  520.  
  521.  
  522. /*
  523.  * Routine to convert a protocol-format event (wire) to a client event
  524.  * structure (client) for a PEXMaxHitsReachedEvent.  XESetWireToEvent is
  525.  * called in PEXInitialize to set this up with Xlib.
  526.  */
  527.  
  528. Status
  529. _PEXConvertMaxHitsEvent (display, client, wire)
  530.  
  531. INPUT    Display        *display;
  532. INPUT    XEvent        *client;
  533. INPUT    xEvent        *wire;
  534.  
  535. {
  536.     pexMaxHitsReachedEvent    *wireevent;
  537.     PEXMaxHitsReachedEvent    *clientevent;
  538.  
  539.  
  540.     /*
  541.      * Set up the pointers.
  542.      */
  543.  
  544.     wireevent = (pexMaxHitsReachedEvent *) wire;
  545.     clientevent = (PEXMaxHitsReachedEvent *) client;
  546.  
  547.  
  548.     /*
  549.      * Now fill in the client structure.
  550.      */
  551.  
  552.     clientevent->type = wireevent->type & 0x7f;
  553.     clientevent->serial = wireevent->sequenceNumber;
  554.     clientevent->send_event = (wireevent->type & 0x80) != 0;
  555.  
  556.  
  557.     /*
  558.      * MSB set if event came from SendEvent request.
  559.      */
  560.  
  561.     clientevent->display = display;
  562.     clientevent->renderer = wireevent->rdr;
  563.  
  564.  
  565.     /*
  566.      * Tell Xlib to add this to the event queue.
  567.      */
  568.  
  569.     return (True);
  570. }
  571.  
  572.  
  573. #define GetPickRecordSize(_pickType) \
  574.     (_pickType == PEXPickDeviceNPCHitVolume ? \
  575.     sizeof (PEXPDNPCHitVolume) : sizeof (PEXPDDCHitBox));
  576.  
  577.  
  578. void
  579. PEXBeginPickOne (display, drawable, renderer, structure_id,
  580.     method, pick_device_type, pick_record)
  581.  
  582. INPUT Display        *display;
  583. INPUT Drawable        drawable;
  584. INPUT PEXRenderer    renderer;
  585. INPUT long        structure_id;
  586. INPUT int        method;
  587. INPUT int        pick_device_type;
  588. INPUT PEXPickRecord    *pick_record;
  589. {
  590.     pexBeginPickOneReq    *req;
  591.     unsigned int     rec_size;
  592.     int            convertFP;
  593.     PEXEnumTypeIndex    *ptr;
  594.  
  595.  
  596.     /*
  597.      * Lock around the critical section, for multithreading.
  598.      */
  599.  
  600.     LockDisplay (display);
  601.  
  602.  
  603.     /*
  604.      * Put the request in the X request buffer.
  605.      */
  606.  
  607.     rec_size = GetPickRecordSize (pick_device_type);
  608.  
  609.     PEXGetFPReqExtra (BeginPickOne, (4 + rec_size), req, convertFP);
  610.     req->method = method;
  611.     req->rdr = renderer;
  612.     req->drawable = drawable;
  613.     req->sid = structure_id;
  614.  
  615.     ptr = (PEXEnumTypeIndex *) &req[1];
  616.     *ptr = pick_device_type;
  617.     ptr += 2;
  618.  
  619.     COPY_AREA ((char *) pick_record, (char *) ptr, rec_size);
  620.  
  621.  
  622.     /*
  623.      * Done, so unlock and check for synchronous-ness.
  624.      */
  625.  
  626.     UnlockDisplay (display);
  627.     PEXSyncHandle (display);
  628. }
  629.  
  630.  
  631. PEXPickPath *
  632. PEXEndPickOne (display, renderer, status_return, undetectable_return)
  633.  
  634. INPUT Display            *display;
  635. INPUT PEXRenderer        renderer;
  636. OUTPUT int            *status_return;
  637. OUTPUT int            *undetectable_return;
  638.  
  639. {
  640.     pexEndPickOneReq        *req;
  641.     pexEndPickOneReply        rep;
  642.     PEXPickPath            *pathRet;
  643.     unsigned int        size;
  644.  
  645.  
  646.     /*
  647.      * Lock around the critical section, for multithreading.
  648.      */
  649.  
  650.     LockDisplay (display);
  651.  
  652.  
  653.     /*
  654.      * Put the request in the X request buffer and get a reply.
  655.      */
  656.  
  657.     PEXGetReq (EndPickOne, req);
  658.     req->rdr = renderer;
  659.  
  660.     if (_XReply (display, &rep, 0, xFalse) == 0)
  661.     {
  662.         UnlockDisplay (display);
  663.         PEXSyncHandle (display);
  664.         return (NULL);               /* return an error */
  665.     }
  666.  
  667.     *status_return = rep.pickStatus;
  668.     *undetectable_return = rep.betterPick;
  669.  
  670.  
  671.     /*
  672.      * Allocate a buffer for the path to pass back to the client.
  673.      * If possible, use the pick path cache.
  674.      */
  675.  
  676.     size = sizeof (PEXPickPath) + 
  677.     rep.numPickElRefs * sizeof (PEXPickElementRef);
  678.  
  679.     if (!PEXPickCacheInUse && size <= PEXPickCacheSize)
  680.     {
  681.     pathRet = PEXPickCache;
  682.     PEXPickCacheInUse = 1;
  683.     }
  684.     else
  685.     pathRet = (PEXPickPath *) PEXAllocBuf ((unsigned) size);
  686.  
  687.     pathRet->elements = (PEXPickElementRef *) (pathRet + 1);
  688.     pathRet->count = rep.numPickElRefs;
  689.  
  690.     _XRead (display, (char *) (pathRet->elements), (long) (rep.length << 2));
  691.  
  692.  
  693.     /*
  694.      * Done, so unlock and check for synchronous-ness.
  695.      */
  696.  
  697.     UnlockDisplay (display);
  698.     PEXSyncHandle (display);
  699.  
  700.     return (pathRet);
  701. }
  702.  
  703.  
  704. PEXPickPath *
  705. PEXPickOne (display, drawable, renderer, structure, method,
  706.     pick_device_type, pick_record, status_return, undetectable_return)
  707.  
  708. INPUT Display            *display;
  709. INPUT Drawable            drawable;
  710. INPUT PEXRenderer        renderer;
  711. INPUT PEXStructure          structure;
  712. INPUT int            method;
  713. INPUT int            pick_device_type;
  714. INPUT PEXPickRecord        *pick_record;
  715. OUTPUT int            *status_return;
  716. OUTPUT int            *undetectable_return;
  717.  
  718. {
  719.     pexPickOneReq    *req;
  720.     pexPickOneReply    rep;
  721.     unsigned int     rec_size, size;
  722.     int            convertFP;
  723.     PEXEnumTypeIndex    *ptr;
  724.     PEXPickPath        *pathRet;
  725.  
  726.  
  727.     /*
  728.      * Lock around the critical section, for multithreading.
  729.      */
  730.  
  731.     LockDisplay (display);
  732.  
  733.  
  734.     /*
  735.      * Put the request in the X request buffer and get a reply.
  736.      */
  737.  
  738.     rec_size = GetPickRecordSize (pick_device_type);
  739.  
  740.     PEXGetFPReqExtra (PickOne, (4 + rec_size), req, convertFP);
  741.     req->method = method;
  742.     req->rdr = renderer;
  743.     req->drawable = drawable;
  744.     req->sid = structure;
  745.  
  746.     ptr = (PEXEnumTypeIndex *) &req[1];
  747.     *ptr = pick_device_type;
  748.     ptr += 2;
  749.  
  750.     COPY_AREA ((char *) pick_record, (char *) ptr, rec_size);
  751.  
  752.     if (_XReply (display, &rep, 0, xFalse) == 0)
  753.     {
  754.         UnlockDisplay (display);
  755.         PEXSyncHandle (display);
  756.         return (NULL);               /* return an error */
  757.     }
  758.  
  759.     *status_return = rep.pickStatus;
  760.     *undetectable_return = rep.betterPick;
  761.  
  762.  
  763.     /*
  764.      * Allocate a buffer for the path to pass back to the client.
  765.      * If possible, use the pick path cache.
  766.      */
  767.  
  768.     size = sizeof (PEXPickPath) + 
  769.     rep.numPickElRefs * sizeof (PEXPickElementRef);
  770.  
  771.     if (!PEXPickCacheInUse && size <= PEXPickCacheSize)
  772.     {
  773.     pathRet = PEXPickCache;
  774.     PEXPickCacheInUse = 1;
  775.     }
  776.     else
  777.     pathRet = (PEXPickPath *) PEXAllocBuf ((unsigned) size);
  778.  
  779.     pathRet->elements = (PEXPickElementRef *) (pathRet + 1);
  780.     pathRet->count = rep.numPickElRefs;
  781.  
  782.     _XRead (display, (char *) (pathRet->elements), (long) (rep.length << 2));
  783.  
  784.  
  785.     /*
  786.      * Done, so unlock and check for synchronous-ness.
  787.      */
  788.  
  789.     UnlockDisplay (display);
  790.     PEXSyncHandle (display);
  791.  
  792.     return (pathRet);
  793. }
  794.  
  795.  
  796. void
  797. PEXBeginPickAll (display, drawable, renderer, structure_id, method,
  798.     send_event, max_hits, pick_device_type, pick_record)
  799.  
  800. INPUT Display        *display;
  801. INPUT Drawable        drawable;
  802. INPUT PEXRenderer    renderer;
  803. INPUT long        structure_id;
  804. INPUT int        method;
  805. INPUT int        send_event;
  806. INPUT int        max_hits;
  807. INPUT int        pick_device_type;
  808. INPUT PEXPickRecord    *pick_record;
  809. {
  810.     pexBeginPickAllReq    *req;
  811.     unsigned int    rec_size;
  812.     int            convertFP;
  813.     PEXEnumTypeIndex    *ptr;
  814.  
  815.  
  816.     /*
  817.      * Lock around the critical section, for multithreading.
  818.      */
  819.  
  820.     LockDisplay (display);
  821.  
  822.  
  823.     /*
  824.      * Put the request in the X request buffer.
  825.      */
  826.  
  827.     rec_size = GetPickRecordSize (pick_device_type);
  828.  
  829.     PEXGetFPReqExtra (BeginPickAll, (4 + rec_size), req, convertFP);
  830.     req->method = method;
  831.     req->rdr = renderer;
  832.     req->drawable = drawable;
  833.     req->sid = structure_id;
  834.     req->sendEvent = send_event;
  835.     req->pickMaxHits = max_hits;
  836.  
  837.     ptr = (PEXEnumTypeIndex *) &req[1];
  838.     *ptr = pick_device_type;
  839.     ptr += 2;
  840.  
  841.     COPY_AREA ((char *) pick_record, (char *) ptr, rec_size);
  842.  
  843.  
  844.     /*
  845.      * Done, so unlock and check for synchronous-ness.
  846.      */
  847.  
  848.     UnlockDisplay (display);
  849.     PEXSyncHandle (display);
  850. }
  851.  
  852.  
  853. PEXPickPath *
  854. PEXEndPickAll (display, renderer, status_return, more_return, count_return)
  855.  
  856. INPUT Display        *display;
  857. INPUT PEXRenderer    renderer;
  858. OUTPUT int        *status_return;
  859. OUTPUT int        *more_return;
  860. OUTPUT unsigned long    *count_return;
  861.  
  862. {
  863.     pexEndPickAllReq        *req;
  864.     pexEndPickAllReply        rep;
  865.     PEXPickPath            *psp, *pspRet;
  866.     char            *prep, *prep_save;
  867.     PEXPickElementRef        *per;
  868.     int                i;
  869.     int                numElements;
  870.     unsigned int        total_size, size;
  871.  
  872.  
  873.     /*
  874.      * Lock around the critical section, for multithreading.
  875.      */
  876.  
  877.     LockDisplay (display);
  878.  
  879.  
  880.     /*
  881.      * Put the request in the X request buffer and get a reply.
  882.      */
  883.  
  884.     PEXGetReq (EndPickAll, req);
  885.     req->rdr = renderer;
  886.  
  887.     if (_XReply (display, &rep, 0, xFalse) == 0)
  888.     {
  889.         UnlockDisplay (display);
  890.         PEXSyncHandle (display);
  891.     *count_return = 0;
  892.     return (NULL);           /* return an error */
  893.     }
  894.  
  895.     *status_return = rep.pickStatus;
  896.     *more_return = rep.morePicks;
  897.     *count_return = rep.numPicked;
  898.  
  899.  
  900.     /*
  901.      * Allocate a scratch buffer and copy the reply data to the buffer.
  902.      */
  903.  
  904.     prep = _XAllocScratch (display, (unsigned long) (rep.length << 2));
  905.  
  906.     _XRead (display, (char *) prep, (long) (rep.length << 2));
  907.  
  908.  
  909.     /*
  910.      * Allocate a buffer for the replies to pass back to the client.
  911.      * If possible, use the pick path cache.
  912.      */
  913.  
  914.     prep_save = prep;
  915.     total_size = rep.numPicked * sizeof (PEXPickPath);
  916.  
  917.     for (i = 0; i < rep.numPicked; i++)
  918.     {
  919.     numElements = *((CARD32 *) prep);
  920.     prep += sizeof (CARD32);
  921.     size = numElements * sizeof (PEXPickElementRef);
  922.     prep += size;
  923.     total_size += size;
  924.     }
  925.  
  926.     if (!PEXPickCacheInUse && total_size <= PEXPickCacheSize)
  927.     {
  928.     pspRet = PEXPickCache;
  929.     PEXPickCacheInUse = 1;
  930.     }
  931.     else
  932.     pspRet = (PEXPickPath *) PEXAllocBuf ((unsigned) total_size);
  933.  
  934.     psp = pspRet;
  935.     prep = prep_save;
  936.     per = (PEXPickElementRef *) ((char *) psp +
  937.     rep.numPicked * sizeof (PEXPickPath));
  938.  
  939.     for (i = 0; i < rep.numPicked; i++)
  940.     {
  941.     numElements = *((CARD32 *) prep);
  942.     prep += sizeof (CARD32);
  943.     size = numElements * sizeof (PEXPickElementRef);
  944.     COPY_AREA (prep, (char *) per, size);
  945.     psp->count = numElements;
  946.     psp->elements = per;
  947.     psp++;
  948.     per += numElements;
  949.     prep += size;
  950.     }
  951.  
  952.  
  953.     /*
  954.      * Done, so unlock and check for synchronous-ness.
  955.      */
  956.  
  957.     UnlockDisplay (display);
  958.     PEXSyncHandle (display);
  959.  
  960.     return (pspRet);
  961. }
  962.  
  963.  
  964. PEXPickPath *
  965. PEXPickAll (display, drawable, renderer, method, max_hits, pick_device_type,
  966.     pick_record, status_return, more_return, count_return)
  967.  
  968. INPUT Display        *display;
  969. INPUT Drawable        drawable;
  970. INPUT PEXRenderer    renderer;
  971. INPUT int        method;
  972. INPUT int        max_hits;
  973. INPUT int        pick_device_type;
  974. INPUT PEXPickRecord    *pick_record;
  975. OUTPUT int        *status_return;
  976. OUTPUT int        *more_return;
  977. OUTPUT unsigned long    *count_return;
  978.  
  979.  
  980. {
  981.     pexPickAllReq        *req;
  982.     pexPickAllReply        rep;
  983.     PEXPickPath            *psp, *pspRet;
  984.     char            *prep, *prep_save;
  985.     PEXPickElementRef        *per;
  986.     int                numElements, i;
  987.     unsigned int        rec_size, total_size, size;
  988.     int                convertFP;
  989.     PEXEnumTypeIndex        *ptr;
  990.  
  991.  
  992.     /*
  993.      * Lock around the critical section, for multithreading.
  994.      */
  995.  
  996.     LockDisplay (display);
  997.  
  998.  
  999.     /*
  1000.      * Put the request in the X request buffer and get a reply.
  1001.      */
  1002.  
  1003.     rec_size = GetPickRecordSize (pick_device_type);
  1004.  
  1005.     PEXGetFPReqExtra (PickAll, (4 + rec_size), req, convertFP);
  1006.     req->method = method;
  1007.     req->rdr = renderer;
  1008.     req->drawable = drawable;
  1009.     req->pickMaxHits = max_hits;
  1010.  
  1011.     ptr = (PEXEnumTypeIndex *) &req[1];
  1012.     *ptr = pick_device_type;
  1013.     ptr += 2;
  1014.  
  1015.     COPY_AREA ((char *) pick_record, (char *) ptr, rec_size);
  1016.  
  1017.     if (_XReply (display, &rep, 0, xFalse) == 0)
  1018.     {
  1019.         UnlockDisplay (display);
  1020.         PEXSyncHandle (display);
  1021.     *count_return = 0;
  1022.     return (NULL);           /* return an error */
  1023.     }
  1024.  
  1025.     *status_return = rep.pickStatus;
  1026.     *more_return = rep.morePicks;
  1027.     *count_return = rep.numPicked;
  1028.  
  1029.  
  1030.     /*
  1031.      * Allocate a scratch buffer and copy the reply data to the buffer.
  1032.      */
  1033.  
  1034.     prep = _XAllocScratch (display, (unsigned long) (rep.length << 2));
  1035.  
  1036.     _XRead (display, (char *) prep, (long) (rep.length << 2));
  1037.  
  1038.  
  1039.     /*
  1040.      * Allocate a buffer for the replies to pass back to the client.
  1041.      * If possible, use the pick path cache.
  1042.      */
  1043.  
  1044.     prep_save = prep;
  1045.     total_size = rep.numPicked * sizeof (PEXPickPath);
  1046.  
  1047.     for (i = 0; i < rep.numPicked; i++)
  1048.     {
  1049.     numElements = *((CARD32 *) prep);
  1050.     prep += sizeof (CARD32);
  1051.     size = numElements * sizeof (PEXPickElementRef);
  1052.     prep += size;
  1053.     total_size += size;
  1054.     }
  1055.  
  1056.     if (!PEXPickCacheInUse && total_size <= PEXPickCacheSize)
  1057.     {
  1058.     pspRet = PEXPickCache;
  1059.     PEXPickCacheInUse = 1;
  1060.     }
  1061.     else
  1062.     pspRet = (PEXPickPath *) PEXAllocBuf ((unsigned) total_size);
  1063.  
  1064.     psp = pspRet;
  1065.     prep = prep_save;
  1066.     per = (PEXPickElementRef *) ((char *) psp +
  1067.     rep.numPicked * sizeof (PEXPickPath));
  1068.  
  1069.     for (i = 0; i < rep.numPicked; i++)
  1070.     {
  1071.     numElements = *((CARD32 *) prep);
  1072.     prep += sizeof (CARD32);
  1073.     size = numElements * sizeof (PEXPickElementRef);
  1074.     COPY_AREA (prep, (char *) per, size);
  1075.     psp->count = numElements;
  1076.     psp->elements = per;
  1077.     psp++;
  1078.     per += numElements;
  1079.     prep += size;
  1080.     }
  1081.  
  1082.  
  1083.     /*
  1084.      * Done, so unlock and check for synchronous-ness.
  1085.      */
  1086.  
  1087.     UnlockDisplay (display);
  1088.     PEXSyncHandle (display);
  1089.  
  1090.     return (pspRet);
  1091. }
  1092.