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