/*
*
* Copyright © 2000 SuSE, 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 of SuSE not be used in advertising or
* publicity pertaining to distribution of the software without specific,
* written prior permission. SuSE makes no representations about the
* suitability of this software for any purpose. It is provided "as is"
* without express or implied warranty.
*
* SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
* 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.
*
* Author: Keith Packard, SuSE, Inc.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "Xrenderint.h"
XRenderExtInfo XRenderExtensionInfo;
char XRenderExtensionName[] = RENDER_NAME;
static int XRenderCloseDisplay (Display *dpy, XExtCodes *codes);
/*
* XRenderExtFindDisplay - look for a display in this extension; keeps a
* cache of the most-recently used for efficiency. (Replaces
* XextFindDisplay.)
*/
static XRenderExtDisplayInfo *
XRenderExtFindDisplay (XRenderExtInfo *extinfo,
Display *dpy)
{
XRenderExtDisplayInfo *dpyinfo;
/*
* see if this was the most recently accessed display
*/
if ((dpyinfo = extinfo->cur) && dpyinfo->display == dpy)
return dpyinfo;
/*
* look for display in list
*/
_XLockMutex(_Xglobal_lock);
for (dpyinfo = extinfo->head; dpyinfo; dpyinfo = dpyinfo->next) {
if (dpyinfo->display == dpy) {
extinfo->cur = dpyinfo; /* cache most recently used */
_XUnlockMutex(_Xglobal_lock);
return dpyinfo;
}
}
_XUnlockMutex(_Xglobal_lock);
return NULL;
}
/*
* If the server is missing support for any of the required depths on
* any screen, tell the application that Render is not present.
*/
#define DEPTH_MASK(d) (1 << ((d) - 1))
/*
* Render requires support for depth 1, 4, 8, 24 and 32 pixmaps
*/
#define REQUIRED_DEPTHS (DEPTH_MASK(1) | \
DEPTH_MASK(4) | \
DEPTH_MASK(8) | \
DEPTH_MASK(24) | \
DEPTH_MASK(32))
typedef struct _DepthCheckRec {
struct _DepthCheckRec *next;
Display *dpy;
CARD32 missing;
unsigned long serial;
} DepthCheckRec, *DepthCheckPtr;
static DepthCheckPtr depthChecks;
static int
XRenderDepthCheckErrorHandler (Display *dpy, XErrorEvent *evt)
{
if (evt->request_code == X_CreatePixmap && evt->error_code == BadValue)
{
DepthCheckPtr d;
_XLockMutex(_Xglobal_lock);
for (d = depthChecks; d; d = d->next)
if (d->dpy == dpy)
{
if ((long) (evt->serial - d->serial) >= 0)
d->missing |= DEPTH_MASK(evt->resourceid);
break;
}
_XUnlockMutex (_Xglobal_lock);
}
return 0;
}
static Bool
XRenderHasDepths (Display *dpy)
{
int s;
for (s = 0; s < ScreenCount (dpy); s++)
{
CARD32 depths = 0;
CARD32 missing;
Screen *scr = ScreenOfDisplay (dpy, s);
int d;
for (d = 0; d < scr->ndepths; d++)
depths |= DEPTH_MASK(scr->depths[d].depth);
missing = ~depths & REQUIRED_DEPTHS;
if (missing)
{
DepthCheckRec dc, **dp;
XErrorHandler previousHandler;
/*
* Ok, this is ugly. It should be sufficient at this
* point to just return False, but Xinerama is broken at
* this point and only advertises depths which have an
* associated visual. Of course, the other depths still
* work, but the only way to find out is to try them.
*/
dc.dpy = dpy;
dc.missing = 0;
dc.serial = XNextRequest (dpy);
_XLockMutex(_Xglobal_lock);
dc.next = depthChecks;
depthChecks = &dc;
_XUnlockMutex (_Xglobal_lock);
/*
* I suspect this is not really thread safe, but Xlib doesn't
* provide a lot of options here
*/
previousHandler = XSetErrorHandler (XRenderDepthCheckErrorHandler);
/*
* Try each missing depth and see if pixmap creation succeeds
*/
for (d = 1; d <= 32; d++)
/* don't check depth 1 == Xcursor recurses... */
if ((missing & DEPTH_MASK(d)) && d != 1)
{
Pixmap p;
p = XCreatePixmap (dpy, RootWindow (dpy, s), 1, 1, d);
XFreePixmap (dpy, p);
}
XSync (dpy, False);
XSetErrorHandler (previousHandler);
/*
* Unhook from the list of depth check records
*/
_XLockMutex(_Xglobal_lock);
for (dp = &depthChecks; *dp; dp = &(*dp)->next)
{
if (*dp == &dc)
{
*dp = dc.next;
break;
}
}
_XUnlockMutex (_Xglobal_lock);
if (dc.missing)
return False;
}
}
return True;
}
/*
* XRenderExtAddDisplay - add a display to this extension. (Replaces
* XextAddDisplay)
*/
static XRenderExtDisplayInfo *
XRenderExtAddDisplay (XRenderExtInfo *extinfo,
Display *dpy,
char *ext_name)
{
XRenderExtDisplayInfo *dpyinfo;
dpyinfo = (XRenderExtDisplayInfo *) Xmalloc (sizeof (XRenderExtDisplayInfo));
if (!dpyinfo) return NULL;
dpyinfo->display = dpy;
dpyinfo->info = NULL;
if (XRenderHasDepths (dpy))
dpyinfo->codes = XInitExtension (dpy, ext_name);
else
dpyinfo->codes = NULL;
/*
* if the server has the extension, then we can initialize the
* appropriate function vectors
*/
if (dpyinfo->codes) {
XESetCloseDisplay (dpy, dpyinfo->codes->extension,
XRenderCloseDisplay);
} else {
/* The server doesn't have this extension.
* Use a private Xlib-internal extension to hang the close_display
* hook on so that the "cache" (extinfo->cur) is properly cleaned.
* (XBUG 7955)
*/
XExtCodes *codes = XAddExtension(dpy);
if (!codes) {
XFree(dpyinfo);
return NULL;
}
XESetCloseDisplay (dpy, codes->extension, XRenderCloseDisplay);
}
/*
* now, chain it onto the list
*/
_XLockMutex(_Xglobal_lock);
dpyinfo->next = extinfo->head;
extinfo->head = dpyinfo;
extinfo->cur = dpyinfo;
extinfo->ndisplays++;
_XUnlockMutex(_Xglobal_lock);
return dpyinfo;
}
/*
* XRenderExtRemoveDisplay - remove the indicated display from the
* extension object. (Replaces XextRemoveDisplay.)
*/
static int
XRenderExtRemoveDisplay (XRenderExtInfo *extinfo, Display *dpy)
{
XRenderExtDisplayInfo *dpyinfo, *prev;
/*
* locate this display and its back link so that it can be removed
*/
_XLockMutex(_Xglobal_lock);
prev = NULL;
for (dpyinfo = extinfo->head; dpyinfo; dpyinfo = dpyinfo->next) {
if (dpyinfo->display == dpy) break;
prev = dpyinfo;
}
if (!dpyinfo) {
_XUnlockMutex(_Xglobal_lock);
return 0; /* hmm, actually an error */
}
/*
* remove the display from the list; handles going to zero
*/
if (prev)
prev->next = dpyinfo->next;
else
extinfo->head = dpyinfo->next;
extinfo->ndisplays--;
if (dpyinfo == extinfo->cur) extinfo->cur = NULL; /* flush cache */
_XUnlockMutex(_Xglobal_lock);
Xfree ((char *) dpyinfo);
return 1;
}
XRenderExtDisplayInfo *
XRenderFindDisplay (Display *dpy)
{
XRenderExtDisplayInfo *dpyinfo;
dpyinfo = XRenderExtFindDisplay (&XRenderExtensionInfo, dpy);
if (!dpyinfo)
dpyinfo = XRenderExtAddDisplay (&XRenderExtensionInfo, dpy,
XRenderExtensionName);
return dpyinfo;
}
static int
XRenderCloseDisplay (Display *dpy, XExtCodes *codes)
{
XRenderExtDisplayInfo *info = XRenderFindDisplay (dpy);
if (info && info->info) XFree (info->info);
return XRenderExtRemoveDisplay (&XRenderExtensionInfo, dpy);
}
/****************************************************************************
* *
* Render public interfaces *
* *
****************************************************************************/
Bool XRenderQueryExtension (Display *dpy, int *event_basep, int *error_basep)
{
XRenderExtDisplayInfo *info = XRenderFindDisplay (dpy);
if (RenderHasExtension(info)) {
*event_basep = info->codes->first_event;
*error_basep = info->codes->first_error;
return True;
} else {
return False;
}
}
Status XRenderQueryVersion (Display *dpy,
int *major_versionp,
int *minor_versionp)
{
XRenderExtDisplayInfo *info = XRenderFindDisplay (dpy);
XRenderInfo *xri;
if (!RenderHasExtension (info))
return 0;
if (!XRenderQueryFormats (dpy))
return 0;
xri = info->info;
*major_versionp = xri->major_version;
*minor_versionp = xri->minor_version;
return 1;
}
static XRenderPictFormat *
_XRenderFindFormat (XRenderInfo *xri, PictFormat format)
{
int nf;
for (nf = 0; nf < xri->nformat; nf++)
if (xri->format[nf].id == format)
return &xri->format[nf];
return 0;
}
static Visual *
_XRenderFindVisual (Display *dpy, VisualID vid)
{
return _XVIDtoVisual (dpy, vid);
}
typedef struct _renderVersionState {
unsigned long version_seq;
Bool error;
int major_version;
int minor_version;
} _XrenderVersionState;
static Bool
_XRenderVersionHandler (Display *dpy,
xReply *rep,
char *buf,
int len,
XPointer data)
{
xRenderQueryVersionReply replbuf;
xRenderQueryVersionReply *repl;
_XrenderVersionState *state = (_XrenderVersionState *) data;
if (dpy->last_request_read != state->version_seq)
return False;
if (rep->generic.type == X_Error)
{
state->error = True;
return False;
}
repl = (xRenderQueryVersionReply *)
_XGetAsyncReply(dpy, (char *)&replbuf, rep, buf, len,
(SIZEOF(xRenderQueryVersionReply) - SIZEOF(xReply)) >> 2,
True);
state->major_version = repl->majorVersion;
state->minor_version = repl->minorVersion;
return True;
}
Status
XRenderQueryFormats (Display *dpy)
{
XRenderExtDisplayInfo *info = XRenderFindDisplay (dpy);
_XAsyncHandler async;
_XrenderVersionState async_state;
xRenderQueryVersionReq *vreq;
xRenderQueryPictFormatsReply rep;
xRenderQueryPictFormatsReq *req;
XRenderInfo *xri;
XRenderPictFormat *format;
XRenderScreen *screen;
XRenderDepth *depth;
XRenderVisual *visual;
xPictFormInfo *xFormat;
xPictScreen *xScreen;
xPictDepth *xDepth;
xPictVisual *xVisual;
CARD32 *xSubpixel;
void *xData;
int nf, ns, nd, nv;
int rlength;
int nbytes;
RenderCheckExtension (dpy, info, 0);
LockDisplay (dpy);
if (info->info)
{
UnlockDisplay (dpy);
return 1;
}
GetReq (RenderQueryVersion, vreq);
vreq->reqType = info->codes->major_opcode;
vreq->renderReqType = X_RenderQueryVersion;
vreq->majorVersion = RENDER_MAJOR;
vreq->minorVersion = RENDER_MINOR;
async_state.version_seq = dpy->request;
async_state.error = False;
async.next = dpy->async_handlers;
async.handler = _XRenderVersionHandler;
async.data = (XPointer) &async_state;
dpy->async_handlers = &async;
GetReq (RenderQueryPictFormats, req);
req->reqType = info->codes->major_opcode;
req->renderReqType = X_RenderQueryPictFormats;
if (!_XReply (dpy, (xReply *) &rep, 0, xFalse))
{
DeqAsyncHandler (dpy, &async);
UnlockDisplay (dpy);
SyncHandle ();
return 0;
}
DeqAsyncHandler (dpy, &async);
if (async_state.error)
{
UnlockDisplay(dpy);
SyncHandle();
return 0;
}
/*
* Check for the lack of sub-pixel data
*/
if (async_state.major_version == 0 && async_state.minor_version < 6)
rep.numSubpixel = 0;
xri = (XRenderInfo *) Xmalloc (sizeof (XRenderInfo) +
rep.numFormats * sizeof (XRenderPictFormat) +
rep.numScreens * sizeof (XRenderScreen) +
rep.numDepths * sizeof (XRenderDepth) +
rep.numVisuals * sizeof (XRenderVisual));
rlength = (rep.numFormats * sizeof (xPictFormInfo) +
rep.numScreens * sizeof (xPictScreen) +
rep.numDepths * sizeof (xPictDepth) +
rep.numVisuals * sizeof (xPictVisual) +
rep.numSubpixel * 4);
xData = (void *) Xmalloc (rlength);
nbytes = (int) rep.length << 2;
if (!xri || !xData || nbytes < rlength)
{
if (xri) Xfree (xri);
if (xData) Xfree (xData);
_XEatData (dpy, nbytes);
UnlockDisplay (dpy);
SyncHandle ();
return 0;
}
xri->major_version = async_state.major_version;
xri->minor_version = async_state.minor_version;
xri->format = (XRenderPictFormat *) (xri + 1);
xri->nformat = rep.numFormats;
xri->screen = (XRenderScreen *) (xri->format + rep.numFormats);
xri->nscreen = rep.numScreens;
xri->depth = (XRenderDepth *) (xri->screen + rep.numScreens);
xri->ndepth = rep.numDepths;
xri->visual = (XRenderVisual *) (xri->depth + rep.numDepths);
xri->nvisual = rep.numVisuals;
_XRead (dpy, (char *) xData, rlength);
format = xri->format;
xFormat = (xPictFormInfo *) xData;
for (nf = 0; nf < rep.numFormats; nf++)
{
format->id = xFormat->id;
format->type = xFormat->type;
format->depth = xFormat->depth;
format->direct.red = xFormat->direct.red;
format->direct.redMask = xFormat->direct.redMask;
format->direct.green = xFormat->direct.green;
format->direct.greenMask = xFormat->direct.greenMask;
format->direct.blue = xFormat->direct.blue;
format->direct.blueMask = xFormat->direct.blueMask;
format->direct.alpha = xFormat->direct.alpha;
format->direct.alphaMask = xFormat->direct.alphaMask;
format->colormap = xFormat->colormap;
format++;
xFormat++;
}
xScreen = (xPictScreen *) xFormat;
screen = xri->screen;
depth = xri->depth;
visual = xri->visual;
for (ns = 0; ns < xri->nscreen; ns++)
{
screen->depths = depth;
screen->ndepths = xScreen->nDepth;
screen->fallback = _XRenderFindFormat (xri, xScreen->fallback);
screen->subpixel = SubPixelUnknown;
xDepth = (xPictDepth *) (xScreen + 1);
for (nd = 0; nd < screen->ndepths; nd++)
{
depth->depth = xDepth->depth;
depth->nvisuals = xDepth->nPictVisuals;
depth->visuals = visual;
xVisual = (xPictVisual *) (xDepth + 1);
for (nv = 0; nv < depth->nvisuals; nv++)
{
visual->visual = _XRenderFindVisual (dpy, xVisual->visual);
visual->format = _XRenderFindFormat (xri, xVisual->format);
visual++;
xVisual++;
}
depth++;
xDepth = (xPictDepth *) xVisual;
}
screen++;
xScreen = (xPictScreen *) xDepth;
}
xSubpixel = (CARD32 *) xScreen;
screen = xri->screen;
for (ns = 0; ns < rep.numSubpixel; ns++)
{
screen->subpixel = *xSubpixel;
xSubpixel++;
screen++;
}
info->info = xri;
/*
* Skip any extra data
*/
if (nbytes > rlength)
_XEatData (dpy, (unsigned long) (nbytes - rlength));
UnlockDisplay (dpy);
SyncHandle ();
Xfree (xData);
return 1;
}
int
XRenderQuerySubpixelOrder (Display *dpy, int screen)
{
XRenderExtDisplayInfo *info = XRenderFindDisplay (dpy);
XRenderInfo *xri;
if (!RenderHasExtension (info))
return SubPixelUnknown;
if (!XRenderQueryFormats (dpy))
return SubPixelUnknown;
xri = info->info;
return xri->screen[screen].subpixel;
}
Bool
XRenderSetSubpixelOrder (Display *dpy, int screen, int subpixel)
{
XRenderExtDisplayInfo *info = XRenderFindDisplay (dpy);
XRenderInfo *xri;
if (!RenderHasExtension (info))
return False;
if (!XRenderQueryFormats (dpy))
return False;
xri = info->info;
xri->screen[screen].subpixel = subpixel;
return True;
}
XRenderPictFormat *
XRenderFindVisualFormat (Display *dpy, _Xconst Visual *visual)
{
XRenderExtDisplayInfo *info = XRenderFindDisplay (dpy);
int nv;
XRenderInfo *xri;
XRenderVisual *xrv;
RenderCheckExtension (dpy, info, 0);
if (!XRenderQueryFormats (dpy))
return 0;
xri = info->info;
for (nv = 0, xrv = xri->visual; nv < xri->nvisual; nv++, xrv++)
if (xrv->visual == visual)
return xrv->format;
return 0;
}
XRenderPictFormat *
XRenderFindFormat (Display *dpy,
unsigned long mask,
_Xconst XRenderPictFormat *template,
int count)
{
XRenderExtDisplayInfo *info = XRenderFindDisplay (dpy);
int nf;
XRenderInfo *xri;
RenderCheckExtension (dpy, info, 0);
if (!XRenderQueryFormats (dpy))
return 0;
xri = info->info;
for (nf = 0; nf < xri->nformat; nf++)
{
if (mask & PictFormatID)
if (template->id != xri->format[nf].id)
continue;
if (mask & PictFormatType)
if (template->type != xri->format[nf].type)
continue;
if (mask & PictFormatDepth)
if (template->depth != xri->format[nf].depth)
continue;
if (mask & PictFormatRed)
if (template->direct.red != xri->format[nf].direct.red)
continue;
if (mask & PictFormatRedMask)
if (template->direct.redMask != xri->format[nf].direct.redMask)
continue;
if (mask & PictFormatGreen)
if (template->direct.green != xri->format[nf].direct.green)
continue;
if (mask & PictFormatGreenMask)
if (template->direct.greenMask != xri->format[nf].direct.greenMask)
continue;
if (mask & PictFormatBlue)
if (template->direct.blue != xri->format[nf].direct.blue)
continue;
if (mask & PictFormatBlueMask)
if (template->direct.blueMask != xri->format[nf].direct.blueMask)
continue;
if (mask & PictFormatAlpha)
if (template->direct.alpha != xri->format[nf].direct.alpha)
continue;
if (mask & PictFormatAlphaMask)
if (template->direct.alphaMask != xri->format[nf].direct.alphaMask)
continue;
if (mask & PictFormatColormap)
if (template->colormap != xri->format[nf].colormap)
continue;
if (count-- == 0)
return &xri->format[nf];
}
return 0;
}
XRenderPictFormat *
XRenderFindStandardFormat (Display *dpy,
int format)
{
static struct {
XRenderPictFormat templ;
unsigned long mask;
} standardFormats[PictStandardNUM] = {
/* PictStandardARGB32 */
{
{
0, /* id */
PictTypeDirect, /* type */
32, /* depth */
{ /* direct */
16, /* direct.red */
0xff, /* direct.redMask */
8, /* direct.green */
0xff, /* direct.greenMask */
0, /* direct.blue */
0xff, /* direct.blueMask */
24, /* direct.alpha */
0xff, /* direct.alphaMask */
},
0, /* colormap */
},
PictFormatType |
PictFormatDepth |
PictFormatRed |
PictFormatRedMask |
PictFormatGreen |
PictFormatGreenMask |
PictFormatBlue |
PictFormatBlueMask |
PictFormatAlpha |
PictFormatAlphaMask,
},
/* PictStandardRGB24 */
{
{
0, /* id */
PictTypeDirect, /* type */
24, /* depth */
{ /* direct */
16, /* direct.red */
0xff, /* direct.redMask */
8, /* direct.green */
0xff, /* direct.greenMask */
0, /* direct.blue */
0xff, /* direct.blueMask */
0, /* direct.alpha */
0x00, /* direct.alphaMask */
},
0, /* colormap */
},
PictFormatType |
PictFormatDepth |
PictFormatRed |
PictFormatRedMask |
PictFormatGreen |
PictFormatGreenMask |
PictFormatBlue |
PictFormatBlueMask |
PictFormatAlphaMask,
},
/* PictStandardA8 */
{
{
0, /* id */
PictTypeDirect, /* type */
8, /* depth */
{ /* direct */
0, /* direct.red */
0x00, /* direct.redMask */
0, /* direct.green */
0x00, /* direct.greenMask */
0, /* direct.blue */
0x00, /* direct.blueMask */
0, /* direct.alpha */
0xff, /* direct.alphaMask */
},
0, /* colormap */
},
PictFormatType |
PictFormatDepth |
PictFormatRedMask |
PictFormatGreenMask |
PictFormatBlueMask |
PictFormatAlpha |
PictFormatAlphaMask,
},
/* PictStandardA4 */
{
{
0, /* id */
PictTypeDirect, /* type */
4, /* depth */
{ /* direct */
0, /* direct.red */
0x00, /* direct.redMask */
0, /* direct.green */
0x00, /* direct.greenMask */
0, /* direct.blue */
0x00, /* direct.blueMask */
0, /* direct.alpha */
0x0f, /* direct.alphaMask */
},
0, /* colormap */
},
PictFormatType |
PictFormatDepth |
PictFormatRedMask |
PictFormatGreenMask |
PictFormatBlueMask |
PictFormatAlpha |
PictFormatAlphaMask,
},
/* PictStandardA1 */
{
{
0, /* id */
PictTypeDirect, /* type */
1, /* depth */
{ /* direct */
0, /* direct.red */
0x00, /* direct.redMask */
0, /* direct.green */
0x00, /* direct.greenMask */
0, /* direct.blue */
0x00, /* direct.blueMask */
0, /* direct.alpha */
0x01, /* direct.alphaMask */
},
0, /* colormap */
},
PictFormatType |
PictFormatDepth |
PictFormatRedMask |
PictFormatGreenMask |
PictFormatBlueMask |
PictFormatAlpha |
PictFormatAlphaMask,
},
};
if (0 <= format && format < PictStandardNUM)
return XRenderFindFormat (dpy,
standardFormats[format].mask,
&standardFormats[format].templ,
0);
return 0;
}
XIndexValue *
XRenderQueryPictIndexValues(Display *dpy,
_Xconst XRenderPictFormat *format,
int *num)
{
XRenderExtDisplayInfo *info = XRenderFindDisplay (dpy);
xRenderQueryPictIndexValuesReq *req;
xRenderQueryPictIndexValuesReply rep;
XIndexValue *values;
int nbytes, nread, rlength, i;
RenderCheckExtension (dpy, info, 0);
LockDisplay (dpy);
GetReq (RenderQueryPictIndexValues, req);
req->reqType = info->codes->major_opcode;
req->renderReqType = X_RenderQueryPictIndexValues;
req->format = format->id;
if (!_XReply (dpy, (xReply *) &rep, 0, xFalse))
{
UnlockDisplay (dpy);
SyncHandle ();
return 0;
}
/* request data length */
nbytes = (long)rep.length << 2;
/* bytes of actual data in the request */
nread = rep.numIndexValues * SIZEOF (xIndexValue);
/* size of array returned to application */
rlength = rep.numIndexValues * sizeof (XIndexValue);
/* allocate returned data */
values = (XIndexValue *)Xmalloc (rlength);
if (!values)
{
_XEatData (dpy, nbytes);
UnlockDisplay (dpy);
SyncHandle ();
return 0;
}
/* read the values one at a time and convert */
*num = rep.numIndexValues;
for(i = 0; i < rep.numIndexValues; i++)
{
xIndexValue value;
_XRead (dpy, (char *) &value, SIZEOF (xIndexValue));
values[i].pixel = value.pixel;
values[i].red = value.red;
values[i].green = value.green;
values[i].blue = value.blue;
values[i].alpha = value.alpha;
}
/* skip any padding */
if(nbytes > nread)
{
_XEatData (dpy, (unsigned long) (nbytes - nread));
}
UnlockDisplay (dpy);
SyncHandle ();
return values;
}
|