diff options
Diffstat (limited to 'src/xcms/cmsCmap.c')
-rw-r--r-- | src/xcms/cmsCmap.c | 492 |
1 files changed, 492 insertions, 0 deletions
diff --git a/src/xcms/cmsCmap.c b/src/xcms/cmsCmap.c new file mode 100644 index 0000000..84d60a4 --- /dev/null +++ b/src/xcms/cmsCmap.c @@ -0,0 +1,492 @@ +/* $Xorg: cmsCmap.c,v 1.3 2000/08/17 19:45:09 cpqbld Exp $ */ + +/* + * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc. + * All Rights Reserved + * + * This file is a component of an X Window System-specific implementation + * of Xcms based on the TekColor Color Management System. Permission is + * hereby granted to use, copy, modify, sell, and otherwise distribute this + * software and its documentation for any purpose and without fee, provided + * that this copyright, permission, and disclaimer notice is reproduced in + * all copies of this software and in supporting documentation. TekColor + * is a trademark of Tektronix, Inc. + * + * Tektronix makes no representation about the suitability of this software + * for any purpose. It is provided "as is" and with all faults. + * + * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE, + * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE. + * + * + * NAME + * XcmsCmap.c - Client Colormap Management Routines + * + * DESCRIPTION + * Routines that store additional information about + * colormaps being used by the X Client. + * + * + */ + +#define NEED_EVENTS +#define NEED_REPLIES +#include "Xlibint.h" +#include "Xcmsint.h" +#include "Xutil.h" + +/* + * FORWARD DECLARATIONS + */ +XcmsCmapRec *_XcmsAddCmapRec(); +static void _XcmsFreeClientCmaps(); + + +/************************************************************************ + * * + * PRIVATE INTERFACES * + * * + ************************************************************************/ + +/* + * NAME + * CmapRecForColormap + * + * SYNOPSIS + */ +static XcmsCmapRec * +CmapRecForColormap(dpy, cmap) + Display *dpy; + Colormap cmap; +/* + * DESCRIPTION + * Find the corresponding XcmsCmapRec for cmap. In not found + * this routines attempts to create one. + * + * RETURNS + * Returns NULL if failed; otherwise the address to + * the corresponding XcmsCmapRec. + * + */ +{ + XcmsCmapRec *pRec; + int nScrn; + int i, j; + XVisualInfo visualTemplate; /* Template of the visual we want */ + XVisualInfo *visualList; /* List for visuals that match */ + int nVisualsMatched; /* Number of visuals that match */ + Window tmpWindow; + Visual *vp; + unsigned long border = 0; + _XAsyncHandler async; + _XAsyncErrorState async_state; + + for (pRec = (XcmsCmapRec *)dpy->cms.clientCmaps; pRec != NULL; + pRec = pRec->pNext) { + if (pRec->cmapID == cmap) { + return(pRec); + } + } + + /* + * Can't find an XcmsCmapRec associated with cmap in our records. + * Let's try to see if its a default colormap + */ + nScrn = ScreenCount(dpy); + for (i = 0; i < nScrn; i++) { + if (cmap == DefaultColormap(dpy, i)) { + /* It is ... lets go ahead and store that info */ + if ((pRec = _XcmsAddCmapRec(dpy, cmap, RootWindow(dpy, i), + DefaultVisual(dpy, i))) == NULL) { + return((XcmsCmapRec *)NULL); + } + pRec->ccc = XcmsCreateCCC( + dpy, + i, /* screenNumber */ + DefaultVisual(dpy, i), + (XcmsColor *)NULL, /* clientWhitePt */ + (XcmsCompressionProc)NULL, /* gamutCompProc */ + (XPointer)NULL, /* gamutCompClientData */ + (XcmsWhiteAdjustProc)NULL, /* whitePtAdjProc */ + (XPointer)NULL /* whitePtAdjClientData */ + ); + return(pRec); + } + } + + /* + * Nope, its not a default colormap, so it's probably a foreign color map + * of which we have no specific details. Let's go through the + * rigorous process of finding this colormap: + * for each screen + * for each screen's visual types + * create a window with cmap specified as the colormap + * if successful + * Add a CmapRec + * Create an XcmsCCC + * return the CmapRec + * else + * continue + */ + + async_state.error_code = 0; /* don't care */ + async_state.major_opcode = X_CreateWindow; + async_state.minor_opcode = 0; + for (i = 0; i < nScrn; i++) { + visualTemplate.screen = i; + visualList = XGetVisualInfo(dpy, VisualScreenMask, &visualTemplate, + &nVisualsMatched); + if (nVisualsMatched == 0) { + continue; + } + + /* + * Attempt to create a window with cmap + */ + j = 0; + do { + vp = (visualList+j)->visual; + LockDisplay(dpy); + { + register xCreateWindowReq *req; + + GetReq(CreateWindow, req); + async_state.min_sequence_number = dpy->request; + async_state.max_sequence_number = dpy->request; + async_state.error_count = 0; + async.next = dpy->async_handlers; + async.handler = _XAsyncErrorHandler; + async.data = (XPointer)&async_state; + dpy->async_handlers = &async; + req->parent = RootWindow(dpy, i); + req->x = 0; + req->y = 0; + req->width = 1; + req->height = 1; + req->borderWidth = 0; + req->depth = (visualList+j)->depth; + req->class = CopyFromParent; + req->visual = vp->visualid; + tmpWindow = req->wid = XAllocID(dpy); + req->mask = CWBorderPixel | CWColormap; + req->length += 2; + Data32 (dpy, (long *) &border, 4); + Data32 (dpy, (long *) &cmap, 4); + } + { + xGetInputFocusReply rep; + register xReq *req; + + GetEmptyReq(GetInputFocus, req); + (void) _XReply (dpy, (xReply *)&rep, 0, xTrue); + } + DeqAsyncHandler(dpy, &async); + UnlockDisplay(dpy); + SyncHandle(); + } while (async_state.error_count > 0 && ++j < nVisualsMatched); + + Xfree((char *)visualList); + + /* + * if successful + */ + if (j < nVisualsMatched) { + if ((pRec = _XcmsAddCmapRec(dpy, cmap, tmpWindow, vp)) == NULL) + return((XcmsCmapRec *)NULL); + pRec->ccc = XcmsCreateCCC( + dpy, + i, /* screenNumber */ + vp, + (XcmsColor *)NULL, /* clientWhitePt */ + (XcmsCompressionProc)NULL, /* gamutCompProc */ + (XPointer)NULL, /* gamutCompClientData */ + (XcmsWhiteAdjustProc)NULL, /* whitePtAdjProc */ + (XPointer)NULL /* whitePtAdjClientData */ + ); + XDestroyWindow(dpy, tmpWindow); + return(pRec); + } + } + + return(NULL); +} + + + +/************************************************************************ + * * + * API PRIVATE INTERFACES * + * * + ************************************************************************/ + +/* + * NAME + * _XcmsAddCmapRec + * + * SYNOPSIS + */ +XcmsCmapRec * +_XcmsAddCmapRec(dpy, cmap, windowID, visual) + Display *dpy; + Colormap cmap; + Window windowID; + Visual *visual; +/* + * DESCRIPTION + * Create an XcmsCmapRec for the specified cmap, windowID, + * and visual, then adds it to its list of CmapRec's. + * + * RETURNS + * Returns NULL if failed; otherwise the address to + * the added XcmsCmapRec. + * + */ +{ + XcmsCmapRec *pNew; + + if ((pNew = (XcmsCmapRec *) Xcalloc(1, (unsigned) sizeof(XcmsCmapRec))) + == NULL) { + return((XcmsCmapRec *)NULL); + } + + pNew->cmapID = cmap; + pNew->dpy = dpy; + pNew->windowID = windowID; + pNew->visual = visual; + pNew->pNext = (XcmsCmapRec *)dpy->cms.clientCmaps; + dpy->cms.clientCmaps = (XPointer)pNew; + dpy->free_funcs->clientCmaps = _XcmsFreeClientCmaps; + + /* + * Note, we don't create the XcmsCCC for pNew->ccc here because + * it may require the use of XGetWindowAttributes (a round trip request) + * to determine the screen. + */ + return(pNew); +} + + +/* + * NAME + * _XcmsCopyCmapRecAndFree + * + * SYNOPSIS + */ +XcmsCmapRec * +_XcmsCopyCmapRecAndFree(dpy, src_cmap, copy_cmap) + Display *dpy; + Colormap src_cmap; + Colormap copy_cmap; +/* + * DESCRIPTION + * Augments Xlib's XCopyColormapAndFree() to copy + * XcmsCmapRecs. + * + * RETURNS + * Returns NULL if failed; otherwise the address to + * the copy XcmsCmapRec. + * + */ +{ + XcmsCmapRec *pRec_src; + XcmsCmapRec *pRec_copy; + + if ((pRec_src = CmapRecForColormap(dpy, src_cmap)) != NULL) { + pRec_copy =_XcmsAddCmapRec(dpy, copy_cmap, pRec_src->windowID, + pRec_src->visual); + if (pRec_copy != NULL && pRec_src->ccc) { + pRec_copy->ccc = (XcmsCCC)Xcalloc(1, (unsigned) sizeof(XcmsCCCRec)); + memcpy((char *)pRec_copy->ccc, (char *)pRec_src->ccc, + sizeof(XcmsCCCRec)); + } + return(pRec_copy); + } + return((XcmsCmapRec *)NULL); +} + + +/* + * NAME + * _XcmsDeleteCmapRec + * + * SYNOPSIS + */ +void +_XcmsDeleteCmapRec(dpy, cmap) + Display *dpy; + Colormap cmap; +/* + * DESCRIPTION + * Removes and frees the specified XcmsCmapRec structure + * from the linked list of structures. + * + * RETURNS + * void + * + */ +{ + XcmsCmapRec **pPrevPtr; + XcmsCmapRec *pRec; + int scr; + + /* If it is the default cmap for a screen, do not delete it, + * because the server will not actually free it */ + for (scr = ScreenCount(dpy); --scr >= 0; ) { + if (cmap == DefaultColormap(dpy, scr)) + return; + } + + /* search for it in the list */ + pPrevPtr = (XcmsCmapRec **)&dpy->cms.clientCmaps; + while ((pRec = *pPrevPtr) && (pRec->cmapID != cmap)) { + pPrevPtr = &pRec->pNext; + } + + if (pRec) { + if (pRec->ccc) { + XcmsFreeCCC(pRec->ccc); + } + *pPrevPtr = pRec->pNext; + Xfree((char *)pRec); + } +} + + +/* + * NAME + * _XcmsFreeClientCmaps + * + * SYNOPSIS + */ +static void +_XcmsFreeClientCmaps(dpy) + Display *dpy; +/* + * DESCRIPTION + * Frees all XcmsCmapRec structures in the linked list + * and sets dpy->cms.clientCmaps to NULL. + * + * RETURNS + * void + * + */ +{ + XcmsCmapRec *pRecNext, *pRecFree; + + pRecNext = (XcmsCmapRec *)dpy->cms.clientCmaps; + while (pRecNext != NULL) { + pRecFree = pRecNext; + pRecNext = pRecNext->pNext; + if (pRecFree->ccc) { + /* Free the XcmsCCC structure */ + XcmsFreeCCC(pRecFree->ccc); + } + /* Now free the XcmsCmapRec structure */ + Xfree((char *)pRecFree); + } + dpy->cms.clientCmaps = (XPointer)NULL; +} + + + +/************************************************************************ + * * + * PUBLIC INTERFACES * + * * + ************************************************************************/ + +/* + * NAME + * XcmsCCCOfColormap + * + * SYNOPSIS + */ +XcmsCCC +XcmsCCCOfColormap(dpy, cmap) + Display *dpy; + Colormap cmap; +/* + * DESCRIPTION + * Finds the XcmsCCC associated with the specified colormap. + * + * RETURNS + * Returns NULL if failed; otherwise the address to + * the associated XcmsCCC structure. + * + */ +{ + XWindowAttributes windowAttr; + XcmsCmapRec *pRec; + int nScrn = ScreenCount(dpy); + int i; + + if ((pRec = CmapRecForColormap(dpy, cmap)) != NULL) { + if (pRec->ccc) { + /* XcmsCmapRec already has a XcmsCCC */ + return(pRec->ccc); + } + + /* + * The XcmsCmapRec does not have a XcmsCCC yet, so let's create + * one. But first, we need to know the screen associated with + * cmap, so use XGetWindowAttributes() to extract that + * information. Unless, of course there is only one screen!! + */ + if (nScrn == 1) { + /* Assume screenNumber == 0 */ + return(pRec->ccc = XcmsCreateCCC( + dpy, + 0, /* screenNumber */ + pRec->visual, + (XcmsColor *)NULL, /* clientWhitePt */ + (XcmsCompressionProc)NULL, /* gamutCompProc */ + (XPointer)NULL, /* gamutCompClientData */ + (XcmsWhiteAdjustProc)NULL, /* whitePtAdjProc */ + (XPointer)NULL /* whitePtAdjClientData */ + )); + } else { + if (XGetWindowAttributes(dpy, pRec->windowID, &windowAttr)) { + for (i = 0; i < nScrn; i++) { + if (ScreenOfDisplay(dpy, i) == windowAttr.screen) { + return(pRec->ccc = XcmsCreateCCC( + dpy, + i, /* screenNumber */ + pRec->visual, + (XcmsColor *)NULL, /* clientWhitePt */ + (XcmsCompressionProc)NULL, /* gamutCompProc */ + (XPointer)NULL, /* gamutCompClientData */ + (XcmsWhiteAdjustProc)NULL, /* whitePtAdjProc */ + (XPointer)NULL /* whitePtAdjClientData */ + )); + } + } + } + } + } + + /* + * No such cmap + */ + return(NULL); +} + +XcmsCCC XcmsSetCCCOfColormap(dpy, cmap, ccc) + Display *dpy; + Colormap cmap; + XcmsCCC ccc; +{ + XcmsCCC prev_ccc = NULL; + XcmsCmapRec *pRec; + + pRec = CmapRecForColormap(dpy, cmap); + if (pRec) { + prev_ccc = pRec->ccc; + pRec->ccc = ccc; + } + return prev_ccc; +} |