cd5ce11c3e4cb479dba35d14d050884208b7bf93
[org.ibex.core.git] / src / org / xwt / plat / X11.cc
1 // Copyright 2002 Adam Megacz, see the COPYING file for licensing [LGPL]
2 // see below for copyright information on the second portion of this file
3
4 #include "POSIX.cc"
5
6 #include <X11/Xlib.h>
7 #include <X11/extensions/XShm.h>
8 #include <X11/keysymdef.h>
9 #include <X11/keysym.h>
10 #include <X11/cursorfont.h>
11 #include <X11/Xutil.h>
12 #include <X11/Xatom.h>
13 #include <X11/Xmu/StdCmap.h>
14
15 #include <java/lang/String.h>
16 #include <org/xwt/Surface.h>
17 #include <org/xwt/Picture.h>
18 #include <org/xwt/Box.h>
19 #include <org/xwt/plat/X11.h>
20 #include <org/xwt/plat/X11$X11Surface.h>
21 #include <org/xwt/plat/X11$X11Picture.h>
22 #include <org/xwt/plat/X11$X11PixelBuffer.h>
23 #include <org/xwt/util/Semaphore.h>
24 #include <org/xwt/Platform.h>
25 #include <java/lang/Long.h>
26 #include <java/util/Hashtable.h>
27 #include <org/xwt/util/Log.h>
28
29 #include <java/lang/System.h>
30 #include <java/io/PrintStream.h>
31
32 // static (per-xserver) data
33 static Visual* visual;
34 static Colormap s_colormap;
35 static XStandardColormap* colormap_info;
36 static XShmSegmentInfo shm_info;
37 static Window selectionWindow;
38 static int shm_supported = 0;
39 static int shm_pixmaps_supported;
40 static int screen_num;
41 static int colorDepth = 0;
42 static Display* display;
43 static int shm_size = 0;
44
45 #define min(a, b) ((a) < (b) ? (a) : (b))
46 #define max(a, b) ((a) < (b) ? (b) : (a))
47
48 // X11PixelBuffer //////////////////////////////////////////////////////////////////////
49
50 // ensures that the shared memory is at least size bytes; if not, allocates 3/2 * size
51 static void ensureShmSize(int size) {
52     if (size > shm_size) {
53         if (shm_size > 0) {
54             XShmDetach(display, &shm_info);
55             shmdt(shm_info.shmaddr);
56             shmctl(shm_info.shmid, IPC_RMID, 0);
57         }
58         shm_size = 3 * size / 2;
59         shm_info.shmid = shmget(IPC_PRIVATE, shm_size, IPC_CREAT | 0777 | IPC_EXCL);
60         shm_info.shmaddr = (char*)shmat(shm_info.shmid, 0, 0);
61         shm_info.readOnly = False;
62         XSync(display, False);
63         shmctl(shm_info.shmid, IPC_RMID, 0);
64         XShmAttach(display, &shm_info);
65         XSync(display, False);
66     }
67 }
68
69 void org::xwt::plat::X11$X11PixelBuffer::fastDrawPicture(org::xwt::Picture* s,
70                                                             jint dx1, jint dy1, jint dx2, jint dy2, jint sx1, jint sy1, jint sx2, jint sy2) {
71     org::xwt::plat::X11$X11Picture* source = (org::xwt::plat::X11$X11Picture*)s;
72
73     // it's safe to clip manually since we no that no scaling will be done
74     if (dx1 < clipx) { sx1 += ((clipx - dx1) * (sx2 - sx1)) / (dx2 - dx1); dx1 = clipx; }
75     if (dy1 < clipy) { sy1 += ((clipy - dy1) * (sy2 - sy1)) / (dy2 - dy1); dy1 = clipy; }
76     if (dx2 > clipx + clipw) { sx2 -= ((dx2 - clipx - clipw) * (sx2 - sx1)) / (dx2 - dx1); dx2 = clipx + clipw; }
77     if (dy2 > clipy + cliph) { sy2 -= ((dy2 - clipy - cliph) * (sy2 - sy1)) / (dy2 - dy1); dy2 = clipy + cliph; }
78     if (dx1 > clipx + clipw) return;
79     if (dy1 > clipy + cliph) return;
80     if (dx2 - dx1 <= 0 || dy2 - dy1 <= 0) return;
81     
82     if (source->doublebuf->stipple != NULL) {
83         XSetClipMask(display, (*((GC*)clipped_gc)), *((Pixmap*)source->doublebuf->stipple));
84         XSetClipOrigin(display, (*((GC*)clipped_gc)), dx1 - sx1, dy1 - sy1);
85     } else {
86         XSetClipMask(display, (*((GC*)clipped_gc)), None);
87     }
88     XCopyArea(display, *((Pixmap*)source->doublebuf->pm), (*((Pixmap*)pm)), (*((GC*)clipped_gc)), sx1, sy1, sx2 - sx1, sy2 - sy1, dx1, dy1);
89 }
90
91 void org::xwt::plat::X11$X11PixelBuffer::slowDrawPicture(org::xwt::Picture* s,
92                                                             jint dx1, jint dy1, jint dx2, jint dy2, jint sx1, jint sy1, jint sx2, jint sy2, int rgb, int alphaOnly) {
93
94     org::xwt::plat::X11$X11Picture* source = (org::xwt::plat::X11$X11Picture*)s;
95     XImage* xi; 
96
97     // FASTEST: shared pixmap; twiddle bits in video ram directly
98     if (shared_pixmap) {
99         XSync(display, False);  // ensure that all pending operations have rendered
100         xi = (XImage*)fake_ximage;
101
102     // MEDIUM: write to a shared ximage, then ask the server to do the blit
103     } else if (shm_supported) {
104         xi = XShmCreateImage(display, visual, colorDepth, ZPixmap, NULL, &shm_info, dx2 - dx1, dy2 - dy1);
105         ensureShmSize(xi->bytes_per_line * xi->height);
106         xi->data = shm_info.shmaddr;
107         XShmGetImage(display, (*((Pixmap*)pm)), xi, dx1, dy1, AllPlanes);
108         
109     // SLOWEST: write to an ximage, copy it through the TCP connection, ask the server to do the blit
110     } else {
111         xi = XGetImage(display, (*((Pixmap*)pm)), dx1, dy1, dx2 - dx1, dy2 - dy1, AllPlanes, ZPixmap);
112     }
113     
114     int* sourcedata = (int*)elements(source->data);
115     for(int y=max(dy1, clipy); y<min(dy2, clipy + cliph); y++) {
116         
117         char* current_pixel = (xi->data + y * xi->bytes_per_line) +
118             (shared_pixmap ? max(dx1, clipx) * (xi->bits_per_pixel / 8) : - 1 * dy1 * xi->bytes_per_line);
119         
120         for(int x=max(dx1, clipx); x<min(dx2, clipx + clipw); x++, current_pixel += xi->bits_per_pixel / 8) {
121             int source_x = ((x - dx1) * (sx2 - sx1)) / (dx2 - dx1) + sx1;
122             int source_y = ((y - dy1) * (sy2 - sy1)) / (dy2 - dy1) + sy1;
123             
124             int sourcepixel = sourcedata[source_x + source_y * source->getWidth()];
125             int alpha = (sourcepixel & 0xFF000000) >> 24;
126
127             // FEATURE: be smarter here; can we do something better for the alphaonly case?
128             if (alphaOnly) sourcepixel = rgb;
129             int source_red = (sourcepixel & 0x00FF0000) >> 16;
130             int source_green = (sourcepixel & 0x0000FF00) >> 8;
131             int source_blue = (sourcepixel & 0x000000FF);
132             int red = 0, blue = 0, green = 0;
133             
134             if (alpha == 0x00) continue;
135             if (alpha != 0xFF) {
136                 int targetpixel;
137                 switch (xi->bits_per_pixel) {
138                 case 8: targetpixel = (int)(*current_pixel); break;
139                 case 16: targetpixel = (int)(*((uint16_t*)current_pixel)); break;
140                 case 24: targetpixel = (((int)*current_pixel) << 16) | (((int)*(current_pixel + 1)) << 8) | (((int)*(current_pixel + 2))); break;
141                 case 32: targetpixel = *((int*)current_pixel); break;
142                 default: org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: bpp not a multiple of 8!"));
143                 }
144                 
145                 targetpixel -= colormap_info->base_pixel;
146                 
147                 // if you're on some wierd display that isn't either RGB or BGR, that's your problem, not mine
148                 if (colormap_info->red_mult > colormap_info->green_mult && colormap_info->green_mult > colormap_info->blue_mult) {
149                     red = targetpixel / colormap_info->red_mult;
150                     green = (targetpixel - red * colormap_info->red_mult) / colormap_info->green_mult;
151                     blue = (targetpixel - red * colormap_info->red_mult - green * colormap_info->green_mult) / colormap_info->blue_mult;
152                 } else {
153                     blue = targetpixel / colormap_info->blue_mult;
154                     green = (targetpixel - blue * colormap_info->blue_mult) / colormap_info->green_mult;
155                     red = (targetpixel - blue * colormap_info->blue_mult - green * colormap_info->green_mult) / colormap_info->red_mult;
156                 }
157             }
158             
159             red = ((source_red * colormap_info->red_max * alpha) + (red * 0xFF * (0xFF - alpha))) / (0xFF * 0xFF);
160             green = ((source_green * colormap_info->green_max * alpha) + (green * 0xFF * (0xFF - alpha))) / (0xFF * 0xFF);
161             blue = ((source_blue * colormap_info->blue_max * alpha) + (blue * 0xFF * (0xFF - alpha))) / (0xFF * 0xFF);
162             uint32_t destpixel = red * colormap_info->red_mult + green * colormap_info->green_mult +
163                 blue * colormap_info->blue_mult + colormap_info->base_pixel;
164
165             switch (xi->bits_per_pixel) {
166             case 8: *current_pixel = (char)(destpixel & 0xFF); break;
167             case 16: *((uint16_t*)current_pixel) = (uint16_t)destpixel; break;
168             case 24: {
169                 int offset = (int)current_pixel & 0x3;
170                 uint64_t dest = ((uint64_t)destpixel) << (8 * offset);
171                 uint64_t mask = ((uint64_t)0xffffff) << (8 * offset);
172                 uint64_t* base = (uint64_t*)(current_pixel - offset);
173                 *base = (*base & ~mask) | dest;
174                 break;
175             }
176             case 32: *((uint32_t*)current_pixel) = destpixel; break;
177             default: org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: bpp not a multiple of 8!"));
178             }
179         }
180     }
181     
182     if (shared_pixmap) {
183         // do nothing, we wrote directly to video memory
184         
185     } else if (shm_supported) {
186         XShmPutImage(display, (*((Pixmap*)pm)), (*((GC*)gc)), xi, 0, 0, dx1, dy1, dx2 - dx1, dy2 - dy1, False);
187         XDestroyImage(xi);
188         
189     } else {
190         XPutImage(display, (*((Pixmap*)pm)), (*((GC*)gc)), xi, 0, 0, dx1, dy1, dx2 - dx1, dy2 - dy1);
191         
192     }
193 }
194
195 void org::xwt::plat::X11$X11PixelBuffer::finalize() {
196     if (shared_pixmap) {
197         XShmSegmentInfo *sinfo = (XShmSegmentInfo*)shm_segment;
198         XShmDetach(display, sinfo);
199         shmdt(sinfo->shmaddr);
200         shmctl(sinfo->shmid, IPC_RMID, 0);
201         XDestroyImage((XImage*)fake_ximage);
202         free(sinfo);
203     }
204     if (stipple) {
205         XFreePixmap(display, *((Pixmap*)stipple));
206         free(stipple);
207     }
208     XFreePixmap(display, *((Pixmap*)pm));
209     XFreeGC(display, *((GC*)gc));
210     XFreeGC(display, *((GC*)clipped_gc));
211 }
212
213 void org::xwt::plat::X11$X11PixelBuffer::natInit() {
214     
215     if (width == 0 || height == 0) return;
216     shared_pixmap &= shm_supported & shm_pixmaps_supported; // refuse to use shared pixmaps if we don't have shm
217     pm = (gnu::gcj::RawData*)malloc(sizeof(Pixmap));
218
219     if (!shared_pixmap)
220         (*((Pixmap*)pm)) = XCreatePixmap(display, RootWindow(display, screen_num), width, height, colorDepth);
221     else {
222         XShmSegmentInfo *sinfo = (XShmSegmentInfo*)malloc(sizeof(XShmSegmentInfo));
223         shm_segment = (gnu::gcj::RawData*)sinfo;
224         ((XImage*)fake_ximage) = XShmCreateImage(display, visual, colorDepth, ZPixmap, NULL, sinfo, width, height);
225         sinfo->shmid = shmget(IPC_PRIVATE, ((XImage*)fake_ximage)->bytes_per_line * height, IPC_CREAT | 0777 | IPC_EXCL);
226         ((XImage*)fake_ximage)->data = sinfo->shmaddr = (char*)shmat(sinfo->shmid, 0, 0);
227         sinfo->readOnly = False;
228         XShmAttach(display, sinfo);
229         XSync(display, False);
230         shmctl(sinfo->shmid, IPC_RMID, 0);
231         (*((Pixmap*)pm)) = XShmCreatePixmap(display, RootWindow(display, screen_num), sinfo->shmaddr, sinfo, width, height, colorDepth);
232         XSync(display, False);
233     }
234
235     gc = (gnu::gcj::RawData*)malloc(sizeof(GC));
236     clipped_gc = (gnu::gcj::RawData*)malloc(sizeof(GC));
237     (*((GC*)gc)) = XCreateGC(display, (*((Pixmap*)pm)), 0, 0);
238     (*((GC*)clipped_gc)) = XCreateGC(display, (*((Pixmap*)pm)), 0, 0);
239     
240     XGCValues vm;
241     vm.graphics_exposures = 0;
242     XChangeGC(display, (*((GC*)gc)), GCGraphicsExposures, &vm);
243     XChangeGC(display, (*((GC*)clipped_gc)), GCGraphicsExposures, &vm);
244 }    
245
246 void org::xwt::plat::X11$X11PixelBuffer::createStipple(org::xwt::plat::X11$X11Picture* xpi) {
247
248     stipple = (gnu::gcj::RawData*)malloc(sizeof(Pixmap));
249     (*((Pixmap*)stipple)) = XCreatePixmap(display, RootWindow(display, screen_num), width, height, 1);
250
251     XImage xi;
252     xi.data = (char*)malloc((width + 1) * height);
253     xi.width = width;
254     xi.height = height;
255     xi.xoffset = 0;
256     xi.format = ZPixmap;
257     xi.bitmap_pad = 8;
258     xi.bitmap_unit = 8;
259     xi.byte_order = LSBFirst;
260     xi.depth = 1;
261     xi.bytes_per_line = (width / 8) + 1;
262     xi.bits_per_pixel = 1;
263     
264     jint* d = (jint*)elements(xpi->data);
265     memset(xi.data, 0xFF, (width + 1) * height);
266     for(int x=0; x<width; x++)
267         for (int y=0; y<height; y++)
268             xi.data[y * xi.bytes_per_line + (x/8)] &= ~(((d[x + y * width] & 0xFF000000) != 0 ? 0 : 1) << (x % 8));
269
270     GC stipple_gc = XCreateGC(display, (*((Pixmap*)stipple)), 0, 0);
271
272     XGCValues vm;
273     vm.graphics_exposures = 0;
274     XChangeGC(display, stipple_gc, GCGraphicsExposures, &vm);
275
276     XPutImage(display, (*((Pixmap*)stipple)), stipple_gc, &xi, 0, 0, 0, 0, width, height);
277 }
278
279 void org::xwt::plat::X11$X11Surface::blit(org::xwt::PixelBuffer* db, jint sx, jint sy, jint dx, jint dy, jint dx2, jint dy2) {
280     org::xwt::plat::X11$X11PixelBuffer *xdb = (org::xwt::plat::X11$X11PixelBuffer*)db;
281     XCopyArea(display, *((Pixmap*)xdb->pm), *((Window*)window), *((GC*)gc), sx, sy, dx2 - dx, dy2 - dy, dx, dy);
282     XFlush(display);
283 }
284
285 void org::xwt::plat::X11$X11PixelBuffer::fillRect (jint x, jint y, jint x2, jint y2, jint argb) {
286     
287     jint w = x2 - x;
288     jint h = y2 - y;
289
290     if (x < clipx) { w -= (clipx - x); x = clipx; }
291     if (y < clipy) { h -= (clipy - y); y = clipy; }
292     if (x + w > clipx + clipw) w = (clipx + clipw - x);
293     if (y + h > clipy + cliph) h = (cliph + clipy - y);
294
295     XSetForeground(display, (*((GC*)gc)),
296                    ((((argb & 0x00FF0000) >> 16) * colormap_info->red_max) / 0xFF) * colormap_info->red_mult + 
297                    ((((argb & 0x0000FF00) >> 8) * colormap_info->green_max) / 0xFF) * colormap_info->green_mult + 
298                    ((((argb & 0x000000FF)) * colormap_info->blue_max) / 0xFF) * colormap_info->blue_mult +
299                    colormap_info->base_pixel
300                    );
301     
302     XFillRectangle(display, (*((Pixmap*)pm)), (*((GC*)gc)), x, y, w, h);
303 }
304
305
306 // X11Surface //////////////////////////////////////////////////////////////////////
307
308 void org::xwt::plat::X11$X11Surface::setIcon(org::xwt::Picture* pic) {
309     org::xwt::plat::X11$X11Picture* p = ((org::xwt::plat::X11$X11Picture*)pic);
310     org::xwt::plat::X11$X11PixelBuffer* old_dbuf = p->doublebuf;
311     p->buildPixelBuffer(1);
312     XWMHints xwmh;
313     memset(&xwmh, 0, sizeof(XWMHints));
314     xwmh.flags |= IconPixmapHint | IconMaskHint;
315     xwmh.icon_pixmap = *((Pixmap*)p->doublebuf->pm);
316     xwmh.icon_mask = *((Pixmap*)p->doublebuf->stipple);
317     XSetWMHints(display, (*((Window*)window)), &xwmh);
318     p->doublebuf = old_dbuf;
319 }
320
321 void org::xwt::plat::X11$X11Surface::setTitleBarText(java::lang::String* s) {
322     int len = min(JvGetStringUTFLength(s), 1024);
323     char buf[len + 1];
324     JvGetStringUTFRegion(s, 0, len, buf);
325     buf[len] = '\0';
326     
327     XTextProperty tp;
328     tp.value = (unsigned char*)buf;
329     tp.nitems = len;
330     tp.encoding = XA_STRING;
331     tp.format = 8;
332     XSetTextProperty(display, (*((Window*)window)), &tp, XA_WM_NAME);
333     XSetTextProperty(display, (*((Window*)window)), &tp, XA_WM_ICON_NAME);
334 }
335
336 void org::xwt::plat::X11$X11Surface::setLimits(jint minw, jint minh, jint maxw, jint maxh) {
337     XSizeHints hints;
338     hints.min_width = minw;
339     hints.min_height = minh;
340     hints.max_width = maxw;
341     hints.max_height = maxh;
342     hints.flags = PMinSize | PMaxSize;
343     XSetWMNormalHints(display, (*((Window*)window)), &hints);
344 }
345
346 void org::xwt::plat::X11$X11Surface::setSize (jint width, jint height) {
347     if (width <= 0 || height <= 0) return;
348     XResizeWindow(display, (*((Window*)window)), width, height);
349     XFlush(display);
350 }
351
352 void org::xwt::plat::X11$X11Surface::setLocation () { XMoveWindow(display, (*((Window*)window)), root->x, root->y); }
353 void org::xwt::plat::X11$X11Surface::toFront() { XRaiseWindow(display, (*((Window*)window))); }
354 void org::xwt::plat::X11$X11Surface::toBack() { XLowerWindow(display, (*((Window*)window))); }
355
356 void org::xwt::plat::X11$X11Surface::_dispose() {
357     // without this we get phantom messages after the window is gone
358     org::xwt::plat::X11::windowToSurfaceMap->remove(new java::lang::Long(*((Window*)window)));
359     XDestroyWindow(display, (*((Window*)window)));
360 }
361
362 void org::xwt::plat::X11$X11Surface::setInvisible(jboolean i) {
363     if (i) XUnmapWindow(display, (*((Window*)window)));
364     else XMapRaised(display, (*((Window*)window)));
365     XFlush(display);
366 }
367
368 void org::xwt::plat::X11$X11Surface::_setMinimized(jboolean b) {
369     if (b) XIconifyWindow(display, (*((Window*)window)), screen_num);
370     else XMapRaised(display, (*((Window*)window)));
371     XFlush(display);
372 }
373
374 void org::xwt::plat::X11$X11Surface::natInit() {
375     XSetWindowAttributes xswa;
376     window = (gnu::gcj::RawData*)malloc(sizeof(Window));
377     xswa.bit_gravity = NorthWestGravity;
378     xswa.colormap = s_colormap;
379     xswa.event_mask = ExposureMask | ButtonPressMask | StructureNotifyMask |
380         KeyPressMask | KeyReleaseMask | ButtonPressMask |
381         ButtonReleaseMask | EnterWindowMask | LeaveWindowMask |
382         PointerMotionMask | ButtonMotionMask | ConfigureNotify | FocusChangeMask;
383     *((Window*)window) = XCreateWindow(display, RootWindow(display, screen_num), 10, 10, 10, 10, 0,
384                                        colorDepth, InputOutput, CopyFromParent,
385                                        CWColormap | CWBitGravity | CWEventMask, &xswa);
386     
387     if (!framed) {
388         // I don't know why this works....
389         int dat[5] = { 0x2, 0xbffff804, 0x0, 0x817f560, 0x8110694 };
390         XChangeProperty(display, (*((Window*)window)),
391                         XInternAtom(display, "_MOTIF_WM_HINTS", False),
392                         XInternAtom(display, "_MOTIF_WM_HINTS", False),
393                         32, 
394                         PropModeReplace,
395                         (unsigned char*)dat,
396                         5);
397     }
398     
399     XTextProperty tp;
400     tp.value = (unsigned char*)"XWT";
401     tp.nitems = 3;
402     tp.encoding = XA_STRING;
403     tp.format = 8;
404     XSetTextProperty(display, (*((Window*)window)), &tp, XA_WM_CLASS);
405     
406     Atom proto = XInternAtom(display, "WM_DELETE_WINDOW", False);
407     XSetWMProtocols(display, (*((Window*)window)), &proto, 1);
408     
409     XSelectInput(display, (*((Window*)window)), StructureNotifyMask);
410     org::xwt::plat::X11::windowToSurfaceMap->put(new java::lang::Long(*((Window*)window)), this);
411
412     XEvent e;
413     XMapRaised(display, (*((Window*)window)));
414     XFlush(display);
415
416     waitForCreation->block();
417     XSelectInput(display, (*((Window*)window)), xswa.event_mask);
418     XFlush(display);
419
420     gc = (gnu::gcj::RawData*)malloc(sizeof(GC));
421     *((GC*)gc) = XCreateGC(display, (*((Window*)window)), 0, 0);
422     
423     XGCValues vm;
424     vm.graphics_exposures = 0;
425     XChangeGC(display, *((GC*)gc), GCGraphicsExposures, &vm);
426 }
427
428
429 void org::xwt::plat::X11$X11Surface::dispatchEvent(gnu::gcj::RawData* ev) {
430
431     XEvent* e = (XEvent*)ev;
432     if (e->type == Expose) {
433         XExposeEvent *expose = (XExposeEvent*)(e);
434         Dirty(expose->x, expose->y, expose->width, expose->height);
435         
436     } else if (e->type == MapNotify) { Minimized(0); waitForCreation->release();
437     } else if (e->type == UnmapNotify) { Minimized(1);
438     } else if (e->type == FocusIn) { Focused(1);
439     } else if (e->type == FocusOut) { Focused(0);
440     } else if (e->type == ClientMessage) {
441         if (((XClientMessageEvent*)(e))->data.l[0] == XInternAtom(display, "WM_DELETE_WINDOW", False)) Close();
442     
443     } else if (e->type == KeyPress || e->type == KeyRelease) {
444         XKeyEvent *xbe = (XKeyEvent*)(e);
445         
446         // drop faked KeyRelease events generated by the X server's autorepeat
447         if (e->type == KeyRelease) {
448             char depressed[32];
449             XQueryKeymap(display, depressed);
450             if ((depressed[(xbe->keycode & 0xff) / 8] & (0x1 << (xbe->keycode % 8))) >> (xbe->keycode % 8)) return;
451         }
452         
453         char ss[20];
454         char* s = ss;
455         
456         unsigned int savestate = xbe->state;
457         xbe->state = xbe->state & ShiftMask;      // ignore everything except shiftmask
458         XLookupString(xbe, s, 20, NULL, NULL);
459         xbe->state = savestate;
460         
461         if (s != NULL && s[0] != '\0' && s[1] == '\0' && s[0] >= 0x20 && s[0] <= 0x7E) {
462             int i = s[0];
463             
464         } else {
465             KeySym ks = XKeycodeToKeysym(display, xbe->keycode, 0);
466             switch (ks) {
467             case XK_BackSpace: s = "back_space"; break;
468             case XK_Tab: s = "tab"; break;
469             case XK_Linefeed: s = "enter"; break;
470             case XK_Return: s = "enter"; break;
471             case XK_Scroll_Lock: s = "scroll_lock"; break;
472             case XK_Escape: s = "escape"; break;
473             case XK_Insert: s = "insert"; break;
474             case XK_Delete: s = "delete"; break;
475             case XK_Home: s = "home"; break;
476             case XK_Left: s = "left"; break;
477             case XK_Up: s = "up"; break;
478             case XK_Right: s = "right"; break;
479             case XK_Down: s = "down"; break;
480             case XK_Page_Up: s = "page_up"; break;
481             case XK_Page_Down: s = "page_down"; break;
482             case XK_End: s = "end"; break;
483             case XK_Num_Lock: s = "num_lock"; break;
484             case XK_KP_Tab: s = "tab"; break;
485             case XK_KP_Enter: s = "enter"; break;
486             case XK_KP_F1: s = "f1"; break;
487             case XK_KP_F2: s = "f2"; break;
488             case XK_KP_F3: s = "f3"; break;
489             case XK_KP_F4: s = "f4"; break;
490             case XK_KP_Home: s = "home"; break;
491             case XK_KP_Left: s = "left"; break;
492             case XK_KP_Up: s = "up"; break;
493             case XK_KP_Right: s = "right"; break;
494             case XK_KP_Down: s = "down"; break;
495             case XK_KP_Page_Up: s = "page_up"; break;
496             case XK_KP_Page_Down: s = "page_down"; break;
497             case XK_KP_End: s = "end"; break;
498             case XK_KP_Insert: s = "insert"; break;
499             case XK_KP_Delete: s = "delete"; break;
500             case XK_F1: s = "f1"; break;
501             case XK_F2: s = "f2"; break;
502             case XK_F3: s = "f3"; break;
503             case XK_F4: s = "f4"; break;
504             case XK_F5: s = "f5"; break;
505             case XK_F6: s = "f6"; break;
506             case XK_F7: s = "f7"; break;
507             case XK_F8: s = "f8"; break;
508             case XK_F9: s = "f9"; break;
509             case XK_F10: s = "f10"; break;
510             case XK_F11: s = "f11"; break;
511             case XK_F12: s = "f12"; break;
512             case XK_Shift_L: s = "shift"; break;
513             case XK_Shift_R: s = "shift"; break;
514             case XK_Control_L: s = "control"; break;
515             case XK_Control_R: s = "control"; break;
516             case XK_Meta_L: s = "alt"; break;
517             case XK_Meta_R: s = "alt"; break;
518             case XK_Alt_L: s = "alt"; break;
519             case XK_Alt_R: s = "alt"; break;
520             default: return;
521             }
522         }
523         
524         jstring s2 = JvNewStringLatin1(s);
525         if (e->type == KeyPress) KeyPressed((xbe->state & LockMask) ? s2->toUpperCase() : s2);
526         if (e->type == KeyRelease) KeyReleased(s2);
527         
528     } else if (e->type == ButtonPress) {
529         XButtonEvent* xbe = (XButtonEvent*)(e);
530         if (xbe->button == 2) xbe->button = 3;
531         else if (xbe->button == 3) xbe->button = 2;
532         Press(xbe->button);
533         
534     } else if (e->type == ButtonRelease) {
535         XButtonEvent* xbe = (XButtonEvent*)(e);
536         if (xbe->button == 2) xbe->button = 3;
537         else if (xbe->button == 3) xbe->button = 2;
538         Release(xbe->button);
539         
540     } else if (e->type == MotionNotify) {
541         XMotionEvent* xme = (XMotionEvent*)(e);
542         Move(xme->x, xme->y);
543         
544     } else if (e->type == EnterNotify || e->type == LeaveNotify) {
545         XCrossingEvent* xce = (XCrossingEvent*)(e);
546         Move(xce->x, xce->y);
547         
548     } else if (e->type == ConfigureNotify) {
549         Window child;
550         int x_out, y_out;
551         XConfigureEvent* xce = (XConfigureEvent*)(e);
552         XTranslateCoordinates(display, (*((Window*)window)), RootWindow(display, screen_num), 0, 0, &x_out, &y_out, &child);
553         if (xce->width != root->width || xce->height != root->height) SizeChange(xce->width, xce->height);
554         if (x_out != root->x || y_out != root->y) PosChange(x_out, y_out);
555         
556     }
557 }
558
559 static jstring crosshair, east, hand, move, north, northeast, northwest,
560     south, southeast, southwest, text, west, wait_string;
561 static Cursor crosshair_cursor, east_cursor, hand_cursor, move_cursor, north_cursor,
562     northeast_cursor, northwest_cursor, south_cursor, southeast_cursor,
563     southwest_cursor, text_cursor, west_cursor, wait_cursor, default_cursor;
564
565 void org::xwt::plat::X11$X11Surface::syncCursor() {
566     
567     Cursor curs;
568     if (cursor->equals(crosshair)) curs = crosshair_cursor;
569     else if (cursor->equals(east)) curs = east_cursor;
570     else if (cursor->equals(hand)) curs = hand_cursor;
571     else if (cursor->equals(move)) curs = move_cursor;
572     else if (cursor->equals(north)) curs = north_cursor;
573     else if (cursor->equals(northeast)) curs = northeast_cursor;
574     else if (cursor->equals(northwest)) curs = northwest_cursor;
575     else if (cursor->equals(south)) curs = south_cursor;
576     else if (cursor->equals(southeast)) curs = southeast_cursor;
577     else if (cursor->equals(southwest)) curs = southwest_cursor;
578     else if (cursor->equals(text)) curs = text_cursor;
579     else if (cursor->equals(west)) curs = west_cursor;
580     else if (cursor->equals(wait_string)) curs = wait_cursor;
581     else curs = default_cursor;
582     
583     XDefineCursor(display, (*((Window*)window)), curs);
584 }
585
586
587
588 // X11 ///////////////////////////////////////////////////////////////////
589
590 jint org::xwt::plat::X11::_getScreenWidth() { return WidthOfScreen(DefaultScreenOfDisplay(display)); }
591 jint org::xwt::plat::X11::_getScreenHeight() { return HeightOfScreen(DefaultScreenOfDisplay(display)); }
592
593 static void dispatchSelectionEvent(XEvent* e) {
594     if (e->type == SelectionNotify) {
595         XSelectionEvent* xsn = (XSelectionEvent*)(e);
596         if (xsn->property == None) org::xwt::plat::X11::clipboard = JvNewStringLatin1("", 0);
597         else {
598             Atom returntype;
599             int returnformat;
600             unsigned long numitems;
601             unsigned char* ret;
602             unsigned long bytes_after;
603             XGetWindowProperty(display, xsn->requestor, xsn->property, 0, 4096,
604                                True, AnyPropertyType, &returntype, &returnformat,
605                                &numitems, &bytes_after, &ret);
606             org::xwt::plat::X11::clipboard =
607                 (returntype == None ? JvNewStringLatin1("", 0) : JvNewStringLatin1((char*)ret, strlen((char*)ret)));
608         }
609         org::xwt::plat::X11::waiting_for_selection_event->release();
610         
611     } else if (e->type == SelectionRequest) {
612         XSelectionRequestEvent* xsr = (XSelectionRequestEvent*)(e);
613         XSelectionEvent xsn;
614         xsn.type = SelectionNotify;
615         xsn.serial = xsr->serial;
616         xsn.send_event = True;
617         xsn.display = display;
618         xsn.requestor = xsr->requestor;
619         xsn.selection = xsr->selection;
620         xsn.target = xsr->target;
621         xsn.property = xsr->property;
622         xsn.time = xsr->time;
623         
624         int len = min(1024, JvGetStringUTFLength(org::xwt::plat::X11::clipboard));
625         char buf[len + 1];
626         JvGetStringUTFRegion(org::xwt::plat::X11::clipboard, 0, len, buf);
627         buf[len] = '\0';
628         
629         XChangeProperty(display, xsr->requestor, xsr->property, xsr->target, 8, PropModeReplace, (unsigned char*)buf, len + 1);
630         XSendEvent(display, xsr->requestor, True, 0, (XEvent*)(&xsn));
631     }        
632 }
633
634 void org::xwt::plat::X11::eventThread() {
635     XEvent e;
636     while(true) {
637         XNextEvent(display, &e);
638         if (e.type == SelectionNotify || e.type == SelectionRequest) {
639             dispatchSelectionEvent(&e);
640         } else {
641             org::xwt::plat::X11$X11Surface* surface =
642                 (org::xwt::plat::X11$X11Surface*)windowToSurfaceMap->get(new java::lang::Long(((XAnyEvent*)&e)->window));
643             if (surface != NULL) surface->dispatchEvent((gnu::gcj::RawData*)&e);
644         }
645     }
646 }
647
648 jstring org::xwt::plat::X11::_getClipBoard() {
649     XConvertSelection(display, XA_PRIMARY, XA_STRING, XInternAtom(display, "VT_SELECTION", False), selectionWindow, CurrentTime);
650     XFlush(display);
651     org::xwt::plat::X11::waiting_for_selection_event->block();
652     return clipboard;
653 }
654
655 void org::xwt::plat::X11::_setClipBoard(jstring s) {
656     clipboard = s;
657     int len = JvGetStringUTFLength(clipboard);
658     char buf[len + 1];
659     JvGetStringUTFRegion(clipboard, 0, len, buf);
660     buf[len] = '\0';
661     XSetSelectionOwner(display, XInternAtom(display, "PRIMARY", 0), selectionWindow, CurrentTime);
662 }
663
664 typedef int (X11ErrorHandler)(Display*, XErrorEvent*);
665 int errorHandler(Display* d, XErrorEvent* e) {
666     // this error handler is only installed during the initial
667     // test to see if shm is present
668     shm_supported = 0;
669 }
670
671 void org::xwt::plat::X11::natInit() {
672
673     if (!XInitThreads())
674         org::xwt::Platform::criticalAbort(JvNewStringLatin1("Your X11 libraries do not support multithreaded programs"));
675
676     char* DISPLAY = getenv("DISPLAY");
677     if (DISPLAY == NULL || strlen(DISPLAY) == 0) DISPLAY = ":0.0";
678     display = XOpenDisplay(DISPLAY);
679
680     if (display == 0)
681         org::xwt::Platform::criticalAbort(JvNewStringLatin1("Unable to connect to X11 display server"));
682
683     screen_num = XDefaultScreen(display);
684     colorDepth = (jint)(DefaultDepth(((Display*)display), 0));
685     shm_info.shmaddr = NULL;
686
687     // FIXME: SHM doesn't work on Darwin
688     //shm_supported = (XShmQueryExtension(display) == True);
689     if (shm_supported) {
690         X11ErrorHandler* oldHandler = XSetErrorHandler(errorHandler);
691         XShmSegmentInfo sinfo;
692         sinfo.shmid = shmget(IPC_PRIVATE, 1, IPC_CREAT | 0777 | IPC_EXCL);
693         sinfo.readOnly = False;
694         // if the server is remote, this will trigger the error handler
695         XShmAttach(display, &sinfo);
696         XSync(display, False);
697         XSetErrorHandler(oldHandler);
698     }
699
700     if (shm_supported)
701         shm_pixmaps_supported = (XShmPixmapFormat(display) == ZPixmap);
702     
703     crosshair = JvNewStringLatin1("crosshair");
704     east = JvNewStringLatin1("east");
705     hand = JvNewStringLatin1("hand");
706     move = JvNewStringLatin1("move");
707     north = JvNewStringLatin1("north");
708     northeast = JvNewStringLatin1("northeast");
709     northwest = JvNewStringLatin1("northwest");
710     south = JvNewStringLatin1("south");
711     southeast = JvNewStringLatin1("southeast");
712     southwest = JvNewStringLatin1("southwest");
713     text = JvNewStringLatin1("text");
714     west = JvNewStringLatin1("west");
715     wait_string = JvNewStringLatin1("wait");
716     crosshair_cursor = XCreateFontCursor(display, XC_tcross);
717     east_cursor = XCreateFontCursor(display, XC_right_side);
718     hand_cursor = XCreateFontCursor(display, XC_hand2);
719     move_cursor = XCreateFontCursor(display, XC_fleur);
720     north_cursor = XCreateFontCursor(display, XC_top_side);
721     northeast_cursor = XCreateFontCursor(display, XC_top_right_corner);
722     northwest_cursor = XCreateFontCursor(display, XC_left_side);
723     south_cursor = XCreateFontCursor(display, XC_bottom_side);
724     southeast_cursor = XCreateFontCursor(display, XC_bottom_right_corner);
725     southwest_cursor = XCreateFontCursor(display, XC_bottom_left_corner);
726     text_cursor = XCreateFontCursor(display, XC_xterm);
727     west_cursor = XCreateFontCursor(display, XC_right_side);
728     wait_cursor = XCreateFontCursor(display, XC_watch);
729     default_cursor = XCreateFontCursor(display, XC_left_ptr);
730
731     selectionWindow = XCreateWindow(display, RootWindow(display, screen_num), 0, 0, 1, 1, 0, colorDepth, InputOutput, CopyFromParent, 0, NULL);
732     visual = DefaultVisual(display, screen_num);
733     char buf[255];
734     sprintf(buf, "X11 DISPLAY: %s", XDisplayString(display));
735     org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
736     sprintf(buf, "X11 SHM:     %s", shm_supported ? "enabled" : "disabled");
737     org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
738     sprintf(buf, "X11 Visual:  %x %x %x bits: %i visualid: %i depth: %i",
739             visual->red_mask, visual->green_mask, visual->blue_mask, visual->bits_per_rgb, visual->visualid, colorDepth);
740     org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
741
742     // FIXME: don't know why (True, False) is the best solution...
743     if(XmuLookupStandardColormap(display, screen_num, visual->visualid, colorDepth, XA_RGB_BEST_MAP, True, False) == 0)
744         org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: XmuLookupStandardColormap failed"));
745     
746     XStandardColormap* best_map_info = NULL;
747     int count;
748     if (XGetRGBColormaps(display, RootWindow(display, screen_num), &best_map_info, &count, XA_RGB_BEST_MAP) == 0)
749         org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: couldn't allocate a standard colormap"));
750     if (!best_map_info->colormap)
751         org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: XmuLookupStandardColomap succeded, but no colormap was found on the root window"));
752     if (best_map_info->red_max == 0)
753         org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: standard colormap exists, but was improperly allocated"));
754     s_colormap = best_map_info->colormap;
755     colormap_info = best_map_info;
756
757     sprintf(buf, "            red_max / red_mult: %x %x", colormap_info->red_max, colormap_info->red_mult);
758     org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
759     sprintf(buf, "            green_max / green_mult: %x %x", colormap_info->green_max, colormap_info->green_mult);
760     org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
761     sprintf(buf, "            blue_max / blue_mult: %x %x", colormap_info->blue_max, colormap_info->blue_mult);
762     org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
763     sprintf(buf, "            base_pixel: %x", colormap_info->base_pixel);
764     org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
765 }
766
767
768
769 //////////////////////////////////////////////////////////////////////////////
770 //////////////////////////////////////////////////////////////////////////////
771 //////////////////////////////////////////////////////////////////////////////
772 //////////////////////////////////////////////////////////////////////////////
773 //                                                                          //
774 // Everything below this point was taken, cut-and-paste, from the           //
775 // source for libXmu. It implements the official 'standard colormap         //
776 // creation algorithm.  I made some small changes to                        //
777 // XmuDeleteStandardColormap                                                //
778 //                                                                          //
779 //////////////////////////////////////////////////////////////////////////////
780 //////////////////////////////////////////////////////////////////////////////
781 //////////////////////////////////////////////////////////////////////////////
782 //////////////////////////////////////////////////////////////////////////////
783
784 /* $Xorg: LookupCmap.c,v 1.4 2001/02/09 02:03:53 xorgcvs Exp $ */
785
786 /* 
787  
788 Copyright 1989, 1998  The Open Group
789
790 Permission to use, copy, modify, distribute, and sell this software and its
791 documentation for any purpose is hereby granted without fee, provided that
792 the above copyright notice appear in all copies and that both that
793 copyright notice and this permission notice appear in supporting
794 documentation.
795
796 The above copyright notice and this permission notice shall be included in
797 all copies or substantial portions of the Software.
798
799 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
800 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
801 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
802 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
803 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
804 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
805
806 Except as contained in this notice, the name of The Open Group shall not be
807 used in advertising or otherwise to promote the sale, use or other dealings
808 in this Software without prior written authorization from The Open Group.
809
810 */
811 /* $XFree86: xc/lib/Xmu/LookupCmap.c,v 1.8 2001/12/14 19:55:47 dawes Exp $ */
812
813 /*
814  * Author:  Donna Converse, MIT X Consortium
815  */
816
817 #include <stdio.h>
818 #include <X11/Xlib.h>
819 #include <X11/Xatom.h>
820 #include <X11/Xutil.h>
821 #include <X11/Xmu/StdCmap.h>
822 #include <stdlib.h>
823
824 /*
825  * Prototypes
826  */
827 static Status lookup(Display*, int, VisualID, Atom, XStandardColormap*, Bool);
828
829 /*
830  * To create a standard colormap if one does not currently exist, or
831  * replace the currently existing standard colormap, use 
832  * XmuLookupStandardColormap().
833  *
834  * Given a screen, a visual, and a property, XmuLookupStandardColormap()
835  * will determine the best allocation for the property under the specified
836  * visual, and determine the whether to create a new colormap or to use
837  * the default colormap of the screen.  It will call XmuStandardColormap()
838  * to create the standard colormap.
839  *
840  * If replace is true, any previous definition of the property will be 
841  * replaced.  If retain is true, the property and the colormap will be
842  * made permanent for the duration of the server session.  However,
843  * pre-existing property definitions which are not replaced cannot be made
844  * permanent by a call to XmuLookupStandardColormap(); a request to retain 
845  * resources pertains to newly created resources.
846  *
847  * Returns 0 on failure, non-zero on success.  A request to create a 
848  * standard colormap upon a visual which cannot support such a map is
849  * considered a failure.  An example of this would be requesting any
850  * standard colormap property on a monochrome visual, or, requesting an
851  * RGB_BEST_MAP on a display whose colormap size is 16.
852  */
853
854 Status
855 XmuLookupStandardColormap(Display *dpy, int screen, VisualID visualid,
856                           unsigned int depth, Atom property,
857                           Bool replace, Bool retain)
858      /*
859       * dpy             - specifies X server connection
860       * screen          - specifies screen of display
861       * visualid        - specifies the visual type
862       * depth           - specifies  the visual type
863       * property        - a standard colormap property
864       * replace         - specifies whether to replace
865       * retain          - specifies whether to retain
866       */
867 {
868     Display             *odpy;          /* original display connection */
869     XStandardColormap   *colormap;      
870     XVisualInfo         vinfo_template, *vinfo; /* visual */
871     long                vinfo_mask;
872     unsigned long       r_max, g_max, b_max;    /* allocation */
873     int                 count;  
874     Colormap            cmap;                   /* colormap ID */
875     Status              status = 0;
876
877
878     /* Match the requested visual */
879
880     vinfo_template.visualid = visualid; 
881     vinfo_template.screen = screen;
882     vinfo_template.depth = depth;
883     vinfo_mask = VisualIDMask | VisualScreenMask | VisualDepthMask;
884     if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &count)) ==
885         NULL)
886         return 0;
887
888     /* Monochrome visuals have no standard maps */
889
890     if (vinfo->colormap_size <= 2) {
891         XFree((char *) vinfo);
892         return 0;       
893     }
894
895     /* If the requested property already exists on this screen, and, 
896      * if the replace flag has not been set to true, return success.
897      * lookup() will remove a pre-existing map if replace is true.
898      */
899
900     if (lookup(dpy, screen, visualid, property, (XStandardColormap *) NULL,
901                replace) && !replace) {
902         XFree((char *) vinfo);
903         return 1;
904     }
905
906     /* Determine the best allocation for this property under the requested
907      * visualid and depth, and determine whether or not to use the default
908      * colormap of the screen.
909      */
910
911     if (!XmuGetColormapAllocation(vinfo, property, &r_max, &g_max, &b_max)) {
912         XFree((char *) vinfo);
913         return 0;
914     }
915
916     cmap = (property == XA_RGB_DEFAULT_MAP &&
917             visualid == XVisualIDFromVisual(DefaultVisual(dpy, screen)))
918         ? DefaultColormap(dpy, screen) : None;
919
920     /* If retaining resources, open a new connection to the same server */
921
922     if (retain) {
923         odpy = dpy;
924         if ((dpy = XOpenDisplay(XDisplayString(odpy))) == NULL) {
925             XFree((char *) vinfo);
926             return 0;
927         }
928     }
929
930     /* Create the standard colormap */
931
932     colormap = XmuStandardColormap(dpy, screen, visualid, depth, property,
933                                    cmap, r_max, g_max, b_max);
934
935     /* Set the standard colormap property */
936
937     if (colormap) {
938         XGrabServer(dpy);
939
940         if (lookup(dpy, screen, visualid, property, colormap, replace) &&
941             !replace) {
942             /* Someone has defined the property since we last looked.
943              * Since we will not replace it, release our own resources.
944              * If this is the default map, our allocations will be freed 
945              * when this connection closes.
946              */
947             if (colormap->killid == ReleaseByFreeingColormap)
948             XFreeColormap(dpy, colormap->colormap);
949         } else if (retain) {
950                 XSetCloseDownMode(dpy, RetainPermanent);
951         }
952         XUngrabServer(dpy);
953         XFree((char *) colormap);
954         status = 1;
955     }
956
957     if (retain)
958         XCloseDisplay(dpy);
959     XFree((char *) vinfo);
960     return status;
961 }
962
963 /***************************************************************************/
964
965 /* Lookup a standard colormap property.  If the property is RGB_DEFAULT_MAP,
966  * the visualid is used to determine whether the indicated standard colormap
967  * exists.  If the map exists and replace is true, delete the resources used
968  * by the map and remove the property.  Return true if the map exists,
969  * or did exist and was deleted; return false if the map was not found.
970  *
971  * Note that this is not the way that a Status return is normally used.
972  *
973  * If new is not NULL, new points to an XStandardColormap structure which
974  * describes a standard colormap of the specified property.  It will be made
975  * a standard colormap of the screen if none already exists, or if replace 
976  * is true.
977  */
978
979 static Status
980 lookup(Display *dpy, int screen, VisualID visualid, Atom property,
981        XStandardColormap *cnew, Bool replace)
982      /*
983       * dpy             - specifies display connection
984       * screen          - specifies screen number
985       * visualid        - specifies visualid for std map
986       * property        - specifies colormap property name
987       * cnew            - specifies a standard colormap
988       * replace         - specifies whether to replace
989       */
990 {
991     register int        i;
992     int                 count;
993     XStandardColormap   *stdcmaps, *s;
994     Window              win = RootWindow(dpy, screen);
995
996     /* The property does not already exist */
997
998     if (! XGetRGBColormaps(dpy, win, &stdcmaps, &count, property)) {
999         if (cnew)
1000             XSetRGBColormaps(dpy, win, cnew, 1, property);
1001         return 0;
1002     }
1003
1004     /* The property exists and is not describing the RGB_DEFAULT_MAP */
1005
1006     if (property != XA_RGB_DEFAULT_MAP) {
1007         if (replace) {
1008             XmuDeleteStandardColormap(dpy, screen, property);
1009             if (cnew)
1010                 XSetRGBColormaps(dpy, win, cnew, 1, property);
1011         }
1012         XFree((char *)stdcmaps);
1013         return 1;
1014     }
1015
1016     /* The property exists and is RGB_DEFAULT_MAP */
1017     
1018     for (i=0, s=stdcmaps; (i < count) && (s->visualid != visualid); i++, s++)
1019         ;
1020
1021     /* No RGB_DEFAULT_MAP property matches the given visualid */
1022
1023     if (i == count) {
1024         if (cnew) {
1025             XStandardColormap   *m, *maps;
1026
1027             s = (XStandardColormap *) malloc((unsigned) ((count+1) * sizeof
1028                                               (XStandardColormap)));
1029
1030             for (i = 0, m = s, maps = stdcmaps; i < count; i++, m++, maps++) {
1031                 m->colormap   = maps->colormap;
1032                 m->red_max    = maps->red_max;
1033                 m->red_mult   = maps->red_mult;
1034                 m->green_max  = maps->green_max;
1035                 m->green_mult = maps->green_mult;
1036                 m->blue_max   = maps->blue_max;
1037                 m->blue_mult  = maps->blue_mult;
1038                 m->base_pixel = maps->base_pixel;
1039                 m->visualid   = maps->visualid;
1040                 m->killid     = maps->killid;
1041             }
1042             m->colormap   = cnew->colormap;
1043             m->red_max    = cnew->red_max;
1044             m->red_mult   = cnew->red_mult;
1045             m->green_max  = cnew->green_max;
1046             m->green_mult = cnew->green_mult;
1047             m->blue_max   = cnew->blue_max;
1048             m->blue_mult  = cnew->blue_mult;
1049             m->base_pixel = cnew->base_pixel;
1050             m->visualid   = cnew->visualid;
1051             m->killid     = cnew->killid;
1052
1053             XSetRGBColormaps(dpy, win, s, ++count, property);
1054             free((char *) s);
1055         }
1056         XFree((char *) stdcmaps);
1057         return 0;
1058     }
1059
1060     /* Found an RGB_DEFAULT_MAP property with a matching visualid */
1061
1062     if (replace) {
1063         /* Free old resources first - we may need them, particularly in 
1064          * the default colormap of the screen.  However, because of this,
1065          * it is possible that we will destroy the old resource and fail 
1066          * to create a new one if XmuStandardColormap() fails.
1067          */
1068
1069         if (count == 1) {
1070             XmuDeleteStandardColormap(dpy, screen, property);
1071             if (cnew)
1072                 XSetRGBColormaps(dpy, win, cnew, 1, property);
1073         }
1074         else {
1075             XStandardColormap   *map;
1076
1077             /* s still points to the matching standard colormap */
1078
1079             if (s->killid == ReleaseByFreeingColormap) {
1080                 if ((s->colormap != None) &&
1081                     (s->colormap != DefaultColormap(dpy, screen)))
1082                     XFreeColormap(dpy, s->colormap);
1083             }
1084             else if (s->killid != None)
1085                 XKillClient(dpy, s->killid);
1086
1087             map = (cnew) ? cnew : stdcmaps + --count;
1088
1089             s->colormap   = map->colormap;
1090             s->red_max    = map->red_max;
1091             s->red_mult   = map->red_mult;
1092             s->green_max  = map->green_max;
1093             s->green_mult = map->green_mult;
1094             s->blue_max   = map->blue_max;
1095             s->blue_mult  = map->blue_mult;
1096             s->visualid   = map->visualid;
1097             s->killid     = map->killid;
1098
1099             XSetRGBColormaps(dpy, win, stdcmaps, count, property);
1100         }
1101     }
1102     XFree((char *) stdcmaps);
1103     return 1;
1104 }
1105
1106 /* $Xorg: CmapAlloc.c,v 1.4 2001/02/09 02:03:51 xorgcvs Exp $ */
1107
1108 /* 
1109
1110 Copyright 1989, 1994, 1998  The Open Group
1111
1112 Permission to use, copy, modify, distribute, and sell this software and its
1113 documentation for any purpose is hereby granted without fee, provided that
1114 the above copyright notice appear in all copies and that both that
1115 copyright notice and this permission notice appear in supporting
1116 documentation.
1117
1118 The above copyright notice and this permission notice shall be included in
1119 all copies or substantial portions of the Software.
1120
1121 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1122 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1123 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
1124 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1125 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1126 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1127
1128 Except as contained in this notice, the name of The Open Group shall not be
1129 used in advertising or otherwise to promote the sale, use or other dealings
1130 in this Software without prior written authorization from The Open Group.
1131
1132 */
1133 /* $XFree86: xc/lib/Xmu/CmapAlloc.c,v 1.7 2001/12/14 19:55:35 dawes Exp $ */
1134
1135 /*
1136  * Author:  Donna Converse, MIT X Consortium
1137  */
1138
1139 #include <X11/Xlib.h>
1140 #include <X11/Xatom.h>
1141 #include <X11/Xutil.h>
1142 #include <X11/Xmu/StdCmap.h>
1143 #include <stdio.h>
1144
1145 #define lowbit(x) ((x) & (~(x) + 1))
1146
1147 /*
1148  * Prototypes
1149  */
1150 static void best_allocation(XVisualInfo*, unsigned long*, unsigned long*,
1151                             unsigned long*);
1152 static int default_allocation(XVisualInfo*, unsigned long*,
1153                               unsigned long*, unsigned long*);
1154 static void gray_allocation(int, unsigned long*, unsigned long*,
1155                             unsigned long*);
1156 static int icbrt(int);
1157 static int icbrt_with_bits(int, int);
1158 static int icbrt_with_guess(int, int);
1159
1160 /* To determine the best allocation of reds, greens, and blues in a 
1161  * standard colormap, use XmuGetColormapAllocation.
1162  *      vinfo           specifies visual information for a chosen visual
1163  *      property        specifies one of the standard colormap property names
1164  *      red_max         returns maximum red value 
1165  *      green_max       returns maximum green value
1166  *      blue_max        returns maximum blue value
1167  *
1168  * XmuGetColormapAllocation returns 0 on failure, non-zero on success.
1169  * It is assumed that the visual is appropriate for the colormap property.
1170  */
1171
1172 Status
1173 XmuGetColormapAllocation(XVisualInfo *vinfo, Atom property,
1174                          unsigned long *red_max,
1175                          unsigned long *green_max,
1176                          unsigned long *blue_max)
1177 {
1178     Status      status = 1;
1179
1180     if (vinfo->colormap_size <= 2)
1181         return 0;
1182
1183     switch (property)
1184     {
1185       case XA_RGB_DEFAULT_MAP:
1186         status = default_allocation(vinfo, red_max, green_max, blue_max);
1187         break;
1188       case XA_RGB_BEST_MAP:
1189         best_allocation(vinfo, red_max, green_max, blue_max);
1190         break;
1191       case XA_RGB_GRAY_MAP:
1192         gray_allocation(vinfo->colormap_size, red_max, green_max, blue_max);
1193         break;
1194       case XA_RGB_RED_MAP:
1195         *red_max = vinfo->colormap_size - 1;
1196         *green_max = *blue_max = 0;
1197         break;
1198       case XA_RGB_GREEN_MAP:
1199         *green_max = vinfo->colormap_size - 1;
1200         *red_max = *blue_max = 0;
1201         break;
1202       case XA_RGB_BLUE_MAP:
1203         *blue_max = vinfo->colormap_size - 1;
1204         *red_max = *green_max = 0;
1205         break;
1206       default:
1207         status = 0;
1208     }
1209     return status;
1210 }
1211
1212 /****************************************************************************/
1213 /* Determine the appropriate color allocations of a gray scale.
1214  *
1215  * Keith Packard, MIT X Consortium
1216  */
1217
1218 static void
1219 gray_allocation(int n, unsigned long *red_max, unsigned long *green_max,
1220                 unsigned long *blue_max)
1221 {
1222     *red_max = (n * 30) / 100;
1223     *green_max = (n * 59) / 100; 
1224     *blue_max = (n * 11) / 100; 
1225     *green_max += ((n - 1) - (*red_max + *green_max + *blue_max));
1226 }
1227
1228 /****************************************************************************/
1229 /* Determine an appropriate color allocation for the RGB_DEFAULT_MAP.
1230  * If a map has less than a minimum number of definable entries, we do not
1231  * produce an allocation for an RGB_DEFAULT_MAP.  
1232  *
1233  * For 16 planes, the default colormap will have 27 each RGB; for 12 planes,
1234  * 12 each.  For 8 planes, let n = the number of colormap entries, which may
1235  * be 256 or 254.  Then, maximum red value = floor(cube_root(n - 125)) - 1.
1236  * Maximum green and maximum blue values are identical to maximum red.
1237  * This leaves at least 125 cells which clients can allocate.
1238  *
1239  * Return 0 if an allocation has been determined, non-zero otherwise.
1240  */
1241
1242 static int
1243 default_allocation(XVisualInfo *vinfo, unsigned long *red,
1244                    unsigned long *green, unsigned long *blue)
1245 {
1246     int                 ngrays;         /* number of gray cells */
1247
1248     switch (vinfo->c_class)
1249       {
1250       case PseudoColor:
1251         
1252         if (vinfo->colormap_size > 65000)
1253           /* intended for displays with 16 planes */
1254           *red = *green = *blue = (unsigned long) 27;
1255         else if (vinfo->colormap_size > 4000)
1256           /* intended for displays with 12 planes */
1257             *red = *green = *blue = (unsigned long) 12;
1258       else if (vinfo->colormap_size < 250)
1259             return 0;
1260       else
1261             /* intended for displays with 8 planes */
1262             *red = *green = *blue = (unsigned long)
1263           (icbrt(vinfo->colormap_size - 125) - 1);
1264       break;
1265       
1266     case DirectColor:
1267       
1268         if (vinfo->colormap_size < 10)
1269             return 0;
1270         *red = *green = *blue = vinfo->colormap_size / 2 - 1;
1271         break;
1272
1273       case TrueColor:
1274
1275         *red = vinfo->red_mask / lowbit(vinfo->red_mask);
1276         *green = vinfo->green_mask / lowbit(vinfo->green_mask);
1277         *blue = vinfo->blue_mask / lowbit(vinfo->blue_mask);
1278         break;
1279
1280       case GrayScale:
1281
1282         if (vinfo->colormap_size > 65000)
1283             ngrays = 4096;
1284         else if (vinfo->colormap_size > 4000)
1285             ngrays = 512;
1286         else if (vinfo->colormap_size < 250)
1287             return 0;
1288         else
1289             ngrays = 12;
1290         gray_allocation(ngrays, red, green, blue);
1291         break;
1292         
1293       default:
1294         return 0;
1295     }
1296     return 1;
1297 }
1298
1299 /****************************************************************************/
1300 /* Determine an appropriate color allocation for the RGB_BEST_MAP.
1301  *
1302  * For a DirectColor or TrueColor visual, the allocation is determined
1303  * by the red_mask, green_mask, and blue_mask members of the visual info.
1304  *
1305  * Otherwise, if the colormap size is an integral power of 2, determine
1306  * the allocation according to the number of bits given to each color,
1307  * with green getting more than red, and red more than blue, if there
1308  * are to be inequities in the distribution.  If the colormap size is
1309  * not an integral power of 2, let n = the number of colormap entries.
1310  * Then maximum red value = floor(cube_root(n)) - 1;
1311  *      maximum blue value = floor(cube_root(n)) - 1;
1312  *      maximum green value = n / ((# red values) * (# blue values)) - 1;
1313  * Which, on a GPX, allows for 252 entries in the best map, out of 254
1314  * defineable colormap entries.
1315  */
1316  
1317 static void
1318 best_allocation(XVisualInfo *vinfo, unsigned long *red, unsigned long *green,
1319                 unsigned long *blue)
1320 {
1321
1322     if (vinfo->c_class == DirectColor ||        vinfo->c_class == TrueColor)
1323     {
1324         *red = vinfo->red_mask;
1325         while ((*red & 01) == 0)
1326             *red >>= 1;
1327         *green = vinfo->green_mask;
1328         while ((*green & 01) == 0)
1329             *green >>=1;
1330         *blue = vinfo->blue_mask;
1331         while ((*blue & 01) == 0)
1332             *blue >>= 1;
1333     }
1334     else
1335     {
1336         register int bits, n;
1337         
1338         /* Determine n such that n is the least integral power of 2 which is
1339          * greater than or equal to the number of entries in the colormap.
1340          */
1341         n = 1;
1342         bits = 0;
1343         while (vinfo->colormap_size > n)
1344         {
1345             n = n << 1;
1346             bits++;
1347         }
1348         
1349         /* If the number of entries in the colormap is a power of 2, determine
1350          * the allocation by "dealing" the bits, first to green, then red, then
1351          * blue.  If not, find the maximum integral red, green, and blue values
1352          * which, when multiplied together, do not exceed the number of 
1353
1354          * colormap entries.
1355          */
1356         if (n == vinfo->colormap_size)
1357         {
1358             register int r, g, b;
1359             b = bits / 3;
1360             g = b + ((bits % 3) ? 1 : 0);
1361             r = b + (((bits % 3) == 2) ? 1 : 0);
1362             *red = 1 << r;
1363             *green = 1 << g;
1364             *blue = 1 << b;
1365         }
1366         else
1367         {
1368             *red = icbrt_with_bits(vinfo->colormap_size, bits);
1369             *blue = *red;       
1370             *green = (vinfo->colormap_size / ((*red) * (*blue)));
1371         }
1372         (*red)--;
1373         (*green)--;
1374         (*blue)--;
1375     }
1376     return;
1377 }
1378
1379 /*
1380  * integer cube roots by Newton's method
1381  *
1382  * Stephen Gildea, MIT X Consortium, July 1991
1383  */
1384
1385 static int
1386 icbrt(int a)
1387 {
1388     register int bits = 0;
1389     register unsigned n = a;
1390
1391     while (n)
1392     {
1393         bits++;
1394         n >>= 1;
1395     }
1396     return icbrt_with_bits(a, bits);
1397 }
1398
1399
1400 static int
1401 icbrt_with_bits(int a, int bits)
1402      /* bits - log 2 of a */
1403 {
1404     return icbrt_with_guess(a, a>>2*bits/3);
1405 }
1406
1407 #ifdef _X_ROOT_STATS
1408 int icbrt_loopcount;
1409 #endif
1410
1411 /* Newton's Method:  x_n+1 = x_n - ( f(x_n) / f'(x_n) ) */
1412
1413 /* for cube roots, x^3 - a = 0,  x_new = x - 1/3 (x - a/x^2) */
1414
1415 /*
1416  * Quick and dirty cube roots.  Nothing fancy here, just Newton's method.
1417  * Only works for positive integers (since that's all we need).
1418  * We actually return floor(cbrt(a)) because that's what we need here, too.
1419  */
1420
1421 static int
1422 icbrt_with_guess(int a, int guess)
1423 {
1424     register int delta;
1425
1426 #ifdef _X_ROOT_STATS
1427     icbrt_loopcount = 0;
1428 #endif
1429     if (a <= 0)
1430         return 0;
1431     if (guess < 1)
1432         guess = 1;
1433
1434     do {
1435 #ifdef _X_ROOT_STATS
1436         icbrt_loopcount++;
1437 #endif
1438         delta = (guess - a/(guess*guess))/3;
1439 #ifdef DEBUG
1440         printf("pass %d: guess=%d, delta=%d\n", icbrt_loopcount, guess, delta);
1441 #endif
1442         guess -= delta;
1443     } while (delta != 0);
1444
1445     if (guess*guess*guess > a)
1446         guess--;
1447
1448     return guess;
1449 }
1450
1451
1452 /* $Xorg: StdCmap.c,v 1.4 2001/02/09 02:03:53 xorgcvs Exp $ */
1453
1454 /* 
1455
1456 Copyright 1989, 1998  The Open Group
1457
1458 Permission to use, copy, modify, distribute, and sell this software and its
1459 documentation for any purpose is hereby granted without fee, provided that
1460 the above copyright notice appear in all copies and that both that
1461 copyright notice and this permission notice appear in supporting
1462 documentation.
1463
1464 The above copyright notice and this permission notice shall be included in
1465 all copies or substantial portions of the Software.
1466
1467 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1468 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1469 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
1470 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1471 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1472 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1473
1474 Except as contained in this notice, the name of The Open Group shall not be
1475 used in advertising or otherwise to promote the sale, use or other dealings
1476 in this Software without prior written authorization from The Open Group.
1477
1478 */
1479 /* $XFree86: xc/lib/Xmu/StdCmap.c,v 1.6 2001/12/14 19:55:48 dawes Exp $ */
1480
1481 /*
1482  * Author:  Donna Converse, MIT X Consortium
1483  */
1484
1485 #include <stdio.h>
1486 #include <X11/Xlib.h>
1487 #include <X11/Xatom.h>
1488 #include <X11/Xutil.h>
1489 #include <X11/Xmu/StdCmap.h>
1490
1491 #define lowbit(x) ((x) & (~(x) + 1))
1492
1493 /*
1494  * Prototypes
1495  */
1496 /* argument restrictions */
1497 static Status valid_args(XVisualInfo*, unsigned long, unsigned long,
1498                          unsigned long, Atom);
1499
1500 /*
1501  * To create any one standard colormap, use XmuStandardColormap().
1502  *
1503  * Create a standard colormap for the given screen, visualid, and visual
1504  * depth, with the given red, green, and blue maximum values, with the
1505  * given standard property name.  Return a pointer to an XStandardColormap
1506  * structure which describes the newly created colormap, upon success.
1507  * Upon failure, return NULL.
1508  * 
1509  * XmuStandardColormap() calls XmuCreateColormap() to create the map.
1510  *
1511  * Resources created by this function are not made permanent; that is the
1512  * caller's responsibility.
1513  */
1514
1515 XStandardColormap *
1516 XmuStandardColormap(Display *dpy, int screen, VisualID visualid,
1517                     unsigned int depth, Atom property, Colormap cmap,
1518                     unsigned long red_max, unsigned long green_max,
1519                     unsigned long blue_max)
1520      /*
1521       * dpy                             - specifies X server connection
1522       * screen                          - specifies display screen
1523       * visualid                        - identifies the visual type
1524       * depth                           - identifies the visual type
1525       * property                        - a standard colormap property
1526       * cmap                            - specifies colormap ID or None
1527       * red_max, green_max, blue_max    - allocations
1528       */
1529 {
1530     XStandardColormap   *stdcmap;
1531     Status              status;
1532     XVisualInfo         vinfo_template, *vinfo;
1533     long                vinfo_mask;
1534     int                 n;
1535
1536     /* Match the required visual information to an actual visual */
1537     vinfo_template.visualid = visualid; 
1538     vinfo_template.screen = screen;
1539     vinfo_template.depth = depth;
1540     vinfo_mask = VisualIDMask | VisualScreenMask | VisualDepthMask;
1541     if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &n)) == NULL)
1542         return 0;
1543
1544     /* Check the validity of the combination of visual characteristics,
1545      * allocation, and colormap property.  Create an XStandardColormap
1546      * structure.
1547      */
1548
1549     if (! valid_args(vinfo, red_max, green_max, blue_max, property)
1550         || ((stdcmap = XAllocStandardColormap()) == NULL)) {
1551         XFree((char *) vinfo);
1552         return 0;
1553     }
1554
1555     /* Fill in the XStandardColormap structure */
1556
1557     if (cmap == DefaultColormap(dpy, screen)) {
1558         /* Allocating out of the default map, cannot use XFreeColormap() */
1559         Window win = XCreateWindow(dpy, RootWindow(dpy, screen), 1, 1, 1, 1,
1560                                    0, 0, InputOnly, vinfo->visual,
1561                                    (unsigned long) 0,
1562                                    (XSetWindowAttributes *)NULL);
1563         stdcmap->killid  = (XID) XCreatePixmap(dpy, win, 1, 1, depth);
1564         XDestroyWindow(dpy, win);
1565         stdcmap->colormap = cmap;
1566     } else {
1567         stdcmap->killid = ReleaseByFreeingColormap;
1568         stdcmap->colormap = XCreateColormap(dpy, RootWindow(dpy, screen),
1569                                             vinfo->visual, AllocNone);
1570     }
1571     stdcmap->red_max = red_max;
1572     stdcmap->green_max = green_max;
1573     stdcmap->blue_max = blue_max;
1574     if (property == XA_RGB_GRAY_MAP) 
1575         stdcmap->red_mult = stdcmap->green_mult = stdcmap->blue_mult = 1;
1576     else if (vinfo->c_class == TrueColor || vinfo->c_class == DirectColor) {
1577         stdcmap->red_mult = lowbit(vinfo->red_mask);
1578         stdcmap->green_mult = lowbit(vinfo->green_mask);
1579         stdcmap->blue_mult = lowbit(vinfo->blue_mask);
1580     } else {
1581         stdcmap->red_mult = (red_max > 0)
1582             ? (green_max + 1) * (blue_max + 1) : 0;
1583         stdcmap->green_mult = (green_max > 0) ? blue_max + 1 : 0;
1584         stdcmap->blue_mult = (blue_max > 0) ? 1 : 0;
1585     }
1586     stdcmap->base_pixel = 0;                    /* base pixel may change */
1587     stdcmap->visualid = vinfo->visualid;
1588
1589     /* Make the colormap */
1590
1591     status = XmuCreateColormap(dpy, stdcmap);
1592
1593     /* Clean up */
1594
1595     XFree((char *) vinfo);
1596     if (!status) {
1597
1598         /* Free the colormap or the pixmap, if we created one */
1599         if (stdcmap->killid == ReleaseByFreeingColormap)
1600             XFreeColormap(dpy, stdcmap->colormap);
1601         else if (stdcmap->killid != None)
1602             XFreePixmap(dpy, stdcmap->killid);
1603         
1604         XFree((char *) stdcmap);
1605         return (XStandardColormap *) NULL;
1606     }
1607     return stdcmap;
1608 }
1609
1610 /****************************************************************************/
1611 static Status
1612 valid_args(XVisualInfo *vinfo, unsigned long red_max, unsigned long green_max,
1613            unsigned long blue_max, Atom property)
1614      /*
1615       * vinfo                           - specifies visual
1616       * red_max, green_max, blue_max    - specifies alloc
1617       * property                        - specifies property name
1618       */
1619 {
1620     unsigned long       ncolors;        /* number of colors requested */
1621
1622     /* Determine that the number of colors requested is <= map size */
1623
1624     if ((vinfo->c_class == DirectColor) || (vinfo->c_class == TrueColor)) {
1625         unsigned long mask;
1626
1627         mask = vinfo->red_mask;
1628         while (!(mask & 1))
1629             mask >>= 1;
1630         if (red_max > mask)
1631             return 0;
1632         mask = vinfo->green_mask;
1633         while (!(mask & 1))
1634             mask >>= 1;
1635         if (green_max > mask)
1636             return 0;
1637         mask = vinfo->blue_mask;
1638         while (!(mask & 1))
1639             mask >>= 1;
1640         if (blue_max > mask)
1641             return 0;
1642     } else if (property == XA_RGB_GRAY_MAP) {
1643         ncolors = red_max + green_max + blue_max + 1;
1644         if (ncolors > vinfo->colormap_size)
1645             return 0;
1646     } else {
1647         ncolors = (red_max + 1) * (green_max + 1) * (blue_max + 1);
1648         if (ncolors > vinfo->colormap_size)
1649             return 0;
1650     }
1651     
1652     /* Determine that the allocation and visual make sense for the property */
1653
1654     switch (property)
1655     {
1656       case XA_RGB_DEFAULT_MAP:
1657         if (red_max == 0 || green_max == 0 || blue_max == 0)
1658             return 0;
1659         break;
1660       case XA_RGB_RED_MAP:
1661         if (red_max == 0)
1662             return 0;
1663         break;
1664       case XA_RGB_GREEN_MAP:
1665         if (green_max == 0)
1666             return 0;
1667         break;
1668       case XA_RGB_BLUE_MAP:     
1669         if (blue_max == 0)
1670             return 0;
1671         break;
1672       case XA_RGB_BEST_MAP:
1673         if (red_max == 0 || green_max == 0 || blue_max == 0)
1674             return 0;
1675         break;
1676       case XA_RGB_GRAY_MAP:
1677         if (red_max == 0 || blue_max == 0 || green_max == 0)
1678             return 0;
1679         break;
1680       default:
1681         return 0;
1682     }
1683     return 1;
1684 }
1685
1686
1687 /* $Xorg: CrCmap.c,v 1.4 2001/02/09 02:03:51 xorgcvs Exp $ */
1688
1689 /* 
1690
1691 Copyright 1989, 1998  The Open Group
1692
1693 Permission to use, copy, modify, distribute, and sell this software and its
1694 documentation for any purpose is hereby granted without fee, provided that
1695 the above copyright notice appear in all copies and that both that
1696 copyright notice and this permission notice appear in supporting
1697 documentation.
1698
1699 The above copyright notice and this permission notice shall be included in
1700 all copies or substantial portions of the Software.
1701
1702 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1703 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1704 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
1705 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1706 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1707 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1708
1709 Except as contained in this notice, the name of The Open Group shall not be
1710 used in advertising or otherwise to promote the sale, use or other dealings
1711 in this Software without prior written authorization from The Open Group.
1712
1713 */
1714 /* $XFree86: xc/lib/Xmu/CrCmap.c,v 3.7 2001/12/14 19:55:36 dawes Exp $ */
1715
1716 /*
1717  * Author:  Donna Converse, MIT X Consortium
1718  */
1719
1720 /*
1721  * CreateCmap.c - given a standard colormap description, make the map.
1722  */
1723
1724 #include <stdio.h>
1725 #include <stdlib.h>
1726 #include <X11/Xlib.h>
1727 #include <X11/Xutil.h>
1728 #include <X11/Xmu/StdCmap.h>
1729
1730 /*
1731  * Prototypes
1732  */
1733 /* allocate entire map Read Only */
1734 static int ROmap(Display*, Colormap, unsigned long[], int, int);
1735
1736 /* allocate a cell, prefer Read Only */
1737 static Status ROorRWcell(Display*, Colormap, unsigned long[], int,
1738                          XColor*, unsigned long);
1739
1740 /* allocate a cell Read Write */
1741 static Status RWcell(Display*, Colormap, XColor*, XColor*, unsigned long*);
1742
1743 /* for quicksort */
1744 static int compare(_Xconst void*, _Xconst void*);
1745
1746 /* find contiguous sequence of cells */
1747 static Status contiguous(unsigned long[], int, int, unsigned long, int*, int*);
1748
1749 /* frees resources before quitting */
1750 static void free_cells(Display*, Colormap, unsigned long[], int, int);
1751
1752 /* create a map in a RO visual type */
1753 static Status readonly_map(Display*, XVisualInfo*, XStandardColormap*);
1754
1755 /* create a map in a RW visual type */
1756 static Status readwrite_map(Display*, XVisualInfo*, XStandardColormap*);
1757
1758 #define lowbit(x) ((x) & (~(x) + 1))
1759 #define TRUEMATCH(mult,max,mask) \
1760     (colormap->max * colormap->mult <= vinfo->mask && \
1761      lowbit(vinfo->mask) == colormap->mult)
1762
1763 /*
1764  * To create any one colormap which is described by an XStandardColormap
1765  * structure, use XmuCreateColormap().
1766  *
1767  * Return 0 on failure, non-zero on success.
1768  * Resources created by this function are not made permanent.
1769  * No argument error checking is provided.  Use at your own risk.
1770  *
1771  * All colormaps are created with read only allocations, with the exception
1772  * of read only allocations of colors in the default map or otherwise
1773  * which fail to return the expected pixel value, and these are individually 
1774  * defined as read/write allocations.  This is done so that all the cells
1775  * defined in the default map are contiguous, for use in image processing.
1776  * This typically happens with White and Black in the default map.
1777  *
1778  * Colormaps of static visuals are considered to be successfully created if
1779  * the map of the static visual matches the definition given in the
1780  * standard colormap structure.
1781  */
1782    
1783 Status
1784 XmuCreateColormap(Display *dpy, XStandardColormap *colormap)
1785      /* dpy      - specifies the connection under which the map is created
1786       * colormap - specifies the map to be created, and returns, particularly
1787       *            if the map is created as a subset of the default colormap
1788       *            of the screen, the base_pixel of the map.
1789                                          */
1790 {
1791     XVisualInfo         vinfo_template; /* template visual information */
1792     XVisualInfo         *vinfo;         /* matching visual information */
1793     XVisualInfo         *vpointer;      /* for freeing the entire list */
1794     long                vinfo_mask;     /* specifies the visual mask value */
1795     int                 n;              /* number of matching visuals */
1796     int                 status;         
1797
1798     vinfo_template.visualid = colormap->visualid;
1799     vinfo_mask = VisualIDMask;
1800     if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &n)) == NULL)
1801         return 0;
1802
1803     /* A visual id may be valid on multiple screens.  Also, there may 
1804      * be multiple visuals with identical visual ids at different depths.  
1805      * If the colormap is the Default Colormap, use the Default Visual.
1806      * Otherwise, arbitrarily, use the deepest visual.
1807      */
1808     vpointer = vinfo;
1809     if (n > 1)
1810     {
1811         register int    i;
1812         register int    screen_number;
1813         Bool            def_cmap;
1814
1815         def_cmap = False;
1816         for (screen_number = ScreenCount(dpy); --screen_number >= 0; )
1817             if (colormap->colormap == DefaultColormap(dpy, screen_number)) {
1818                 def_cmap = True;
1819                 break;
1820             }
1821
1822         if (def_cmap) {
1823             for (i=0; i < n; i++, vinfo++) {
1824                 if (vinfo->visual == DefaultVisual(dpy, screen_number))
1825                         break;
1826             }
1827         } else {
1828             int                 maxdepth = 0;
1829             XVisualInfo         *v = NULL;
1830
1831             for (i=0; i < n; i++, vinfo++)
1832                 if (vinfo->depth > maxdepth) {
1833                     maxdepth = vinfo->depth;
1834                     v = vinfo;
1835                 }
1836             vinfo = v;
1837         }
1838     }
1839
1840     if (vinfo->c_class == PseudoColor || vinfo->c_class == DirectColor ||
1841         vinfo->c_class == GrayScale)
1842         status = readwrite_map(dpy, vinfo, colormap);
1843     else if (vinfo->c_class == TrueColor)
1844         status = TRUEMATCH(red_mult, red_max, red_mask) &&
1845                  TRUEMATCH(green_mult, green_max, green_mask) &&
1846                  TRUEMATCH(blue_mult, blue_max, blue_mask);
1847     else 
1848         status = readonly_map(dpy, vinfo, colormap);
1849     
1850     XFree((char *) vpointer);
1851     return status;
1852 }
1853
1854 /****************************************************************************/
1855 static Status
1856 readwrite_map(Display *dpy, XVisualInfo *vinfo, XStandardColormap *colormap)
1857 {
1858     register unsigned long i, n;        /* index counters */
1859     unsigned long       ncolors;        /* number of colors to be defined */
1860     int                 npixels;        /* number of pixels allocated R/W */
1861     int                 first_index;    /* first index of pixels to use */
1862     int                 remainder;      /* first index of remainder */
1863     XColor              color;          /* the definition of a color */
1864     unsigned long       *pixels;        /* array of colormap pixels */
1865     unsigned long       delta;
1866
1867     
1868     /* Determine ncolors, the number of colors to be defined.
1869      * Insure that 1 < ncolors <= the colormap size.
1870      */
1871     if (vinfo->c_class == DirectColor) {
1872         ncolors = colormap->red_max;
1873         if (colormap->green_max > ncolors)
1874             ncolors = colormap->green_max;
1875         if (colormap->blue_max > ncolors)
1876             ncolors = colormap->blue_max;
1877         ncolors++;
1878         delta = lowbit(vinfo->red_mask) +
1879                 lowbit(vinfo->green_mask) +
1880                 lowbit(vinfo->blue_mask);
1881     } else {
1882         ncolors = colormap->red_max * colormap->red_mult +
1883                   colormap->green_max * colormap->green_mult +
1884                   colormap->blue_max * colormap->blue_mult + 1;
1885         delta = 1;
1886     }
1887     if (ncolors <= 1 || (int) ncolors > vinfo->colormap_size)   return 0;
1888
1889     /* Allocate Read/Write as much of the colormap as we can possibly get.
1890      * Then insure that the pixels we were allocated are given in 
1891      * monotonically increasing order, using a quicksort.  Next, insure
1892      * that our allocation includes a subset of contiguous pixels at least
1893      * as long as the number of colors to be defined.  Now we know that 
1894      * these conditions are met:
1895      *  1) There are no free cells in the colormap.
1896      *  2) We have a contiguous sequence of pixels, monotonically 
1897      *     increasing, of length >= the number of colors requested.
1898      *
1899      * One cell at a time, we will free, compute the next color value, 
1900      * then allocate read only.  This takes a long time.
1901      * This is done to insure that cells are allocated read only in the
1902      * contiguous order which we prefer.  If the server has a choice of
1903      * cells to grant to an allocation request, the server may give us any
1904      * cell, so that is why we do these slow gymnastics.
1905      */
1906
1907     if ((pixels = (unsigned long *) calloc((unsigned) vinfo->colormap_size,
1908                                       sizeof(unsigned long))) == NULL)
1909         return 0;
1910
1911     if ((npixels = ROmap(dpy, colormap->colormap, pixels,
1912                            vinfo->colormap_size, ncolors)) == 0) {
1913         free((char *) pixels);
1914         return 0;
1915     }
1916
1917     qsort((char *) pixels, npixels, sizeof(unsigned long), compare);
1918
1919     if (!contiguous(pixels, npixels, ncolors, delta, &first_index, &remainder))
1920     {
1921         /* can't find enough contiguous cells, give up */
1922         XFreeColors(dpy, colormap->colormap, pixels, npixels,
1923                     (unsigned long) 0);
1924         free((char *) pixels);
1925         return 0;
1926     }
1927     colormap->base_pixel = pixels[first_index];
1928
1929     /* construct a gray map */
1930     if (colormap->red_mult == 1 && colormap->green_mult == 1 &&
1931         colormap->blue_mult == 1)
1932         for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
1933         {
1934             color.pixel = n;
1935             color.blue = color.green = color.red =
1936                 (unsigned short) ((i * 65535) / (colormap->red_max +
1937                                                  colormap->green_max +
1938                                                  colormap->blue_max));
1939
1940             if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
1941                              first_index + i))
1942                 return 0;
1943         }
1944
1945     /* construct a red ramp map */
1946     else if (colormap->green_max == 0 && colormap->blue_max == 0)
1947         for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
1948         {
1949             color.pixel = n;
1950             color.red = (unsigned short) ((i * 65535) / colormap->red_max);
1951             color.green = color.blue = 0;
1952
1953             if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
1954                              first_index + i))
1955                 return 0;
1956         }
1957
1958     /* construct a green ramp map */
1959     else if (colormap->red_max == 0 && colormap->blue_max == 0)
1960         for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
1961         {
1962             color.pixel = n;
1963             color.green = (unsigned short) ((i * 65535) / colormap->green_max);
1964             color.red = color.blue = 0;
1965
1966             if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
1967                              first_index + i))
1968                 return 0;
1969         }
1970
1971     /* construct a blue ramp map */
1972     else if (colormap->red_max == 0 && colormap->green_max == 0)
1973         for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
1974         {
1975             color.pixel = n;
1976             color.blue = (unsigned short) ((i * 65535) / colormap->blue_max);
1977             color.red = color.green = 0;
1978
1979             if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
1980                              first_index + i))
1981                 return 0;
1982         }
1983
1984     /* construct a standard red green blue cube map */
1985     else
1986     {
1987 #define calc(max,mult) (((n / colormap->mult) % \
1988                          (colormap->max + 1)) * 65535) / colormap->max
1989
1990         for (n=0, i=0; i < ncolors; i++, n += delta)
1991         {
1992             color.pixel = n + colormap->base_pixel;
1993             color.red = calc(red_max, red_mult);
1994             color.green = calc(green_max, green_mult);
1995             color.blue = calc(blue_max, blue_mult);
1996             if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
1997                              first_index + i))
1998                 return 0;
1999         }
2000 #undef calc
2001     }
2002     /* We have a read-only map defined.  Now free unused cells,
2003      * first those occuring before the contiguous sequence begins,
2004      * then any following the contiguous sequence.
2005      */
2006
2007     if (first_index)
2008         XFreeColors(dpy, colormap->colormap, pixels, first_index, 
2009                     (unsigned long) 0);
2010     if (remainder)
2011         XFreeColors(dpy, colormap->colormap,
2012                     &(pixels[first_index + ncolors]), remainder,
2013                     (unsigned long) 0);
2014
2015     free((char *) pixels);
2016     return 1;
2017 }
2018
2019
2020 /****************************************************************************/
2021 static int
2022 ROmap(Display *dpy, Colormap cmap, unsigned long pixels[], int m, int n)
2023      /*
2024       * dpy     - the X server connection
2025       * cmap    - specifies colormap ID
2026       * pixels  - returns pixel allocations
2027       * m       - specifies colormap size
2028       * n       - specifies number of colors
2029       */
2030 {
2031     register int        p;
2032
2033     /* first try to allocate the entire colormap */
2034     if (XAllocColorCells(dpy, cmap, 1, (unsigned long *) NULL, 
2035                          (unsigned) 0, pixels, (unsigned) m))
2036         return m;
2037
2038     /* Allocate all available cells in the colormap, using a binary
2039      * algorithm to discover how many cells we can allocate in the colormap.
2040      */
2041     m--;
2042     while (n <= m) {
2043         p = n + ((m - n + 1) / 2);
2044         if (XAllocColorCells(dpy, cmap, 1, (unsigned long *) NULL,
2045                              (unsigned) 0, pixels, (unsigned) p)) {
2046             if (p == m)
2047                 return p;
2048             else {
2049                 XFreeColors(dpy, cmap, pixels, p, (unsigned long) 0);
2050                 n = p;
2051             }
2052         }
2053         else
2054             m = p - 1;
2055     }
2056     return 0;
2057 }
2058       
2059
2060 /****************************************************************************/
2061 static Status
2062 contiguous(unsigned long pixels[], int npixels, int ncolors,
2063            unsigned long delta, int *first, int *rem)
2064      /* pixels  - specifies allocated pixels
2065       * npixels - specifies count of alloc'd pixels
2066       * ncolors - specifies needed sequence length
2067       * delta   - between pixels
2068       * first   - returns first index of sequence
2069       * rem     - returns first index after sequence, or 0, if none follow
2070       */
2071 {
2072     register int i = 1;         /* walking index into the pixel array */
2073     register int count = 1;     /* length of sequence discovered so far */
2074
2075     *first = 0;
2076     if (npixels == ncolors) {
2077         *rem = 0;
2078         return 1;
2079     }
2080     *rem = npixels - 1;
2081     while (count < ncolors && ncolors - count <= *rem)
2082     {
2083         if (pixels[i-1] + delta == pixels[i])
2084             count++;
2085         else {
2086             count = 1;
2087             *first = i;
2088         }
2089         i++;
2090         (*rem)--;
2091     }
2092     if (count != ncolors)
2093         return 0;
2094     return 1;
2095 }
2096
2097
2098 /****************************************************************************/
2099 static Status
2100 ROorRWcell(Display *dpy, Colormap cmap, unsigned long pixels[],
2101            int npixels, XColor *color, unsigned long p)
2102 {
2103     unsigned long       pixel;
2104     XColor              request;
2105
2106     /* Free the read/write allocation of one cell in the colormap.
2107      * Request a read only allocation of one cell in the colormap.
2108      * If the read only allocation cannot be granted, give up, because
2109      * there must be no free cells in the colormap.
2110      * If the read only allocation is granted, but gives us a cell which
2111      * is not the one that we just freed, it is probably the case that
2112      * we are trying allocate White or Black or some other color which
2113      * already has a read-only allocation in the map.  So we try to 
2114      * allocate the previously freed cell with a read/write allocation,
2115      * because we want contiguous cells for image processing algorithms.
2116      */
2117      
2118     pixel = color->pixel;
2119     request.red = color->red;
2120     request.green = color->green;
2121     request.blue = color->blue;
2122
2123     XFreeColors(dpy, cmap, &pixel, 1, (unsigned long) 0);
2124     if (! XAllocColor(dpy, cmap, color) 
2125         || (color->pixel != pixel &&
2126             (!RWcell(dpy, cmap, color, &request, &pixel)))) 
2127     {
2128         free_cells(dpy, cmap, pixels, npixels, (int)p);
2129         return 0;
2130     }
2131     return 1;
2132 }
2133
2134
2135 /****************************************************************************/
2136 static void
2137 free_cells(Display *dpy, Colormap cmap, unsigned long pixels[],
2138            int npixels, int p)
2139      /*
2140       * pixels  - to be freed
2141       * npixels - original number allocated
2142       */
2143 {
2144     /* One of the npixels allocated has already been freed.
2145      * p is the index of the freed pixel.
2146      * First free the pixels preceeding p, and there are p of them;
2147      * then free the pixels following p, there are npixels - p - 1 of them.
2148      */
2149     XFreeColors(dpy, cmap, pixels, p, (unsigned long) 0);
2150     XFreeColors(dpy, cmap, &(pixels[p+1]), npixels - p - 1, (unsigned long) 0);
2151     free((char *) pixels);
2152 }
2153
2154
2155 /****************************************************************************/
2156 static Status
2157 RWcell(Display *dpy, Colormap cmap, XColor *color, XColor *request,
2158        unsigned long *pixel)
2159 {
2160     unsigned long       n = *pixel;
2161
2162     XFreeColors(dpy, cmap, &(color->pixel), 1, (unsigned long)0);
2163     if (! XAllocColorCells(dpy, cmap, (Bool) 0, (unsigned long *) NULL,
2164                            (unsigned) 0, pixel, (unsigned) 1))
2165         return 0;
2166     if (*pixel != n)
2167     {
2168         XFreeColors(dpy, cmap, pixel, 1, (unsigned long) 0);
2169         return 0;
2170     }
2171     color->pixel = *pixel;
2172     color->flags = DoRed | DoGreen | DoBlue;
2173     color->red = request->red;
2174     color->green = request->green;
2175     color->blue = request->blue;
2176     XStoreColors(dpy, cmap, color, 1);
2177     return 1;
2178 }
2179
2180
2181 /****************************************************************************/
2182 static int
2183 compare(_Xconst void *e1, _Xconst void *e2)
2184 {
2185   return ((int)(*(long *)e1 - *(long *)e2));
2186 }
2187
2188
2189 /****************************************************************************/
2190 static Status
2191 readonly_map(Display *dpy, XVisualInfo *vinfo, XStandardColormap *colormap)
2192 {
2193     int                 i, last_pixel;
2194     XColor              color;
2195
2196     last_pixel = (colormap->red_max + 1) * (colormap->green_max + 1) * 
2197         (colormap->blue_max + 1) + colormap->base_pixel - 1;
2198
2199     for(i=colormap->base_pixel; i <= last_pixel; i++) {
2200
2201         color.pixel = (unsigned long) i;
2202         color.red = (unsigned short)
2203             (((i/colormap->red_mult) * 65535) / colormap->red_max);
2204
2205         if (vinfo->c_class == StaticColor) {
2206             color.green = (unsigned short)
2207                 ((((i/colormap->green_mult) % (colormap->green_max + 1)) *
2208                   65535) / colormap->green_max);
2209             color.blue = (unsigned short)
2210                 (((i%colormap->green_mult) * 65535) / colormap->blue_max);
2211         }
2212         else    /* vinfo->c_class == GrayScale, old style allocation XXX */
2213             color.green = color.blue = color.red;
2214
2215         XAllocColor(dpy, colormap->colormap, &color);
2216         if (color.pixel != (unsigned long) i)
2217             return 0;
2218     }
2219     return 1;
2220 }
2221
2222
2223 /* $Xorg: DelCmap.c,v 1.4 2001/02/09 02:03:52 xorgcvs Exp $ */
2224
2225 /* 
2226  
2227 Copyright 1989, 1998  The Open Group
2228
2229 Permission to use, copy, modify, distribute, and sell this software and its
2230 documentation for any purpose is hereby granted without fee, provided that
2231 the above copyright notice appear in all copies and that both that
2232 copyright notice and this permission notice appear in supporting
2233 documentation.
2234
2235 The above copyright notice and this permission notice shall be included in
2236 all copies or substantial portions of the Software.
2237
2238 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2239 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2240 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
2241 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
2242 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
2243 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2244
2245 Except as contained in this notice, the name of The Open Group shall not be
2246 used in advertising or otherwise to promote the sale, use or other dealings
2247 in this Software without prior written authorization from The Open Group.
2248
2249 */
2250 /* $XFree86: xc/lib/Xmu/DelCmap.c,v 1.7 2001/12/14 19:55:40 dawes Exp $ */
2251
2252 /*
2253  * Author:  Donna Converse, MIT X Consortium
2254  */
2255
2256 #include <X11/Xlib.h>
2257 #include <X11/Xutil.h>
2258 #include <X11/Xmu/StdCmap.h>
2259
2260 int ignoreErrorHandler(Display* d, XErrorEvent* e) { }
2261
2262 /* To remove any standard colormap property, use XmuDeleteStandardColormap().
2263  * XmuDeleteStandardColormap() will remove the specified property from the
2264  * specified screen, releasing any resources used by the colormap(s) of the
2265  * property if possible.
2266  */
2267
2268 void
2269 XmuDeleteStandardColormap(Display *dpy, int screen, Atom property)
2270      /* dpy;            - specifies the X server to connect to
2271       * screen          - specifies the screen of the display
2272       * property        - specifies the standard colormap property
2273       */
2274 {
2275     XStandardColormap   *stdcmaps, *s;
2276     int                 count = 0;
2277
2278     if (XGetRGBColormaps(dpy, RootWindow(dpy, screen), &stdcmaps, &count,
2279                          property))
2280         {
2281             for (s=stdcmaps; count > 0; count--, s++) {
2282                 if ((s->killid == ReleaseByFreeingColormap) &&
2283                     (s->colormap != None) &&
2284                     (s->colormap != DefaultColormap(dpy, screen))) {
2285
2286                     // UGLY HACK written in by Adam Megacz -- sometimes s->colormap isn't valid, so we do some shuffling
2287                     X11ErrorHandler* oldHandler = XSetErrorHandler(ignoreErrorHandler);
2288                     XSync(dpy, False);
2289                     XFreeColormap(dpy, s->colormap);
2290                     XSync(dpy, False);
2291                     XSetErrorHandler(oldHandler);
2292                     XSync(dpy, False);
2293
2294                 } else if (s->killid != None) {
2295                     XKillClient(dpy, s->killid);
2296                 }
2297             }
2298             XDeleteProperty(dpy, RootWindow(dpy, screen), property);
2299             XFree((char *) stdcmaps);
2300             XSync(dpy, False);
2301         }
2302 }
2303