1
/* $Xorg: cmsCmap.c,v 1.3 2000/08/17 19:45:09 cpqbld Exp $ */
4
* Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc.
7
* This file is a component of an X Window System-specific implementation
8
* of Xcms based on the TekColor Color Management System. Permission is
9
* hereby granted to use, copy, modify, sell, and otherwise distribute this
10
* software and its documentation for any purpose and without fee, provided
11
* that this copyright, permission, and disclaimer notice is reproduced in
12
* all copies of this software and in supporting documentation. TekColor
13
* is a trademark of Tektronix, Inc.
15
* Tektronix makes no representation about the suitability of this software
16
* for any purpose. It is provided "as is" and with all faults.
18
* TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE,
19
* INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20
* PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY
21
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
22
* RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF
23
* CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
24
* CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE.
28
* XcmsCmap.c - Client Colormap Management Routines
31
* Routines that store additional information about
32
* colormaps being used by the X Client.
44
* FORWARD DECLARATIONS
46
XcmsCmapRec *_XcmsAddCmapRec();
47
static void _XcmsFreeClientCmaps();
50
/************************************************************************
52
* PRIVATE INTERFACES *
54
************************************************************************/
63
CmapRecForColormap(dpy, cmap)
68
* Find the corresponding XcmsCmapRec for cmap. In not found
69
* this routines attempts to create one.
72
* Returns NULL if failed; otherwise the address to
73
* the corresponding XcmsCmapRec.
80
XVisualInfo visualTemplate; /* Template of the visual we want */
81
XVisualInfo *visualList; /* List for visuals that match */
82
int nVisualsMatched; /* Number of visuals that match */
85
unsigned long border = 0;
87
_XAsyncErrorState async_state;
89
for (pRec = (XcmsCmapRec *)dpy->cms.clientCmaps; pRec != NULL;
91
if (pRec->cmapID == cmap) {
97
* Can't find an XcmsCmapRec associated with cmap in our records.
98
* Let's try to see if its a default colormap
100
nScrn = ScreenCount(dpy);
101
for (i = 0; i < nScrn; i++) {
102
if (cmap == DefaultColormap(dpy, i)) {
103
/* It is ... lets go ahead and store that info */
104
if ((pRec = _XcmsAddCmapRec(dpy, cmap, RootWindow(dpy, i),
105
DefaultVisual(dpy, i))) == NULL) {
106
return((XcmsCmapRec *)NULL);
108
pRec->ccc = XcmsCreateCCC(
110
i, /* screenNumber */
111
DefaultVisual(dpy, i),
112
(XcmsColor *)NULL, /* clientWhitePt */
113
(XcmsCompressionProc)NULL, /* gamutCompProc */
114
(XPointer)NULL, /* gamutCompClientData */
115
(XcmsWhiteAdjustProc)NULL, /* whitePtAdjProc */
116
(XPointer)NULL /* whitePtAdjClientData */
123
* Nope, its not a default colormap, so it's probably a foreign color map
124
* of which we have no specific details. Let's go through the
125
* rigorous process of finding this colormap:
127
* for each screen's visual types
128
* create a window with cmap specified as the colormap
137
async_state.error_code = 0; /* don't care */
138
async_state.major_opcode = X_CreateWindow;
139
async_state.minor_opcode = 0;
140
for (i = 0; i < nScrn; i++) {
141
visualTemplate.screen = i;
142
visualList = XGetVisualInfo(dpy, VisualScreenMask, &visualTemplate,
144
if (nVisualsMatched == 0) {
149
* Attempt to create a window with cmap
153
vp = (visualList+j)->visual;
156
register xCreateWindowReq *req;
158
GetReq(CreateWindow, req);
159
async_state.min_sequence_number = dpy->request;
160
async_state.max_sequence_number = dpy->request;
161
async_state.error_count = 0;
162
async.next = dpy->async_handlers;
163
async.handler = _XAsyncErrorHandler;
164
async.data = (XPointer)&async_state;
165
dpy->async_handlers = &async;
166
req->parent = RootWindow(dpy, i);
171
req->borderWidth = 0;
172
req->depth = (visualList+j)->depth;
173
req->class = CopyFromParent;
174
req->visual = vp->visualid;
175
tmpWindow = req->wid = XAllocID(dpy);
176
req->mask = CWBorderPixel | CWColormap;
178
Data32 (dpy, (long *) &border, 4);
179
Data32 (dpy, (long *) &cmap, 4);
182
xGetInputFocusReply rep;
185
GetEmptyReq(GetInputFocus, req);
186
(void) _XReply (dpy, (xReply *)&rep, 0, xTrue);
188
DeqAsyncHandler(dpy, &async);
191
} while (async_state.error_count > 0 && ++j < nVisualsMatched);
193
Xfree((char *)visualList);
198
if (j < nVisualsMatched) {
199
if ((pRec = _XcmsAddCmapRec(dpy, cmap, tmpWindow, vp)) == NULL)
200
return((XcmsCmapRec *)NULL);
201
pRec->ccc = XcmsCreateCCC(
203
i, /* screenNumber */
205
(XcmsColor *)NULL, /* clientWhitePt */
206
(XcmsCompressionProc)NULL, /* gamutCompProc */
207
(XPointer)NULL, /* gamutCompClientData */
208
(XcmsWhiteAdjustProc)NULL, /* whitePtAdjProc */
209
(XPointer)NULL /* whitePtAdjClientData */
211
XDestroyWindow(dpy, tmpWindow);
221
/************************************************************************
223
* API PRIVATE INTERFACES *
225
************************************************************************/
234
_XcmsAddCmapRec(dpy, cmap, windowID, visual)
241
* Create an XcmsCmapRec for the specified cmap, windowID,
242
* and visual, then adds it to its list of CmapRec's.
245
* Returns NULL if failed; otherwise the address to
246
* the added XcmsCmapRec.
252
if ((pNew = (XcmsCmapRec *) Xcalloc(1, (unsigned) sizeof(XcmsCmapRec)))
254
return((XcmsCmapRec *)NULL);
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;
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.
276
* _XcmsCopyCmapRecAndFree
281
_XcmsCopyCmapRecAndFree(dpy, src_cmap, copy_cmap)
287
* Augments Xlib's XCopyColormapAndFree() to copy
291
* Returns NULL if failed; otherwise the address to
292
* the copy XcmsCmapRec.
296
XcmsCmapRec *pRec_src;
297
XcmsCmapRec *pRec_copy;
299
if ((pRec_src = CmapRecForColormap(dpy, src_cmap)) != NULL) {
300
pRec_copy =_XcmsAddCmapRec(dpy, copy_cmap, pRec_src->windowID,
302
if (pRec_copy != NULL && pRec_src->ccc) {
303
pRec_copy->ccc = (XcmsCCC)Xcalloc(1, (unsigned) sizeof(XcmsCCCRec));
304
memcpy((char *)pRec_copy->ccc, (char *)pRec_src->ccc,
309
return((XcmsCmapRec *)NULL);
320
_XcmsDeleteCmapRec(dpy, cmap)
325
* Removes and frees the specified XcmsCmapRec structure
326
* from the linked list of structures.
333
XcmsCmapRec **pPrevPtr;
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))
344
/* search for it in the list */
345
pPrevPtr = (XcmsCmapRec **)&dpy->cms.clientCmaps;
346
while ((pRec = *pPrevPtr) && (pRec->cmapID != cmap)) {
347
pPrevPtr = &pRec->pNext;
352
XcmsFreeCCC(pRec->ccc);
354
*pPrevPtr = pRec->pNext;
362
* _XcmsFreeClientCmaps
367
_XcmsFreeClientCmaps(dpy)
371
* Frees all XcmsCmapRec structures in the linked list
372
* and sets dpy->cms.clientCmaps to NULL.
379
XcmsCmapRec *pRecNext, *pRecFree;
381
pRecNext = (XcmsCmapRec *)dpy->cms.clientCmaps;
382
while (pRecNext != NULL) {
384
pRecNext = pRecNext->pNext;
386
/* Free the XcmsCCC structure */
387
XcmsFreeCCC(pRecFree->ccc);
389
/* Now free the XcmsCmapRec structure */
390
Xfree((char *)pRecFree);
392
dpy->cms.clientCmaps = (XPointer)NULL;
397
/************************************************************************
399
* PUBLIC INTERFACES *
401
************************************************************************/
410
XcmsCCCOfColormap(dpy, cmap)
415
* Finds the XcmsCCC associated with the specified colormap.
418
* Returns NULL if failed; otherwise the address to
419
* the associated XcmsCCC structure.
423
XWindowAttributes windowAttr;
425
int nScrn = ScreenCount(dpy);
428
if ((pRec = CmapRecForColormap(dpy, cmap)) != NULL) {
430
/* XcmsCmapRec already has a XcmsCCC */
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!!
441
/* Assume screenNumber == 0 */
442
return(pRec->ccc = XcmsCreateCCC(
444
0, /* screenNumber */
446
(XcmsColor *)NULL, /* clientWhitePt */
447
(XcmsCompressionProc)NULL, /* gamutCompProc */
448
(XPointer)NULL, /* gamutCompClientData */
449
(XcmsWhiteAdjustProc)NULL, /* whitePtAdjProc */
450
(XPointer)NULL /* whitePtAdjClientData */
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(
458
i, /* screenNumber */
460
(XcmsColor *)NULL, /* clientWhitePt */
461
(XcmsCompressionProc)NULL, /* gamutCompProc */
462
(XPointer)NULL, /* gamutCompClientData */
463
(XcmsWhiteAdjustProc)NULL, /* whitePtAdjProc */
464
(XPointer)NULL /* whitePtAdjClientData */
478
XcmsCCC XcmsSetCCCOfColormap(dpy, cmap, ccc)
483
XcmsCCC prev_ccc = NULL;
486
pRec = CmapRecForColormap(dpy, cmap);
488
prev_ccc = pRec->ccc;