/* $XConsortium: XcmsCmap.c,v 1.11 91/07/25 01:08:28 rws Exp $" */
* Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc.
* 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.
* XcmsCmap.c - Client Colormap Management Routines
* Routines that store additional information about
* colormaps being used by the X Client.
XcmsCmapRec
*_XcmsAddCmapRec();
static void _XcmsFreeClientCmaps();
static unsigned char CreateWindowStatus
;
/************************************************************************
************************************************************************/
* CreateWindowErrorHandler
CreateWindowErrorHandler(dpy
, errorp
)
* Error Hander used in CmapRecForColormap() to catch
* errors occuring when creating a window with a foreign
if (errorp
->request_code
== X_CreateWindow
) {
CreateWindowStatus
= errorp
->error_code
;
CmapRecForColormap(dpy
, cmap
)
* Find the corresponding XcmsCmapRec for cmap. In not found
* this routines attempts to create one.
* Returns NULL if failed; otherwise the address to
* the corresponding XcmsCmapRec.
XVisualInfo visualTemplate
; /* Template of the visual we want */
XVisualInfo
*visualList
; /* List for visuals that match */
int nVisualsMatched
; /* Number of visuals that match */
XSetWindowAttributes windowAttr
;
int (*oldErrorHandler
)();
for (pRec
= (XcmsCmapRec
*)dpy
->cms
.clientCmaps
; pRec
!= NULL
;
if (pRec
->cmapID
== cmap
) {
* 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(
(XcmsColor
*)NULL
, /* clientWhitePt */
(XcmsCompressionProc
)NULL
, /* gamutCompProc */
(XPointer
)NULL
, /* gamutCompClientData */
(XcmsWhiteAdjustProc
)NULL
, /* whitePtAdjProc */
(XPointer
)NULL
/* whitePtAdjClientData */
* 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's visual types
* attempt to set the window's colormap to cmap
* Before we start into this ugly process, let's sync up.
* Setup Temporary Error Handler
oldErrorHandler
= XSetErrorHandler(CreateWindowErrorHandler
);
for (i
= 0; i
< nScrn
; i
++) {
visualTemplate
.screen
= i
;
visualList
= XGetVisualInfo(dpy
, VisualScreenMask
, &visualTemplate
,
if (nVisualsMatched
== 0) {
windowAttr
.colormap
= cmap
;
* Call routine that attempts to create a window with cmap
CreateWindowStatus
= Success
;
tmpWindow
= XCreateWindow(dpy
, RootWindow(dpy
, i
),
} while (CreateWindowStatus
!= Success
&& ++j
< nVisualsMatched
);
if (CreateWindowStatus
== Success
) {
if ((pRec
= _XcmsAddCmapRec(dpy
, cmap
, tmpWindow
,
(visualList
+j
)->visual
)) == NULL
) {
return((XcmsCmapRec
*)NULL
);
pRec
->ccc
= XcmsCreateCCC(
(XcmsColor
*)NULL
, /* clientWhitePt */
(XcmsCompressionProc
)NULL
, /* gamutCompProc */
(XPointer
)NULL
, /* gamutCompClientData */
(XcmsWhiteAdjustProc
)NULL
, /* whitePtAdjProc */
(XPointer
)NULL
/* whitePtAdjClientData */
XSetErrorHandler(oldErrorHandler
);
XDestroyWindow(dpy
, tmpWindow
);
XFree((XPointer
)visualList
);
* Otherwise continue ....
XFree((XPointer
)visualList
);
* Unsetup Temporary Error Handler
XSetErrorHandler(oldErrorHandler
);
/************************************************************************
* API PRIVATE INTERFACES *
************************************************************************/
_XcmsAddCmapRec(dpy
, cmap
, windowID
, visual
)
* Create an XcmsCmapRec for the specified cmap, windowID,
* and visual, then adds it to its list of CmapRec's.
* Returns NULL if failed; otherwise the address to
if ((pNew
= (XcmsCmapRec
*) Xcalloc(1, (unsigned) sizeof(XcmsCmapRec
)))
return((XcmsCmapRec
*)NULL
);
pNew
->windowID
= windowID
;
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.
* _XcmsCopyCmapRecAndFree
_XcmsCopyCmapRecAndFree(dpy
, src_cmap
, copy_cmap
)
* Augments Xlib's XCopyColormapAndFree() to copy
* Returns NULL if failed; otherwise the address to
if ((pRec_src
= CmapRecForColormap(dpy
, src_cmap
)) != NULL
) {
pRec_copy
=_XcmsAddCmapRec(dpy
, copy_cmap
, pRec_src
->windowID
,
if (pRec_copy
!= NULL
&& pRec_src
->ccc
) {
pRec_copy
->ccc
= (XcmsCCC
)Xcalloc(1, (unsigned) sizeof(XcmsCCCRec
));
bcopy((char *)pRec_src
->ccc
, (char *)pRec_copy
->ccc
,
return((XcmsCmapRec
*)NULL
);
_XcmsDeleteCmapRec(dpy
, cmap
)
* Removes and frees the specified XcmsCmapRec structure
* from the linked list of structures.
/* 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
))
/* search for it in the list */
pPrevPtr
= (XcmsCmapRec
**)&dpy
->cms
.clientCmaps
;
while ((pRec
= *pPrevPtr
) && (pRec
->cmapID
!= cmap
)) {
_XcmsFreeClientCmaps(dpy
)
* Frees all XcmsCmapRec structures in the linked list
* and sets dpy->cms.clientCmaps to NULL.
XcmsCmapRec
*pRecNext
, *pRecFree
;
pRecNext
= (XcmsCmapRec
*)dpy
->cms
.clientCmaps
;
while (pRecNext
!= NULL
) {
pRecNext
= pRecNext
->pNext
;
/* Free the XcmsCCC structure */
XcmsFreeCCC(pRecFree
->ccc
);
/* Now free the XcmsCmapRec structure */
dpy
->cms
.clientCmaps
= (XPointer
)NULL
;
/************************************************************************
************************************************************************/
XcmsCCCOfColormap(dpy
, cmap
)
* Finds the XcmsCCC associated with the specified colormap.
* Returns NULL if failed; otherwise the address to
* the associated XcmsCCC structure.
XWindowAttributes windowAttr
;
int nScrn
= ScreenCount(dpy
);
if ((pRec
= CmapRecForColormap(dpy
, cmap
)) != NULL
) {
/* XcmsCmapRec already has a XcmsCCC */
* 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!!
/* Assume screenNumber == 0 */
return(pRec
->ccc
= XcmsCreateCCC(
(XcmsColor
*)NULL
, /* clientWhitePt */
(XcmsCompressionProc
)NULL
, /* gamutCompProc */
(XPointer
)NULL
, /* gamutCompClientData */
(XcmsWhiteAdjustProc
)NULL
, /* whitePtAdjProc */
(XPointer
)NULL
/* whitePtAdjClientData */
if (XGetWindowAttributes(dpy
, pRec
->windowID
, &windowAttr
)) {
for (i
= 0; i
< nScrn
; i
++) {
if (ScreenOfDisplay(dpy
, i
) == windowAttr
.screen
) {
return(pRec
->ccc
= XcmsCreateCCC(
(XcmsColor
*)NULL
, /* clientWhitePt */
(XcmsCompressionProc
)NULL
, /* gamutCompProc */
(XPointer
)NULL
, /* gamutCompClientData */
(XcmsWhiteAdjustProc
)NULL
, /* whitePtAdjProc */
(XPointer
)NULL
/* whitePtAdjClientData */