00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include <stdio.h>
00039 #include <stdlib.h>
00040 #include <X11/Xlib.h>
00041 #include <X11/Xutil.h>
00042 #include <X11/Xmu/StdCmap.h>
00043
00044
00045
00046
00047
00048 static int ROmap(Display*, Colormap, unsigned long[], int, int);
00049
00050
00051 static Status ROorRWcell(Display*, Colormap, unsigned long[], int,
00052 XColor*, unsigned long);
00053
00054
00055 static Status RWcell(Display*, Colormap, XColor*, XColor*, unsigned long*);
00056
00057
00058 static int compare(_Xconst void*, _Xconst void*);
00059
00060
00061 static Status contiguous(unsigned long[], int, int, unsigned long, int*, int*);
00062
00063
00064 static void free_cells(Display*, Colormap, unsigned long[], int, int);
00065
00066
00067 static Status readonly_map(Display*, XVisualInfo*, XStandardColormap*);
00068
00069
00070 static Status readwrite_map(Display*, XVisualInfo*, XStandardColormap*);
00071
00072 #define lowbit(x) ((x) & (~(x) + 1))
00073 #define TRUEMATCH(mult,max,mask) \
00074 (colormap->max * colormap->mult <= vinfo->mask && \
00075 lowbit(vinfo->mask) == colormap->mult)
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097 Status
00098 XmuCreateColormap(Display *dpy, XStandardColormap *colormap)
00099
00100
00101
00102
00103
00104 {
00105 XVisualInfo vinfo_template;
00106 XVisualInfo *vinfo;
00107 XVisualInfo *vpointer;
00108 long vinfo_mask;
00109 int n;
00110 int status;
00111
00112 vinfo_template.visualid = colormap->visualid;
00113 vinfo_mask = VisualIDMask;
00114 if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &n)) == NULL)
00115 return 0;
00116
00117
00118
00119
00120
00121
00122 vpointer = vinfo;
00123 if (n > 1)
00124 {
00125 register int i;
00126 register int screen_number;
00127 Bool def_cmap;
00128
00129 def_cmap = False;
00130 for (screen_number = ScreenCount(dpy); --screen_number >= 0; )
00131 if (colormap->colormap == DefaultColormap(dpy, screen_number)) {
00132 def_cmap = True;
00133 break;
00134 }
00135
00136 if (def_cmap) {
00137 for (i=0; i < n; i++, vinfo++) {
00138 if (vinfo->visual == DefaultVisual(dpy, screen_number))
00139 break;
00140 }
00141 } else {
00142 int maxdepth = 0;
00143 XVisualInfo *v = NULL;
00144
00145 for (i=0; i < n; i++, vinfo++)
00146 if (vinfo->depth > maxdepth) {
00147 maxdepth = vinfo->depth;
00148 v = vinfo;
00149 }
00150 vinfo = v;
00151 }
00152 }
00153
00154 if (vinfo->class == PseudoColor || vinfo->class == DirectColor ||
00155 vinfo->class == GrayScale)
00156 status = readwrite_map(dpy, vinfo, colormap);
00157 else if (vinfo->class == TrueColor)
00158 status = TRUEMATCH(red_mult, red_max, red_mask) &&
00159 TRUEMATCH(green_mult, green_max, green_mask) &&
00160 TRUEMATCH(blue_mult, blue_max, blue_mask);
00161 else
00162 status = readonly_map(dpy, vinfo, colormap);
00163
00164 XFree((char *) vpointer);
00165 return status;
00166 }
00167
00168
00169 static Status
00170 readwrite_map(Display *dpy, XVisualInfo *vinfo, XStandardColormap *colormap)
00171 {
00172 register unsigned long i, n;
00173 unsigned long ncolors;
00174 int npixels;
00175 int first_index;
00176 int remainder;
00177 XColor color;
00178 unsigned long *pixels;
00179 unsigned long delta;
00180
00181
00182
00183
00184
00185 if (vinfo->class == DirectColor) {
00186 ncolors = colormap->red_max;
00187 if (colormap->green_max > ncolors)
00188 ncolors = colormap->green_max;
00189 if (colormap->blue_max > ncolors)
00190 ncolors = colormap->blue_max;
00191 ncolors++;
00192 delta = lowbit(vinfo->red_mask) +
00193 lowbit(vinfo->green_mask) +
00194 lowbit(vinfo->blue_mask);
00195 } else {
00196 ncolors = colormap->red_max * colormap->red_mult +
00197 colormap->green_max * colormap->green_mult +
00198 colormap->blue_max * colormap->blue_mult + 1;
00199 delta = 1;
00200 }
00201 if (ncolors <= 1 || (int) ncolors > vinfo->colormap_size) return 0;
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221 if ((pixels = (unsigned long *) calloc((unsigned) vinfo->colormap_size,
00222 sizeof(unsigned long))) == NULL)
00223 return 0;
00224
00225 if ((npixels = ROmap(dpy, colormap->colormap, pixels,
00226 vinfo->colormap_size, ncolors)) == 0) {
00227 free((char *) pixels);
00228 return 0;
00229 }
00230
00231 qsort((char *) pixels, npixels, sizeof(unsigned long), compare);
00232
00233 if (!contiguous(pixels, npixels, ncolors, delta, &first_index, &remainder))
00234 {
00235
00236 XFreeColors(dpy, colormap->colormap, pixels, npixels,
00237 (unsigned long) 0);
00238 free((char *) pixels);
00239 return 0;
00240 }
00241 colormap->base_pixel = pixels[first_index];
00242
00243
00244 if (colormap->red_mult == 1 && colormap->green_mult == 1 &&
00245 colormap->blue_mult == 1)
00246 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
00247 {
00248 color.pixel = n;
00249 color.blue = color.green = color.red =
00250 (unsigned short) ((i * 65535) / (colormap->red_max +
00251 colormap->green_max +
00252 colormap->blue_max));
00253
00254 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
00255 first_index + i))
00256 return 0;
00257 }
00258
00259
00260 else if (colormap->green_max == 0 && colormap->blue_max == 0)
00261 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
00262 {
00263 color.pixel = n;
00264 color.red = (unsigned short) ((i * 65535) / colormap->red_max);
00265 color.green = color.blue = 0;
00266
00267 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
00268 first_index + i))
00269 return 0;
00270 }
00271
00272
00273 else if (colormap->red_max == 0 && colormap->blue_max == 0)
00274 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
00275 {
00276 color.pixel = n;
00277 color.green = (unsigned short) ((i * 65535) / colormap->green_max);
00278 color.red = color.blue = 0;
00279
00280 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
00281 first_index + i))
00282 return 0;
00283 }
00284
00285
00286 else if (colormap->red_max == 0 && colormap->green_max == 0)
00287 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
00288 {
00289 color.pixel = n;
00290 color.blue = (unsigned short) ((i * 65535) / colormap->blue_max);
00291 color.red = color.green = 0;
00292
00293 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
00294 first_index + i))
00295 return 0;
00296 }
00297
00298
00299 else
00300 {
00301 #define calc(max,mult) (((n / colormap->mult) % \
00302 (colormap->max + 1)) * 65535) / colormap->max
00303
00304 for (n=0, i=0; i < ncolors; i++, n += delta)
00305 {
00306 color.pixel = n + colormap->base_pixel;
00307 color.red = calc(red_max, red_mult);
00308 color.green = calc(green_max, green_mult);
00309 color.blue = calc(blue_max, blue_mult);
00310 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
00311 first_index + i))
00312 return 0;
00313 }
00314 #undef calc
00315 }
00316
00317
00318
00319
00320
00321 if (first_index)
00322 XFreeColors(dpy, colormap->colormap, pixels, first_index,
00323 (unsigned long) 0);
00324 if (remainder)
00325 XFreeColors(dpy, colormap->colormap,
00326 &(pixels[first_index + ncolors]), remainder,
00327 (unsigned long) 0);
00328
00329 free((char *) pixels);
00330 return 1;
00331 }
00332
00333
00334
00335 static int
00336 ROmap(Display *dpy, Colormap cmap, unsigned long pixels[], int m, int n)
00337
00338
00339
00340
00341
00342
00343
00344 {
00345 register int p;
00346
00347
00348 if (XAllocColorCells(dpy, cmap, 1, (unsigned long *) NULL,
00349 (unsigned) 0, pixels, (unsigned) m))
00350 return m;
00351
00352
00353
00354
00355 m--;
00356 while (n <= m) {
00357 p = n + ((m - n + 1) / 2);
00358 if (XAllocColorCells(dpy, cmap, 1, (unsigned long *) NULL,
00359 (unsigned) 0, pixels, (unsigned) p)) {
00360 if (p == m)
00361 return p;
00362 else {
00363 XFreeColors(dpy, cmap, pixels, p, (unsigned long) 0);
00364 n = p;
00365 }
00366 }
00367 else
00368 m = p - 1;
00369 }
00370 return 0;
00371 }
00372
00373
00374
00375 static Status
00376 contiguous(unsigned long pixels[], int npixels, int ncolors,
00377 unsigned long delta, int *first, int *rem)
00378
00379
00380
00381
00382
00383
00384
00385 {
00386 register int i = 1;
00387 register int count = 1;
00388
00389 *first = 0;
00390 if (npixels == ncolors) {
00391 *rem = 0;
00392 return 1;
00393 }
00394 *rem = npixels - 1;
00395 while (count < ncolors && ncolors - count <= *rem)
00396 {
00397 if (pixels[i-1] + delta == pixels[i])
00398 count++;
00399 else {
00400 count = 1;
00401 *first = i;
00402 }
00403 i++;
00404 (*rem)--;
00405 }
00406 if (count != ncolors)
00407 return 0;
00408 return 1;
00409 }
00410
00411
00412
00413 static Status
00414 ROorRWcell(Display *dpy, Colormap cmap, unsigned long pixels[],
00415 int npixels, XColor *color, unsigned long p)
00416 {
00417 unsigned long pixel;
00418 XColor request;
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432 pixel = color->pixel;
00433 request.red = color->red;
00434 request.green = color->green;
00435 request.blue = color->blue;
00436
00437 XFreeColors(dpy, cmap, &pixel, 1, (unsigned long) 0);
00438 if (! XAllocColor(dpy, cmap, color)
00439 || (color->pixel != pixel &&
00440 (!RWcell(dpy, cmap, color, &request, &pixel))))
00441 {
00442 free_cells(dpy, cmap, pixels, npixels, (int)p);
00443 return 0;
00444 }
00445 return 1;
00446 }
00447
00448
00449
00450 static void
00451 free_cells(Display *dpy, Colormap cmap, unsigned long pixels[],
00452 int npixels, int p)
00453
00454
00455
00456
00457 {
00458
00459
00460
00461
00462
00463 XFreeColors(dpy, cmap, pixels, p, (unsigned long) 0);
00464 XFreeColors(dpy, cmap, &(pixels[p+1]), npixels - p - 1, (unsigned long) 0);
00465 free((char *) pixels);
00466 }
00467
00468
00469
00470 static Status
00471 RWcell(Display *dpy, Colormap cmap, XColor *color, XColor *request,
00472 unsigned long *pixel)
00473 {
00474 unsigned long n = *pixel;
00475
00476 XFreeColors(dpy, cmap, &(color->pixel), 1, (unsigned long)0);
00477 if (! XAllocColorCells(dpy, cmap, (Bool) 0, (unsigned long *) NULL,
00478 (unsigned) 0, pixel, (unsigned) 1))
00479 return 0;
00480 if (*pixel != n)
00481 {
00482 XFreeColors(dpy, cmap, pixel, 1, (unsigned long) 0);
00483 return 0;
00484 }
00485 color->pixel = *pixel;
00486 color->flags = DoRed | DoGreen | DoBlue;
00487 color->red = request->red;
00488 color->green = request->green;
00489 color->blue = request->blue;
00490 XStoreColors(dpy, cmap, color, 1);
00491 return 1;
00492 }
00493
00494
00495
00496 static int
00497 compare(_Xconst void *e1, _Xconst void *e2)
00498 {
00499 return ((int)(*(long *)e1 - *(long *)e2));
00500 }
00501
00502
00503
00504 static Status
00505 readonly_map(Display *dpy, XVisualInfo *vinfo, XStandardColormap *colormap)
00506 {
00507 int i, last_pixel;
00508 XColor color;
00509
00510 last_pixel = (colormap->red_max + 1) * (colormap->green_max + 1) *
00511 (colormap->blue_max + 1) + colormap->base_pixel - 1;
00512
00513 for(i=colormap->base_pixel; i <= last_pixel; i++) {
00514
00515 color.pixel = (unsigned long) i;
00516 color.red = (unsigned short)
00517 (((i/colormap->red_mult) * 65535) / colormap->red_max);
00518
00519 if (vinfo->class == StaticColor) {
00520 color.green = (unsigned short)
00521 ((((i/colormap->green_mult) % (colormap->green_max + 1)) *
00522 65535) / colormap->green_max);
00523 color.blue = (unsigned short)
00524 (((i%colormap->green_mult) * 65535) / colormap->blue_max);
00525 }
00526 else
00527 color.green = color.blue = color.red;
00528
00529 XAllocColor(dpy, colormap->colormap, &color);
00530 if (color.pixel != (unsigned long) i)
00531 return 0;
00532 }
00533 return 1;
00534 }