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