cmsCmap.c revision 818534a1
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 */ 48static void _XcmsFreeClientCmaps(Display *dpy); 49 50 51/************************************************************************ 52 * * 53 * PRIVATE INTERFACES * 54 * * 55 ************************************************************************/ 56 57/* 58 * NAME 59 * CmapRecForColormap 60 * 61 * SYNOPSIS 62 */ 63static XcmsCmapRec * 64CmapRecForColormap( 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 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 */ 234XcmsCmapRec * 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 */ 280XcmsCmapRec * 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 */ 319void 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 */ 366static void 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 */ 409XcmsCCC 410XcmsCCCOfColormap( 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 478XcmsCCC 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