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