1
2 /*
3 * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc.
4 * All Rights Reserved
5 *
6 * This file is a component of an X Window System-specific implementation
7 * of Xcms based on the TekColor Color Management System. Permission is
8 * hereby granted to use, copy, modify, sell, and otherwise distribute this
9 * software and its documentation for any purpose and without fee, provided
10 * that this copyright, permission, and disclaimer notice is reproduced in
11 * all copies of this software and in supporting documentation. TekColor
12 * is a trademark of Tektronix, Inc.
13 *
14 * Tektronix makes no representation about the suitability of this software
15 * for any purpose. It is provided "as is" and with all faults.
16 *
17 * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE,
18 * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
19 * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY
20 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
21 * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF
22 * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
23 * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE.
24 *
25 *
26 * NAME
27 * XcmsCmap.c - Client Colormap Management Routines
28 *
29 * DESCRIPTION
30 * Routines that store additional information about
31 * colormaps being used by the X Client.
32 *
33 *
34 */
35
36 #ifdef HAVE_CONFIG_H
37 #include <config.h>
38 #endif
39 #include "Xlibint.h"
40 #include "Xcmsint.h"
41 #include "Xutil.h"
42 #include "Cmap.h"
43 #include "Cv.h"
44
45 /*
46 * FORWARD DECLARATIONS
47 */
48 static void _XcmsFreeClientCmaps(Display *dpy);
49
50
51 /************************************************************************
52 * *
53 * PRIVATE INTERFACES *
54 * *
55 ************************************************************************/
56
57 /*
58 * NAME
59 * CmapRecForColormap
60 *
61 * SYNOPSIS
62 */
63 static XcmsCmapRec *
CmapRecForColormap(Display * dpy,Colormap cmap)64 CmapRecForColormap(
65 Display *dpy,
66 Colormap cmap)
67 /*
68 * DESCRIPTION
69 * Find the corresponding XcmsCmapRec for cmap. In not found
70 * this routines attempts to create one.
71 *
72 * RETURNS
73 * Returns NULL if failed; otherwise the address to
74 * the corresponding XcmsCmapRec.
75 *
76 */
77 {
78 XcmsCmapRec *pRec;
79 int nScrn;
80 int i, j;
81 XVisualInfo visualTemplate; /* Template of the visual we want */
82 XVisualInfo *visualList; /* List for visuals that match */
83 int nVisualsMatched; /* Number of visuals that match */
84 Window tmpWindow;
85 Visual *vp;
86 unsigned long border = 0;
87 _XAsyncHandler async;
88 _XAsyncErrorState async_state;
89
90 for (pRec = (XcmsCmapRec *)dpy->cms.clientCmaps; pRec != NULL;
91 pRec = pRec->pNext) {
92 if (pRec->cmapID == cmap) {
93 return(pRec);
94 }
95 }
96
97 /*
98 * Can't find an XcmsCmapRec associated with cmap in our records.
99 * Let's try to see if its a default colormap
100 */
101 nScrn = ScreenCount(dpy);
102 for (i = 0; i < nScrn; i++) {
103 if (cmap == DefaultColormap(dpy, i)) {
104 /* It is ... lets go ahead and store that info */
105 if ((pRec = _XcmsAddCmapRec(dpy, cmap, RootWindow(dpy, i),
106 DefaultVisual(dpy, i))) == NULL) {
107 return((XcmsCmapRec *)NULL);
108 }
109 pRec->ccc = XcmsCreateCCC(
110 dpy,
111 i, /* screenNumber */
112 DefaultVisual(dpy, i),
113 (XcmsColor *)NULL, /* clientWhitePt */
114 (XcmsCompressionProc)NULL, /* gamutCompProc */
115 (XPointer)NULL, /* gamutCompClientData */
116 (XcmsWhiteAdjustProc)NULL, /* whitePtAdjProc */
117 (XPointer)NULL /* whitePtAdjClientData */
118 );
119 return(pRec);
120 }
121 }
122
123 /*
124 * Nope, its not a default colormap, so it's probably a foreign color map
125 * of which we have no specific details. Let's go through the
126 * rigorous process of finding this colormap:
127 * for each screen
128 * for each screen's visual types
129 * create a window with cmap specified as the colormap
130 * if successful
131 * Add a CmapRec
132 * Create an XcmsCCC
133 * return the CmapRec
134 * else
135 * continue
136 */
137
138 async_state.error_code = 0; /* don't care */
139 async_state.major_opcode = X_CreateWindow;
140 async_state.minor_opcode = 0;
141 for (i = 0; i < nScrn; i++) {
142 visualTemplate.screen = i;
143 visualList = XGetVisualInfo(dpy, VisualScreenMask, &visualTemplate,
144 &nVisualsMatched);
145 if (visualList == NULL) {
146 continue;
147 }
148
149 /*
150 * Attempt to create a window with cmap
151 */
152 j = 0;
153 do {
154 vp = (visualList+j)->visual;
155 LockDisplay(dpy);
156 {
157 register xCreateWindowReq *req;
158
159 GetReq(CreateWindow, req);
160 async_state.min_sequence_number = dpy->request;
161 async_state.max_sequence_number = dpy->request;
162 async_state.error_count = 0;
163 async.next = dpy->async_handlers;
164 async.handler = _XAsyncErrorHandler;
165 async.data = (XPointer)&async_state;
166 dpy->async_handlers = &async;
167 req->parent = RootWindow(dpy, i);
168 req->x = 0;
169 req->y = 0;
170 req->width = 1;
171 req->height = 1;
172 req->borderWidth = 0;
173 req->depth = (visualList+j)->depth;
174 req->class = CopyFromParent;
175 req->visual = vp->visualid;
176 tmpWindow = req->wid = XAllocID(dpy);
177 req->mask = CWBorderPixel | CWColormap;
178 req->length += 2;
179 Data32 (dpy, (long *) &border, 4);
180 Data32 (dpy, (long *) &cmap, 4);
181 }
182 {
183 xGetInputFocusReply rep;
184 _X_UNUSED register xReq *req;
185
186 GetEmptyReq(GetInputFocus, req);
187 (void) _XReply (dpy, (xReply *)&rep, 0, xTrue);
188 }
189 DeqAsyncHandler(dpy, &async);
190 UnlockDisplay(dpy);
191 SyncHandle();
192 } while (async_state.error_count > 0 && ++j < nVisualsMatched);
193
194 Xfree(visualList);
195
196 /*
197 * if successful
198 */
199 if (j < nVisualsMatched) {
200 if ((pRec = _XcmsAddCmapRec(dpy, cmap, tmpWindow, vp)) == NULL)
201 return((XcmsCmapRec *)NULL);
202 pRec->ccc = XcmsCreateCCC(
203 dpy,
204 i, /* screenNumber */
205 vp,
206 (XcmsColor *)NULL, /* clientWhitePt */
207 (XcmsCompressionProc)NULL, /* gamutCompProc */
208 (XPointer)NULL, /* gamutCompClientData */
209 (XcmsWhiteAdjustProc)NULL, /* whitePtAdjProc */
210 (XPointer)NULL /* whitePtAdjClientData */
211 );
212 XDestroyWindow(dpy, tmpWindow);
213 return(pRec);
214 }
215 }
216
217 return(NULL);
218 }
219
220
221
222 /************************************************************************
223 * *
224 * API PRIVATE INTERFACES *
225 * *
226 ************************************************************************/
227
228 /*
229 * NAME
230 * _XcmsAddCmapRec
231 *
232 * SYNOPSIS
233 */
234 XcmsCmapRec *
_XcmsAddCmapRec(Display * dpy,Colormap cmap,Window windowID,Visual * visual)235 _XcmsAddCmapRec(
236 Display *dpy,
237 Colormap cmap,
238 Window windowID,
239 Visual *visual)
240 /*
241 * DESCRIPTION
242 * Create an XcmsCmapRec for the specified cmap, windowID,
243 * and visual, then adds it to its list of CmapRec's.
244 *
245 * RETURNS
246 * Returns NULL if failed; otherwise the address to
247 * the added XcmsCmapRec.
248 *
249 */
250 {
251 XcmsCmapRec *pNew;
252
253 if ((pNew = Xcalloc(1, sizeof(XcmsCmapRec))) == NULL) {
254 return((XcmsCmapRec *)NULL);
255 }
256
257 pNew->cmapID = cmap;
258 pNew->dpy = dpy;
259 pNew->windowID = windowID;
260 pNew->visual = visual;
261 pNew->pNext = (XcmsCmapRec *)dpy->cms.clientCmaps;
262 dpy->cms.clientCmaps = (XPointer)pNew;
263 dpy->free_funcs->clientCmaps = _XcmsFreeClientCmaps;
264
265 /*
266 * Note, we don't create the XcmsCCC for pNew->ccc here because
267 * it may require the use of XGetWindowAttributes (a round trip request)
268 * to determine the screen.
269 */
270 return(pNew);
271 }
272
273
274 /*
275 * NAME
276 * _XcmsCopyCmapRecAndFree
277 *
278 * SYNOPSIS
279 */
280 XcmsCmapRec *
_XcmsCopyCmapRecAndFree(Display * dpy,Colormap src_cmap,Colormap copy_cmap)281 _XcmsCopyCmapRecAndFree(
282 Display *dpy,
283 Colormap src_cmap,
284 Colormap copy_cmap)
285 /*
286 * DESCRIPTION
287 * Augments Xlib's XCopyColormapAndFree() to copy
288 * XcmsCmapRecs.
289 *
290 * RETURNS
291 * Returns NULL if failed; otherwise the address to
292 * the copy XcmsCmapRec.
293 *
294 */
295 {
296 XcmsCmapRec *pRec_src;
297 XcmsCmapRec *pRec_copy;
298
299 if ((pRec_src = CmapRecForColormap(dpy, src_cmap)) != NULL) {
300 pRec_copy =_XcmsAddCmapRec(dpy, copy_cmap, pRec_src->windowID,
301 pRec_src->visual);
302 if (pRec_copy != NULL && pRec_src->ccc) {
303 pRec_copy->ccc = Xcalloc(1, sizeof(XcmsCCCRec));
304 memcpy((char *)pRec_copy->ccc, (char *)pRec_src->ccc,
305 sizeof(XcmsCCCRec));
306 }
307 return(pRec_copy);
308 }
309 return((XcmsCmapRec *)NULL);
310 }
311
312
313 /*
314 * NAME
315 * _XcmsDeleteCmapRec
316 *
317 * SYNOPSIS
318 */
319 void
_XcmsDeleteCmapRec(Display * dpy,Colormap cmap)320 _XcmsDeleteCmapRec(
321 Display *dpy,
322 Colormap cmap)
323 /*
324 * DESCRIPTION
325 * Removes and frees the specified XcmsCmapRec structure
326 * from the linked list of structures.
327 *
328 * RETURNS
329 * void
330 *
331 */
332 {
333 XcmsCmapRec **pPrevPtr;
334 XcmsCmapRec *pRec;
335 int scr;
336
337 /* If it is the default cmap for a screen, do not delete it,
338 * because the server will not actually free it */
339 for (scr = ScreenCount(dpy); --scr >= 0; ) {
340 if (cmap == DefaultColormap(dpy, scr))
341 return;
342 }
343
344 /* search for it in the list */
345 pPrevPtr = (XcmsCmapRec **)&dpy->cms.clientCmaps;
346 while ((pRec = *pPrevPtr) && (pRec->cmapID != cmap)) {
347 pPrevPtr = &pRec->pNext;
348 }
349
350 if (pRec) {
351 if (pRec->ccc) {
352 XcmsFreeCCC(pRec->ccc);
353 }
354 *pPrevPtr = pRec->pNext;
355 Xfree(pRec);
356 }
357 }
358
359
360 /*
361 * NAME
362 * _XcmsFreeClientCmaps
363 *
364 * SYNOPSIS
365 */
366 static void
_XcmsFreeClientCmaps(Display * dpy)367 _XcmsFreeClientCmaps(
368 Display *dpy)
369 /*
370 * DESCRIPTION
371 * Frees all XcmsCmapRec structures in the linked list
372 * and sets dpy->cms.clientCmaps to NULL.
373 *
374 * RETURNS
375 * void
376 *
377 */
378 {
379 XcmsCmapRec *pRecNext, *pRecFree;
380
381 pRecNext = (XcmsCmapRec *)dpy->cms.clientCmaps;
382 while (pRecNext != NULL) {
383 pRecFree = pRecNext;
384 pRecNext = pRecNext->pNext;
385 if (pRecFree->ccc) {
386 /* Free the XcmsCCC structure */
387 XcmsFreeCCC(pRecFree->ccc);
388 }
389 /* Now free the XcmsCmapRec structure */
390 Xfree(pRecFree);
391 }
392 dpy->cms.clientCmaps = (XPointer)NULL;
393 }
394
395
396
397 /************************************************************************
398 * *
399 * PUBLIC INTERFACES *
400 * *
401 ************************************************************************/
402
403 /*
404 * NAME
405 * XcmsCCCOfColormap
406 *
407 * SYNOPSIS
408 */
409 XcmsCCC
XcmsCCCOfColormap(Display * dpy,Colormap cmap)410 XcmsCCCOfColormap(
411 Display *dpy,
412 Colormap cmap)
413 /*
414 * DESCRIPTION
415 * Finds the XcmsCCC associated with the specified colormap.
416 *
417 * RETURNS
418 * Returns NULL if failed; otherwise the address to
419 * the associated XcmsCCC structure.
420 *
421 */
422 {
423 XWindowAttributes windowAttr;
424 XcmsCmapRec *pRec;
425 int nScrn = ScreenCount(dpy);
426 int i;
427
428 if ((pRec = CmapRecForColormap(dpy, cmap)) != NULL) {
429 if (pRec->ccc) {
430 /* XcmsCmapRec already has a XcmsCCC */
431 return(pRec->ccc);
432 }
433
434 /*
435 * The XcmsCmapRec does not have a XcmsCCC yet, so let's create
436 * one. But first, we need to know the screen associated with
437 * cmap, so use XGetWindowAttributes() to extract that
438 * information. Unless, of course there is only one screen!!
439 */
440 if (nScrn == 1) {
441 /* Assume screenNumber == 0 */
442 return(pRec->ccc = XcmsCreateCCC(
443 dpy,
444 0, /* screenNumber */
445 pRec->visual,
446 (XcmsColor *)NULL, /* clientWhitePt */
447 (XcmsCompressionProc)NULL, /* gamutCompProc */
448 (XPointer)NULL, /* gamutCompClientData */
449 (XcmsWhiteAdjustProc)NULL, /* whitePtAdjProc */
450 (XPointer)NULL /* whitePtAdjClientData */
451 ));
452 } else {
453 if (XGetWindowAttributes(dpy, pRec->windowID, &windowAttr)) {
454 for (i = 0; i < nScrn; i++) {
455 if (ScreenOfDisplay(dpy, i) == windowAttr.screen) {
456 return(pRec->ccc = XcmsCreateCCC(
457 dpy,
458 i, /* screenNumber */
459 pRec->visual,
460 (XcmsColor *)NULL, /* clientWhitePt */
461 (XcmsCompressionProc)NULL, /* gamutCompProc */
462 (XPointer)NULL, /* gamutCompClientData */
463 (XcmsWhiteAdjustProc)NULL, /* whitePtAdjProc */
464 (XPointer)NULL /* whitePtAdjClientData */
465 ));
466 }
467 }
468 }
469 }
470 }
471
472 /*
473 * No such cmap
474 */
475 return(NULL);
476 }
477
XcmsSetCCCOfColormap(Display * dpy,Colormap cmap,XcmsCCC ccc)478 XcmsCCC XcmsSetCCCOfColormap(
479 Display *dpy,
480 Colormap cmap,
481 XcmsCCC ccc)
482 {
483 XcmsCCC prev_ccc = NULL;
484 XcmsCmapRec *pRec;
485
486 pRec = CmapRecForColormap(dpy, cmap);
487 if (pRec) {
488 prev_ccc = pRec->ccc;
489 pRec->ccc = ccc;
490 }
491 return prev_ccc;
492 }
493