1/*
2 * Copyright 2001-2004 Red Hat Inc., Durham, North Carolina.
3 *
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation on the rights to use, copy, modify, merge,
10 * publish, distribute, sublicense, and/or sell copies of the Software,
11 * and to permit persons to whom the Software is furnished to do so,
12 * subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial
16 * portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 * NON-INFRINGEMENT.  IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
22 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
23 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 * SOFTWARE.
26 */
27
28/*
29 * Authors:
30 *   Kevin E. Martin <kem@redhat.com>
31 *
32 */
33
34/** \file
35 * Colormap support. */
36
37#ifdef HAVE_DMX_CONFIG_H
38#include <dmx-config.h>
39#endif
40
41#include "dmx.h"
42#include "dmxlog.h"
43#include "dmxsync.h"
44#include "dmxcmap.h"
45#include "dmxvisual.h"
46
47#include "micmap.h"
48
49static Bool dmxAllocateColormapPrivates(ColormapPtr pColormap)
50{
51    dmxColormapPrivPtr   pCmapPriv;
52
53    pCmapPriv = (dmxColormapPrivPtr)malloc(sizeof(*pCmapPriv));
54    if (!pCmapPriv)
55	return FALSE;
56    pCmapPriv->cmap = (Colormap)0;
57
58    DMX_SET_COLORMAP_PRIV(pColormap, pCmapPriv);
59
60    return TRUE;
61}
62
63/** Create \a pColormap on the back-end server. */
64Bool dmxBECreateColormap(ColormapPtr pColormap)
65{
66    ScreenPtr           pScreen   = pColormap->pScreen;
67    DMXScreenInfo      *dmxScreen = &dmxScreens[pScreen->myNum];
68    dmxColormapPrivPtr  pCmapPriv = DMX_GET_COLORMAP_PRIV(pColormap);
69    VisualPtr           pVisual   = pColormap->pVisual;
70    Visual             *visual    = dmxLookupVisual(pScreen, pVisual);
71
72    if (visual) {
73       pCmapPriv->cmap = XCreateColormap(dmxScreen->beDisplay,
74                                         dmxScreen->scrnWin,
75                                         visual,
76                                         (pVisual->class & DynamicClass ?
77                                          AllocAll : AllocNone));
78       return pCmapPriv->cmap != 0;
79    }
80    else {
81       dmxLog(dmxWarning, "dmxBECreateColormap: No visual found\n");
82       return 0;
83    }
84}
85
86/** Create colormap on back-end server associated with \a pColormap's
87 *  screen. */
88Bool dmxCreateColormap(ColormapPtr pColormap)
89{
90    ScreenPtr           pScreen   = pColormap->pScreen;
91    DMXScreenInfo      *dmxScreen = &dmxScreens[pScreen->myNum];
92    Bool                ret       = TRUE;
93
94    if (!dmxAllocateColormapPrivates(pColormap))
95	return FALSE;
96
97    if (dmxScreen->beDisplay) {
98	if (!dmxBECreateColormap(pColormap))
99	    return FALSE;
100    }
101
102    DMX_UNWRAP(CreateColormap, dmxScreen, pScreen);
103    if (pScreen->CreateColormap)
104	ret = pScreen->CreateColormap(pColormap);
105    DMX_WRAP(CreateColormap, dmxCreateColormap, dmxScreen, pScreen);
106
107    return ret;
108}
109
110/** Destroy \a pColormap on the back-end server. */
111Bool dmxBEFreeColormap(ColormapPtr pColormap)
112{
113    ScreenPtr           pScreen   = pColormap->pScreen;
114    DMXScreenInfo      *dmxScreen = &dmxScreens[pScreen->myNum];
115    dmxColormapPrivPtr  pCmapPriv = DMX_GET_COLORMAP_PRIV(pColormap);
116
117    if (pCmapPriv->cmap) {
118	XFreeColormap(dmxScreen->beDisplay, pCmapPriv->cmap);
119	pCmapPriv->cmap = (Colormap)0;
120	return TRUE;
121    }
122
123    return FALSE;
124}
125
126/** Destroy colormap on back-end server associated with \a pColormap's
127 *  screen. */
128void dmxDestroyColormap(ColormapPtr pColormap)
129{
130    ScreenPtr           pScreen   = pColormap->pScreen;
131    DMXScreenInfo      *dmxScreen = &dmxScreens[pScreen->myNum];
132    dmxColormapPrivPtr  pCmapPriv = DMX_GET_COLORMAP_PRIV(pColormap);
133
134    if (dmxScreen->beDisplay)
135	dmxBEFreeColormap(pColormap);
136    free(pCmapPriv);
137    DMX_SET_COLORMAP_PRIV(pColormap, NULL);
138
139    DMX_UNWRAP(DestroyColormap, dmxScreen, pScreen);
140    if (pScreen->DestroyColormap)
141	pScreen->DestroyColormap(pColormap);
142    DMX_WRAP(DestroyColormap, dmxDestroyColormap, dmxScreen, pScreen);
143}
144
145/** Install colormap on back-end server associated with \a pColormap's
146 *  screen. */
147void dmxInstallColormap(ColormapPtr pColormap)
148{
149    ScreenPtr           pScreen   = pColormap->pScreen;
150    DMXScreenInfo      *dmxScreen = &dmxScreens[pScreen->myNum];
151    dmxColormapPrivPtr  pCmapPriv = DMX_GET_COLORMAP_PRIV(pColormap);
152
153    DMX_UNWRAP(InstallColormap, dmxScreen, pScreen);
154    if (pScreen->InstallColormap)
155	pScreen->InstallColormap(pColormap);
156    DMX_WRAP(InstallColormap, dmxInstallColormap, dmxScreen, pScreen);
157
158    if (dmxScreen->beDisplay) {
159	XInstallColormap(dmxScreen->beDisplay, pCmapPriv->cmap);
160	dmxSync(dmxScreen, FALSE);
161    }
162}
163
164/** Store colors in \a pColormap on back-end server associated with \a
165 *  pColormap's screen. */
166void dmxStoreColors(ColormapPtr pColormap, int ndef, xColorItem *pdef)
167{
168    ScreenPtr           pScreen   = pColormap->pScreen;
169    DMXScreenInfo      *dmxScreen = &dmxScreens[pScreen->myNum];
170    dmxColormapPrivPtr  pCmapPriv = DMX_GET_COLORMAP_PRIV(pColormap);
171
172    if (dmxScreen->beDisplay && (pColormap->pVisual->class & DynamicClass)) {
173        XColor *color = malloc(sizeof(*color) * ndef);
174        int    i;
175
176        if (color) {
177            for (i = 0; i < ndef; i++) {
178                color[i].pixel = pdef[i].pixel;
179                color[i].red   = pdef[i].red;
180                color[i].blue  = pdef[i].blue;
181                color[i].green = pdef[i].green;
182                color[i].flags = pdef[i].flags;
183                color[i].pad   = pdef[i].pad;
184            }
185            XStoreColors(dmxScreen->beDisplay, pCmapPriv->cmap, color, ndef);
186            free(color);
187        } else {                /* xalloc failed, so fallback */
188            XColor c;
189            for (i = 0; i < ndef; i++) {
190                c.pixel = pdef[i].pixel;
191                c.red   = pdef[i].red;
192                c.blue  = pdef[i].blue;
193                c.green = pdef[i].green;
194                c.flags = pdef[i].flags;
195                c.pad   = pdef[i].pad;
196                XStoreColor(dmxScreen->beDisplay, pCmapPriv->cmap, &c);
197            }
198        }
199	dmxSync(dmxScreen, FALSE);
200    }
201
202    DMX_UNWRAP(StoreColors, dmxScreen, pScreen);
203    if (pScreen->StoreColors)
204	pScreen->StoreColors(pColormap, ndef, pdef);
205    DMX_WRAP(StoreColors, dmxStoreColors, dmxScreen, pScreen);
206}
207
208/** Create the DMX server's default colormap. */
209Bool dmxCreateDefColormap(ScreenPtr pScreen)
210{
211    return miCreateDefColormap(pScreen);
212}
213