#include #include #include "lx.h" #include "internal.h" typedef struct lookup_color_priv LOOKUP_COLOR_PRIV; struct lookup_color_priv { LX_OP *op; int *succp; void (*done)(LX_CONN *, const unsigned char *, void *); void *reqarg; } ; static void done_lookup_color(LX_CONN *xc, const unsigned char *rep, void *pv) { LOOKUP_COLOR_PRIV *p; LX_OP *op; p = pv; if (p->succp) *p->succp = 1; op = xc->pendf; op->done = p->done; op->reqarg = p->reqarg; free(p); (*op->done)(xc,rep,op->reqarg); } static int err_lookup_color(LX_CONN *xc __attribute__((__unused__)), const LX_X_ERR *e, void *pv) { LOOKUP_COLOR_PRIV *p; if (e->type != LXXE_Name) return(0); p = pv; if (p->succp) *p->succp = 0; free(p); return(1); } /* * There's a bit of an issue here. * * We'd like, for example, #fff to be equivalent to #ffffffffffff. But * we'd also like #888 to be equivalent to #800080008000. I don't see * any good way to get both, so I'm considering the former more * important and going with the code below. */ static LX_OP *do_lookup_color(const char *call, LX_CONN *xc, LX_XID cmap, const char *name, int namelen, unsigned int *r, unsigned int *g, unsigned int *b, int *succp) { int i; LX_OP *op; LOOKUP_COLOR_PRIV *priv; if (xc->flags & XCF_FAIL) { lx__bad_call(xc,call); return(0); } if (namelen == -1) namelen = strlen(name); if ((namelen > 0) && (name[0] == '#')) { unsigned int mask; unsigned int mul; unsigned int rgbshift; unsigned int fieldshift; unsigned long long int v; int dv; v = 0; switch <"fail"> (namelen) { case 4: mask = 0x000f; mul = 0x1111; rgbshift = 0; fieldshift = 4; if (0) { case 7: mask = 0x00ff; mul = 0x0101; rgbshift = 0; fieldshift = 8; } if (0) { case 10: mask = 0x0fff; mul = 0x1001; rgbshift = 8; fieldshift = 12; } if (0) { case 13: mask = 0xffff; mul = 0x0001; rgbshift = 0; fieldshift = 16; } for (i=1;i; } v = (v << 4) + dv; } if (b) *b = ((v & mask) * mul) >> rgbshift; v >>= fieldshift; if (g) *g = ((v & mask) * mul) >> rgbshift; v >>= fieldshift; if (r) *r = ((v & mask) * mul) >> rgbshift; *succp = 1; return(lx__predone_op(xc)); break; } } priv = malloc(sizeof(LOOKUP_COLOR_PRIV)); if (! priv) { lx__nomem_fail(xc); return(0); } op = lx__do_LookupColor(call,xc,cmap,name,namelen,r,g,b,0,0,0); if (! op) { free(priv); return(0); } priv->op = op; priv->succp = succp; priv->done = op->done; priv->reqarg = op->reqarg; op->done = &done_lookup_color; op->reqarg = priv; op->err = &err_lookup_color; return(op); } LX_OP *lx_lookup_color(LX_CONN *xc, LX_XID cmap, const char *name, int namelen, unsigned int *xr, unsigned int *xg, unsigned int *xb, int *succp) { return(do_lookup_color("lx_lookup_color",xc,cmap,name,namelen,xr,xg,xb,succp)); } LX_OP *lx_lookup_color_rgb(LX_CONN *xc, LX_XID cmap, const char *name, int namelen, LX_RGB *xrgb, int *succp) { return(do_lookup_color("lx_lookup_color_rgb",xc,cmap,name,namelen,&xrgb->r,&xrgb->g,&xrgb->b,succp)); }