1 /* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */
2 
3 #ifndef __EXSB_COMMON_H__
4 #define __EXSB_COMMON_H__
5 
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <X11/Xlib.h>
9 
10 /* --- static functions --- */
11 
get_closest_xcolor_pseudo(Display * display,int screen,Colormap cmap,XColor * color,XColor * closest_color)12 static void get_closest_xcolor_pseudo(Display *display, int screen, Colormap cmap, XColor *color,
13                                       XColor *closest_color) {
14   XColor *all_colors;
15   int i;
16   int closest_index = 0;
17   unsigned long min = 0xffffffff;
18   unsigned long diff;
19   unsigned long diff_r = 0, diff_g = 0, diff_b = 0;
20   int ncells = DisplayCells(display, screen);
21 
22   all_colors = malloc(ncells * sizeof(XColor));
23 
24   /* get all colors from default colormap */
25   for (i = 0; i < ncells; i++) {
26     all_colors[i].pixel = i;
27   }
28   XQueryColors(display, cmap, all_colors, ncells);
29 
30   /* find closest color */
31   for (i = 0; i < ncells; i++) {
32     diff_r = (color->red - all_colors[i].red) >> 8;
33     diff_g = (color->green - all_colors[i].green) >> 8;
34     diff_b = (color->blue - all_colors[i].blue) >> 8;
35 
36     diff = diff_r * diff_r + diff_g * diff_g + diff_b * diff_b;
37 
38     if (diff < min) /* closest ? */
39     {
40       min = diff;
41       closest_index = i;
42     }
43   }
44 
45   closest_color->red = all_colors[closest_index].red;
46   closest_color->green = all_colors[closest_index].green;
47   closest_color->blue = all_colors[closest_index].blue;
48   closest_color->flags = DoRed | DoGreen | DoBlue;
49 
50   free(all_colors);
51 
52   if (XAllocColor(display, cmap, closest_color) == 0) {
53     closest_color->pixel = BlackPixel(display, screen);
54   }
55 }
56 
57 /* --- global functions -- */
58 
exsb_get_pixel(Display * display,int screen,Colormap cmap,Visual * visual,char * color_name)59 static unsigned long exsb_get_pixel(Display *display, int screen, Colormap cmap, Visual *visual,
60                                     char *color_name) {
61   XColor color;
62   XColor closest_color;
63 
64   if (XParseColor(display, cmap, color_name, &color) == 0) {
65     return BlackPixel(display, screen);
66   }
67 
68   if (XAllocColor(display, cmap, &color) == 0) {
69     if (visual->class == PseudoColor || visual->class == GrayScale) {
70       get_closest_xcolor_pseudo(display, screen, cmap, &color, &closest_color);
71       return closest_color.pixel;
72     }
73 
74     return BlackPixel(display, screen);
75   }
76 
77   return color.pixel;
78 }
79 
80 #endif
81