Tizen 2.1 base
[framework/uifw/xorg/lib/libxmu.git] / src / LookupCmap.c
1 /*
2
3 Copyright 1989, 1998  The Open Group
4
5 Permission to use, copy, modify, distribute, and sell this software and its
6 documentation for any purpose is hereby granted without fee, provided that
7 the above copyright notice appear in all copies and that both that
8 copyright notice and this permission notice appear in supporting
9 documentation.
10
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
13
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
21 Except as contained in this notice, the name of The Open Group shall not be
22 used in advertising or otherwise to promote the sale, use or other dealings
23 in this Software without prior written authorization from The Open Group.
24
25 */
26
27 /*
28  * Author:  Donna Converse, MIT X Consortium
29  */
30
31 #ifdef HAVE_CONFIG_H
32 #include <config.h>
33 #endif
34 #include <stdio.h>
35 #include <X11/Xlib.h>
36 #include <X11/Xatom.h>
37 #include <X11/Xutil.h>
38 #include <X11/Xmu/StdCmap.h>
39 #include <stdlib.h>
40
41 /*
42  * Prototypes
43  */
44 static Status lookup(Display*, int, VisualID, Atom, XStandardColormap*, Bool);
45
46 /*
47  * To create a standard colormap if one does not currently exist, or
48  * replace the currently existing standard colormap, use
49  * XmuLookupStandardColormap().
50  *
51  * Given a screen, a visual, and a property, XmuLookupStandardColormap()
52  * will determine the best allocation for the property under the specified
53  * visual, and determine the whether to create a new colormap or to use
54  * the default colormap of the screen.  It will call XmuStandardColormap()
55  * to create the standard colormap.
56  *
57  * If replace is true, any previous definition of the property will be
58  * replaced.  If retain is true, the property and the colormap will be
59  * made permanent for the duration of the server session.  However,
60  * pre-existing property definitions which are not replaced cannot be made
61  * permanent by a call to XmuLookupStandardColormap(); a request to retain
62  * resources pertains to newly created resources.
63  *
64  * Returns 0 on failure, non-zero on success.  A request to create a
65  * standard colormap upon a visual which cannot support such a map is
66  * considered a failure.  An example of this would be requesting any
67  * standard colormap property on a monochrome visual, or, requesting an
68  * RGB_BEST_MAP on a display whose colormap size is 16.
69  */
70
71 Status
72 XmuLookupStandardColormap(Display *dpy, int screen, VisualID visualid,
73                           unsigned int depth, Atom property,
74                           Bool replace, Bool retain)
75      /*
76       * dpy             - specifies X server connection
77       * screen          - specifies screen of display
78       * visualid        - specifies the visual type
79       * depth           - specifies  the visual type
80       * property        - a standard colormap property
81       * replace         - specifies whether to replace
82       * retain          - specifies whether to retain
83       */
84 {
85     Display             *odpy;          /* original display connection */
86     XStandardColormap   *colormap;
87     XVisualInfo         vinfo_template, *vinfo; /* visual */
88     long                vinfo_mask;
89     unsigned long       r_max, g_max, b_max;    /* allocation */
90     int                 count;
91     Colormap            cmap;                   /* colormap ID */
92     Status              status = 0;
93
94
95     /* Match the requested visual */
96
97     vinfo_template.visualid = visualid;
98     vinfo_template.screen = screen;
99     vinfo_template.depth = depth;
100     vinfo_mask = VisualIDMask | VisualScreenMask | VisualDepthMask;
101     if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &count)) ==
102         NULL)
103         return 0;
104
105     /* Monochrome visuals have no standard maps */
106
107     if (vinfo->colormap_size <= 2) {
108         XFree((char *) vinfo);
109         return 0;
110     }
111
112     /* If the requested property already exists on this screen, and,
113      * if the replace flag has not been set to true, return success.
114      * lookup() will remove a pre-existing map if replace is true.
115      */
116
117     if (lookup(dpy, screen, visualid, property, (XStandardColormap *) NULL,
118                replace) && !replace) {
119         XFree((char *) vinfo);
120         return 1;
121     }
122
123     /* Determine the best allocation for this property under the requested
124      * visualid and depth, and determine whether or not to use the default
125      * colormap of the screen.
126      */
127
128     if (!XmuGetColormapAllocation(vinfo, property, &r_max, &g_max, &b_max)) {
129         XFree((char *) vinfo);
130         return 0;
131     }
132
133     cmap = (property == XA_RGB_DEFAULT_MAP &&
134             visualid == XVisualIDFromVisual(DefaultVisual(dpy, screen)))
135         ? DefaultColormap(dpy, screen) : None;
136
137     /* If retaining resources, open a new connection to the same server */
138
139     if (retain) {
140         odpy = dpy;
141         if ((dpy = XOpenDisplay(XDisplayString(odpy))) == NULL) {
142             XFree((char *) vinfo);
143             return 0;
144         }
145     }
146
147     /* Create the standard colormap */
148
149     colormap = XmuStandardColormap(dpy, screen, visualid, depth, property,
150                                    cmap, r_max, g_max, b_max);
151
152     /* Set the standard colormap property */
153
154     if (colormap) {
155         XGrabServer(dpy);
156
157         if (lookup(dpy, screen, visualid, property, colormap, replace) &&
158             !replace) {
159             /* Someone has defined the property since we last looked.
160              * Since we will not replace it, release our own resources.
161              * If this is the default map, our allocations will be freed
162              * when this connection closes.
163              */
164             if (colormap->killid == ReleaseByFreeingColormap)
165                 XFreeColormap(dpy, colormap->colormap);
166         }
167         else if (retain) {
168                 XSetCloseDownMode(dpy, RetainPermanent);
169         }
170         XUngrabServer(dpy);
171         XFree((char *) colormap);
172         status = 1;
173     }
174
175     if (retain)
176         XCloseDisplay(dpy);
177     XFree((char *) vinfo);
178     return status;
179 }
180
181 /***************************************************************************/
182
183 /* Lookup a standard colormap property.  If the property is RGB_DEFAULT_MAP,
184  * the visualid is used to determine whether the indicated standard colormap
185  * exists.  If the map exists and replace is true, delete the resources used
186  * by the map and remove the property.  Return true if the map exists,
187  * or did exist and was deleted; return false if the map was not found.
188  *
189  * Note that this is not the way that a Status return is normally used.
190  *
191  * If new is not NULL, new points to an XStandardColormap structure which
192  * describes a standard colormap of the specified property.  It will be made
193  * a standard colormap of the screen if none already exists, or if replace
194  * is true.
195  */
196
197 static Status
198 lookup(Display *dpy, int screen, VisualID visualid, Atom property,
199        XStandardColormap *cnew, Bool replace)
200      /*
201       * dpy             - specifies display connection
202       * screen          - specifies screen number
203       * visualid        - specifies visualid for std map
204       * property        - specifies colormap property name
205       * cnew            - specifies a standard colormap
206       * replace         - specifies whether to replace
207       */
208 {
209     register int        i;
210     int                 count;
211     XStandardColormap   *stdcmaps, *s;
212     Window              win = RootWindow(dpy, screen);
213
214     /* The property does not already exist */
215
216     if (! XGetRGBColormaps(dpy, win, &stdcmaps, &count, property)) {
217         if (cnew)
218             XSetRGBColormaps(dpy, win, cnew, 1, property);
219         return 0;
220     }
221
222     /* The property exists and is not describing the RGB_DEFAULT_MAP */
223
224     if (property != XA_RGB_DEFAULT_MAP) {
225         if (replace) {
226             XmuDeleteStandardColormap(dpy, screen, property);
227             if (cnew)
228                 XSetRGBColormaps(dpy, win, cnew, 1, property);
229         }
230         XFree((char *)stdcmaps);
231         return 1;
232     }
233
234     /* The property exists and is RGB_DEFAULT_MAP */
235
236     for (i=0, s=stdcmaps; (i < count) && (s->visualid != visualid); i++, s++)
237         ;
238
239     /* No RGB_DEFAULT_MAP property matches the given visualid */
240
241     if (i == count) {
242         if (cnew) {
243             XStandardColormap   *m, *maps;
244
245             s = (XStandardColormap *) malloc((unsigned) ((count+1) * sizeof
246                                               (XStandardColormap)));
247
248             for (i = 0, m = s, maps = stdcmaps; i < count; i++, m++, maps++) {
249                 m->colormap   = maps->colormap;
250                 m->red_max    = maps->red_max;
251                 m->red_mult   = maps->red_mult;
252                 m->green_max  = maps->green_max;
253                 m->green_mult = maps->green_mult;
254                 m->blue_max   = maps->blue_max;
255                 m->blue_mult  = maps->blue_mult;
256                 m->base_pixel = maps->base_pixel;
257                 m->visualid   = maps->visualid;
258                 m->killid     = maps->killid;
259             }
260             m->colormap   = cnew->colormap;
261             m->red_max    = cnew->red_max;
262             m->red_mult   = cnew->red_mult;
263             m->green_max  = cnew->green_max;
264             m->green_mult = cnew->green_mult;
265             m->blue_max   = cnew->blue_max;
266             m->blue_mult  = cnew->blue_mult;
267             m->base_pixel = cnew->base_pixel;
268             m->visualid   = cnew->visualid;
269             m->killid     = cnew->killid;
270
271             XSetRGBColormaps(dpy, win, s, ++count, property);
272             free((char *) s);
273         }
274         XFree((char *) stdcmaps);
275         return 0;
276     }
277
278     /* Found an RGB_DEFAULT_MAP property with a matching visualid */
279
280     if (replace) {
281         /* Free old resources first - we may need them, particularly in
282          * the default colormap of the screen.  However, because of this,
283          * it is possible that we will destroy the old resource and fail
284          * to create a new one if XmuStandardColormap() fails.
285          */
286
287         if (count == 1) {
288             XmuDeleteStandardColormap(dpy, screen, property);
289             if (cnew)
290                 XSetRGBColormaps(dpy, win, cnew, 1, property);
291         }
292         else {
293             XStandardColormap   *map;
294
295             /* s still points to the matching standard colormap */
296
297             if (s->killid == ReleaseByFreeingColormap) {
298                 if ((s->colormap != None) &&
299                     (s->colormap != DefaultColormap(dpy, screen)))
300                     XFreeColormap(dpy, s->colormap);
301             }
302             else if (s->killid != None)
303                 XKillClient(dpy, s->killid);
304
305             map = (cnew) ? cnew : stdcmaps + --count;
306
307             s->colormap   = map->colormap;
308             s->red_max    = map->red_max;
309             s->red_mult   = map->red_mult;
310             s->green_max  = map->green_max;
311             s->green_mult = map->green_mult;
312             s->blue_max   = map->blue_max;
313             s->blue_mult  = map->blue_mult;
314             s->visualid   = map->visualid;
315             s->killid     = map->killid;
316
317             XSetRGBColormaps(dpy, win, stdcmaps, count, property);
318         }
319     }
320     XFree((char *) stdcmaps);
321     return 1;
322 }