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