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