2003/02/05 21:51:50
authormegacz <megacz@xwt.org>
Fri, 30 Jan 2004 06:51:10 +0000 (06:51 +0000)
committermegacz <megacz@xwt.org>
Fri, 30 Jan 2004 06:51:10 +0000 (06:51 +0000)
darcs-hash:20040130065110-2ba56-bf357911c0b7e04ff3ac4a1d51765bbf32cce87e.gz

src/org/xwt/plat/Linux.xml
src/org/xwt/plat/POSIX.cc
src/org/xwt/plat/POSIX.java
src/org/xwt/plat/X11.cc [new file with mode: 0644]
src/org/xwt/plat/X11.java [new file with mode: 0644]

index 1bb1630..36ae917 100644 (file)
@@ -4,9 +4,9 @@
 
     <target name="build">
         <property name="gcc-target" value=""/>
-        <property name="linkflags" value="-L/usr/X11R6/lib -lX11 -lXext --static"/>
+        <property name="linkflags" value="-L/usr/X11R6/lib -lX11 -lXext -ldl --static"/>
         <property name="binaryname" value="xwt"/>
-        <property name="subplat" value="POSIX"/>
+        <property name="subplat" value="X11"/>
         <ant target="build" antfile="src/org/xwt/plat/GCJ.xml"/>
     </target>
                                                                          
index f34fbdf..203ac8a 100644 (file)
@@ -1,16 +1,6 @@
 // Copyright 2002 Adam Megacz, see the COPYING file for licensing [LGPL]
 // see below for copyright information on the second portion of this file
 
-#include <sys/ipc.h>
-#include <sys/shm.h>
-#include <X11/Xlib.h>
-#include <X11/extensions/XShm.h>
-#include <X11/keysymdef.h>
-#include <X11/keysym.h>
-#include <X11/cursorfont.h>
-#include <X11/Xutil.h>
-#include <X11/Xatom.h>
-#include <X11/Xmu/StdCmap.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <gcj/cni.h>
 #include <signal.h>
 
-#include <java/lang/String.h>
-#include <org/xwt/Surface.h>
-#include <org/xwt/Picture.h>
-#include <org/xwt/Box.h>
-#include <org/xwt/plat/POSIX.h>
-#include <org/xwt/plat/POSIX$X11Surface.h>
-#include <org/xwt/plat/POSIX$X11Picture.h>
-#include <org/xwt/plat/POSIX$X11DoubleBuffer.h>
-#include <org/xwt/util/Semaphore.h>
-#include <org/xwt/Platform.h>
-#include <java/lang/Long.h>
-#include <java/util/Hashtable.h>
-#include <org/xwt/util/Log.h>
-
-#include <java/lang/System.h>
-#include <java/io/PrintStream.h>
-
-// static (per-xserver) data
-static Visual* visual;
-static Colormap s_colormap;
-static XStandardColormap* colormap_info;
-static XShmSegmentInfo shm_info;
-static Window selectionWindow;
-static int shm_supported;
-static int shm_pixmaps_supported;
-static int screen_num;
-static int colorDepth = 0;
-static Display* display;
-static int shm_size = 0;
-
-#define min(a, b) ((a) < (b) ? (a) : (b))
-#define max(a, b) ((a) < (b) ? (b) : (a))
-
-// X11DoubleBuffer //////////////////////////////////////////////////////////////////////
-
-// ensures that the shared memory is at least size bytes; if not, allocates 3/2 * size
-static void ensureShmSize(int size) {
-    if (size > shm_size) {
-        if (shm_size > 0) {
-            XShmDetach(display, &shm_info);
-            shmdt(shm_info.shmaddr);
-            shmctl(shm_info.shmid, IPC_RMID, 0);
-        }
-        shm_size = 3 * size / 2;
-        shm_info.shmid = shmget(IPC_PRIVATE, shm_size, IPC_CREAT | 0777 | IPC_EXCL);
-        shm_info.shmaddr = (char*)shmat(shm_info.shmid, 0, 0);
-        shm_info.readOnly = False;
-        XSync(display, False);
-        shmctl(shm_info.shmid, IPC_RMID, 0);
-        XShmAttach(display, &shm_info);
-        XSync(display, False);
-    }
-}
-
-void org::xwt::plat::POSIX$X11DoubleBuffer::fastDrawPicture(org::xwt::Picture* s,
-                                                            jint dx1, jint dy1, jint dx2, jint dy2, jint sx1, jint sy1, jint sx2, jint sy2) {
-    org::xwt::plat::POSIX$X11Picture* source = (org::xwt::plat::POSIX$X11Picture*)s;
-
-    // it's safe to clip manually since we no that no scaling will be done
-    if (dx1 < clipx) { sx1 += ((clipx - dx1) * (sx2 - sx1)) / (dx2 - dx1); dx1 = clipx; }
-    if (dy1 < clipy) { sy1 += ((clipy - dy1) * (sy2 - sy1)) / (dy2 - dy1); dy1 = clipy; }
-    if (dx2 > clipx + clipw) { sx2 -= ((dx2 - clipx - clipw) * (sx2 - sx1)) / (dx2 - dx1); dx2 = clipx + clipw; }
-    if (dy2 > clipy + cliph) { sy2 -= ((dy2 - clipy - cliph) * (sy2 - sy1)) / (dy2 - dy1); dy2 = clipy + cliph; }
-    if (dx1 > clipx + clipw) return;
-    if (dy1 > clipy + cliph) return;
-    if (dx2 - dx1 <= 0 || dy2 - dy1 <= 0) return;
-    
-    if (source->doublebuf->stipple != NULL) {
-        XSetClipMask(display, (*((GC*)clipped_gc)), *((Pixmap*)source->doublebuf->stipple));
-        XSetClipOrigin(display, (*((GC*)clipped_gc)), dx1 - sx1, dy1 - sy1);
-    } else {
-        XSetClipMask(display, (*((GC*)clipped_gc)), None);
-    }
-    XCopyArea(display, *((Pixmap*)source->doublebuf->pm), (*((Pixmap*)pm)), (*((GC*)clipped_gc)), sx1, sy1, sx2 - sx1, sy2 - sy1, dx1, dy1);
-}
-
-void org::xwt::plat::POSIX$X11DoubleBuffer::slowDrawPicture(org::xwt::Picture* s,
-                                                            jint dx1, jint dy1, jint dx2, jint dy2, jint sx1, jint sy1, jint sx2, jint sy2) {
-
-    org::xwt::plat::POSIX$X11Picture* source = (org::xwt::plat::POSIX$X11Picture*)s;
-    XImage* xi; 
-
-    // FASTEST: shared pixmap; twiddle bits in video ram directly
-    if (shared_pixmap) {
-        XSync(display, False);  // ensure that all pending operations have rendered
-        xi = (XImage*)fake_ximage;
-
-    // MEDIUM: write to a shared ximage, then ask the server to do the blit
-    } else if (shm_supported) {
-        xi = XShmCreateImage(display, visual, colorDepth, ZPixmap, NULL, &shm_info, dx2 - dx1, dy2 - dy1);
-        ensureShmSize(xi->bytes_per_line * xi->height);
-        xi->data = shm_info.shmaddr;
-        XShmGetImage(display, (*((Pixmap*)pm)), xi, dx1, dy1, AllPlanes);
-        
-    // SLOWEST: write to an ximage, copy it through the TCP connection, ask the server to do the blit
-    } else {
-        xi = XGetImage(display, (*((Pixmap*)pm)), dx1, dy1, dx2 - dx1, dy2 - dy1, AllPlanes, ZPixmap);
-    }
-    
-    int* sourcedata = (int*)elements(source->data);
-    for(int y=max(dy1, clipy); y<min(dy2, clipy + cliph); y++) {
-        
-        char* current_pixel = (xi->data + y * xi->bytes_per_line) +
-            (shared_pixmap ? max(dx1, clipx) * (xi->bits_per_pixel / 8) : - 1 * dy1 * xi->bytes_per_line);
-        
-        for(int x=max(dx1, clipx); x<min(dx2, clipx + clipw); x++, current_pixel += xi->bits_per_pixel / 8) {
-            int source_x = ((x - dx1) * (sx2 - sx1)) / (dx2 - dx1) + sx1;
-            int source_y = ((y - dy1) * (sy2 - sy1)) / (dy2 - dy1) + sy1;
-            
-            int sourcepixel = sourcedata[source_x + source_y * source->getWidth()];
-            int alpha = (sourcepixel & 0xFF000000) >> 24;
-            int source_red = (sourcepixel & 0x00FF0000) >> 16;
-            int source_green = (sourcepixel & 0x0000FF00) >> 8;
-            int source_blue = (sourcepixel & 0x000000FF);
-            int red = 0, blue = 0, green = 0;
-            
-            if (alpha == 0x00) continue;
-            if (alpha != 0xFF) {
-                int targetpixel;
-                switch (xi->bits_per_pixel) {
-                case 8: targetpixel = (int)(*current_pixel); break;
-                case 16: targetpixel = (int)(*((u_int16_t*)current_pixel)); break;
-                case 24: targetpixel = (((int)*current_pixel) << 16) | (((int)*(current_pixel + 1)) << 8) | (((int)*(current_pixel + 2))); break;
-                case 32: targetpixel = *((int*)current_pixel); break;
-                default: org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: bpp not a multiple of 8!"));
-                }
-                
-                targetpixel -= colormap_info->base_pixel;
-                
-                // if you're on some wierd display that isn't either RGB or BGR, that's your problem, not mine
-                if (colormap_info->red_mult > colormap_info->green_mult && colormap_info->green_mult > colormap_info->blue_mult) {
-                    red = targetpixel / colormap_info->red_mult;
-                    green = (targetpixel - red * colormap_info->red_mult) / colormap_info->green_mult;
-                    blue = (targetpixel - red * colormap_info->red_mult - green * colormap_info->green_mult) / colormap_info->blue_mult;
-                } else {
-                    blue = targetpixel / colormap_info->blue_mult;
-                    green = (targetpixel - blue * colormap_info->blue_mult) / colormap_info->green_mult;
-                    red = (targetpixel - blue * colormap_info->blue_mult - green * colormap_info->green_mult) / colormap_info->red_mult;
-                }
-            }
-            
-            red = ((source_red * colormap_info->red_max * alpha) + (red * 0xFF * (0xFF - alpha))) / (0xFF * 0xFF);
-            green = ((source_green * colormap_info->green_max * alpha) + (green * 0xFF * (0xFF - alpha))) / (0xFF * 0xFF);
-            blue = ((source_blue * colormap_info->blue_max * alpha) + (blue * 0xFF * (0xFF - alpha))) / (0xFF * 0xFF);
-            u_int32_t destpixel = red * colormap_info->red_mult + green * colormap_info->green_mult +
-                blue * colormap_info->blue_mult + colormap_info->base_pixel;
-
-            switch (xi->bits_per_pixel) {
-            case 8: *current_pixel = (char)(destpixel & 0xFF); break;
-            case 16: *((u_int16_t*)current_pixel) = (u_int16_t)destpixel; break;
-            case 24: {
-                int offset = (int)current_pixel & 0x3;
-                u_int64_t dest = ((u_int64_t)destpixel) << (8 * offset);
-                u_int64_t mask = ((u_int64_t)0xffffff) << (8 * offset);
-                u_int64_t* base = (u_int64_t*)(current_pixel - offset);
-                *base = (*base & ~mask) | dest;
-                break;
-            }
-            case 32: *((u_int32_t*)current_pixel) = destpixel; break;
-            default: org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: bpp not a multiple of 8!"));
-            }
-        }
-    }
-    
-    if (shared_pixmap) {
-        // do nothing, we wrote directly to video memory
-        
-    } else if (shm_supported) {
-        XShmPutImage(display, (*((Pixmap*)pm)), (*((GC*)gc)), xi, 0, 0, dx1, dy1, dx2 - dx1, dy2 - dy1, False);
-        XDestroyImage(xi);
-        
-    } else {
-        XPutImage(display, (*((Pixmap*)pm)), (*((GC*)gc)), xi, 0, 0, dx1, dy1, dx2 - dx1, dy2 - dy1);
-        
-    }
-}
-
-void org::xwt::plat::POSIX$X11DoubleBuffer::finalize() {
-    if (shared_pixmap) {
-        XShmSegmentInfo *sinfo = (XShmSegmentInfo*)shm_segment;
-        XShmDetach(display, sinfo);
-        shmdt(sinfo->shmaddr);
-        shmctl(sinfo->shmid, IPC_RMID, 0);
-        XDestroyImage((XImage*)fake_ximage);
-        free(sinfo);
-    }
-    if (stipple) {
-        XFreePixmap(display, *((Pixmap*)stipple));
-        free(stipple);
-    }
-    XFreePixmap(display, *((Pixmap*)pm));
-    XFreeGC(display, *((GC*)gc));
-    XFreeGC(display, *((GC*)clipped_gc));
-}
-
-void org::xwt::plat::POSIX$X11DoubleBuffer::natInit() {
-    
-    if (width == 0 || height == 0) return;
-    shared_pixmap &= shm_supported & shm_pixmaps_supported; // refuse to use shared pixmaps if we don't have shm
-    pm = (gnu::gcj::RawData*)malloc(sizeof(Pixmap));
-
-    if (!shared_pixmap)
-        (*((Pixmap*)pm)) = XCreatePixmap(display, RootWindow(display, screen_num), width, height, colorDepth);
-    else {
-        XShmSegmentInfo *sinfo = (XShmSegmentInfo*)malloc(sizeof(XShmSegmentInfo));
-        shm_segment = (gnu::gcj::RawData*)sinfo;
-        ((XImage*)fake_ximage) = XShmCreateImage(display, visual, colorDepth, ZPixmap, NULL, sinfo, width, height);
-        sinfo->shmid = shmget(IPC_PRIVATE, ((XImage*)fake_ximage)->bytes_per_line * height, IPC_CREAT | 0777 | IPC_EXCL);
-        ((XImage*)fake_ximage)->data = sinfo->shmaddr = (char*)shmat(sinfo->shmid, 0, 0);
-        sinfo->readOnly = False;
-        XShmAttach(display, sinfo);
-        XSync(display, False);
-        shmctl(sinfo->shmid, IPC_RMID, 0);
-        (*((Pixmap*)pm)) = XShmCreatePixmap(display, RootWindow(display, screen_num), sinfo->shmaddr, sinfo, width, height, colorDepth);
-        XSync(display, False);
-    }
-
-    gc = (gnu::gcj::RawData*)malloc(sizeof(GC));
-    clipped_gc = (gnu::gcj::RawData*)malloc(sizeof(GC));
-    (*((GC*)gc)) = XCreateGC(display, (*((Pixmap*)pm)), 0, 0);
-    (*((GC*)clipped_gc)) = XCreateGC(display, (*((Pixmap*)pm)), 0, 0);
-    
-    XGCValues vm;
-    vm.graphics_exposures = 0;
-    XChangeGC(display, (*((GC*)gc)), GCGraphicsExposures, &vm);
-    XChangeGC(display, (*((GC*)clipped_gc)), GCGraphicsExposures, &vm);
-}    
-
-void org::xwt::plat::POSIX$X11DoubleBuffer::createStipple(org::xwt::plat::POSIX$X11Picture* xpi) {
-
-    stipple = (gnu::gcj::RawData*)malloc(sizeof(Pixmap));
-    (*((Pixmap*)stipple)) = XCreatePixmap(display, RootWindow(display, screen_num), width, height, 1);
-
-    XImage xi;
-    xi.data = (char*)malloc((width + 1) * height);
-    xi.width = width;
-    xi.height = height;
-    xi.xoffset = 0;
-    xi.format = ZPixmap;
-    xi.bitmap_pad = 8;
-    xi.bitmap_unit = 8;
-    xi.byte_order = LSBFirst;
-    xi.depth = 1;
-    xi.bytes_per_line = (width / 8) + 1;
-    xi.bits_per_pixel = 1;
-    
-    jint* d = (jint*)elements(xpi->data);
-    memset(xi.data, 0xFF, (width + 1) * height);
-    for(int x=0; x<width; x++)
-        for (int y=0; y<height; y++)
-            xi.data[y * xi.bytes_per_line + (x/8)] &= ~(((d[x + y * width] & 0xFF000000) != 0 ? 0 : 1) << (x % 8));
-
-    GC stipple_gc = XCreateGC(display, (*((Pixmap*)stipple)), 0, 0);
-
-    XGCValues vm;
-    vm.graphics_exposures = 0;
-    XChangeGC(display, stipple_gc, GCGraphicsExposures, &vm);
-
-    XPutImage(display, (*((Pixmap*)stipple)), stipple_gc, &xi, 0, 0, 0, 0, width, height);
-}
-
-void org::xwt::plat::POSIX$X11Surface::blit(org::xwt::DoubleBuffer* db, jint sx, jint sy, jint dx, jint dy, jint dx2, jint dy2) {
-    org::xwt::plat::POSIX$X11DoubleBuffer *xdb = (org::xwt::plat::POSIX$X11DoubleBuffer*)db;
-    XCopyArea(display, *((Pixmap*)xdb->pm), *((Window*)window), *((GC*)gc), sx, sy, dx2 - dx, dy2 - dy, dx, dy);
-    XFlush(display);
-}
-
-void org::xwt::plat::POSIX$X11DoubleBuffer::fillRect (jint x, jint y, jint x2, jint y2, jint argb) {
-    
-    jint w = x2 - x;
-    jint h = y2 - y;
-
-    if (x < clipx) { w -= (clipx - x); x = clipx; }
-    if (y < clipy) { h -= (clipy - y); y = clipy; }
-    if (x + w > clipx + clipw) w = (clipx + clipw - x);
-    if (y + h > clipy + cliph) h = (cliph + clipy - y);
-
-    XSetForeground(display, (*((GC*)gc)),
-                   ((((argb & 0x00FF0000) >> 16) * colormap_info->red_max) / 0xFF) * colormap_info->red_mult + 
-                   ((((argb & 0x0000FF00) >> 8) * colormap_info->green_max) / 0xFF) * colormap_info->green_mult + 
-                   ((((argb & 0x000000FF)) * colormap_info->blue_max) / 0xFF) * colormap_info->blue_mult +
-                   colormap_info->base_pixel
-                   );
-    
-    XFillRectangle(display, (*((Pixmap*)pm)), (*((GC*)gc)), x, y, w, h);
-}
-
-void org::xwt::plat::POSIX$X11DoubleBuffer::drawString(::java::lang::String* font, ::java::lang::String* text, jint x, jint y, jint argb) {
-    
-    XRectangle rect;
-    rect.x = clipx, rect.y = clipy; rect.width = clipw; rect.height = cliph;
-    XSetClipMask(display, (*((GC*)clipped_gc)), None);
-    XSetClipRectangles(display, (*((GC*)clipped_gc)), 0, 0, &rect, 1, YSorted);
-    XSetForeground(display, (*((GC*)clipped_gc)),
-                   ((((argb & 0x00FF0000) >> 16) * colormap_info->red_max) / 0xFF) * colormap_info->red_mult + 
-                   ((((argb & 0x0000FF00) >> 8) * colormap_info->green_max) / 0xFF) * colormap_info->green_mult + 
-                   ((((argb & 0x000000FF)) * colormap_info->blue_max) / 0xFF) * colormap_info->blue_mult +
-                   colormap_info->base_pixel
-                   );
-    
-    // Grab the string
-    int len = min(1024, JvGetStringUTFLength(text));
-    char buf[len + 1];
-    JvGetStringUTFRegion(text, 0, len, buf);
-    buf[len] = '\0';
-    
-    // Build the XTextItem structure
-    XTextItem textitem;
-    textitem.chars = buf;
-    textitem.nchars = len;
-    textitem.delta = 0;
-    textitem.font = ((XFontStruct*)org::xwt::plat::POSIX::fontToXFont(font))->fid;
-    
-    // Draw the text
-    XDrawText(display, (*((Pixmap*)pm)), (*((GC*)clipped_gc)), x, y, &textitem, 1);
-}
-
-
-// X11Surface //////////////////////////////////////////////////////////////////////
-
-void org::xwt::plat::POSIX$X11Surface::setIcon(org::xwt::Picture* pic) {
-    org::xwt::plat::POSIX$X11Picture* p = ((org::xwt::plat::POSIX$X11Picture*)pic);
-    org::xwt::plat::POSIX$X11DoubleBuffer* old_dbuf = p->doublebuf;
-    p->buildDoubleBuffer(1);
-    XWMHints xwmh;
-    memset(&xwmh, 0, sizeof(XWMHints));
-    xwmh.flags |= IconPixmapHint | IconMaskHint;
-    xwmh.icon_pixmap = *((Pixmap*)p->doublebuf->pm);
-    xwmh.icon_mask = *((Pixmap*)p->doublebuf->stipple);
-    XSetWMHints(display, (*((Window*)window)), &xwmh);
-    p->doublebuf = old_dbuf;
-}
-
-void org::xwt::plat::POSIX$X11Surface::setTitleBarText(java::lang::String* s) {
-    int len = min(JvGetStringUTFLength(s), 1024);
-    char buf[len + 1];
-    JvGetStringUTFRegion(s, 0, len, buf);
-    buf[len] = '\0';
-    
-    XTextProperty tp;
-    tp.value = (unsigned char*)buf;
-    tp.nitems = len;
-    tp.encoding = XA_STRING;
-    tp.format = 8;
-    XSetTextProperty(display, (*((Window*)window)), &tp, XA_WM_NAME);
-    XSetTextProperty(display, (*((Window*)window)), &tp, XA_WM_ICON_NAME);
-}
-
-void org::xwt::plat::POSIX$X11Surface::setLimits(jint minw, jint minh, jint maxw, jint maxh) {
-    XSizeHints hints;
-    hints.min_width = minw;
-    hints.min_height = minh;
-    hints.max_width = maxw;
-    hints.max_height = maxh;
-    hints.flags = PMinSize | PMaxSize;
-    XSetWMNormalHints(display, (*((Window*)window)), &hints);
-}
-
-void org::xwt::plat::POSIX$X11Surface::setSize (jint width, jint height) {
-    if (width <= 0 || height <= 0) return;
-    XResizeWindow(display, (*((Window*)window)), width, height);
-    XFlush(display);
-}
-
-void org::xwt::plat::POSIX$X11Surface::setLocation (jint x, jint y) { XMoveWindow(display, (*((Window*)window)), x, y); }
-void org::xwt::plat::POSIX$X11Surface::toFront() { XRaiseWindow(display, (*((Window*)window))); }
-void org::xwt::plat::POSIX$X11Surface::toBack() { XLowerWindow(display, (*((Window*)window))); }
-
-void org::xwt::plat::POSIX$X11Surface::_dispose() {
-    // without this we get phantom messages after the window is gone
-    org::xwt::plat::POSIX::windowToSurfaceMap->remove(new java::lang::Long(*((Window*)window)));
-    XDestroyWindow(display, (*((Window*)window)));
-}
-
-void org::xwt::plat::POSIX$X11Surface::setInvisible(jboolean i) {
-    if (i) XUnmapWindow(display, (*((Window*)window)));
-    else XMapRaised(display, (*((Window*)window)));
-    XFlush(display);
-}
-
-void org::xwt::plat::POSIX$X11Surface::_setMinimized(jboolean b) {
-    if (b) XIconifyWindow(display, (*((Window*)window)), screen_num);
-    else XMapRaised(display, (*((Window*)window)));
-    XFlush(display);
-}
-
-void org::xwt::plat::POSIX$X11Surface::natInit() {
-    XSetWindowAttributes xswa;
-    window = (gnu::gcj::RawData*)malloc(sizeof(Window));
-    xswa.bit_gravity = NorthWestGravity;
-    xswa.colormap = s_colormap;
-    xswa.event_mask = ExposureMask | ButtonPressMask | StructureNotifyMask |
-        KeyPressMask | KeyReleaseMask | ButtonPressMask |
-        ButtonReleaseMask | EnterWindowMask | LeaveWindowMask |
-        PointerMotionMask | ButtonMotionMask | ConfigureNotify | FocusChangeMask;
-    *((Window*)window) = XCreateWindow(display, RootWindow(display, screen_num), 10, 10, 10, 10, 0,
-                                       colorDepth, InputOutput, CopyFromParent,
-                                       CWColormap | CWBitGravity | CWEventMask, &xswa);
-    
-    if (!framed) {
-        // I don't know why this works....
-        int dat[5] = { 0x2, 0xbffff804, 0x0, 0x817f560, 0x8110694 };
-        XChangeProperty(display, (*((Window*)window)),
-                        XInternAtom(display, "_MOTIF_WM_HINTS", False),
-                        XInternAtom(display, "_MOTIF_WM_HINTS", False),
-                        32, 
-                        PropModeReplace,
-                        (unsigned char*)dat,
-                        5);
-    }
-    
-    XTextProperty tp;
-    tp.value = (unsigned char*)"XWT";
-    tp.nitems = 3;
-    tp.encoding = XA_STRING;
-    tp.format = 8;
-    XSetTextProperty(display, (*((Window*)window)), &tp, XA_WM_CLASS);
-    
-    Atom proto = XInternAtom(display, "WM_DELETE_WINDOW", False);
-    XSetWMProtocols(display, (*((Window*)window)), &proto, 1);
-    
-    XSelectInput(display, (*((Window*)window)), StructureNotifyMask);
-    org::xwt::plat::POSIX::windowToSurfaceMap->put(new java::lang::Long(*((Window*)window)), this);
-
-    XEvent e;
-    XMapRaised(display, (*((Window*)window)));
-    XFlush(display);
-
-    waitForCreation->block();
-    XSelectInput(display, (*((Window*)window)), xswa.event_mask);
-    XFlush(display);
-
-    gc = (gnu::gcj::RawData*)malloc(sizeof(GC));
-    *((GC*)gc) = XCreateGC(display, (*((Window*)window)), 0, 0);
-    
-    XGCValues vm;
-    vm.graphics_exposures = 0;
-    XChangeGC(display, *((GC*)gc), GCGraphicsExposures, &vm);
-}
-
-
-void org::xwt::plat::POSIX$X11Surface::dispatchEvent(gnu::gcj::RawData* ev) {
-
-    XEvent* e = (XEvent*)ev;
-    if (e->type == Expose) {
-        XExposeEvent *expose = (XExposeEvent*)(e);
-        Dirty(expose->x, expose->y, expose->width, expose->height);
-        
-    } else if (e->type == ClientMessage) { if (((XClientMessageEvent*)(e))->data.l[0] == XInternAtom(display, "WM_DELETE_WINDOW", False)) Close();
-    } else if (e->type == MapNotify) { Minimized(0); waitForCreation->release();
-    } else if (e->type == UnmapNotify) { Minimized(1);
-    } else if (e->type == FocusIn) { Focused(1);
-    } else if (e->type == FocusOut) { Focused(0);
-    
-    } else if (e->type == KeyPress || e->type == KeyRelease) {
-        XKeyEvent *xbe = (XKeyEvent*)(e);
-        
-        // drop faked KeyRelease events generated by the X server's autorepeat
-        if (e->type == KeyRelease) {
-            char depressed[32];
-            XQueryKeymap(display, depressed);
-            if ((depressed[(xbe->keycode & 0xff) / 8] & (0x1 << (xbe->keycode % 8))) >> (xbe->keycode % 8)) return;
-        }
-        
-        char ss[20];
-        char* s = ss;
-        
-        unsigned int savestate = xbe->state;
-        xbe->state = xbe->state & ShiftMask;      // ignore everything except shiftmask
-        XLookupString(xbe, s, 20, NULL, NULL);
-        xbe->state = savestate;
-        
-        if (s != NULL && s[0] != '\0' && s[1] == '\0' && s[0] >= 0x20 && s[0] <= 0x7E) {
-            int i = s[0];
-            
-        } else {
-            KeySym ks = XKeycodeToKeysym(display, xbe->keycode, 0);
-            switch (ks) {
-            case XK_BackSpace: s = "back_space"; break;
-            case XK_Tab: s = "tab"; break;
-            case XK_Linefeed: s = "enter"; break;
-            case XK_Return: s = "enter"; break;
-            case XK_Scroll_Lock: s = "scroll_lock"; break;
-            case XK_Escape: s = "escape"; break;
-            case XK_Insert: s = "insert"; break;
-            case XK_Delete: s = "delete"; break;
-            case XK_Home: s = "home"; break;
-            case XK_Left: s = "left"; break;
-            case XK_Up: s = "up"; break;
-            case XK_Right: s = "right"; break;
-            case XK_Down: s = "down"; break;
-            case XK_Page_Up: s = "page_up"; break;
-            case XK_Page_Down: s = "page_down"; break;
-            case XK_End: s = "end"; break;
-            case XK_Num_Lock: s = "num_lock"; break;
-            case XK_KP_Tab: s = "tab"; break;
-            case XK_KP_Enter: s = "enter"; break;
-            case XK_KP_F1: s = "f1"; break;
-            case XK_KP_F2: s = "f2"; break;
-            case XK_KP_F3: s = "f3"; break;
-            case XK_KP_F4: s = "f4"; break;
-            case XK_KP_Home: s = "home"; break;
-            case XK_KP_Left: s = "left"; break;
-            case XK_KP_Up: s = "up"; break;
-            case XK_KP_Right: s = "right"; break;
-            case XK_KP_Down: s = "down"; break;
-            case XK_KP_Page_Up: s = "page_up"; break;
-            case XK_KP_Page_Down: s = "page_down"; break;
-            case XK_KP_End: s = "end"; break;
-            case XK_KP_Insert: s = "insert"; break;
-            case XK_KP_Delete: s = "delete"; break;
-            case XK_F1: s = "f1"; break;
-            case XK_F2: s = "f2"; break;
-            case XK_F3: s = "f3"; break;
-            case XK_F4: s = "f4"; break;
-            case XK_F5: s = "f5"; break;
-            case XK_F6: s = "f6"; break;
-            case XK_F7: s = "f7"; break;
-            case XK_F8: s = "f8"; break;
-            case XK_F9: s = "f9"; break;
-            case XK_F10: s = "f10"; break;
-            case XK_F11: s = "f11"; break;
-            case XK_F12: s = "f12"; break;
-            case XK_Shift_L: s = "shift"; break;
-            case XK_Shift_R: s = "shift"; break;
-            case XK_Control_L: s = "control"; break;
-            case XK_Control_R: s = "control"; break;
-            case XK_Meta_L: s = "alt"; break;
-            case XK_Meta_R: s = "alt"; break;
-            case XK_Alt_L: s = "alt"; break;
-            case XK_Alt_R: s = "alt"; break;
-            default: return;
-            }
-        }
-        
-        jstring s2 = JvNewStringLatin1(s);
-        if (e->type == KeyPress) KeyPressed((xbe->state & LockMask) ? s2->toUpperCase() : s2);
-        if (e->type == KeyRelease) KeyReleased(s2);
-        
-    } else if (e->type == ButtonPress) {
-        XButtonEvent* xbe = (XButtonEvent*)(e);
-        if (xbe->button == 2) xbe->button = 3;
-        else if (xbe->button == 3) xbe->button = 2;
-        Press(xbe->button);
-        
-    } else if (e->type == ButtonRelease) {
-        XButtonEvent* xbe = (XButtonEvent*)(e);
-        if (xbe->button == 2) xbe->button = 3;
-        else if (xbe->button == 3) xbe->button = 2;
-        Release(xbe->button);
-        
-    } else if (e->type == MotionNotify) {
-        XMotionEvent* xme = (XMotionEvent*)(e);
-        Move(xme->x, xme->y);
-        
-    } else if (e->type == EnterNotify || e->type == LeaveNotify) {
-        XCrossingEvent* xce = (XCrossingEvent*)(e);
-        Move(xce->x, xce->y);
-        
-    } else if (e->type == ConfigureNotify) {
-        Window child;
-        int x_out, y_out;
-        XConfigureEvent* xce = (XConfigureEvent*)(e);
-        XTranslateCoordinates(display, (*((Window*)window)), RootWindow(display, screen_num), 0, 0, &x_out, &y_out, &child);
-        if (xce->width != width || xce->height != height) SizeChange(xce->width, xce->height);
-        if (x_out != root->abs(0) || y_out != root->abs(1)) PosChange(x_out, y_out);
-        
-    }
-}
-
-static jstring crosshair, east, hand, move, north, northeast, northwest,
-    south, southeast, southwest, text, west, wait_string;
-static Cursor crosshair_cursor, east_cursor, hand_cursor, move_cursor, north_cursor,
-    northeast_cursor, northwest_cursor, south_cursor, southeast_cursor,
-    southwest_cursor, text_cursor, west_cursor, wait_cursor, default_cursor;
-
-void org::xwt::plat::POSIX$X11Surface::syncCursor() {
-    
-    Cursor curs;
-    if (cursor->equals(crosshair)) curs = crosshair_cursor;
-    else if (cursor->equals(east)) curs = east_cursor;
-    else if (cursor->equals(hand)) curs = hand_cursor;
-    else if (cursor->equals(move)) curs = move_cursor;
-    else if (cursor->equals(north)) curs = north_cursor;
-    else if (cursor->equals(northeast)) curs = northeast_cursor;
-    else if (cursor->equals(northwest)) curs = northwest_cursor;
-    else if (cursor->equals(south)) curs = south_cursor;
-    else if (cursor->equals(southeast)) curs = southeast_cursor;
-    else if (cursor->equals(southwest)) curs = southwest_cursor;
-    else if (cursor->equals(text)) curs = text_cursor;
-    else if (cursor->equals(west)) curs = west_cursor;
-    else if (cursor->equals(wait_string)) curs = wait_cursor;
-    else curs = default_cursor;
-    
-    XDefineCursor(display, (*((Window*)window)), curs);
-}
-
-
-
-// POSIX ///////////////////////////////////////////////////////////////////
-
-jint org::xwt::plat::POSIX::_getScreenWidth() { return WidthOfScreen(DefaultScreenOfDisplay(display)); }
-jint org::xwt::plat::POSIX::_getScreenHeight() { return HeightOfScreen(DefaultScreenOfDisplay(display)); }
-
 jstring org::xwt::plat::POSIX::_getEnv(jstring key) {
     int len = JvGetStringUTFLength(key);
     char buf[len + 1];
@@ -653,1735 +39,3 @@ void org::xwt::plat::POSIX::spawnChildProcess(JArray<jstring>* cmd) {
     }
 }
 
-static void dispatchSelectionEvent(XEvent* e) {
-    if (e->type == SelectionNotify) {
-        XSelectionEvent* xsn = (XSelectionEvent*)(e);
-        if (xsn->property == None) org::xwt::plat::POSIX::clipboard = JvNewStringLatin1("", 0);
-        else {
-            Atom returntype;
-            int returnformat;
-            unsigned long numitems;
-            unsigned char* ret;
-            unsigned long bytes_after;
-            XGetWindowProperty(display, xsn->requestor, xsn->property, 0, 4096,
-                               True, AnyPropertyType, &returntype, &returnformat,
-                               &numitems, &bytes_after, &ret);
-            org::xwt::plat::POSIX::clipboard =
-                (returntype == None ? JvNewStringLatin1("", 0) : JvNewStringLatin1((char*)ret, strlen((char*)ret)));
-        }
-        org::xwt::plat::POSIX::waiting_for_selection_event->release();
-        
-    } else if (e->type == SelectionRequest) {
-        XSelectionRequestEvent* xsr = (XSelectionRequestEvent*)(e);
-        XSelectionEvent xsn;
-        xsn.type = SelectionNotify;
-        xsn.serial = xsr->serial;
-        xsn.send_event = True;
-        xsn.display = display;
-        xsn.requestor = xsr->requestor;
-        xsn.selection = xsr->selection;
-        xsn.target = xsr->target;
-        xsn.property = xsr->property;
-        xsn.time = xsr->time;
-        
-        int len = min(1024, JvGetStringUTFLength(org::xwt::plat::POSIX::clipboard));
-        char buf[len + 1];
-        JvGetStringUTFRegion(org::xwt::plat::POSIX::clipboard, 0, len, buf);
-        buf[len] = '\0';
-        
-        XChangeProperty(display, xsr->requestor, xsr->property, xsr->target, 8, PropModeReplace, (unsigned char*)buf, len + 1);
-        XSendEvent(display, xsr->requestor, True, 0, (XEvent*)(&xsn));
-    }        
-}
-
-void org::xwt::plat::POSIX::eventThread() {
-    XEvent e;
-    while(true) {
-        XNextEvent(display, &e);
-        if (e.type == SelectionNotify || e.type == SelectionRequest) {
-            dispatchSelectionEvent(&e);
-        } else {
-            org::xwt::plat::POSIX$X11Surface* surface =
-                (org::xwt::plat::POSIX$X11Surface*)windowToSurfaceMap->get(new java::lang::Long(((XAnyEvent*)&e)->window));
-            if (surface != NULL) surface->dispatchEvent((gnu::gcj::RawData*)&e);
-        }
-    }
-}
-
-jstring org::xwt::plat::POSIX::_getClipBoard() {
-    XConvertSelection(display, XA_PRIMARY, XA_STRING, XInternAtom(display, "VT_SELECTION", False), selectionWindow, CurrentTime);
-    XFlush(display);
-    org::xwt::plat::POSIX::waiting_for_selection_event->block();
-    return clipboard;
-}
-
-void org::xwt::plat::POSIX::_setClipBoard(jstring s) {
-    clipboard = s;
-    int len = JvGetStringUTFLength(clipboard);
-    char buf[len + 1];
-    JvGetStringUTFRegion(clipboard, 0, len, buf);
-    buf[len] = '\0';
-    XSetSelectionOwner(display, XInternAtom(display, "PRIMARY", 0), selectionWindow, CurrentTime);
-}
-
-typedef int (X11ErrorHandler)(Display*, XErrorEvent*);
-int errorHandler(Display* d, XErrorEvent* e) {
-    // this error handler is only installed during the initial
-    // test to see if shm is present
-    shm_supported = 0;
-}
-
-void org::xwt::plat::POSIX::natInit() {
-
-    if (!XInitThreads())
-        org::xwt::Platform::criticalAbort(JvNewStringLatin1("Your X11 libraries do not support multithreaded programs"));
-
-    display = XOpenDisplay(NULL);
-    screen_num = XDefaultScreen(display);
-    colorDepth = (jint)(DefaultDepth(((Display*)display), 0));
-    shm_info.shmaddr = NULL;
-
-    shm_supported = (XShmQueryExtension(display) == True);
-    if (shm_supported) {
-        X11ErrorHandler* oldHandler = XSetErrorHandler(errorHandler);
-        XShmSegmentInfo sinfo;
-        sinfo.shmid = shmget(IPC_PRIVATE, 1, IPC_CREAT | 0777 | IPC_EXCL);
-        sinfo.readOnly = False;
-        // if the server is remote, this will trigger the error handler
-        XShmAttach(display, &sinfo);
-        XSync(display, False);
-        XSetErrorHandler(oldHandler);
-    }
-
-    if (shm_supported)
-        shm_pixmaps_supported = (XShmPixmapFormat(display) == ZPixmap);
-    
-    crosshair = JvNewStringLatin1("crosshair");
-    east = JvNewStringLatin1("east");
-    hand = JvNewStringLatin1("hand");
-    move = JvNewStringLatin1("move");
-    north = JvNewStringLatin1("north");
-    northeast = JvNewStringLatin1("northeast");
-    northwest = JvNewStringLatin1("northwest");
-    south = JvNewStringLatin1("south");
-    southeast = JvNewStringLatin1("southeast");
-    southwest = JvNewStringLatin1("southwest");
-    text = JvNewStringLatin1("text");
-    west = JvNewStringLatin1("west");
-    wait_string = JvNewStringLatin1("wait");
-    crosshair_cursor = XCreateFontCursor(display, XC_tcross);
-    east_cursor = XCreateFontCursor(display, XC_right_side);
-    hand_cursor = XCreateFontCursor(display, XC_hand2);
-    move_cursor = XCreateFontCursor(display, XC_fleur);
-    north_cursor = XCreateFontCursor(display, XC_top_side);
-    northeast_cursor = XCreateFontCursor(display, XC_top_right_corner);
-    northwest_cursor = XCreateFontCursor(display, XC_left_side);
-    south_cursor = XCreateFontCursor(display, XC_bottom_side);
-    southeast_cursor = XCreateFontCursor(display, XC_bottom_right_corner);
-    southwest_cursor = XCreateFontCursor(display, XC_bottom_left_corner);
-    text_cursor = XCreateFontCursor(display, XC_xterm);
-    west_cursor = XCreateFontCursor(display, XC_right_side);
-    wait_cursor = XCreateFontCursor(display, XC_watch);
-    default_cursor = XCreateFontCursor(display, XC_left_ptr);
-
-    selectionWindow = XCreateWindow(display, RootWindow(display, screen_num), 0, 0, 1, 1, 0, colorDepth, InputOutput, CopyFromParent, 0, NULL);
-    visual = DefaultVisual(display, screen_num);
-    char buf[255];
-    sprintf(buf, "X11 DISPLAY: %s", XDisplayString(display));
-    org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
-    sprintf(buf, "X11 SHM:     %s", shm_supported ? "enabled" : "disabled");
-    org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
-    sprintf(buf, "X11 Visual:  %x %x %x bits: %i visualid: %i depth: %i",
-            visual->red_mask, visual->green_mask, visual->blue_mask, visual->bits_per_rgb, visual->visualid, colorDepth);
-    org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
-
-    // FIXME: don't know why (True, False) is the best solution...
-    if(XmuLookupStandardColormap(display, screen_num, visual->visualid, colorDepth, XA_RGB_BEST_MAP, True, False) == 0)
-        org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: XmuLookupStandardColormap failed"));
-    
-    XStandardColormap* best_map_info = NULL;
-    int count;
-    if (XGetRGBColormaps(display, RootWindow(display, screen_num), &best_map_info, &count, XA_RGB_BEST_MAP) == 0)
-        org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: couldn't allocate a standard colormap"));
-    if (!best_map_info->colormap)
-        org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: XmuLookupStandardColomap succeded, but no colormap was found on the root window"));
-    if (best_map_info->red_max == 0)
-        org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: standard colormap exists, but was improperly allocated"));
-    s_colormap = best_map_info->colormap;
-    colormap_info = best_map_info;
-
-    sprintf(buf, "            red_max / red_mult: %x %x", colormap_info->red_max, colormap_info->red_mult);
-    org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
-    sprintf(buf, "            green_max / green_mult: %x %x", colormap_info->green_max, colormap_info->green_mult);
-    org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
-    sprintf(buf, "            blue_max / blue_mult: %x %x", colormap_info->blue_max, colormap_info->blue_mult);
-    org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
-    sprintf(buf, "            base_pixel: %x", colormap_info->base_pixel);
-    org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
-}
-
-JArray<java::lang::String*>* org::xwt::plat::POSIX::listNativeFonts() {
-    int numfonts;
-    char** xfonts = XListFonts(display, "-*-*-*-*-normal-*-*-*-*-*-*-*-*-*", 0xFFFFFFFF, &numfonts);
-    JArray<java::lang::String*>* fonts = (JArray<java::lang::String*>*)JvNewObjectArray(numfonts, &(::java::lang::String::class$), NULL);
-    java::lang::String** jfonts = (java::lang::String**)(elements(fonts));
-    for(int i=0; i<numfonts; i++)
-        jfonts[i] = JvNewStringLatin1(xfonts[i], strlen(xfonts[i]));
-    return fonts;
-}
-
-gnu::gcj::RawData* org::xwt::plat::POSIX::fontStringToStruct(jstring s) {
-    int len = min(1024, JvGetStringUTFLength(s));
-    char buf[len + 1];
-    JvGetStringUTFRegion(s, 0, len, buf);
-    buf[len] = '\0';
-    return (gnu::gcj::RawData*)XLoadQueryFont(display, buf);
-}
-
-jint org::xwt::plat::POSIX::_getMaxAscent(::java::lang::String* font) { return ((XFontStruct*)fontToXFont(font))->max_bounds.ascent; }
-jint org::xwt::plat::POSIX::_getMaxDescent(::java::lang::String* font) { return ((XFontStruct*)fontToXFont(font))->max_bounds.descent; }
-jint org::xwt::plat::POSIX::_stringWidth(::java::lang::String* font, ::java::lang::String* text) {
-    if (text == NULL) return 0;
-    int len = JvGetStringUTFLength(text);
-    char buf[len + 1];
-    JvGetStringUTFRegion(text, 0, len, buf);
-    buf[len] = '\0';
-    return XTextWidth((XFontStruct*)fontToXFont(font), buf, len);
-}
-
-
-//////////////////////////////////////////////////////////////////////////////
-//////////////////////////////////////////////////////////////////////////////
-//////////////////////////////////////////////////////////////////////////////
-//////////////////////////////////////////////////////////////////////////////
-//                                                                          //
-// Everything below this point was taken, cut-and-paste, from the           //
-// source for libXmu. It implements the official 'standard colormap         //
-// creation algorithm.  I made some small changes to                        //
-// XmuDeleteStandardColormap                                                //
-//                                                                          //
-//////////////////////////////////////////////////////////////////////////////
-//////////////////////////////////////////////////////////////////////////////
-//////////////////////////////////////////////////////////////////////////////
-//////////////////////////////////////////////////////////////////////////////
-
-/* $Xorg: LookupCmap.c,v 1.4 2001/02/09 02:03:53 xorgcvs Exp $ */
-
-/* 
-Copyright 1989, 1998  The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
-
-*/
-/* $XFree86: xc/lib/Xmu/LookupCmap.c,v 1.8 2001/12/14 19:55:47 dawes Exp $ */
-
-/*
- * Author:  Donna Converse, MIT X Consortium
- */
-
-#include <stdio.h>
-#include <X11/Xlib.h>
-#include <X11/Xatom.h>
-#include <X11/Xutil.h>
-#include <X11/Xmu/StdCmap.h>
-#include <stdlib.h>
-
-/*
- * Prototypes
- */
-static Status lookup(Display*, int, VisualID, Atom, XStandardColormap*, Bool);
-
-/*
- * To create a standard colormap if one does not currently exist, or
- * replace the currently existing standard colormap, use 
- * XmuLookupStandardColormap().
- *
- * Given a screen, a visual, and a property, XmuLookupStandardColormap()
- * will determine the best allocation for the property under the specified
- * visual, and determine the whether to create a new colormap or to use
- * the default colormap of the screen.  It will call XmuStandardColormap()
- * to create the standard colormap.
- *
- * If replace is true, any previous definition of the property will be 
- * replaced.  If retain is true, the property and the colormap will be
- * made permanent for the duration of the server session.  However,
- * pre-existing property definitions which are not replaced cannot be made
- * permanent by a call to XmuLookupStandardColormap(); a request to retain 
- * resources pertains to newly created resources.
- *
- * Returns 0 on failure, non-zero on success.  A request to create a 
- * standard colormap upon a visual which cannot support such a map is
- * considered a failure.  An example of this would be requesting any
- * standard colormap property on a monochrome visual, or, requesting an
- * RGB_BEST_MAP on a display whose colormap size is 16.
- */
-
-Status
-XmuLookupStandardColormap(Display *dpy, int screen, VisualID visualid,
-                         unsigned int depth, Atom property,
-                         Bool replace, Bool retain)
-     /*
-      * dpy            - specifies X server connection
-      * screen                 - specifies screen of display
-      * visualid       - specifies the visual type
-      * depth          - specifies  the visual type
-      * property       - a standard colormap property
-      * replace                - specifies whether to replace
-      * retain         - specifies whether to retain
-      */
-{
-    Display            *odpy;          /* original display connection */
-    XStandardColormap  *colormap;      
-    XVisualInfo                vinfo_template, *vinfo; /* visual */
-    long               vinfo_mask;
-    unsigned long      r_max, g_max, b_max;    /* allocation */
-    int                        count;  
-    Colormap           cmap;                   /* colormap ID */
-    Status             status = 0;
-
-
-    /* Match the requested visual */
-
-    vinfo_template.visualid = visualid;        
-    vinfo_template.screen = screen;
-    vinfo_template.depth = depth;
-    vinfo_mask = VisualIDMask | VisualScreenMask | VisualDepthMask;
-    if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &count)) ==
-       NULL)
-       return 0;
-
-    /* Monochrome visuals have no standard maps */
-
-    if (vinfo->colormap_size <= 2) {
-       XFree((char *) vinfo);
-       return 0;       
-    }
-
-    /* If the requested property already exists on this screen, and, 
-     * if the replace flag has not been set to true, return success.
-     * lookup() will remove a pre-existing map if replace is true.
-     */
-
-    if (lookup(dpy, screen, visualid, property, (XStandardColormap *) NULL,
-              replace) && !replace) {
-       XFree((char *) vinfo);
-       return 1;
-    }
-
-    /* Determine the best allocation for this property under the requested
-     * visualid and depth, and determine whether or not to use the default
-     * colormap of the screen.
-     */
-
-    if (!XmuGetColormapAllocation(vinfo, property, &r_max, &g_max, &b_max)) {
-       XFree((char *) vinfo);
-       return 0;
-    }
-
-    cmap = (property == XA_RGB_DEFAULT_MAP &&
-           visualid == XVisualIDFromVisual(DefaultVisual(dpy, screen)))
-       ? DefaultColormap(dpy, screen) : None;
-
-    /* If retaining resources, open a new connection to the same server */
-
-    if (retain) {
-        odpy = dpy;
-        if ((dpy = XOpenDisplay(XDisplayString(odpy))) == NULL) {
-            XFree((char *) vinfo);
-            return 0;
-        }
-    }
-
-    /* Create the standard colormap */
-
-    colormap = XmuStandardColormap(dpy, screen, visualid, depth, property,
-                                  cmap, r_max, g_max, b_max);
-
-    /* Set the standard colormap property */
-
-    if (colormap) {
-       XGrabServer(dpy);
-
-       if (lookup(dpy, screen, visualid, property, colormap, replace) &&
-           !replace) {
-           /* Someone has defined the property since we last looked.
-            * Since we will not replace it, release our own resources.
-            * If this is the default map, our allocations will be freed 
-            * when this connection closes.
-            */
-           if (colormap->killid == ReleaseByFreeingColormap)
-            XFreeColormap(dpy, colormap->colormap);
-       } else if (retain) {
-               XSetCloseDownMode(dpy, RetainPermanent);
-       }
-       XUngrabServer(dpy);
-       XFree((char *) colormap);
-       status = 1;
-    }
-
-    if (retain)
-       XCloseDisplay(dpy);
-    XFree((char *) vinfo);
-    return status;
-}
-
-/***************************************************************************/
-
-/* Lookup a standard colormap property.  If the property is RGB_DEFAULT_MAP,
- * the visualid is used to determine whether the indicated standard colormap
- * exists.  If the map exists and replace is true, delete the resources used
- * by the map and remove the property.  Return true if the map exists,
- * or did exist and was deleted; return false if the map was not found.
- *
- * Note that this is not the way that a Status return is normally used.
- *
- * If new is not NULL, new points to an XStandardColormap structure which
- * describes a standard colormap of the specified property.  It will be made
- * a standard colormap of the screen if none already exists, or if replace 
- * is true.
- */
-
-static Status
-lookup(Display *dpy, int screen, VisualID visualid, Atom property,
-       XStandardColormap *cnew, Bool replace)
-     /*
-      * dpy            - specifies display connection
-      * screen         - specifies screen number
-      * visualid       - specifies visualid for std map
-      * property       - specifies colormap property name
-      * cnew           - specifies a standard colormap
-      * replace                - specifies whether to replace
-      */
-{
-    register int       i;
-    int                        count;
-    XStandardColormap  *stdcmaps, *s;
-    Window             win = RootWindow(dpy, screen);
-
-    /* The property does not already exist */
-
-    if (! XGetRGBColormaps(dpy, win, &stdcmaps, &count, property)) {
-       if (cnew)
-           XSetRGBColormaps(dpy, win, cnew, 1, property);
-       return 0;
-    }
-
-    /* The property exists and is not describing the RGB_DEFAULT_MAP */
-
-    if (property != XA_RGB_DEFAULT_MAP) {
-       if (replace) {
-           XmuDeleteStandardColormap(dpy, screen, property);
-           if (cnew)
-               XSetRGBColormaps(dpy, win, cnew, 1, property);
-       }
-       XFree((char *)stdcmaps);
-       return 1;
-    }
-
-    /* The property exists and is RGB_DEFAULT_MAP */
-    
-    for (i=0, s=stdcmaps; (i < count) && (s->visualid != visualid); i++, s++)
-       ;
-
-    /* No RGB_DEFAULT_MAP property matches the given visualid */
-
-    if (i == count) {
-       if (cnew) {
-           XStandardColormap   *m, *maps;
-
-           s = (XStandardColormap *) malloc((unsigned) ((count+1) * sizeof
-                                             (XStandardColormap)));
-
-           for (i = 0, m = s, maps = stdcmaps; i < count; i++, m++, maps++) {
-               m->colormap   = maps->colormap;
-               m->red_max    = maps->red_max;
-               m->red_mult   = maps->red_mult;
-               m->green_max  = maps->green_max;
-               m->green_mult = maps->green_mult;
-               m->blue_max   = maps->blue_max;
-               m->blue_mult  = maps->blue_mult;
-               m->base_pixel = maps->base_pixel;
-               m->visualid   = maps->visualid;
-               m->killid     = maps->killid;
-           }
-           m->colormap   = cnew->colormap;
-           m->red_max    = cnew->red_max;
-           m->red_mult   = cnew->red_mult;
-           m->green_max  = cnew->green_max;
-           m->green_mult = cnew->green_mult;
-           m->blue_max   = cnew->blue_max;
-           m->blue_mult  = cnew->blue_mult;
-           m->base_pixel = cnew->base_pixel;
-           m->visualid   = cnew->visualid;
-           m->killid     = cnew->killid;
-
-           XSetRGBColormaps(dpy, win, s, ++count, property);
-           free((char *) s);
-       }
-       XFree((char *) stdcmaps);
-       return 0;
-    }
-
-    /* Found an RGB_DEFAULT_MAP property with a matching visualid */
-
-    if (replace) {
-       /* Free old resources first - we may need them, particularly in 
-        * the default colormap of the screen.  However, because of this,
-        * it is possible that we will destroy the old resource and fail 
-        * to create a new one if XmuStandardColormap() fails.
-        */
-
-       if (count == 1) {
-           XmuDeleteStandardColormap(dpy, screen, property);
-           if (cnew)
-               XSetRGBColormaps(dpy, win, cnew, 1, property);
-       }
-       else {
-           XStandardColormap   *map;
-
-           /* s still points to the matching standard colormap */
-
-           if (s->killid == ReleaseByFreeingColormap) {
-               if ((s->colormap != None) &&
-                   (s->colormap != DefaultColormap(dpy, screen)))
-                   XFreeColormap(dpy, s->colormap);
-           }
-           else if (s->killid != None)
-               XKillClient(dpy, s->killid);
-
-           map = (cnew) ? cnew : stdcmaps + --count;
-
-           s->colormap   = map->colormap;
-           s->red_max    = map->red_max;
-           s->red_mult   = map->red_mult;
-           s->green_max  = map->green_max;
-           s->green_mult = map->green_mult;
-           s->blue_max   = map->blue_max;
-           s->blue_mult  = map->blue_mult;
-           s->visualid   = map->visualid;
-           s->killid     = map->killid;
-
-           XSetRGBColormaps(dpy, win, stdcmaps, count, property);
-       }
-    }
-    XFree((char *) stdcmaps);
-    return 1;
-}
-
-/* $Xorg: CmapAlloc.c,v 1.4 2001/02/09 02:03:51 xorgcvs Exp $ */
-
-/* 
-
-Copyright 1989, 1994, 1998  The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
-
-*/
-/* $XFree86: xc/lib/Xmu/CmapAlloc.c,v 1.7 2001/12/14 19:55:35 dawes Exp $ */
-
-/*
- * Author:  Donna Converse, MIT X Consortium
- */
-
-#include <X11/Xlib.h>
-#include <X11/Xatom.h>
-#include <X11/Xutil.h>
-#include <X11/Xmu/StdCmap.h>
-#include <stdio.h>
-
-#define lowbit(x) ((x) & (~(x) + 1))
-
-/*
- * Prototypes
- */
-static void best_allocation(XVisualInfo*, unsigned long*, unsigned long*,
-                           unsigned long*);
-static int default_allocation(XVisualInfo*, unsigned long*,
-                             unsigned long*, unsigned long*);
-static void gray_allocation(int, unsigned long*, unsigned long*,
-                           unsigned long*);
-static int icbrt(int);
-static int icbrt_with_bits(int, int);
-static int icbrt_with_guess(int, int);
-
-/* To determine the best allocation of reds, greens, and blues in a 
- * standard colormap, use XmuGetColormapAllocation.
- *     vinfo           specifies visual information for a chosen visual
- *     property        specifies one of the standard colormap property names
- *     red_max         returns maximum red value 
- *      green_max      returns maximum green value
- *     blue_max        returns maximum blue value
- *
- * XmuGetColormapAllocation returns 0 on failure, non-zero on success.
- * It is assumed that the visual is appropriate for the colormap property.
- */
-
-Status
-XmuGetColormapAllocation(XVisualInfo *vinfo, Atom property,
-                        unsigned long *red_max,
-                        unsigned long *green_max,
-                        unsigned long *blue_max)
-{
-    Status     status = 1;
-
-    if (vinfo->colormap_size <= 2)
-       return 0;
-
-    switch (property)
-    {
-      case XA_RGB_DEFAULT_MAP:
-       status = default_allocation(vinfo, red_max, green_max, blue_max);
-       break;
-      case XA_RGB_BEST_MAP:
-       best_allocation(vinfo, red_max, green_max, blue_max);
-       break;
-      case XA_RGB_GRAY_MAP:
-       gray_allocation(vinfo->colormap_size, red_max, green_max, blue_max);
-       break;
-      case XA_RGB_RED_MAP:
-       *red_max = vinfo->colormap_size - 1;
-       *green_max = *blue_max = 0;
-       break;
-      case XA_RGB_GREEN_MAP:
-       *green_max = vinfo->colormap_size - 1;
-       *red_max = *blue_max = 0;
-       break;
-      case XA_RGB_BLUE_MAP:
-       *blue_max = vinfo->colormap_size - 1;
-       *red_max = *green_max = 0;
-       break;
-      default:
-       status = 0;
-    }
-    return status;
-}
-
-/****************************************************************************/
-/* Determine the appropriate color allocations of a gray scale.
- *
- * Keith Packard, MIT X Consortium
- */
-
-static void
-gray_allocation(int n, unsigned long *red_max, unsigned long *green_max,
-               unsigned long *blue_max)
-{
-    *red_max = (n * 30) / 100;
-    *green_max = (n * 59) / 100; 
-    *blue_max = (n * 11) / 100; 
-    *green_max += ((n - 1) - (*red_max + *green_max + *blue_max));
-}
-
-/****************************************************************************/
-/* Determine an appropriate color allocation for the RGB_DEFAULT_MAP.
- * If a map has less than a minimum number of definable entries, we do not
- * produce an allocation for an RGB_DEFAULT_MAP.  
- *
- * For 16 planes, the default colormap will have 27 each RGB; for 12 planes,
- * 12 each.  For 8 planes, let n = the number of colormap entries, which may
- * be 256 or 254.  Then, maximum red value = floor(cube_root(n - 125)) - 1.
- * Maximum green and maximum blue values are identical to maximum red.
- * This leaves at least 125 cells which clients can allocate.
- *
- * Return 0 if an allocation has been determined, non-zero otherwise.
- */
-
-static int
-default_allocation(XVisualInfo *vinfo, unsigned long *red,
-                  unsigned long *green, unsigned long *blue)
-{
-    int                        ngrays;         /* number of gray cells */
-
-    switch (vinfo->c_class)
-      {
-      case PseudoColor:
-        
-        if (vinfo->colormap_size > 65000)
-          /* intended for displays with 16 planes */
-          *red = *green = *blue = (unsigned long) 27;
-        else if (vinfo->colormap_size > 4000)
-          /* intended for displays with 12 planes */
-           *red = *green = *blue = (unsigned long) 12;
-      else if (vinfo->colormap_size < 250)
-           return 0;
-      else
-           /* intended for displays with 8 planes */
-           *red = *green = *blue = (unsigned long)
-          (icbrt(vinfo->colormap_size - 125) - 1);
-      break;
-      
-    case DirectColor:
-      
-       if (vinfo->colormap_size < 10)
-           return 0;
-       *red = *green = *blue = vinfo->colormap_size / 2 - 1;
-       break;
-
-      case TrueColor:
-
-       *red = vinfo->red_mask / lowbit(vinfo->red_mask);
-       *green = vinfo->green_mask / lowbit(vinfo->green_mask);
-       *blue = vinfo->blue_mask / lowbit(vinfo->blue_mask);
-       break;
-
-      case GrayScale:
-
-       if (vinfo->colormap_size > 65000)
-           ngrays = 4096;
-       else if (vinfo->colormap_size > 4000)
-           ngrays = 512;
-       else if (vinfo->colormap_size < 250)
-           return 0;
-       else
-           ngrays = 12;
-       gray_allocation(ngrays, red, green, blue);
-       break;
-       
-      default:
-       return 0;
-    }
-    return 1;
-}
-
-/****************************************************************************/
-/* Determine an appropriate color allocation for the RGB_BEST_MAP.
- *
- * For a DirectColor or TrueColor visual, the allocation is determined
- * by the red_mask, green_mask, and blue_mask members of the visual info.
- *
- * Otherwise, if the colormap size is an integral power of 2, determine
- * the allocation according to the number of bits given to each color,
- * with green getting more than red, and red more than blue, if there
- * are to be inequities in the distribution.  If the colormap size is
- * not an integral power of 2, let n = the number of colormap entries.
- * Then maximum red value = floor(cube_root(n)) - 1;
- *     maximum blue value = floor(cube_root(n)) - 1;
- *     maximum green value = n / ((# red values) * (# blue values)) - 1;
- * Which, on a GPX, allows for 252 entries in the best map, out of 254
- * defineable colormap entries.
- */
-static void
-best_allocation(XVisualInfo *vinfo, unsigned long *red, unsigned long *green,
-               unsigned long *blue)
-{
-
-    if (vinfo->c_class == DirectColor ||       vinfo->c_class == TrueColor)
-    {
-       *red = vinfo->red_mask;
-       while ((*red & 01) == 0)
-           *red >>= 1;
-       *green = vinfo->green_mask;
-       while ((*green & 01) == 0)
-           *green >>=1;
-       *blue = vinfo->blue_mask;
-       while ((*blue & 01) == 0)
-           *blue >>= 1;
-    }
-    else
-    {
-       register int bits, n;
-       
-       /* Determine n such that n is the least integral power of 2 which is
-        * greater than or equal to the number of entries in the colormap.
-         */
-       n = 1;
-       bits = 0;
-       while (vinfo->colormap_size > n)
-       {
-           n = n << 1;
-           bits++;
-       }
-       
-       /* If the number of entries in the colormap is a power of 2, determine
-        * the allocation by "dealing" the bits, first to green, then red, then
-        * blue.  If not, find the maximum integral red, green, and blue values
-        * which, when multiplied together, do not exceed the number of 
-
-        * colormap entries.
-        */
-       if (n == vinfo->colormap_size)
-       {
-           register int r, g, b;
-           b = bits / 3;
-           g = b + ((bits % 3) ? 1 : 0);
-           r = b + (((bits % 3) == 2) ? 1 : 0);
-           *red = 1 << r;
-           *green = 1 << g;
-           *blue = 1 << b;
-       }
-       else
-       {
-           *red = icbrt_with_bits(vinfo->colormap_size, bits);
-           *blue = *red;       
-           *green = (vinfo->colormap_size / ((*red) * (*blue)));
-       }
-       (*red)--;
-       (*green)--;
-       (*blue)--;
-    }
-    return;
-}
-
-/*
- * integer cube roots by Newton's method
- *
- * Stephen Gildea, MIT X Consortium, July 1991
- */
-
-static int
-icbrt(int a)
-{
-    register int bits = 0;
-    register unsigned n = a;
-
-    while (n)
-    {
-       bits++;
-       n >>= 1;
-    }
-    return icbrt_with_bits(a, bits);
-}
-
-
-static int
-icbrt_with_bits(int a, int bits)
-     /* bits - log 2 of a */
-{
-    return icbrt_with_guess(a, a>>2*bits/3);
-}
-
-#ifdef _X_ROOT_STATS
-int icbrt_loopcount;
-#endif
-
-/* Newton's Method:  x_n+1 = x_n - ( f(x_n) / f'(x_n) ) */
-
-/* for cube roots, x^3 - a = 0,  x_new = x - 1/3 (x - a/x^2) */
-
-/*
- * Quick and dirty cube roots.  Nothing fancy here, just Newton's method.
- * Only works for positive integers (since that's all we need).
- * We actually return floor(cbrt(a)) because that's what we need here, too.
- */
-
-static int
-icbrt_with_guess(int a, int guess)
-{
-    register int delta;
-
-#ifdef _X_ROOT_STATS
-    icbrt_loopcount = 0;
-#endif
-    if (a <= 0)
-       return 0;
-    if (guess < 1)
-       guess = 1;
-
-    do {
-#ifdef _X_ROOT_STATS
-       icbrt_loopcount++;
-#endif
-       delta = (guess - a/(guess*guess))/3;
-#ifdef DEBUG
-       printf("pass %d: guess=%d, delta=%d\n", icbrt_loopcount, guess, delta);
-#endif
-       guess -= delta;
-    } while (delta != 0);
-
-    if (guess*guess*guess > a)
-       guess--;
-
-    return guess;
-}
-
-
-/* $Xorg: StdCmap.c,v 1.4 2001/02/09 02:03:53 xorgcvs Exp $ */
-
-/* 
-
-Copyright 1989, 1998  The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
-
-*/
-/* $XFree86: xc/lib/Xmu/StdCmap.c,v 1.6 2001/12/14 19:55:48 dawes Exp $ */
-
-/*
- * Author:  Donna Converse, MIT X Consortium
- */
-
-#include <stdio.h>
-#include <X11/Xlib.h>
-#include <X11/Xatom.h>
-#include <X11/Xutil.h>
-#include <X11/Xmu/StdCmap.h>
-
-#define lowbit(x) ((x) & (~(x) + 1))
-
-/*
- * Prototypes
- */
-/* argument restrictions */
-static Status valid_args(XVisualInfo*, unsigned long, unsigned long,
-                        unsigned long, Atom);
-
-/*
- * To create any one standard colormap, use XmuStandardColormap().
- *
- * Create a standard colormap for the given screen, visualid, and visual
- * depth, with the given red, green, and blue maximum values, with the
- * given standard property name.  Return a pointer to an XStandardColormap
- * structure which describes the newly created colormap, upon success.
- * Upon failure, return NULL.
- * 
- * XmuStandardColormap() calls XmuCreateColormap() to create the map.
- *
- * Resources created by this function are not made permanent; that is the
- * caller's responsibility.
- */
-
-XStandardColormap *
-XmuStandardColormap(Display *dpy, int screen, VisualID visualid,
-                   unsigned int depth, Atom property, Colormap cmap,
-                   unsigned long red_max, unsigned long green_max,
-                   unsigned long blue_max)
-     /*
-      * dpy                            - specifies X server connection
-      * screen                         - specifies display screen
-      * visualid                       - identifies the visual type
-      * depth                          - identifies the visual type
-      * property                       - a standard colormap property
-      * cmap                           - specifies colormap ID or None
-      * red_max, green_max, blue_max   - allocations
-      */
-{
-    XStandardColormap  *stdcmap;
-    Status             status;
-    XVisualInfo                vinfo_template, *vinfo;
-    long               vinfo_mask;
-    int                        n;
-
-    /* Match the required visual information to an actual visual */
-    vinfo_template.visualid = visualid;        
-    vinfo_template.screen = screen;
-    vinfo_template.depth = depth;
-    vinfo_mask = VisualIDMask | VisualScreenMask | VisualDepthMask;
-    if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &n)) == NULL)
-       return 0;
-
-    /* Check the validity of the combination of visual characteristics,
-     * allocation, and colormap property.  Create an XStandardColormap
-     * structure.
-     */
-
-    if (! valid_args(vinfo, red_max, green_max, blue_max, property)
-       || ((stdcmap = XAllocStandardColormap()) == NULL)) {
-       XFree((char *) vinfo);
-       return 0;
-    }
-
-    /* Fill in the XStandardColormap structure */
-
-    if (cmap == DefaultColormap(dpy, screen)) {
-       /* Allocating out of the default map, cannot use XFreeColormap() */
-       Window win = XCreateWindow(dpy, RootWindow(dpy, screen), 1, 1, 1, 1,
-                                  0, 0, InputOnly, vinfo->visual,
-                                  (unsigned long) 0,
-                                  (XSetWindowAttributes *)NULL);
-       stdcmap->killid  = (XID) XCreatePixmap(dpy, win, 1, 1, depth);
-       XDestroyWindow(dpy, win);
-       stdcmap->colormap = cmap;
-    } else {
-       stdcmap->killid = ReleaseByFreeingColormap;
-       stdcmap->colormap = XCreateColormap(dpy, RootWindow(dpy, screen),
-                                           vinfo->visual, AllocNone);
-    }
-    stdcmap->red_max = red_max;
-    stdcmap->green_max = green_max;
-    stdcmap->blue_max = blue_max;
-    if (property == XA_RGB_GRAY_MAP) 
-       stdcmap->red_mult = stdcmap->green_mult = stdcmap->blue_mult = 1;
-    else if (vinfo->c_class == TrueColor || vinfo->c_class == DirectColor) {
-       stdcmap->red_mult = lowbit(vinfo->red_mask);
-       stdcmap->green_mult = lowbit(vinfo->green_mask);
-       stdcmap->blue_mult = lowbit(vinfo->blue_mask);
-    } else {
-       stdcmap->red_mult = (red_max > 0)
-           ? (green_max + 1) * (blue_max + 1) : 0;
-       stdcmap->green_mult = (green_max > 0) ? blue_max + 1 : 0;
-       stdcmap->blue_mult = (blue_max > 0) ? 1 : 0;
-    }
-    stdcmap->base_pixel = 0;                   /* base pixel may change */
-    stdcmap->visualid = vinfo->visualid;
-
-    /* Make the colormap */
-
-    status = XmuCreateColormap(dpy, stdcmap);
-
-    /* Clean up */
-
-    XFree((char *) vinfo);
-    if (!status) {
-
-       /* Free the colormap or the pixmap, if we created one */
-       if (stdcmap->killid == ReleaseByFreeingColormap)
-           XFreeColormap(dpy, stdcmap->colormap);
-       else if (stdcmap->killid != None)
-           XFreePixmap(dpy, stdcmap->killid);
-       
-       XFree((char *) stdcmap);
-       return (XStandardColormap *) NULL;
-    }
-    return stdcmap;
-}
-
-/****************************************************************************/
-static Status
-valid_args(XVisualInfo *vinfo, unsigned long red_max, unsigned long green_max,
-          unsigned long blue_max, Atom property)
-     /*
-      * vinfo                          - specifies visual
-      * red_max, green_max, blue_max   - specifies alloc
-      * property                       - specifies property name
-      */
-{
-    unsigned long      ncolors;        /* number of colors requested */
-
-    /* Determine that the number of colors requested is <= map size */
-
-    if ((vinfo->c_class == DirectColor) || (vinfo->c_class == TrueColor)) {
-       unsigned long mask;
-
-       mask = vinfo->red_mask;
-       while (!(mask & 1))
-           mask >>= 1;
-       if (red_max > mask)
-           return 0;
-       mask = vinfo->green_mask;
-       while (!(mask & 1))
-           mask >>= 1;
-       if (green_max > mask)
-           return 0;
-       mask = vinfo->blue_mask;
-       while (!(mask & 1))
-           mask >>= 1;
-       if (blue_max > mask)
-           return 0;
-    } else if (property == XA_RGB_GRAY_MAP) {
-       ncolors = red_max + green_max + blue_max + 1;
-       if (ncolors > vinfo->colormap_size)
-           return 0;
-    } else {
-       ncolors = (red_max + 1) * (green_max + 1) * (blue_max + 1);
-       if (ncolors > vinfo->colormap_size)
-           return 0;
-    }
-    
-    /* Determine that the allocation and visual make sense for the property */
-
-    switch (property)
-    {
-      case XA_RGB_DEFAULT_MAP:
-       if (red_max == 0 || green_max == 0 || blue_max == 0)
-           return 0;
-       break;
-      case XA_RGB_RED_MAP:
-       if (red_max == 0)
-           return 0;
-       break;
-      case XA_RGB_GREEN_MAP:
-       if (green_max == 0)
-           return 0;
-       break;
-      case XA_RGB_BLUE_MAP:    
-       if (blue_max == 0)
-           return 0;
-       break;
-      case XA_RGB_BEST_MAP:
-       if (red_max == 0 || green_max == 0 || blue_max == 0)
-           return 0;
-       break;
-      case XA_RGB_GRAY_MAP:
-       if (red_max == 0 || blue_max == 0 || green_max == 0)
-           return 0;
-       break;
-      default:
-       return 0;
-    }
-    return 1;
-}
-
-
-/* $Xorg: CrCmap.c,v 1.4 2001/02/09 02:03:51 xorgcvs Exp $ */
-
-/* 
-
-Copyright 1989, 1998  The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
-
-*/
-/* $XFree86: xc/lib/Xmu/CrCmap.c,v 3.7 2001/12/14 19:55:36 dawes Exp $ */
-
-/*
- * Author:  Donna Converse, MIT X Consortium
- */
-
-/*
- * CreateCmap.c - given a standard colormap description, make the map.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-#include <X11/Xmu/StdCmap.h>
-
-/*
- * Prototypes
- */
-/* allocate entire map Read Only */
-static int ROmap(Display*, Colormap, unsigned long[], int, int);
-
-/* allocate a cell, prefer Read Only */
-static Status ROorRWcell(Display*, Colormap, unsigned long[], int,
-                        XColor*, unsigned long);
-
-/* allocate a cell Read Write */
-static Status RWcell(Display*, Colormap, XColor*, XColor*, unsigned long*);
-
-/* for quicksort */
-static int compare(_Xconst void*, _Xconst void*);
-
-/* find contiguous sequence of cells */
-static Status contiguous(unsigned long[], int, int, unsigned long, int*, int*);
-
-/* frees resources before quitting */
-static void free_cells(Display*, Colormap, unsigned long[], int, int);
-
-/* create a map in a RO visual type */
-static Status readonly_map(Display*, XVisualInfo*, XStandardColormap*);
-
-/* create a map in a RW visual type */
-static Status readwrite_map(Display*, XVisualInfo*, XStandardColormap*);
-
-#define lowbit(x) ((x) & (~(x) + 1))
-#define TRUEMATCH(mult,max,mask) \
-    (colormap->max * colormap->mult <= vinfo->mask && \
-     lowbit(vinfo->mask) == colormap->mult)
-
-/*
- * To create any one colormap which is described by an XStandardColormap
- * structure, use XmuCreateColormap().
- *
- * Return 0 on failure, non-zero on success.
- * Resources created by this function are not made permanent.
- * No argument error checking is provided.  Use at your own risk.
- *
- * All colormaps are created with read only allocations, with the exception
- * of read only allocations of colors in the default map or otherwise
- * which fail to return the expected pixel value, and these are individually 
- * defined as read/write allocations.  This is done so that all the cells
- * defined in the default map are contiguous, for use in image processing.
- * This typically happens with White and Black in the default map.
- *
- * Colormaps of static visuals are considered to be successfully created if
- * the map of the static visual matches the definition given in the
- * standard colormap structure.
- */
-   
-Status
-XmuCreateColormap(Display *dpy, XStandardColormap *colormap)
-     /* dpy     - specifies the connection under which the map is created
-      * colormap - specifies the map to be created, and returns, particularly
-      *                   if the map is created as a subset of the default colormap
-      *                   of the screen, the base_pixel of the map.
-                                        */
-{
-    XVisualInfo                vinfo_template; /* template visual information */
-    XVisualInfo                *vinfo;         /* matching visual information */
-    XVisualInfo                *vpointer;      /* for freeing the entire list */
-    long               vinfo_mask;     /* specifies the visual mask value */
-    int                n;              /* number of matching visuals */
-    int                        status;         
-
-    vinfo_template.visualid = colormap->visualid;
-    vinfo_mask = VisualIDMask;
-    if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &n)) == NULL)
-       return 0;
-
-    /* A visual id may be valid on multiple screens.  Also, there may 
-     * be multiple visuals with identical visual ids at different depths.  
-     * If the colormap is the Default Colormap, use the Default Visual.
-     * Otherwise, arbitrarily, use the deepest visual.
-     */
-    vpointer = vinfo;
-    if (n > 1)
-    {
-       register int    i;
-       register int    screen_number;
-       Bool            def_cmap;
-
-       def_cmap = False;
-       for (screen_number = ScreenCount(dpy); --screen_number >= 0; )
-           if (colormap->colormap == DefaultColormap(dpy, screen_number)) {
-               def_cmap = True;
-               break;
-           }
-
-       if (def_cmap) {
-           for (i=0; i < n; i++, vinfo++) {
-               if (vinfo->visual == DefaultVisual(dpy, screen_number))
-                       break;
-           }
-       } else {
-           int                 maxdepth = 0;
-           XVisualInfo         *v = NULL;
-
-           for (i=0; i < n; i++, vinfo++)
-               if (vinfo->depth > maxdepth) {
-                   maxdepth = vinfo->depth;
-                   v = vinfo;
-               }
-           vinfo = v;
-       }
-    }
-
-    if (vinfo->c_class == PseudoColor || vinfo->c_class == DirectColor ||
-       vinfo->c_class == GrayScale)
-       status = readwrite_map(dpy, vinfo, colormap);
-    else if (vinfo->c_class == TrueColor)
-       status = TRUEMATCH(red_mult, red_max, red_mask) &&
-                TRUEMATCH(green_mult, green_max, green_mask) &&
-                TRUEMATCH(blue_mult, blue_max, blue_mask);
-    else 
-       status = readonly_map(dpy, vinfo, colormap);
-    
-    XFree((char *) vpointer);
-    return status;
-}
-
-/****************************************************************************/
-static Status
-readwrite_map(Display *dpy, XVisualInfo *vinfo, XStandardColormap *colormap)
-{
-    register unsigned long i, n;       /* index counters */
-    unsigned long      ncolors;        /* number of colors to be defined */
-    int                        npixels;        /* number of pixels allocated R/W */
-    int                        first_index;    /* first index of pixels to use */
-    int                        remainder;      /* first index of remainder */
-    XColor             color;          /* the definition of a color */
-    unsigned long      *pixels;        /* array of colormap pixels */
-    unsigned long      delta;
-
-    
-    /* Determine ncolors, the number of colors to be defined.
-     * Insure that 1 < ncolors <= the colormap size.
-     */
-    if (vinfo->c_class == DirectColor) {
-       ncolors = colormap->red_max;
-       if (colormap->green_max > ncolors)
-           ncolors = colormap->green_max;
-       if (colormap->blue_max > ncolors)
-           ncolors = colormap->blue_max;
-       ncolors++;
-       delta = lowbit(vinfo->red_mask) +
-               lowbit(vinfo->green_mask) +
-               lowbit(vinfo->blue_mask);
-    } else {
-       ncolors = colormap->red_max * colormap->red_mult +
-                 colormap->green_max * colormap->green_mult +
-                 colormap->blue_max * colormap->blue_mult + 1;
-       delta = 1;
-    }
-    if (ncolors <= 1 || (int) ncolors > vinfo->colormap_size)  return 0;
-
-    /* Allocate Read/Write as much of the colormap as we can possibly get.
-     * Then insure that the pixels we were allocated are given in 
-     * monotonically increasing order, using a quicksort.  Next, insure
-     * that our allocation includes a subset of contiguous pixels at least
-     * as long as the number of colors to be defined.  Now we know that 
-     * these conditions are met:
-     * 1) There are no free cells in the colormap.
-     *  2) We have a contiguous sequence of pixels, monotonically 
-     *     increasing, of length >= the number of colors requested.
-     *
-     * One cell at a time, we will free, compute the next color value, 
-     * then allocate read only.  This takes a long time.
-     * This is done to insure that cells are allocated read only in the
-     * contiguous order which we prefer.  If the server has a choice of
-     * cells to grant to an allocation request, the server may give us any
-     * cell, so that is why we do these slow gymnastics.
-     */
-
-    if ((pixels = (unsigned long *) calloc((unsigned) vinfo->colormap_size,
-                                     sizeof(unsigned long))) == NULL)
-       return 0;
-
-    if ((npixels = ROmap(dpy, colormap->colormap, pixels,
-                          vinfo->colormap_size, ncolors)) == 0) {
-       free((char *) pixels);
-       return 0;
-    }
-
-    qsort((char *) pixels, npixels, sizeof(unsigned long), compare);
-
-    if (!contiguous(pixels, npixels, ncolors, delta, &first_index, &remainder))
-    {
-       /* can't find enough contiguous cells, give up */
-       XFreeColors(dpy, colormap->colormap, pixels, npixels,
-                   (unsigned long) 0);
-       free((char *) pixels);
-       return 0;
-    }
-    colormap->base_pixel = pixels[first_index];
-
-    /* construct a gray map */
-    if (colormap->red_mult == 1 && colormap->green_mult == 1 &&
-       colormap->blue_mult == 1)
-       for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
-       {
-           color.pixel = n;
-           color.blue = color.green = color.red =
-               (unsigned short) ((i * 65535) / (colormap->red_max +
-                                                colormap->green_max +
-                                                colormap->blue_max));
-
-           if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
-                            first_index + i))
-               return 0;
-       }
-
-    /* construct a red ramp map */
-    else if (colormap->green_max == 0 && colormap->blue_max == 0)
-       for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
-       {
-           color.pixel = n;
-           color.red = (unsigned short) ((i * 65535) / colormap->red_max);
-           color.green = color.blue = 0;
-
-           if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
-                            first_index + i))
-               return 0;
-       }
-
-    /* construct a green ramp map */
-    else if (colormap->red_max == 0 && colormap->blue_max == 0)
-       for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
-       {
-           color.pixel = n;
-           color.green = (unsigned short) ((i * 65535) / colormap->green_max);
-           color.red = color.blue = 0;
-
-           if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
-                            first_index + i))
-               return 0;
-       }
-
-    /* construct a blue ramp map */
-    else if (colormap->red_max == 0 && colormap->green_max == 0)
-       for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
-       {
-           color.pixel = n;
-           color.blue = (unsigned short) ((i * 65535) / colormap->blue_max);
-           color.red = color.green = 0;
-
-           if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
-                            first_index + i))
-               return 0;
-       }
-
-    /* construct a standard red green blue cube map */
-    else
-    {
-#define calc(max,mult) (((n / colormap->mult) % \
-                        (colormap->max + 1)) * 65535) / colormap->max
-
-       for (n=0, i=0; i < ncolors; i++, n += delta)
-       {
-           color.pixel = n + colormap->base_pixel;
-           color.red = calc(red_max, red_mult);
-           color.green = calc(green_max, green_mult);
-           color.blue = calc(blue_max, blue_mult);
-           if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
-                            first_index + i))
-               return 0;
-       }
-#undef calc
-    }
-    /* We have a read-only map defined.  Now free unused cells,
-     * first those occuring before the contiguous sequence begins,
-     * then any following the contiguous sequence.
-     */
-
-    if (first_index)
-       XFreeColors(dpy, colormap->colormap, pixels, first_index, 
-                   (unsigned long) 0);
-    if (remainder)
-       XFreeColors(dpy, colormap->colormap,
-                   &(pixels[first_index + ncolors]), remainder,
-                   (unsigned long) 0);
-
-    free((char *) pixels);
-    return 1;
-}
-
-
-/****************************************************************************/
-static int
-ROmap(Display *dpy, Colormap cmap, unsigned long pixels[], int m, int n)
-     /*
-      * dpy    - the X server connection
-      * cmap   - specifies colormap ID
-      * pixels - returns pixel allocations
-      * m      - specifies colormap size
-      * n      - specifies number of colors
-      */
-{
-    register int       p;
-
-    /* first try to allocate the entire colormap */
-    if (XAllocColorCells(dpy, cmap, 1, (unsigned long *) NULL, 
-                        (unsigned) 0, pixels, (unsigned) m))
-       return m;
-
-    /* Allocate all available cells in the colormap, using a binary
-     * algorithm to discover how many cells we can allocate in the colormap.
-     */
-    m--;
-    while (n <= m) {
-       p = n + ((m - n + 1) / 2);
-       if (XAllocColorCells(dpy, cmap, 1, (unsigned long *) NULL,
-                            (unsigned) 0, pixels, (unsigned) p)) {
-           if (p == m)
-               return p;
-           else {
-               XFreeColors(dpy, cmap, pixels, p, (unsigned long) 0);
-               n = p;
-           }
-       }
-       else
-           m = p - 1;
-    }
-    return 0;
-}
-      
-
-/****************************************************************************/
-static Status
-contiguous(unsigned long pixels[], int npixels, int ncolors,
-          unsigned long delta, int *first, int *rem)
-     /* pixels - specifies allocated pixels
-      * npixels        - specifies count of alloc'd pixels
-      * ncolors - specifies needed sequence length
-      * delta  - between pixels
-      * first  - returns first index of sequence
-      * rem    - returns first index after sequence, or 0, if none follow
-      */
-{
-    register int i = 1;                /* walking index into the pixel array */
-    register int count = 1;    /* length of sequence discovered so far */
-
-    *first = 0;
-    if (npixels == ncolors) {
-       *rem = 0;
-       return 1;
-    }
-    *rem = npixels - 1;
-    while (count < ncolors && ncolors - count <= *rem)
-    {
-       if (pixels[i-1] + delta == pixels[i])
-           count++;
-       else {
-           count = 1;
-           *first = i;
-       }
-       i++;
-       (*rem)--;
-    }
-    if (count != ncolors)
-       return 0;
-    return 1;
-}
-
-
-/****************************************************************************/
-static Status
-ROorRWcell(Display *dpy, Colormap cmap, unsigned long pixels[],
-          int npixels, XColor *color, unsigned long p)
-{
-    unsigned long      pixel;
-    XColor             request;
-
-    /* Free the read/write allocation of one cell in the colormap.
-     * Request a read only allocation of one cell in the colormap.
-     * If the read only allocation cannot be granted, give up, because
-     * there must be no free cells in the colormap.
-     * If the read only allocation is granted, but gives us a cell which
-     * is not the one that we just freed, it is probably the case that
-     * we are trying allocate White or Black or some other color which
-     * already has a read-only allocation in the map.  So we try to 
-     * allocate the previously freed cell with a read/write allocation,
-     * because we want contiguous cells for image processing algorithms.
-     */
-     
-    pixel = color->pixel;
-    request.red = color->red;
-    request.green = color->green;
-    request.blue = color->blue;
-
-    XFreeColors(dpy, cmap, &pixel, 1, (unsigned long) 0);
-    if (! XAllocColor(dpy, cmap, color) 
-       || (color->pixel != pixel &&
-           (!RWcell(dpy, cmap, color, &request, &pixel)))) 
-    {
-       free_cells(dpy, cmap, pixels, npixels, (int)p);
-       return 0;
-    }
-    return 1;
-}
-
-
-/****************************************************************************/
-static void
-free_cells(Display *dpy, Colormap cmap, unsigned long pixels[],
-          int npixels, int p)
-     /*
-      * pixels - to be freed
-      *        npixels - original number allocated
-      */
-{
-    /* One of the npixels allocated has already been freed.
-     * p is the index of the freed pixel.
-     * First free the pixels preceeding p, and there are p of them;
-     * then free the pixels following p, there are npixels - p - 1 of them.
-     */
-    XFreeColors(dpy, cmap, pixels, p, (unsigned long) 0);
-    XFreeColors(dpy, cmap, &(pixels[p+1]), npixels - p - 1, (unsigned long) 0);
-    free((char *) pixels);
-}
-
-
-/****************************************************************************/
-static Status
-RWcell(Display *dpy, Colormap cmap, XColor *color, XColor *request,
-       unsigned long *pixel)
-{
-    unsigned long      n = *pixel;
-
-    XFreeColors(dpy, cmap, &(color->pixel), 1, (unsigned long)0);
-    if (! XAllocColorCells(dpy, cmap, (Bool) 0, (unsigned long *) NULL,
-                          (unsigned) 0, pixel, (unsigned) 1))
-       return 0;
-    if (*pixel != n)
-    {
-       XFreeColors(dpy, cmap, pixel, 1, (unsigned long) 0);
-       return 0;
-    }
-    color->pixel = *pixel;
-    color->flags = DoRed | DoGreen | DoBlue;
-    color->red = request->red;
-    color->green = request->green;
-    color->blue = request->blue;
-    XStoreColors(dpy, cmap, color, 1);
-    return 1;
-}
-
-
-/****************************************************************************/
-static int
-compare(_Xconst void *e1, _Xconst void *e2)
-{
-  return ((int)(*(long *)e1 - *(long *)e2));
-}
-
-
-/****************************************************************************/
-static Status
-readonly_map(Display *dpy, XVisualInfo *vinfo, XStandardColormap *colormap)
-{
-    int                        i, last_pixel;
-    XColor             color;
-
-    last_pixel = (colormap->red_max + 1) * (colormap->green_max + 1) * 
-       (colormap->blue_max + 1) + colormap->base_pixel - 1;
-
-    for(i=colormap->base_pixel; i <= last_pixel; i++) {
-
-       color.pixel = (unsigned long) i;
-       color.red = (unsigned short)
-           (((i/colormap->red_mult) * 65535) / colormap->red_max);
-
-       if (vinfo->c_class == StaticColor) {
-           color.green = (unsigned short)
-               ((((i/colormap->green_mult) % (colormap->green_max + 1)) *
-                 65535) / colormap->green_max);
-           color.blue = (unsigned short)
-               (((i%colormap->green_mult) * 65535) / colormap->blue_max);
-       }
-       else    /* vinfo->c_class == GrayScale, old style allocation XXX */
-           color.green = color.blue = color.red;
-
-       XAllocColor(dpy, colormap->colormap, &color);
-       if (color.pixel != (unsigned long) i)
-           return 0;
-    }
-    return 1;
-}
-
-
-/* $Xorg: DelCmap.c,v 1.4 2001/02/09 02:03:52 xorgcvs Exp $ */
-
-/* 
-Copyright 1989, 1998  The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
-
-*/
-/* $XFree86: xc/lib/Xmu/DelCmap.c,v 1.7 2001/12/14 19:55:40 dawes Exp $ */
-
-/*
- * Author:  Donna Converse, MIT X Consortium
- */
-
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-#include <X11/Xmu/StdCmap.h>
-
-int ignoreErrorHandler(Display* d, XErrorEvent* e) { }
-
-/* To remove any standard colormap property, use XmuDeleteStandardColormap().
- * XmuDeleteStandardColormap() will remove the specified property from the
- * specified screen, releasing any resources used by the colormap(s) of the
- * property if possible.
- */
-
-void
-XmuDeleteStandardColormap(Display *dpy, int screen, Atom property)
-     /* dpy;           - specifies the X server to connect to
-      * screen         - specifies the screen of the display
-      * property       - specifies the standard colormap property
-      */
-{
-    XStandardColormap  *stdcmaps, *s;
-    int                        count = 0;
-
-    if (XGetRGBColormaps(dpy, RootWindow(dpy, screen), &stdcmaps, &count,
-                         property))
-        {
-            for (s=stdcmaps; count > 0; count--, s++) {
-                if ((s->killid == ReleaseByFreeingColormap) &&
-                    (s->colormap != None) &&
-                    (s->colormap != DefaultColormap(dpy, screen))) {
-
-                    // UGLY HACK written in by Adam Megacz -- sometimes s->colormap isn't valid, so we do some shuffling
-                    X11ErrorHandler* oldHandler = XSetErrorHandler(ignoreErrorHandler);
-                    XSync(dpy, False);
-                    XFreeColormap(dpy, s->colormap);
-                    XSync(dpy, False);
-                    XSetErrorHandler(oldHandler);
-                    XSync(dpy, False);
-
-                } else if (s->killid != None) {
-                    XKillClient(dpy, s->killid);
-                }
-            }
-            XDeleteProperty(dpy, RootWindow(dpy, screen), property);
-            XFree((char *) stdcmaps);
-            XSync(dpy, False);
-        }
-}
-
index e47cc9b..1733572 100644 (file)
@@ -12,45 +12,12 @@ import java.awt.peer.*;
 import org.xwt.util.*;
 import org.xwt.*;
 
-/** Platform implementation for POSIX compliant operating systems with an X11 Server */
+/** Platform implementation for POSIX compliant operating systems */
 public class POSIX extends GCJ {
 
-    // Static Data ///////////////////////////////////////////////////////////
-
-    /**
-     *  When the user reads from the clipboard, the main thread blocks
-     *  on this semaphore until we get an X11 SelectionNotify. Crude,
-     *  but effective. We know that only one thread will ever block on
-     *  this, since only one thread can ever be running JavaScript.
-     */
-    public static Semaphore waiting_for_selection_event = new Semaphore();
-
-    /** our local (in-process) copy of the clipboard */
-    public static String clipboard = null;
-
-    /** map from Window's (casted to jlong, wrapped in java.lang.Long) to X11Surface objects */
-    public static Hashtable windowToSurfaceMap = new Hashtable();
-
-
     // General Methods ///////////////////////////////////////////////////////
 
-    protected String _getAltKeyName() { return System.getProperty("os.name", "").indexOf("SunOS") != -1 ? "Meta" : "Alt"; }
-    protected String[] _listFonts() { return fontList; }
     protected String getDescriptiveName() { return "GCJ Linux Binary"; }
-    protected Picture _createPicture(int[] data, int w, int h) { return new POSIX.X11Picture(data, w, h); }
-    protected DoubleBuffer _createDoubleBuffer(int w, int h, Surface owner) { return new POSIX.X11DoubleBuffer(w, h); }
-    protected Surface _createSurface(Box b, boolean framed) { return new X11Surface(b, framed); }
-    protected boolean _needsAutoClick() { return true; }
-    protected native int _getScreenWidth();
-    protected native int _getScreenHeight();
-    protected native String _getClipBoard();
-    protected native void _setClipBoard(String s);
-    protected native int _stringWidth(String font, String text);
-    protected native int _getMaxAscent(String font);
-    protected native int _getMaxDescent(String font);
-    protected boolean _needsAutoDoubleClick() { return true; }
-    protected native void eventThread();
-    private native void natInit();
 
     /** returns the value of the environment variable key, or null if no such key exists */
     protected native String _getEnv(String key);
@@ -81,300 +48,9 @@ public class POSIX extends GCJ {
     }
 
     public POSIX() { }
-    public void init() {
-        natInit();
-        (new Thread() { public void run() { eventThread(); } }).start();
-        initFonts();
-    }
-
-    // X11Surface /////////////////////////////////////////////////////
-
-    /** Implements a Surface as an X11 Window */
-    public static class X11Surface extends Surface {
-        
-        gnu.gcj.RawData window;
-        gnu.gcj.RawData gc;
-        boolean framed = false;
-        Semaphore waitForCreation = new Semaphore();
-        
-        public native void setInvisible(boolean i);
-        public void _setMaximized(boolean m) { if (Log.on) Log.log(this, "POSIX/X11 can't maximize windows"); }
-        public native void setIcon(Picture p);
-        public native void _setMinimized(boolean b);
-        public native void setTitleBarText(String s);
-        public native void setSize(int w, int h);
-        public native void setLocation(int x, int y);
-        public native void natInit();
-        public native void toFront();
-        public native void toBack();
-        public native void syncCursor();
-        public native void _dispose();
-        public native void setLimits(int minw, int minh, int maxw, int maxh);
-        public native void blit(DoubleBuffer s, int sx, int sy, int dx, int dy, int dx2, int dy2);
-        public native void dispatchEvent(gnu.gcj.RawData ev);
-
-        public X11Surface(Box root, boolean framed) {
-            super(root);
-            this.framed = framed;
-            natInit();
-        }        
-    
-    }
-
-
-    // Our Subclass of Picture ///////////////////////////////////////////////
-
-    /**
-     *  Implements a Picture. No special X11 structure is created
-     *  unless the image has no alpha (in which case a
-     *  non-shared-pixmap DoubleBuffer is created), or all-or-nothing
-     *  alpha (in which case a non-shared-pixmap DoubleBuffer with a
-     *  stipple bitmap is created).
-     */
-    public static class X11Picture implements Picture {
-        
-        int width;
-        int height;
-        int[] data = null;
-        public X11DoubleBuffer doublebuf = null;
-
-        public int getWidth() { return width; }
-        public int getHeight() { return height; }
-
-        public X11Picture(int[] data, int w, int h) {
-            this.data = data;
-            this.width = w;
-            this.height = h;
-            boolean needsStipple = false;
-
-            // if we have any non-0x00, non-0xFF alphas, we can't double buffer ourselves
-            for(int i=0; i<w*h; i++)
-                if ((data[i] & 0xFF000000) == 0xFF000000)
-                    needsStipple = true;
-                else if ((data[i] & 0xFF000000) != 0x00)
-                    return;
-
-            buildDoubleBuffer(needsStipple);
-        }
-
-        void buildDoubleBuffer(boolean needsStipple) {
-            if (doublebuf != null) return;
-            // no point in using a shared pixmap since we'll only write to this image once
-            X11DoubleBuffer b = new X11DoubleBuffer(width, height, false);
-            b.drawPicture(this, 0, 0);
-            if (needsStipple) b.createStipple(this);
-            doublebuf = b;
-        }
-
-    }
-
-    /**
-     *  An X11DoubleBuffer is implemented as an X11 pixmap. "Normal"
-     *  DoubleBuffers will use XShm shared pixmaps if
-     *  available. X11DoubleBuffers created to accelerate Pictures
-     *  with all-or-nothing alpha will not use shared pixmaps, however
-     *  (since they are only written to once.
-     */
-    public static class X11DoubleBuffer implements DoubleBuffer {
-
-        int clipx, clipy, clipw, cliph;
-        int width;
-        int height;
-
-        /** DoubleBuffers of X11Pictures can have stipples -- the stipple of the Picture */
-        RawData stipple = null;
-
-        /** Sets the DoubleBuffer's internal stipple to the alpha==0x00 regions of xpi */
-        public native void createStipple(X11Picture xpi);
-        
-        RawData pm;                    // Pixmap (if any) representing this Picture
-        boolean shared_pixmap = false; // true if pm is a ShmPixmap
-        RawData fake_ximage = null;    // a 'fake' XImage corresponding to the shared pixmap; gives us the address and depth parameters
-        RawData shm_segment = null;    // XShmSegmentInfo
-
-        RawData gc;                    // Graphics Context on pm (never changes, so it's fast)
-        RawData clipped_gc;            // Graphics Context on pm, use this one if you need a clip/stipple
-
-        /** DoubleBuffer mode */
-        public X11DoubleBuffer(int w, int h) { this(w, h, true); }
-        public X11DoubleBuffer(int w, int h, boolean shared_pixmap) {
-            width = clipw = w;
-            height = cliph = h;
-            clipx = clipy = 0;
-            this.shared_pixmap = shared_pixmap;
-            natInit();
-        }
-
-        public void setClip(int x, int y, int x2, int y2) {
-            clipx = x; if (clipx < 0) clipx = 0;
-            clipy = y; if (clipy < 0) clipy = 0;
-            clipw = x2 - x; if (clipw < 0) clipw = 0;
-            cliph = y2 - y; if (cliph < 0) cliph = 0;
-        }
-        
-        public void drawPicture(Picture source, int x, int y) {
-            drawPicture(source, x, y, x + source.getWidth(), y + source.getHeight(), 0, 0, source.getWidth(), source.getHeight());
-        }
-
-        public void drawPicture(Picture source, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2) {
-            if (!(dx2 - dx1 != sx2 - sx1 || dy2 - dy1 != sy2 - sy1) && ((X11Picture)source).doublebuf != null)
-                fastDrawPicture(source, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2);
-            else 
-                slowDrawPicture(source, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2);
-        }
-
-        /** fast path for image drawing (no scaling, all-or-nothing alpha) */
-        public native void fastDrawPicture(Picture source, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2);
-
-        /** slow path for image drawing */
-        public native void slowDrawPicture(Picture source, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2);
-
-        public int getWidth() { return width; }
-        public int getHeight() { return height; }
-        public native void natInit();
-        public native void fillRect(int x, int y, int x2, int y2, int color);
-        public native void drawString(String font, String text, int x, int y, int color);
-        public native void finalize();
-
-    }
-
-
-    // Font Handling ////////////////////////////////////////////////////////////////////
-
-    static String[] fontList = null;
-
-    /** hashtable of all built in X11 fonts; key is XWT font spec, value is X11 font string */
-    static Hashtable nativeFontList = new Hashtable();
-
-    /** cache of all already-looked-up X11 fonts; key is XWT font name, value is a WrappedRawData */
-    static Hashtable xwtFontToFontStruct = new Hashtable();
-
-    /** dumps a list of X11 font strings */
-    private native String[] listNativeFonts();
-
-    /** load native font list */
-    public void initFonts() {
-        // use the font list to build nativeFontList
-        String[] fonts = listNativeFonts();
+    public void init() { }
 
-        Vector v = new Vector();
-        for(int k=0; k<fonts.length; k++) {
-
-            String s = fonts[k].toLowerCase();
-            String s2 = s;
-            try {
-                v.setSize(0);
-                s = s.substring(s.indexOf('-') + 1);
-                while (s.indexOf('-') != -1) {
-                    v.addElement(s.substring(0, s.indexOf('-')));
-                    s = s.substring(s.indexOf('-') + 1);
-                }
-                v.addElement(s);
-                String[] font = new String[v.size()];
-                v.copyInto(font);
-
-                // limit to iso8559 until we can do I18N properly....
-                if (font.length > 12) {
-                    if (!font[12].equals("iso8859") && !font[12].equals("")) continue;
-                    if (font.length < 14 || !font[13].equals("1")) continue;
-                }
-
-                String name = font[1];
-                String size = font[6];
-                String slant = (font[3].equals("i") || font[3].equals("o")) ? "i" : "";
-                String bold = font[2].equals("bold") ? "b" : "";
-                String tail = s2.substring(1 + font[0].length() + 1 + font[1].length() + 1 + font[2].length() + 1 +
-                                           font[3].length() + 1 + font[4].length() + 1);
-                
-                if (bold.equals("*") && slant.equals("*")) {
-                    nativeFontList.put(name + size, font[0] + "-" + font[1] + "-regular-r-" + font[4] + "-" + tail);
-                    nativeFontList.put(name + size + "b", font[0] + "-" + font[1] + "-bold-r-" + font[4] + "-" + tail);
-                    nativeFontList.put(name + size + "i", font[0] + "-" + font[1] + "-regular-i-" + font[4] + "-" + tail);
-                    nativeFontList.put(name + size + "bi", font[0] + "-" + font[1] + "-bold-i-" + font[4] + "-" + tail);
-                    
-                } else if (bold.equals("*")) {
-                    nativeFontList.put(name + size + slant, font[0] + "-" + font[1] + "-regular-" + font[3] + "-" + font[4] + "-" + tail);
-                    nativeFontList.put(name + size + "b" + slant, font[0] + "-" + font[1] + "-bold-" + font[3] + "-" + font[4] + "-" + tail);
-                    
-                } else if (slant.equals("*")) {
-                    nativeFontList.put(name + size + bold, font[0] + "-" + font[1] + "-" + font[2] + "-r-" + font[4] + "-" + tail);
-                    nativeFontList.put(name + size + bold + "i", font[0] + "-" + font[1] + "-" + font[2] + "-i-" + font[4] + "-" + tail);
-                    
-                } else {
-                    nativeFontList.put(name + size + bold + slant, s2);
-                    
-                }
-            } catch (ArrayIndexOutOfBoundsException e) {
-                if (Log.on) Log.log(this, "skipping incomplete font string " + s2);
-                continue;
-            }
-        }
-        fontList = new String[nativeFontList.size()];
-        Enumeration e = nativeFontList.keys();
-        for(int i=0; e.hasMoreElements(); i++) fontList[i] = (String)e.nextElement();
-    }
-
-    /** so we can put XFontStruct's into Hashtables */
-    private static class WrappedRawData {
-        public RawData wrapee = null;
-        public WrappedRawData(RawData r) { wrapee = r; }
-    }
-
-    /** translates an X11 font string into an XFontStruct* */
-    public static native gnu.gcj.RawData fontStringToStruct(String s);
+}
 
-    /** translates an XWT font string into an XFontStruct*, performing caching as well */
-    public static RawData fontToXFont(String s) {
-        if (s == null) s = "sansserif";
-        s = s.toLowerCase();
-        
-        WrappedRawData wrap = (WrappedRawData)xwtFontToFontStruct.get(s);
-        if (wrap != null) return wrap.wrapee;
 
-        String bestmatch = "";
-        int metric = -1 * Integer.MAX_VALUE;
-        ParsedFont arg = new ParsedFont(s);
-        ParsedFont pf = new ParsedFont();
 
-        if (arg.size == -1) arg.size = 10;
-        Enumeration e = nativeFontList.keys();
-        while(e.hasMoreElements()) {
-            String jfont = (String)e.nextElement();
-            pf.parse(jfont);
-            int thismetric = 0;
-            if (!pf.name.equals(arg.name)) {
-                if (pf.name.equals("lucidabright") && arg.name.equals("serif")) thismetric -= 1000;
-                else if (pf.name.equals("times") && arg.name.equals("serif")) thismetric -= 2000;
-                else if (pf.name.equals("helvetica") && arg.name.equals("sansserif")) thismetric -= 1000;
-                else if (pf.name.equals("courier") && arg.name.equals("monospaced")) thismetric -= 1000;
-                else if (pf.name.equals("lucida") && arg.name.equals("dialog")) thismetric -= 1000;
-                else if (pf.name.equals("helvetica") && arg.name.equals("dialog")) thismetric -= 2000;
-                else if (pf.name.equals("fixed") && arg.name.equals("tty")) thismetric -= 1000;
-                else if (pf.name.equals("sansserif")) thismetric -= 4000;
-                else thismetric -= 4004;
-            }
-            if (pf.size != 0) thismetric -= Math.abs(pf.size - arg.size) * 4;
-            if (pf.bold != arg.bold) thismetric -= 1;
-            if (pf.italic != arg.italic) thismetric -= 1;
-            if (thismetric > metric) {
-                metric = thismetric;
-                bestmatch = jfont;
-            }
-        }
-        
-        pf.parse(bestmatch);
-        String target = (String)nativeFontList.get(bestmatch);
-        if (pf.size == 0) {
-            int i = 0;
-            for(int j=0; j<6; j++) i = target.indexOf('-', i + 1);
-            target = target.substring(0, i + 1) + arg.size + target.substring(target.indexOf('-', i+1));
-        }
-        if (Log.on) Log.log(POSIX.class, "mapping font \"" + s + "\" to \"" + target + "\"");
-        RawData ret = fontStringToStruct(target);
-        if (ret == null) ret = fontStringToStruct("fixed");
-        xwtFontToFontStruct.put(s, new WrappedRawData(ret));
-        return ret;
-    }
-
-
-}
diff --git a/src/org/xwt/plat/X11.cc b/src/org/xwt/plat/X11.cc
new file mode 100644 (file)
index 0000000..9fd2ac3
--- /dev/null
@@ -0,0 +1,2357 @@
+// Copyright 2002 Adam Megacz, see the COPYING file for licensing [LGPL]
+// see below for copyright information on the second portion of this file
+
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <X11/Xlib.h>
+#include <X11/extensions/XShm.h>
+#include <X11/keysymdef.h>
+#include <X11/keysym.h>
+#include <X11/cursorfont.h>
+#include <X11/Xutil.h>
+#include <X11/Xatom.h>
+#include <X11/Xmu/StdCmap.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <gcj/cni.h>
+#include <signal.h>
+
+#include <java/lang/String.h>
+#include <org/xwt/Surface.h>
+#include <org/xwt/Picture.h>
+#include <org/xwt/Box.h>
+#include <org/xwt/plat/X11.h>
+#include <org/xwt/plat/X11$X11Surface.h>
+#include <org/xwt/plat/X11$X11Picture.h>
+#include <org/xwt/plat/X11$X11DoubleBuffer.h>
+#include <org/xwt/util/Semaphore.h>
+#include <org/xwt/Platform.h>
+#include <java/lang/Long.h>
+#include <java/util/Hashtable.h>
+#include <org/xwt/util/Log.h>
+
+#include <java/lang/System.h>
+#include <java/io/PrintStream.h>
+
+// static (per-xserver) data
+static Visual* visual;
+static Colormap s_colormap;
+static XStandardColormap* colormap_info;
+static XShmSegmentInfo shm_info;
+static Window selectionWindow;
+static int shm_supported;
+static int shm_pixmaps_supported;
+static int screen_num;
+static int colorDepth = 0;
+static Display* display;
+static int shm_size = 0;
+
+#define min(a, b) ((a) < (b) ? (a) : (b))
+#define max(a, b) ((a) < (b) ? (b) : (a))
+
+// X11DoubleBuffer //////////////////////////////////////////////////////////////////////
+
+// ensures that the shared memory is at least size bytes; if not, allocates 3/2 * size
+static void ensureShmSize(int size) {
+    if (size > shm_size) {
+        if (shm_size > 0) {
+            XShmDetach(display, &shm_info);
+            shmdt(shm_info.shmaddr);
+            shmctl(shm_info.shmid, IPC_RMID, 0);
+        }
+        shm_size = 3 * size / 2;
+        shm_info.shmid = shmget(IPC_PRIVATE, shm_size, IPC_CREAT | 0777 | IPC_EXCL);
+        shm_info.shmaddr = (char*)shmat(shm_info.shmid, 0, 0);
+        shm_info.readOnly = False;
+        XSync(display, False);
+        shmctl(shm_info.shmid, IPC_RMID, 0);
+        XShmAttach(display, &shm_info);
+        XSync(display, False);
+    }
+}
+
+void org::xwt::plat::X11$X11DoubleBuffer::fastDrawPicture(org::xwt::Picture* s,
+                                                            jint dx1, jint dy1, jint dx2, jint dy2, jint sx1, jint sy1, jint sx2, jint sy2) {
+    org::xwt::plat::X11$X11Picture* source = (org::xwt::plat::X11$X11Picture*)s;
+
+    // it's safe to clip manually since we no that no scaling will be done
+    if (dx1 < clipx) { sx1 += ((clipx - dx1) * (sx2 - sx1)) / (dx2 - dx1); dx1 = clipx; }
+    if (dy1 < clipy) { sy1 += ((clipy - dy1) * (sy2 - sy1)) / (dy2 - dy1); dy1 = clipy; }
+    if (dx2 > clipx + clipw) { sx2 -= ((dx2 - clipx - clipw) * (sx2 - sx1)) / (dx2 - dx1); dx2 = clipx + clipw; }
+    if (dy2 > clipy + cliph) { sy2 -= ((dy2 - clipy - cliph) * (sy2 - sy1)) / (dy2 - dy1); dy2 = clipy + cliph; }
+    if (dx1 > clipx + clipw) return;
+    if (dy1 > clipy + cliph) return;
+    if (dx2 - dx1 <= 0 || dy2 - dy1 <= 0) return;
+    
+    if (source->doublebuf->stipple != NULL) {
+        XSetClipMask(display, (*((GC*)clipped_gc)), *((Pixmap*)source->doublebuf->stipple));
+        XSetClipOrigin(display, (*((GC*)clipped_gc)), dx1 - sx1, dy1 - sy1);
+    } else {
+        XSetClipMask(display, (*((GC*)clipped_gc)), None);
+    }
+    XCopyArea(display, *((Pixmap*)source->doublebuf->pm), (*((Pixmap*)pm)), (*((GC*)clipped_gc)), sx1, sy1, sx2 - sx1, sy2 - sy1, dx1, dy1);
+}
+
+void org::xwt::plat::X11$X11DoubleBuffer::slowDrawPicture(org::xwt::Picture* s,
+                                                            jint dx1, jint dy1, jint dx2, jint dy2, jint sx1, jint sy1, jint sx2, jint sy2) {
+
+    org::xwt::plat::X11$X11Picture* source = (org::xwt::plat::X11$X11Picture*)s;
+    XImage* xi; 
+
+    // FASTEST: shared pixmap; twiddle bits in video ram directly
+    if (shared_pixmap) {
+        XSync(display, False);  // ensure that all pending operations have rendered
+        xi = (XImage*)fake_ximage;
+
+    // MEDIUM: write to a shared ximage, then ask the server to do the blit
+    } else if (shm_supported) {
+        xi = XShmCreateImage(display, visual, colorDepth, ZPixmap, NULL, &shm_info, dx2 - dx1, dy2 - dy1);
+        ensureShmSize(xi->bytes_per_line * xi->height);
+        xi->data = shm_info.shmaddr;
+        XShmGetImage(display, (*((Pixmap*)pm)), xi, dx1, dy1, AllPlanes);
+        
+    // SLOWEST: write to an ximage, copy it through the TCP connection, ask the server to do the blit
+    } else {
+        xi = XGetImage(display, (*((Pixmap*)pm)), dx1, dy1, dx2 - dx1, dy2 - dy1, AllPlanes, ZPixmap);
+    }
+    
+    int* sourcedata = (int*)elements(source->data);
+    for(int y=max(dy1, clipy); y<min(dy2, clipy + cliph); y++) {
+        
+        char* current_pixel = (xi->data + y * xi->bytes_per_line) +
+            (shared_pixmap ? max(dx1, clipx) * (xi->bits_per_pixel / 8) : - 1 * dy1 * xi->bytes_per_line);
+        
+        for(int x=max(dx1, clipx); x<min(dx2, clipx + clipw); x++, current_pixel += xi->bits_per_pixel / 8) {
+            int source_x = ((x - dx1) * (sx2 - sx1)) / (dx2 - dx1) + sx1;
+            int source_y = ((y - dy1) * (sy2 - sy1)) / (dy2 - dy1) + sy1;
+            
+            int sourcepixel = sourcedata[source_x + source_y * source->getWidth()];
+            int alpha = (sourcepixel & 0xFF000000) >> 24;
+            int source_red = (sourcepixel & 0x00FF0000) >> 16;
+            int source_green = (sourcepixel & 0x0000FF00) >> 8;
+            int source_blue = (sourcepixel & 0x000000FF);
+            int red = 0, blue = 0, green = 0;
+            
+            if (alpha == 0x00) continue;
+            if (alpha != 0xFF) {
+                int targetpixel;
+                switch (xi->bits_per_pixel) {
+                case 8: targetpixel = (int)(*current_pixel); break;
+                case 16: targetpixel = (int)(*((u_int16_t*)current_pixel)); break;
+                case 24: targetpixel = (((int)*current_pixel) << 16) | (((int)*(current_pixel + 1)) << 8) | (((int)*(current_pixel + 2))); break;
+                case 32: targetpixel = *((int*)current_pixel); break;
+                default: org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: bpp not a multiple of 8!"));
+                }
+                
+                targetpixel -= colormap_info->base_pixel;
+                
+                // if you're on some wierd display that isn't either RGB or BGR, that's your problem, not mine
+                if (colormap_info->red_mult > colormap_info->green_mult && colormap_info->green_mult > colormap_info->blue_mult) {
+                    red = targetpixel / colormap_info->red_mult;
+                    green = (targetpixel - red * colormap_info->red_mult) / colormap_info->green_mult;
+                    blue = (targetpixel - red * colormap_info->red_mult - green * colormap_info->green_mult) / colormap_info->blue_mult;
+                } else {
+                    blue = targetpixel / colormap_info->blue_mult;
+                    green = (targetpixel - blue * colormap_info->blue_mult) / colormap_info->green_mult;
+                    red = (targetpixel - blue * colormap_info->blue_mult - green * colormap_info->green_mult) / colormap_info->red_mult;
+                }
+            }
+            
+            red = ((source_red * colormap_info->red_max * alpha) + (red * 0xFF * (0xFF - alpha))) / (0xFF * 0xFF);
+            green = ((source_green * colormap_info->green_max * alpha) + (green * 0xFF * (0xFF - alpha))) / (0xFF * 0xFF);
+            blue = ((source_blue * colormap_info->blue_max * alpha) + (blue * 0xFF * (0xFF - alpha))) / (0xFF * 0xFF);
+            u_int32_t destpixel = red * colormap_info->red_mult + green * colormap_info->green_mult +
+                blue * colormap_info->blue_mult + colormap_info->base_pixel;
+
+            switch (xi->bits_per_pixel) {
+            case 8: *current_pixel = (char)(destpixel & 0xFF); break;
+            case 16: *((u_int16_t*)current_pixel) = (u_int16_t)destpixel; break;
+            case 24: {
+                int offset = (int)current_pixel & 0x3;
+                u_int64_t dest = ((u_int64_t)destpixel) << (8 * offset);
+                u_int64_t mask = ((u_int64_t)0xffffff) << (8 * offset);
+                u_int64_t* base = (u_int64_t*)(current_pixel - offset);
+                *base = (*base & ~mask) | dest;
+                break;
+            }
+            case 32: *((u_int32_t*)current_pixel) = destpixel; break;
+            default: org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: bpp not a multiple of 8!"));
+            }
+        }
+    }
+    
+    if (shared_pixmap) {
+        // do nothing, we wrote directly to video memory
+        
+    } else if (shm_supported) {
+        XShmPutImage(display, (*((Pixmap*)pm)), (*((GC*)gc)), xi, 0, 0, dx1, dy1, dx2 - dx1, dy2 - dy1, False);
+        XDestroyImage(xi);
+        
+    } else {
+        XPutImage(display, (*((Pixmap*)pm)), (*((GC*)gc)), xi, 0, 0, dx1, dy1, dx2 - dx1, dy2 - dy1);
+        
+    }
+}
+
+void org::xwt::plat::X11$X11DoubleBuffer::finalize() {
+    if (shared_pixmap) {
+        XShmSegmentInfo *sinfo = (XShmSegmentInfo*)shm_segment;
+        XShmDetach(display, sinfo);
+        shmdt(sinfo->shmaddr);
+        shmctl(sinfo->shmid, IPC_RMID, 0);
+        XDestroyImage((XImage*)fake_ximage);
+        free(sinfo);
+    }
+    if (stipple) {
+        XFreePixmap(display, *((Pixmap*)stipple));
+        free(stipple);
+    }
+    XFreePixmap(display, *((Pixmap*)pm));
+    XFreeGC(display, *((GC*)gc));
+    XFreeGC(display, *((GC*)clipped_gc));
+}
+
+void org::xwt::plat::X11$X11DoubleBuffer::natInit() {
+    
+    if (width == 0 || height == 0) return;
+    shared_pixmap &= shm_supported & shm_pixmaps_supported; // refuse to use shared pixmaps if we don't have shm
+    pm = (gnu::gcj::RawData*)malloc(sizeof(Pixmap));
+
+    if (!shared_pixmap)
+        (*((Pixmap*)pm)) = XCreatePixmap(display, RootWindow(display, screen_num), width, height, colorDepth);
+    else {
+        XShmSegmentInfo *sinfo = (XShmSegmentInfo*)malloc(sizeof(XShmSegmentInfo));
+        shm_segment = (gnu::gcj::RawData*)sinfo;
+        ((XImage*)fake_ximage) = XShmCreateImage(display, visual, colorDepth, ZPixmap, NULL, sinfo, width, height);
+        sinfo->shmid = shmget(IPC_PRIVATE, ((XImage*)fake_ximage)->bytes_per_line * height, IPC_CREAT | 0777 | IPC_EXCL);
+        ((XImage*)fake_ximage)->data = sinfo->shmaddr = (char*)shmat(sinfo->shmid, 0, 0);
+        sinfo->readOnly = False;
+        XShmAttach(display, sinfo);
+        XSync(display, False);
+        shmctl(sinfo->shmid, IPC_RMID, 0);
+        (*((Pixmap*)pm)) = XShmCreatePixmap(display, RootWindow(display, screen_num), sinfo->shmaddr, sinfo, width, height, colorDepth);
+        XSync(display, False);
+    }
+
+    gc = (gnu::gcj::RawData*)malloc(sizeof(GC));
+    clipped_gc = (gnu::gcj::RawData*)malloc(sizeof(GC));
+    (*((GC*)gc)) = XCreateGC(display, (*((Pixmap*)pm)), 0, 0);
+    (*((GC*)clipped_gc)) = XCreateGC(display, (*((Pixmap*)pm)), 0, 0);
+    
+    XGCValues vm;
+    vm.graphics_exposures = 0;
+    XChangeGC(display, (*((GC*)gc)), GCGraphicsExposures, &vm);
+    XChangeGC(display, (*((GC*)clipped_gc)), GCGraphicsExposures, &vm);
+}    
+
+void org::xwt::plat::X11$X11DoubleBuffer::createStipple(org::xwt::plat::X11$X11Picture* xpi) {
+
+    stipple = (gnu::gcj::RawData*)malloc(sizeof(Pixmap));
+    (*((Pixmap*)stipple)) = XCreatePixmap(display, RootWindow(display, screen_num), width, height, 1);
+
+    XImage xi;
+    xi.data = (char*)malloc((width + 1) * height);
+    xi.width = width;
+    xi.height = height;
+    xi.xoffset = 0;
+    xi.format = ZPixmap;
+    xi.bitmap_pad = 8;
+    xi.bitmap_unit = 8;
+    xi.byte_order = LSBFirst;
+    xi.depth = 1;
+    xi.bytes_per_line = (width / 8) + 1;
+    xi.bits_per_pixel = 1;
+    
+    jint* d = (jint*)elements(xpi->data);
+    memset(xi.data, 0xFF, (width + 1) * height);
+    for(int x=0; x<width; x++)
+        for (int y=0; y<height; y++)
+            xi.data[y * xi.bytes_per_line + (x/8)] &= ~(((d[x + y * width] & 0xFF000000) != 0 ? 0 : 1) << (x % 8));
+
+    GC stipple_gc = XCreateGC(display, (*((Pixmap*)stipple)), 0, 0);
+
+    XGCValues vm;
+    vm.graphics_exposures = 0;
+    XChangeGC(display, stipple_gc, GCGraphicsExposures, &vm);
+
+    XPutImage(display, (*((Pixmap*)stipple)), stipple_gc, &xi, 0, 0, 0, 0, width, height);
+}
+
+void org::xwt::plat::X11$X11Surface::blit(org::xwt::DoubleBuffer* db, jint sx, jint sy, jint dx, jint dy, jint dx2, jint dy2) {
+    org::xwt::plat::X11$X11DoubleBuffer *xdb = (org::xwt::plat::X11$X11DoubleBuffer*)db;
+    XCopyArea(display, *((Pixmap*)xdb->pm), *((Window*)window), *((GC*)gc), sx, sy, dx2 - dx, dy2 - dy, dx, dy);
+    XFlush(display);
+}
+
+void org::xwt::plat::X11$X11DoubleBuffer::fillRect (jint x, jint y, jint x2, jint y2, jint argb) {
+    
+    jint w = x2 - x;
+    jint h = y2 - y;
+
+    if (x < clipx) { w -= (clipx - x); x = clipx; }
+    if (y < clipy) { h -= (clipy - y); y = clipy; }
+    if (x + w > clipx + clipw) w = (clipx + clipw - x);
+    if (y + h > clipy + cliph) h = (cliph + clipy - y);
+
+    XSetForeground(display, (*((GC*)gc)),
+                   ((((argb & 0x00FF0000) >> 16) * colormap_info->red_max) / 0xFF) * colormap_info->red_mult + 
+                   ((((argb & 0x0000FF00) >> 8) * colormap_info->green_max) / 0xFF) * colormap_info->green_mult + 
+                   ((((argb & 0x000000FF)) * colormap_info->blue_max) / 0xFF) * colormap_info->blue_mult +
+                   colormap_info->base_pixel
+                   );
+    
+    XFillRectangle(display, (*((Pixmap*)pm)), (*((GC*)gc)), x, y, w, h);
+}
+
+void org::xwt::plat::X11$X11DoubleBuffer::drawString(::java::lang::String* font, ::java::lang::String* text, jint x, jint y, jint argb) {
+    
+    XRectangle rect;
+    rect.x = clipx, rect.y = clipy; rect.width = clipw; rect.height = cliph;
+    XSetClipMask(display, (*((GC*)clipped_gc)), None);
+    XSetClipRectangles(display, (*((GC*)clipped_gc)), 0, 0, &rect, 1, YSorted);
+    XSetForeground(display, (*((GC*)clipped_gc)),
+                   ((((argb & 0x00FF0000) >> 16) * colormap_info->red_max) / 0xFF) * colormap_info->red_mult + 
+                   ((((argb & 0x0000FF00) >> 8) * colormap_info->green_max) / 0xFF) * colormap_info->green_mult + 
+                   ((((argb & 0x000000FF)) * colormap_info->blue_max) / 0xFF) * colormap_info->blue_mult +
+                   colormap_info->base_pixel
+                   );
+    
+    // Grab the string
+    int len = min(1024, JvGetStringUTFLength(text));
+    char buf[len + 1];
+    JvGetStringUTFRegion(text, 0, len, buf);
+    buf[len] = '\0';
+    
+    // Build the XTextItem structure
+    XTextItem textitem;
+    textitem.chars = buf;
+    textitem.nchars = len;
+    textitem.delta = 0;
+    textitem.font = ((XFontStruct*)org::xwt::plat::X11::fontToXFont(font))->fid;
+    
+    // Draw the text
+    XDrawText(display, (*((Pixmap*)pm)), (*((GC*)clipped_gc)), x, y, &textitem, 1);
+}
+
+
+// X11Surface //////////////////////////////////////////////////////////////////////
+
+void org::xwt::plat::X11$X11Surface::setIcon(org::xwt::Picture* pic) {
+    org::xwt::plat::X11$X11Picture* p = ((org::xwt::plat::X11$X11Picture*)pic);
+    org::xwt::plat::X11$X11DoubleBuffer* old_dbuf = p->doublebuf;
+    p->buildDoubleBuffer(1);
+    XWMHints xwmh;
+    memset(&xwmh, 0, sizeof(XWMHints));
+    xwmh.flags |= IconPixmapHint | IconMaskHint;
+    xwmh.icon_pixmap = *((Pixmap*)p->doublebuf->pm);
+    xwmh.icon_mask = *((Pixmap*)p->doublebuf->stipple);
+    XSetWMHints(display, (*((Window*)window)), &xwmh);
+    p->doublebuf = old_dbuf;
+}
+
+void org::xwt::plat::X11$X11Surface::setTitleBarText(java::lang::String* s) {
+    int len = min(JvGetStringUTFLength(s), 1024);
+    char buf[len + 1];
+    JvGetStringUTFRegion(s, 0, len, buf);
+    buf[len] = '\0';
+    
+    XTextProperty tp;
+    tp.value = (unsigned char*)buf;
+    tp.nitems = len;
+    tp.encoding = XA_STRING;
+    tp.format = 8;
+    XSetTextProperty(display, (*((Window*)window)), &tp, XA_WM_NAME);
+    XSetTextProperty(display, (*((Window*)window)), &tp, XA_WM_ICON_NAME);
+}
+
+void org::xwt::plat::X11$X11Surface::setLimits(jint minw, jint minh, jint maxw, jint maxh) {
+    XSizeHints hints;
+    hints.min_width = minw;
+    hints.min_height = minh;
+    hints.max_width = maxw;
+    hints.max_height = maxh;
+    hints.flags = PMinSize | PMaxSize;
+    XSetWMNormalHints(display, (*((Window*)window)), &hints);
+}
+
+void org::xwt::plat::X11$X11Surface::setSize (jint width, jint height) {
+    if (width <= 0 || height <= 0) return;
+    XResizeWindow(display, (*((Window*)window)), width, height);
+    XFlush(display);
+}
+
+void org::xwt::plat::X11$X11Surface::setLocation (jint x, jint y) { XMoveWindow(display, (*((Window*)window)), x, y); }
+void org::xwt::plat::X11$X11Surface::toFront() { XRaiseWindow(display, (*((Window*)window))); }
+void org::xwt::plat::X11$X11Surface::toBack() { XLowerWindow(display, (*((Window*)window))); }
+
+void org::xwt::plat::X11$X11Surface::_dispose() {
+    // without this we get phantom messages after the window is gone
+    org::xwt::plat::X11::windowToSurfaceMap->remove(new java::lang::Long(*((Window*)window)));
+    XDestroyWindow(display, (*((Window*)window)));
+}
+
+void org::xwt::plat::X11$X11Surface::setInvisible(jboolean i) {
+    if (i) XUnmapWindow(display, (*((Window*)window)));
+    else XMapRaised(display, (*((Window*)window)));
+    XFlush(display);
+}
+
+void org::xwt::plat::X11$X11Surface::_setMinimized(jboolean b) {
+    if (b) XIconifyWindow(display, (*((Window*)window)), screen_num);
+    else XMapRaised(display, (*((Window*)window)));
+    XFlush(display);
+}
+
+void org::xwt::plat::X11$X11Surface::natInit() {
+    XSetWindowAttributes xswa;
+    window = (gnu::gcj::RawData*)malloc(sizeof(Window));
+    xswa.bit_gravity = NorthWestGravity;
+    xswa.colormap = s_colormap;
+    xswa.event_mask = ExposureMask | ButtonPressMask | StructureNotifyMask |
+        KeyPressMask | KeyReleaseMask | ButtonPressMask |
+        ButtonReleaseMask | EnterWindowMask | LeaveWindowMask |
+        PointerMotionMask | ButtonMotionMask | ConfigureNotify | FocusChangeMask;
+    *((Window*)window) = XCreateWindow(display, RootWindow(display, screen_num), 10, 10, 10, 10, 0,
+                                       colorDepth, InputOutput, CopyFromParent,
+                                       CWColormap | CWBitGravity | CWEventMask, &xswa);
+    
+    if (!framed) {
+        // I don't know why this works....
+        int dat[5] = { 0x2, 0xbffff804, 0x0, 0x817f560, 0x8110694 };
+        XChangeProperty(display, (*((Window*)window)),
+                        XInternAtom(display, "_MOTIF_WM_HINTS", False),
+                        XInternAtom(display, "_MOTIF_WM_HINTS", False),
+                        32, 
+                        PropModeReplace,
+                        (unsigned char*)dat,
+                        5);
+    }
+    
+    XTextProperty tp;
+    tp.value = (unsigned char*)"XWT";
+    tp.nitems = 3;
+    tp.encoding = XA_STRING;
+    tp.format = 8;
+    XSetTextProperty(display, (*((Window*)window)), &tp, XA_WM_CLASS);
+    
+    Atom proto = XInternAtom(display, "WM_DELETE_WINDOW", False);
+    XSetWMProtocols(display, (*((Window*)window)), &proto, 1);
+    
+    XSelectInput(display, (*((Window*)window)), StructureNotifyMask);
+    org::xwt::plat::X11::windowToSurfaceMap->put(new java::lang::Long(*((Window*)window)), this);
+
+    XEvent e;
+    XMapRaised(display, (*((Window*)window)));
+    XFlush(display);
+
+    waitForCreation->block();
+    XSelectInput(display, (*((Window*)window)), xswa.event_mask);
+    XFlush(display);
+
+    gc = (gnu::gcj::RawData*)malloc(sizeof(GC));
+    *((GC*)gc) = XCreateGC(display, (*((Window*)window)), 0, 0);
+    
+    XGCValues vm;
+    vm.graphics_exposures = 0;
+    XChangeGC(display, *((GC*)gc), GCGraphicsExposures, &vm);
+}
+
+
+void org::xwt::plat::X11$X11Surface::dispatchEvent(gnu::gcj::RawData* ev) {
+
+    XEvent* e = (XEvent*)ev;
+    if (e->type == Expose) {
+        XExposeEvent *expose = (XExposeEvent*)(e);
+        Dirty(expose->x, expose->y, expose->width, expose->height);
+        
+    } else if (e->type == MapNotify) { Minimized(0); waitForCreation->release();
+    } else if (e->type == UnmapNotify) { Minimized(1);
+    } else if (e->type == FocusIn) { Focused(1);
+    } else if (e->type == FocusOut) { Focused(0);
+    } else if (e->type == ClientMessage) {
+        if (((XClientMessageEvent*)(e))->data.l[0] == XInternAtom(display, "WM_DELETE_WINDOW", False)) Close();
+    
+    } else if (e->type == KeyPress || e->type == KeyRelease) {
+        XKeyEvent *xbe = (XKeyEvent*)(e);
+        
+        // drop faked KeyRelease events generated by the X server's autorepeat
+        if (e->type == KeyRelease) {
+            char depressed[32];
+            XQueryKeymap(display, depressed);
+            if ((depressed[(xbe->keycode & 0xff) / 8] & (0x1 << (xbe->keycode % 8))) >> (xbe->keycode % 8)) return;
+        }
+        
+        char ss[20];
+        char* s = ss;
+        
+        unsigned int savestate = xbe->state;
+        xbe->state = xbe->state & ShiftMask;      // ignore everything except shiftmask
+        XLookupString(xbe, s, 20, NULL, NULL);
+        xbe->state = savestate;
+        
+        if (s != NULL && s[0] != '\0' && s[1] == '\0' && s[0] >= 0x20 && s[0] <= 0x7E) {
+            int i = s[0];
+            
+        } else {
+            KeySym ks = XKeycodeToKeysym(display, xbe->keycode, 0);
+            switch (ks) {
+            case XK_BackSpace: s = "back_space"; break;
+            case XK_Tab: s = "tab"; break;
+            case XK_Linefeed: s = "enter"; break;
+            case XK_Return: s = "enter"; break;
+            case XK_Scroll_Lock: s = "scroll_lock"; break;
+            case XK_Escape: s = "escape"; break;
+            case XK_Insert: s = "insert"; break;
+            case XK_Delete: s = "delete"; break;
+            case XK_Home: s = "home"; break;
+            case XK_Left: s = "left"; break;
+            case XK_Up: s = "up"; break;
+            case XK_Right: s = "right"; break;
+            case XK_Down: s = "down"; break;
+            case XK_Page_Up: s = "page_up"; break;
+            case XK_Page_Down: s = "page_down"; break;
+            case XK_End: s = "end"; break;
+            case XK_Num_Lock: s = "num_lock"; break;
+            case XK_KP_Tab: s = "tab"; break;
+            case XK_KP_Enter: s = "enter"; break;
+            case XK_KP_F1: s = "f1"; break;
+            case XK_KP_F2: s = "f2"; break;
+            case XK_KP_F3: s = "f3"; break;
+            case XK_KP_F4: s = "f4"; break;
+            case XK_KP_Home: s = "home"; break;
+            case XK_KP_Left: s = "left"; break;
+            case XK_KP_Up: s = "up"; break;
+            case XK_KP_Right: s = "right"; break;
+            case XK_KP_Down: s = "down"; break;
+            case XK_KP_Page_Up: s = "page_up"; break;
+            case XK_KP_Page_Down: s = "page_down"; break;
+            case XK_KP_End: s = "end"; break;
+            case XK_KP_Insert: s = "insert"; break;
+            case XK_KP_Delete: s = "delete"; break;
+            case XK_F1: s = "f1"; break;
+            case XK_F2: s = "f2"; break;
+            case XK_F3: s = "f3"; break;
+            case XK_F4: s = "f4"; break;
+            case XK_F5: s = "f5"; break;
+            case XK_F6: s = "f6"; break;
+            case XK_F7: s = "f7"; break;
+            case XK_F8: s = "f8"; break;
+            case XK_F9: s = "f9"; break;
+            case XK_F10: s = "f10"; break;
+            case XK_F11: s = "f11"; break;
+            case XK_F12: s = "f12"; break;
+            case XK_Shift_L: s = "shift"; break;
+            case XK_Shift_R: s = "shift"; break;
+            case XK_Control_L: s = "control"; break;
+            case XK_Control_R: s = "control"; break;
+            case XK_Meta_L: s = "alt"; break;
+            case XK_Meta_R: s = "alt"; break;
+            case XK_Alt_L: s = "alt"; break;
+            case XK_Alt_R: s = "alt"; break;
+            default: return;
+            }
+        }
+        
+        jstring s2 = JvNewStringLatin1(s);
+        if (e->type == KeyPress) KeyPressed((xbe->state & LockMask) ? s2->toUpperCase() : s2);
+        if (e->type == KeyRelease) KeyReleased(s2);
+        
+    } else if (e->type == ButtonPress) {
+        XButtonEvent* xbe = (XButtonEvent*)(e);
+        if (xbe->button == 2) xbe->button = 3;
+        else if (xbe->button == 3) xbe->button = 2;
+        Press(xbe->button);
+        
+    } else if (e->type == ButtonRelease) {
+        XButtonEvent* xbe = (XButtonEvent*)(e);
+        if (xbe->button == 2) xbe->button = 3;
+        else if (xbe->button == 3) xbe->button = 2;
+        Release(xbe->button);
+        
+    } else if (e->type == MotionNotify) {
+        XMotionEvent* xme = (XMotionEvent*)(e);
+        Move(xme->x, xme->y);
+        
+    } else if (e->type == EnterNotify || e->type == LeaveNotify) {
+        XCrossingEvent* xce = (XCrossingEvent*)(e);
+        Move(xce->x, xce->y);
+        
+    } else if (e->type == ConfigureNotify) {
+        Window child;
+        int x_out, y_out;
+        XConfigureEvent* xce = (XConfigureEvent*)(e);
+        XTranslateCoordinates(display, (*((Window*)window)), RootWindow(display, screen_num), 0, 0, &x_out, &y_out, &child);
+        if (xce->width != width || xce->height != height) SizeChange(xce->width, xce->height);
+        if (x_out != root->abs(0) || y_out != root->abs(1)) PosChange(x_out, y_out);
+        
+    }
+}
+
+static jstring crosshair, east, hand, move, north, northeast, northwest,
+    south, southeast, southwest, text, west, wait_string;
+static Cursor crosshair_cursor, east_cursor, hand_cursor, move_cursor, north_cursor,
+    northeast_cursor, northwest_cursor, south_cursor, southeast_cursor,
+    southwest_cursor, text_cursor, west_cursor, wait_cursor, default_cursor;
+
+void org::xwt::plat::X11$X11Surface::syncCursor() {
+    
+    Cursor curs;
+    if (cursor->equals(crosshair)) curs = crosshair_cursor;
+    else if (cursor->equals(east)) curs = east_cursor;
+    else if (cursor->equals(hand)) curs = hand_cursor;
+    else if (cursor->equals(move)) curs = move_cursor;
+    else if (cursor->equals(north)) curs = north_cursor;
+    else if (cursor->equals(northeast)) curs = northeast_cursor;
+    else if (cursor->equals(northwest)) curs = northwest_cursor;
+    else if (cursor->equals(south)) curs = south_cursor;
+    else if (cursor->equals(southeast)) curs = southeast_cursor;
+    else if (cursor->equals(southwest)) curs = southwest_cursor;
+    else if (cursor->equals(text)) curs = text_cursor;
+    else if (cursor->equals(west)) curs = west_cursor;
+    else if (cursor->equals(wait_string)) curs = wait_cursor;
+    else curs = default_cursor;
+    
+    XDefineCursor(display, (*((Window*)window)), curs);
+}
+
+
+
+// X11 ///////////////////////////////////////////////////////////////////
+
+jint org::xwt::plat::X11::_getScreenWidth() { return WidthOfScreen(DefaultScreenOfDisplay(display)); }
+jint org::xwt::plat::X11::_getScreenHeight() { return HeightOfScreen(DefaultScreenOfDisplay(display)); }
+
+static void dispatchSelectionEvent(XEvent* e) {
+    if (e->type == SelectionNotify) {
+        XSelectionEvent* xsn = (XSelectionEvent*)(e);
+        if (xsn->property == None) org::xwt::plat::X11::clipboard = JvNewStringLatin1("", 0);
+        else {
+            Atom returntype;
+            int returnformat;
+            unsigned long numitems;
+            unsigned char* ret;
+            unsigned long bytes_after;
+            XGetWindowProperty(display, xsn->requestor, xsn->property, 0, 4096,
+                               True, AnyPropertyType, &returntype, &returnformat,
+                               &numitems, &bytes_after, &ret);
+            org::xwt::plat::X11::clipboard =
+                (returntype == None ? JvNewStringLatin1("", 0) : JvNewStringLatin1((char*)ret, strlen((char*)ret)));
+        }
+        org::xwt::plat::X11::waiting_for_selection_event->release();
+        
+    } else if (e->type == SelectionRequest) {
+        XSelectionRequestEvent* xsr = (XSelectionRequestEvent*)(e);
+        XSelectionEvent xsn;
+        xsn.type = SelectionNotify;
+        xsn.serial = xsr->serial;
+        xsn.send_event = True;
+        xsn.display = display;
+        xsn.requestor = xsr->requestor;
+        xsn.selection = xsr->selection;
+        xsn.target = xsr->target;
+        xsn.property = xsr->property;
+        xsn.time = xsr->time;
+        
+        int len = min(1024, JvGetStringUTFLength(org::xwt::plat::X11::clipboard));
+        char buf[len + 1];
+        JvGetStringUTFRegion(org::xwt::plat::X11::clipboard, 0, len, buf);
+        buf[len] = '\0';
+        
+        XChangeProperty(display, xsr->requestor, xsr->property, xsr->target, 8, PropModeReplace, (unsigned char*)buf, len + 1);
+        XSendEvent(display, xsr->requestor, True, 0, (XEvent*)(&xsn));
+    }        
+}
+
+void org::xwt::plat::X11::eventThread() {
+    XEvent e;
+    while(true) {
+        XNextEvent(display, &e);
+        if (e.type == SelectionNotify || e.type == SelectionRequest) {
+            dispatchSelectionEvent(&e);
+        } else {
+            org::xwt::plat::X11$X11Surface* surface =
+                (org::xwt::plat::X11$X11Surface*)windowToSurfaceMap->get(new java::lang::Long(((XAnyEvent*)&e)->window));
+            if (surface != NULL) surface->dispatchEvent((gnu::gcj::RawData*)&e);
+        }
+    }
+}
+
+jstring org::xwt::plat::X11::_getClipBoard() {
+    XConvertSelection(display, XA_PRIMARY, XA_STRING, XInternAtom(display, "VT_SELECTION", False), selectionWindow, CurrentTime);
+    XFlush(display);
+    org::xwt::plat::X11::waiting_for_selection_event->block();
+    return clipboard;
+}
+
+void org::xwt::plat::X11::_setClipBoard(jstring s) {
+    clipboard = s;
+    int len = JvGetStringUTFLength(clipboard);
+    char buf[len + 1];
+    JvGetStringUTFRegion(clipboard, 0, len, buf);
+    buf[len] = '\0';
+    XSetSelectionOwner(display, XInternAtom(display, "PRIMARY", 0), selectionWindow, CurrentTime);
+}
+
+typedef int (X11ErrorHandler)(Display*, XErrorEvent*);
+int errorHandler(Display* d, XErrorEvent* e) {
+    // this error handler is only installed during the initial
+    // test to see if shm is present
+    shm_supported = 0;
+}
+
+void org::xwt::plat::X11::natInit() {
+
+    if (!XInitThreads())
+        org::xwt::Platform::criticalAbort(JvNewStringLatin1("Your X11 libraries do not support multithreaded programs"));
+
+    display = XOpenDisplay(NULL);
+    screen_num = XDefaultScreen(display);
+    colorDepth = (jint)(DefaultDepth(((Display*)display), 0));
+    shm_info.shmaddr = NULL;
+
+    shm_supported = (XShmQueryExtension(display) == True);
+    if (shm_supported) {
+        X11ErrorHandler* oldHandler = XSetErrorHandler(errorHandler);
+        XShmSegmentInfo sinfo;
+        sinfo.shmid = shmget(IPC_PRIVATE, 1, IPC_CREAT | 0777 | IPC_EXCL);
+        sinfo.readOnly = False;
+        // if the server is remote, this will trigger the error handler
+        XShmAttach(display, &sinfo);
+        XSync(display, False);
+        XSetErrorHandler(oldHandler);
+    }
+
+    if (shm_supported)
+        shm_pixmaps_supported = (XShmPixmapFormat(display) == ZPixmap);
+    
+    crosshair = JvNewStringLatin1("crosshair");
+    east = JvNewStringLatin1("east");
+    hand = JvNewStringLatin1("hand");
+    move = JvNewStringLatin1("move");
+    north = JvNewStringLatin1("north");
+    northeast = JvNewStringLatin1("northeast");
+    northwest = JvNewStringLatin1("northwest");
+    south = JvNewStringLatin1("south");
+    southeast = JvNewStringLatin1("southeast");
+    southwest = JvNewStringLatin1("southwest");
+    text = JvNewStringLatin1("text");
+    west = JvNewStringLatin1("west");
+    wait_string = JvNewStringLatin1("wait");
+    crosshair_cursor = XCreateFontCursor(display, XC_tcross);
+    east_cursor = XCreateFontCursor(display, XC_right_side);
+    hand_cursor = XCreateFontCursor(display, XC_hand2);
+    move_cursor = XCreateFontCursor(display, XC_fleur);
+    north_cursor = XCreateFontCursor(display, XC_top_side);
+    northeast_cursor = XCreateFontCursor(display, XC_top_right_corner);
+    northwest_cursor = XCreateFontCursor(display, XC_left_side);
+    south_cursor = XCreateFontCursor(display, XC_bottom_side);
+    southeast_cursor = XCreateFontCursor(display, XC_bottom_right_corner);
+    southwest_cursor = XCreateFontCursor(display, XC_bottom_left_corner);
+    text_cursor = XCreateFontCursor(display, XC_xterm);
+    west_cursor = XCreateFontCursor(display, XC_right_side);
+    wait_cursor = XCreateFontCursor(display, XC_watch);
+    default_cursor = XCreateFontCursor(display, XC_left_ptr);
+
+    selectionWindow = XCreateWindow(display, RootWindow(display, screen_num), 0, 0, 1, 1, 0, colorDepth, InputOutput, CopyFromParent, 0, NULL);
+    visual = DefaultVisual(display, screen_num);
+    char buf[255];
+    sprintf(buf, "X11 DISPLAY: %s", XDisplayString(display));
+    org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
+    sprintf(buf, "X11 SHM:     %s", shm_supported ? "enabled" : "disabled");
+    org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
+    sprintf(buf, "X11 Visual:  %x %x %x bits: %i visualid: %i depth: %i",
+            visual->red_mask, visual->green_mask, visual->blue_mask, visual->bits_per_rgb, visual->visualid, colorDepth);
+    org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
+
+    // FIXME: don't know why (True, False) is the best solution...
+    if(XmuLookupStandardColormap(display, screen_num, visual->visualid, colorDepth, XA_RGB_BEST_MAP, True, False) == 0)
+        org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: XmuLookupStandardColormap failed"));
+    
+    XStandardColormap* best_map_info = NULL;
+    int count;
+    if (XGetRGBColormaps(display, RootWindow(display, screen_num), &best_map_info, &count, XA_RGB_BEST_MAP) == 0)
+        org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: couldn't allocate a standard colormap"));
+    if (!best_map_info->colormap)
+        org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: XmuLookupStandardColomap succeded, but no colormap was found on the root window"));
+    if (best_map_info->red_max == 0)
+        org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: standard colormap exists, but was improperly allocated"));
+    s_colormap = best_map_info->colormap;
+    colormap_info = best_map_info;
+
+    sprintf(buf, "            red_max / red_mult: %x %x", colormap_info->red_max, colormap_info->red_mult);
+    org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
+    sprintf(buf, "            green_max / green_mult: %x %x", colormap_info->green_max, colormap_info->green_mult);
+    org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
+    sprintf(buf, "            blue_max / blue_mult: %x %x", colormap_info->blue_max, colormap_info->blue_mult);
+    org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
+    sprintf(buf, "            base_pixel: %x", colormap_info->base_pixel);
+    org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
+}
+
+JArray<java::lang::String*>* org::xwt::plat::X11::listNativeFonts() {
+    int numfonts;
+    char** xfonts = XListFonts(display, "-*-*-*-*-normal-*-*-*-*-*-*-*-*-*", 0xFFFFFFFF, &numfonts);
+    JArray<java::lang::String*>* fonts = (JArray<java::lang::String*>*)JvNewObjectArray(numfonts, &(::java::lang::String::class$), NULL);
+    java::lang::String** jfonts = (java::lang::String**)(elements(fonts));
+    for(int i=0; i<numfonts; i++)
+        jfonts[i] = JvNewStringLatin1(xfonts[i], strlen(xfonts[i]));
+    return fonts;
+}
+
+gnu::gcj::RawData* org::xwt::plat::X11::fontStringToStruct(jstring s) {
+    int len = min(1024, JvGetStringUTFLength(s));
+    char buf[len + 1];
+    JvGetStringUTFRegion(s, 0, len, buf);
+    buf[len] = '\0';
+    return (gnu::gcj::RawData*)XLoadQueryFont(display, buf);
+}
+
+jint org::xwt::plat::X11::_getMaxAscent(::java::lang::String* font) { return ((XFontStruct*)fontToXFont(font))->max_bounds.ascent; }
+jint org::xwt::plat::X11::_getMaxDescent(::java::lang::String* font) { return ((XFontStruct*)fontToXFont(font))->max_bounds.descent; }
+jint org::xwt::plat::X11::_stringWidth(::java::lang::String* font, ::java::lang::String* text) {
+    if (text == NULL) return 0;
+    int len = JvGetStringUTFLength(text);
+    char buf[len + 1];
+    JvGetStringUTFRegion(text, 0, len, buf);
+    buf[len] = '\0';
+    return XTextWidth((XFontStruct*)fontToXFont(font), buf, len);
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+//                                                                          //
+// Everything below this point was taken, cut-and-paste, from the           //
+// source for libXmu. It implements the official 'standard colormap         //
+// creation algorithm.  I made some small changes to                        //
+// XmuDeleteStandardColormap                                                //
+//                                                                          //
+//////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+/* $Xorg: LookupCmap.c,v 1.4 2001/02/09 02:03:53 xorgcvs Exp $ */
+
+/* 
+Copyright 1989, 1998  The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+*/
+/* $XFree86: xc/lib/Xmu/LookupCmap.c,v 1.8 2001/12/14 19:55:47 dawes Exp $ */
+
+/*
+ * Author:  Donna Converse, MIT X Consortium
+ */
+
+#include <stdio.h>
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#include <X11/Xutil.h>
+#include <X11/Xmu/StdCmap.h>
+#include <stdlib.h>
+
+/*
+ * Prototypes
+ */
+static Status lookup(Display*, int, VisualID, Atom, XStandardColormap*, Bool);
+
+/*
+ * To create a standard colormap if one does not currently exist, or
+ * replace the currently existing standard colormap, use 
+ * XmuLookupStandardColormap().
+ *
+ * Given a screen, a visual, and a property, XmuLookupStandardColormap()
+ * will determine the best allocation for the property under the specified
+ * visual, and determine the whether to create a new colormap or to use
+ * the default colormap of the screen.  It will call XmuStandardColormap()
+ * to create the standard colormap.
+ *
+ * If replace is true, any previous definition of the property will be 
+ * replaced.  If retain is true, the property and the colormap will be
+ * made permanent for the duration of the server session.  However,
+ * pre-existing property definitions which are not replaced cannot be made
+ * permanent by a call to XmuLookupStandardColormap(); a request to retain 
+ * resources pertains to newly created resources.
+ *
+ * Returns 0 on failure, non-zero on success.  A request to create a 
+ * standard colormap upon a visual which cannot support such a map is
+ * considered a failure.  An example of this would be requesting any
+ * standard colormap property on a monochrome visual, or, requesting an
+ * RGB_BEST_MAP on a display whose colormap size is 16.
+ */
+
+Status
+XmuLookupStandardColormap(Display *dpy, int screen, VisualID visualid,
+                         unsigned int depth, Atom property,
+                         Bool replace, Bool retain)
+     /*
+      * dpy            - specifies X server connection
+      * screen                 - specifies screen of display
+      * visualid       - specifies the visual type
+      * depth          - specifies  the visual type
+      * property       - a standard colormap property
+      * replace                - specifies whether to replace
+      * retain         - specifies whether to retain
+      */
+{
+    Display            *odpy;          /* original display connection */
+    XStandardColormap  *colormap;      
+    XVisualInfo                vinfo_template, *vinfo; /* visual */
+    long               vinfo_mask;
+    unsigned long      r_max, g_max, b_max;    /* allocation */
+    int                        count;  
+    Colormap           cmap;                   /* colormap ID */
+    Status             status = 0;
+
+
+    /* Match the requested visual */
+
+    vinfo_template.visualid = visualid;        
+    vinfo_template.screen = screen;
+    vinfo_template.depth = depth;
+    vinfo_mask = VisualIDMask | VisualScreenMask | VisualDepthMask;
+    if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &count)) ==
+       NULL)
+       return 0;
+
+    /* Monochrome visuals have no standard maps */
+
+    if (vinfo->colormap_size <= 2) {
+       XFree((char *) vinfo);
+       return 0;       
+    }
+
+    /* If the requested property already exists on this screen, and, 
+     * if the replace flag has not been set to true, return success.
+     * lookup() will remove a pre-existing map if replace is true.
+     */
+
+    if (lookup(dpy, screen, visualid, property, (XStandardColormap *) NULL,
+              replace) && !replace) {
+       XFree((char *) vinfo);
+       return 1;
+    }
+
+    /* Determine the best allocation for this property under the requested
+     * visualid and depth, and determine whether or not to use the default
+     * colormap of the screen.
+     */
+
+    if (!XmuGetColormapAllocation(vinfo, property, &r_max, &g_max, &b_max)) {
+       XFree((char *) vinfo);
+       return 0;
+    }
+
+    cmap = (property == XA_RGB_DEFAULT_MAP &&
+           visualid == XVisualIDFromVisual(DefaultVisual(dpy, screen)))
+       ? DefaultColormap(dpy, screen) : None;
+
+    /* If retaining resources, open a new connection to the same server */
+
+    if (retain) {
+        odpy = dpy;
+        if ((dpy = XOpenDisplay(XDisplayString(odpy))) == NULL) {
+            XFree((char *) vinfo);
+            return 0;
+        }
+    }
+
+    /* Create the standard colormap */
+
+    colormap = XmuStandardColormap(dpy, screen, visualid, depth, property,
+                                  cmap, r_max, g_max, b_max);
+
+    /* Set the standard colormap property */
+
+    if (colormap) {
+       XGrabServer(dpy);
+
+       if (lookup(dpy, screen, visualid, property, colormap, replace) &&
+           !replace) {
+           /* Someone has defined the property since we last looked.
+            * Since we will not replace it, release our own resources.
+            * If this is the default map, our allocations will be freed 
+            * when this connection closes.
+            */
+           if (colormap->killid == ReleaseByFreeingColormap)
+            XFreeColormap(dpy, colormap->colormap);
+       } else if (retain) {
+               XSetCloseDownMode(dpy, RetainPermanent);
+       }
+       XUngrabServer(dpy);
+       XFree((char *) colormap);
+       status = 1;
+    }
+
+    if (retain)
+       XCloseDisplay(dpy);
+    XFree((char *) vinfo);
+    return status;
+}
+
+/***************************************************************************/
+
+/* Lookup a standard colormap property.  If the property is RGB_DEFAULT_MAP,
+ * the visualid is used to determine whether the indicated standard colormap
+ * exists.  If the map exists and replace is true, delete the resources used
+ * by the map and remove the property.  Return true if the map exists,
+ * or did exist and was deleted; return false if the map was not found.
+ *
+ * Note that this is not the way that a Status return is normally used.
+ *
+ * If new is not NULL, new points to an XStandardColormap structure which
+ * describes a standard colormap of the specified property.  It will be made
+ * a standard colormap of the screen if none already exists, or if replace 
+ * is true.
+ */
+
+static Status
+lookup(Display *dpy, int screen, VisualID visualid, Atom property,
+       XStandardColormap *cnew, Bool replace)
+     /*
+      * dpy            - specifies display connection
+      * screen         - specifies screen number
+      * visualid       - specifies visualid for std map
+      * property       - specifies colormap property name
+      * cnew           - specifies a standard colormap
+      * replace                - specifies whether to replace
+      */
+{
+    register int       i;
+    int                        count;
+    XStandardColormap  *stdcmaps, *s;
+    Window             win = RootWindow(dpy, screen);
+
+    /* The property does not already exist */
+
+    if (! XGetRGBColormaps(dpy, win, &stdcmaps, &count, property)) {
+       if (cnew)
+           XSetRGBColormaps(dpy, win, cnew, 1, property);
+       return 0;
+    }
+
+    /* The property exists and is not describing the RGB_DEFAULT_MAP */
+
+    if (property != XA_RGB_DEFAULT_MAP) {
+       if (replace) {
+           XmuDeleteStandardColormap(dpy, screen, property);
+           if (cnew)
+               XSetRGBColormaps(dpy, win, cnew, 1, property);
+       }
+       XFree((char *)stdcmaps);
+       return 1;
+    }
+
+    /* The property exists and is RGB_DEFAULT_MAP */
+    
+    for (i=0, s=stdcmaps; (i < count) && (s->visualid != visualid); i++, s++)
+       ;
+
+    /* No RGB_DEFAULT_MAP property matches the given visualid */
+
+    if (i == count) {
+       if (cnew) {
+           XStandardColormap   *m, *maps;
+
+           s = (XStandardColormap *) malloc((unsigned) ((count+1) * sizeof
+                                             (XStandardColormap)));
+
+           for (i = 0, m = s, maps = stdcmaps; i < count; i++, m++, maps++) {
+               m->colormap   = maps->colormap;
+               m->red_max    = maps->red_max;
+               m->red_mult   = maps->red_mult;
+               m->green_max  = maps->green_max;
+               m->green_mult = maps->green_mult;
+               m->blue_max   = maps->blue_max;
+               m->blue_mult  = maps->blue_mult;
+               m->base_pixel = maps->base_pixel;
+               m->visualid   = maps->visualid;
+               m->killid     = maps->killid;
+           }
+           m->colormap   = cnew->colormap;
+           m->red_max    = cnew->red_max;
+           m->red_mult   = cnew->red_mult;
+           m->green_max  = cnew->green_max;
+           m->green_mult = cnew->green_mult;
+           m->blue_max   = cnew->blue_max;
+           m->blue_mult  = cnew->blue_mult;
+           m->base_pixel = cnew->base_pixel;
+           m->visualid   = cnew->visualid;
+           m->killid     = cnew->killid;
+
+           XSetRGBColormaps(dpy, win, s, ++count, property);
+           free((char *) s);
+       }
+       XFree((char *) stdcmaps);
+       return 0;
+    }
+
+    /* Found an RGB_DEFAULT_MAP property with a matching visualid */
+
+    if (replace) {
+       /* Free old resources first - we may need them, particularly in 
+        * the default colormap of the screen.  However, because of this,
+        * it is possible that we will destroy the old resource and fail 
+        * to create a new one if XmuStandardColormap() fails.
+        */
+
+       if (count == 1) {
+           XmuDeleteStandardColormap(dpy, screen, property);
+           if (cnew)
+               XSetRGBColormaps(dpy, win, cnew, 1, property);
+       }
+       else {
+           XStandardColormap   *map;
+
+           /* s still points to the matching standard colormap */
+
+           if (s->killid == ReleaseByFreeingColormap) {
+               if ((s->colormap != None) &&
+                   (s->colormap != DefaultColormap(dpy, screen)))
+                   XFreeColormap(dpy, s->colormap);
+           }
+           else if (s->killid != None)
+               XKillClient(dpy, s->killid);
+
+           map = (cnew) ? cnew : stdcmaps + --count;
+
+           s->colormap   = map->colormap;
+           s->red_max    = map->red_max;
+           s->red_mult   = map->red_mult;
+           s->green_max  = map->green_max;
+           s->green_mult = map->green_mult;
+           s->blue_max   = map->blue_max;
+           s->blue_mult  = map->blue_mult;
+           s->visualid   = map->visualid;
+           s->killid     = map->killid;
+
+           XSetRGBColormaps(dpy, win, stdcmaps, count, property);
+       }
+    }
+    XFree((char *) stdcmaps);
+    return 1;
+}
+
+/* $Xorg: CmapAlloc.c,v 1.4 2001/02/09 02:03:51 xorgcvs Exp $ */
+
+/* 
+
+Copyright 1989, 1994, 1998  The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+*/
+/* $XFree86: xc/lib/Xmu/CmapAlloc.c,v 1.7 2001/12/14 19:55:35 dawes Exp $ */
+
+/*
+ * Author:  Donna Converse, MIT X Consortium
+ */
+
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#include <X11/Xutil.h>
+#include <X11/Xmu/StdCmap.h>
+#include <stdio.h>
+
+#define lowbit(x) ((x) & (~(x) + 1))
+
+/*
+ * Prototypes
+ */
+static void best_allocation(XVisualInfo*, unsigned long*, unsigned long*,
+                           unsigned long*);
+static int default_allocation(XVisualInfo*, unsigned long*,
+                             unsigned long*, unsigned long*);
+static void gray_allocation(int, unsigned long*, unsigned long*,
+                           unsigned long*);
+static int icbrt(int);
+static int icbrt_with_bits(int, int);
+static int icbrt_with_guess(int, int);
+
+/* To determine the best allocation of reds, greens, and blues in a 
+ * standard colormap, use XmuGetColormapAllocation.
+ *     vinfo           specifies visual information for a chosen visual
+ *     property        specifies one of the standard colormap property names
+ *     red_max         returns maximum red value 
+ *      green_max      returns maximum green value
+ *     blue_max        returns maximum blue value
+ *
+ * XmuGetColormapAllocation returns 0 on failure, non-zero on success.
+ * It is assumed that the visual is appropriate for the colormap property.
+ */
+
+Status
+XmuGetColormapAllocation(XVisualInfo *vinfo, Atom property,
+                        unsigned long *red_max,
+                        unsigned long *green_max,
+                        unsigned long *blue_max)
+{
+    Status     status = 1;
+
+    if (vinfo->colormap_size <= 2)
+       return 0;
+
+    switch (property)
+    {
+      case XA_RGB_DEFAULT_MAP:
+       status = default_allocation(vinfo, red_max, green_max, blue_max);
+       break;
+      case XA_RGB_BEST_MAP:
+       best_allocation(vinfo, red_max, green_max, blue_max);
+       break;
+      case XA_RGB_GRAY_MAP:
+       gray_allocation(vinfo->colormap_size, red_max, green_max, blue_max);
+       break;
+      case XA_RGB_RED_MAP:
+       *red_max = vinfo->colormap_size - 1;
+       *green_max = *blue_max = 0;
+       break;
+      case XA_RGB_GREEN_MAP:
+       *green_max = vinfo->colormap_size - 1;
+       *red_max = *blue_max = 0;
+       break;
+      case XA_RGB_BLUE_MAP:
+       *blue_max = vinfo->colormap_size - 1;
+       *red_max = *green_max = 0;
+       break;
+      default:
+       status = 0;
+    }
+    return status;
+}
+
+/****************************************************************************/
+/* Determine the appropriate color allocations of a gray scale.
+ *
+ * Keith Packard, MIT X Consortium
+ */
+
+static void
+gray_allocation(int n, unsigned long *red_max, unsigned long *green_max,
+               unsigned long *blue_max)
+{
+    *red_max = (n * 30) / 100;
+    *green_max = (n * 59) / 100; 
+    *blue_max = (n * 11) / 100; 
+    *green_max += ((n - 1) - (*red_max + *green_max + *blue_max));
+}
+
+/****************************************************************************/
+/* Determine an appropriate color allocation for the RGB_DEFAULT_MAP.
+ * If a map has less than a minimum number of definable entries, we do not
+ * produce an allocation for an RGB_DEFAULT_MAP.  
+ *
+ * For 16 planes, the default colormap will have 27 each RGB; for 12 planes,
+ * 12 each.  For 8 planes, let n = the number of colormap entries, which may
+ * be 256 or 254.  Then, maximum red value = floor(cube_root(n - 125)) - 1.
+ * Maximum green and maximum blue values are identical to maximum red.
+ * This leaves at least 125 cells which clients can allocate.
+ *
+ * Return 0 if an allocation has been determined, non-zero otherwise.
+ */
+
+static int
+default_allocation(XVisualInfo *vinfo, unsigned long *red,
+                  unsigned long *green, unsigned long *blue)
+{
+    int                        ngrays;         /* number of gray cells */
+
+    switch (vinfo->c_class)
+      {
+      case PseudoColor:
+        
+        if (vinfo->colormap_size > 65000)
+          /* intended for displays with 16 planes */
+          *red = *green = *blue = (unsigned long) 27;
+        else if (vinfo->colormap_size > 4000)
+          /* intended for displays with 12 planes */
+           *red = *green = *blue = (unsigned long) 12;
+      else if (vinfo->colormap_size < 250)
+           return 0;
+      else
+           /* intended for displays with 8 planes */
+           *red = *green = *blue = (unsigned long)
+          (icbrt(vinfo->colormap_size - 125) - 1);
+      break;
+      
+    case DirectColor:
+      
+       if (vinfo->colormap_size < 10)
+           return 0;
+       *red = *green = *blue = vinfo->colormap_size / 2 - 1;
+       break;
+
+      case TrueColor:
+
+       *red = vinfo->red_mask / lowbit(vinfo->red_mask);
+       *green = vinfo->green_mask / lowbit(vinfo->green_mask);
+       *blue = vinfo->blue_mask / lowbit(vinfo->blue_mask);
+       break;
+
+      case GrayScale:
+
+       if (vinfo->colormap_size > 65000)
+           ngrays = 4096;
+       else if (vinfo->colormap_size > 4000)
+           ngrays = 512;
+       else if (vinfo->colormap_size < 250)
+           return 0;
+       else
+           ngrays = 12;
+       gray_allocation(ngrays, red, green, blue);
+       break;
+       
+      default:
+       return 0;
+    }
+    return 1;
+}
+
+/****************************************************************************/
+/* Determine an appropriate color allocation for the RGB_BEST_MAP.
+ *
+ * For a DirectColor or TrueColor visual, the allocation is determined
+ * by the red_mask, green_mask, and blue_mask members of the visual info.
+ *
+ * Otherwise, if the colormap size is an integral power of 2, determine
+ * the allocation according to the number of bits given to each color,
+ * with green getting more than red, and red more than blue, if there
+ * are to be inequities in the distribution.  If the colormap size is
+ * not an integral power of 2, let n = the number of colormap entries.
+ * Then maximum red value = floor(cube_root(n)) - 1;
+ *     maximum blue value = floor(cube_root(n)) - 1;
+ *     maximum green value = n / ((# red values) * (# blue values)) - 1;
+ * Which, on a GPX, allows for 252 entries in the best map, out of 254
+ * defineable colormap entries.
+ */
+static void
+best_allocation(XVisualInfo *vinfo, unsigned long *red, unsigned long *green,
+               unsigned long *blue)
+{
+
+    if (vinfo->c_class == DirectColor ||       vinfo->c_class == TrueColor)
+    {
+       *red = vinfo->red_mask;
+       while ((*red & 01) == 0)
+           *red >>= 1;
+       *green = vinfo->green_mask;
+       while ((*green & 01) == 0)
+           *green >>=1;
+       *blue = vinfo->blue_mask;
+       while ((*blue & 01) == 0)
+           *blue >>= 1;
+    }
+    else
+    {
+       register int bits, n;
+       
+       /* Determine n such that n is the least integral power of 2 which is
+        * greater than or equal to the number of entries in the colormap.
+         */
+       n = 1;
+       bits = 0;
+       while (vinfo->colormap_size > n)
+       {
+           n = n << 1;
+           bits++;
+       }
+       
+       /* If the number of entries in the colormap is a power of 2, determine
+        * the allocation by "dealing" the bits, first to green, then red, then
+        * blue.  If not, find the maximum integral red, green, and blue values
+        * which, when multiplied together, do not exceed the number of 
+
+        * colormap entries.
+        */
+       if (n == vinfo->colormap_size)
+       {
+           register int r, g, b;
+           b = bits / 3;
+           g = b + ((bits % 3) ? 1 : 0);
+           r = b + (((bits % 3) == 2) ? 1 : 0);
+           *red = 1 << r;
+           *green = 1 << g;
+           *blue = 1 << b;
+       }
+       else
+       {
+           *red = icbrt_with_bits(vinfo->colormap_size, bits);
+           *blue = *red;       
+           *green = (vinfo->colormap_size / ((*red) * (*blue)));
+       }
+       (*red)--;
+       (*green)--;
+       (*blue)--;
+    }
+    return;
+}
+
+/*
+ * integer cube roots by Newton's method
+ *
+ * Stephen Gildea, MIT X Consortium, July 1991
+ */
+
+static int
+icbrt(int a)
+{
+    register int bits = 0;
+    register unsigned n = a;
+
+    while (n)
+    {
+       bits++;
+       n >>= 1;
+    }
+    return icbrt_with_bits(a, bits);
+}
+
+
+static int
+icbrt_with_bits(int a, int bits)
+     /* bits - log 2 of a */
+{
+    return icbrt_with_guess(a, a>>2*bits/3);
+}
+
+#ifdef _X_ROOT_STATS
+int icbrt_loopcount;
+#endif
+
+/* Newton's Method:  x_n+1 = x_n - ( f(x_n) / f'(x_n) ) */
+
+/* for cube roots, x^3 - a = 0,  x_new = x - 1/3 (x - a/x^2) */
+
+/*
+ * Quick and dirty cube roots.  Nothing fancy here, just Newton's method.
+ * Only works for positive integers (since that's all we need).
+ * We actually return floor(cbrt(a)) because that's what we need here, too.
+ */
+
+static int
+icbrt_with_guess(int a, int guess)
+{
+    register int delta;
+
+#ifdef _X_ROOT_STATS
+    icbrt_loopcount = 0;
+#endif
+    if (a <= 0)
+       return 0;
+    if (guess < 1)
+       guess = 1;
+
+    do {
+#ifdef _X_ROOT_STATS
+       icbrt_loopcount++;
+#endif
+       delta = (guess - a/(guess*guess))/3;
+#ifdef DEBUG
+       printf("pass %d: guess=%d, delta=%d\n", icbrt_loopcount, guess, delta);
+#endif
+       guess -= delta;
+    } while (delta != 0);
+
+    if (guess*guess*guess > a)
+       guess--;
+
+    return guess;
+}
+
+
+/* $Xorg: StdCmap.c,v 1.4 2001/02/09 02:03:53 xorgcvs Exp $ */
+
+/* 
+
+Copyright 1989, 1998  The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+*/
+/* $XFree86: xc/lib/Xmu/StdCmap.c,v 1.6 2001/12/14 19:55:48 dawes Exp $ */
+
+/*
+ * Author:  Donna Converse, MIT X Consortium
+ */
+
+#include <stdio.h>
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#include <X11/Xutil.h>
+#include <X11/Xmu/StdCmap.h>
+
+#define lowbit(x) ((x) & (~(x) + 1))
+
+/*
+ * Prototypes
+ */
+/* argument restrictions */
+static Status valid_args(XVisualInfo*, unsigned long, unsigned long,
+                        unsigned long, Atom);
+
+/*
+ * To create any one standard colormap, use XmuStandardColormap().
+ *
+ * Create a standard colormap for the given screen, visualid, and visual
+ * depth, with the given red, green, and blue maximum values, with the
+ * given standard property name.  Return a pointer to an XStandardColormap
+ * structure which describes the newly created colormap, upon success.
+ * Upon failure, return NULL.
+ * 
+ * XmuStandardColormap() calls XmuCreateColormap() to create the map.
+ *
+ * Resources created by this function are not made permanent; that is the
+ * caller's responsibility.
+ */
+
+XStandardColormap *
+XmuStandardColormap(Display *dpy, int screen, VisualID visualid,
+                   unsigned int depth, Atom property, Colormap cmap,
+                   unsigned long red_max, unsigned long green_max,
+                   unsigned long blue_max)
+     /*
+      * dpy                            - specifies X server connection
+      * screen                         - specifies display screen
+      * visualid                       - identifies the visual type
+      * depth                          - identifies the visual type
+      * property                       - a standard colormap property
+      * cmap                           - specifies colormap ID or None
+      * red_max, green_max, blue_max   - allocations
+      */
+{
+    XStandardColormap  *stdcmap;
+    Status             status;
+    XVisualInfo                vinfo_template, *vinfo;
+    long               vinfo_mask;
+    int                        n;
+
+    /* Match the required visual information to an actual visual */
+    vinfo_template.visualid = visualid;        
+    vinfo_template.screen = screen;
+    vinfo_template.depth = depth;
+    vinfo_mask = VisualIDMask | VisualScreenMask | VisualDepthMask;
+    if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &n)) == NULL)
+       return 0;
+
+    /* Check the validity of the combination of visual characteristics,
+     * allocation, and colormap property.  Create an XStandardColormap
+     * structure.
+     */
+
+    if (! valid_args(vinfo, red_max, green_max, blue_max, property)
+       || ((stdcmap = XAllocStandardColormap()) == NULL)) {
+       XFree((char *) vinfo);
+       return 0;
+    }
+
+    /* Fill in the XStandardColormap structure */
+
+    if (cmap == DefaultColormap(dpy, screen)) {
+       /* Allocating out of the default map, cannot use XFreeColormap() */
+       Window win = XCreateWindow(dpy, RootWindow(dpy, screen), 1, 1, 1, 1,
+                                  0, 0, InputOnly, vinfo->visual,
+                                  (unsigned long) 0,
+                                  (XSetWindowAttributes *)NULL);
+       stdcmap->killid  = (XID) XCreatePixmap(dpy, win, 1, 1, depth);
+       XDestroyWindow(dpy, win);
+       stdcmap->colormap = cmap;
+    } else {
+       stdcmap->killid = ReleaseByFreeingColormap;
+       stdcmap->colormap = XCreateColormap(dpy, RootWindow(dpy, screen),
+                                           vinfo->visual, AllocNone);
+    }
+    stdcmap->red_max = red_max;
+    stdcmap->green_max = green_max;
+    stdcmap->blue_max = blue_max;
+    if (property == XA_RGB_GRAY_MAP) 
+       stdcmap->red_mult = stdcmap->green_mult = stdcmap->blue_mult = 1;
+    else if (vinfo->c_class == TrueColor || vinfo->c_class == DirectColor) {
+       stdcmap->red_mult = lowbit(vinfo->red_mask);
+       stdcmap->green_mult = lowbit(vinfo->green_mask);
+       stdcmap->blue_mult = lowbit(vinfo->blue_mask);
+    } else {
+       stdcmap->red_mult = (red_max > 0)
+           ? (green_max + 1) * (blue_max + 1) : 0;
+       stdcmap->green_mult = (green_max > 0) ? blue_max + 1 : 0;
+       stdcmap->blue_mult = (blue_max > 0) ? 1 : 0;
+    }
+    stdcmap->base_pixel = 0;                   /* base pixel may change */
+    stdcmap->visualid = vinfo->visualid;
+
+    /* Make the colormap */
+
+    status = XmuCreateColormap(dpy, stdcmap);
+
+    /* Clean up */
+
+    XFree((char *) vinfo);
+    if (!status) {
+
+       /* Free the colormap or the pixmap, if we created one */
+       if (stdcmap->killid == ReleaseByFreeingColormap)
+           XFreeColormap(dpy, stdcmap->colormap);
+       else if (stdcmap->killid != None)
+           XFreePixmap(dpy, stdcmap->killid);
+       
+       XFree((char *) stdcmap);
+       return (XStandardColormap *) NULL;
+    }
+    return stdcmap;
+}
+
+/****************************************************************************/
+static Status
+valid_args(XVisualInfo *vinfo, unsigned long red_max, unsigned long green_max,
+          unsigned long blue_max, Atom property)
+     /*
+      * vinfo                          - specifies visual
+      * red_max, green_max, blue_max   - specifies alloc
+      * property                       - specifies property name
+      */
+{
+    unsigned long      ncolors;        /* number of colors requested */
+
+    /* Determine that the number of colors requested is <= map size */
+
+    if ((vinfo->c_class == DirectColor) || (vinfo->c_class == TrueColor)) {
+       unsigned long mask;
+
+       mask = vinfo->red_mask;
+       while (!(mask & 1))
+           mask >>= 1;
+       if (red_max > mask)
+           return 0;
+       mask = vinfo->green_mask;
+       while (!(mask & 1))
+           mask >>= 1;
+       if (green_max > mask)
+           return 0;
+       mask = vinfo->blue_mask;
+       while (!(mask & 1))
+           mask >>= 1;
+       if (blue_max > mask)
+           return 0;
+    } else if (property == XA_RGB_GRAY_MAP) {
+       ncolors = red_max + green_max + blue_max + 1;
+       if (ncolors > vinfo->colormap_size)
+           return 0;
+    } else {
+       ncolors = (red_max + 1) * (green_max + 1) * (blue_max + 1);
+       if (ncolors > vinfo->colormap_size)
+           return 0;
+    }
+    
+    /* Determine that the allocation and visual make sense for the property */
+
+    switch (property)
+    {
+      case XA_RGB_DEFAULT_MAP:
+       if (red_max == 0 || green_max == 0 || blue_max == 0)
+           return 0;
+       break;
+      case XA_RGB_RED_MAP:
+       if (red_max == 0)
+           return 0;
+       break;
+      case XA_RGB_GREEN_MAP:
+       if (green_max == 0)
+           return 0;
+       break;
+      case XA_RGB_BLUE_MAP:    
+       if (blue_max == 0)
+           return 0;
+       break;
+      case XA_RGB_BEST_MAP:
+       if (red_max == 0 || green_max == 0 || blue_max == 0)
+           return 0;
+       break;
+      case XA_RGB_GRAY_MAP:
+       if (red_max == 0 || blue_max == 0 || green_max == 0)
+           return 0;
+       break;
+      default:
+       return 0;
+    }
+    return 1;
+}
+
+
+/* $Xorg: CrCmap.c,v 1.4 2001/02/09 02:03:51 xorgcvs Exp $ */
+
+/* 
+
+Copyright 1989, 1998  The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+*/
+/* $XFree86: xc/lib/Xmu/CrCmap.c,v 3.7 2001/12/14 19:55:36 dawes Exp $ */
+
+/*
+ * Author:  Donna Converse, MIT X Consortium
+ */
+
+/*
+ * CreateCmap.c - given a standard colormap description, make the map.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xmu/StdCmap.h>
+
+/*
+ * Prototypes
+ */
+/* allocate entire map Read Only */
+static int ROmap(Display*, Colormap, unsigned long[], int, int);
+
+/* allocate a cell, prefer Read Only */
+static Status ROorRWcell(Display*, Colormap, unsigned long[], int,
+                        XColor*, unsigned long);
+
+/* allocate a cell Read Write */
+static Status RWcell(Display*, Colormap, XColor*, XColor*, unsigned long*);
+
+/* for quicksort */
+static int compare(_Xconst void*, _Xconst void*);
+
+/* find contiguous sequence of cells */
+static Status contiguous(unsigned long[], int, int, unsigned long, int*, int*);
+
+/* frees resources before quitting */
+static void free_cells(Display*, Colormap, unsigned long[], int, int);
+
+/* create a map in a RO visual type */
+static Status readonly_map(Display*, XVisualInfo*, XStandardColormap*);
+
+/* create a map in a RW visual type */
+static Status readwrite_map(Display*, XVisualInfo*, XStandardColormap*);
+
+#define lowbit(x) ((x) & (~(x) + 1))
+#define TRUEMATCH(mult,max,mask) \
+    (colormap->max * colormap->mult <= vinfo->mask && \
+     lowbit(vinfo->mask) == colormap->mult)
+
+/*
+ * To create any one colormap which is described by an XStandardColormap
+ * structure, use XmuCreateColormap().
+ *
+ * Return 0 on failure, non-zero on success.
+ * Resources created by this function are not made permanent.
+ * No argument error checking is provided.  Use at your own risk.
+ *
+ * All colormaps are created with read only allocations, with the exception
+ * of read only allocations of colors in the default map or otherwise
+ * which fail to return the expected pixel value, and these are individually 
+ * defined as read/write allocations.  This is done so that all the cells
+ * defined in the default map are contiguous, for use in image processing.
+ * This typically happens with White and Black in the default map.
+ *
+ * Colormaps of static visuals are considered to be successfully created if
+ * the map of the static visual matches the definition given in the
+ * standard colormap structure.
+ */
+   
+Status
+XmuCreateColormap(Display *dpy, XStandardColormap *colormap)
+     /* dpy     - specifies the connection under which the map is created
+      * colormap - specifies the map to be created, and returns, particularly
+      *                   if the map is created as a subset of the default colormap
+      *                   of the screen, the base_pixel of the map.
+                                        */
+{
+    XVisualInfo                vinfo_template; /* template visual information */
+    XVisualInfo                *vinfo;         /* matching visual information */
+    XVisualInfo                *vpointer;      /* for freeing the entire list */
+    long               vinfo_mask;     /* specifies the visual mask value */
+    int                n;              /* number of matching visuals */
+    int                        status;         
+
+    vinfo_template.visualid = colormap->visualid;
+    vinfo_mask = VisualIDMask;
+    if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &n)) == NULL)
+       return 0;
+
+    /* A visual id may be valid on multiple screens.  Also, there may 
+     * be multiple visuals with identical visual ids at different depths.  
+     * If the colormap is the Default Colormap, use the Default Visual.
+     * Otherwise, arbitrarily, use the deepest visual.
+     */
+    vpointer = vinfo;
+    if (n > 1)
+    {
+       register int    i;
+       register int    screen_number;
+       Bool            def_cmap;
+
+       def_cmap = False;
+       for (screen_number = ScreenCount(dpy); --screen_number >= 0; )
+           if (colormap->colormap == DefaultColormap(dpy, screen_number)) {
+               def_cmap = True;
+               break;
+           }
+
+       if (def_cmap) {
+           for (i=0; i < n; i++, vinfo++) {
+               if (vinfo->visual == DefaultVisual(dpy, screen_number))
+                       break;
+           }
+       } else {
+           int                 maxdepth = 0;
+           XVisualInfo         *v = NULL;
+
+           for (i=0; i < n; i++, vinfo++)
+               if (vinfo->depth > maxdepth) {
+                   maxdepth = vinfo->depth;
+                   v = vinfo;
+               }
+           vinfo = v;
+       }
+    }
+
+    if (vinfo->c_class == PseudoColor || vinfo->c_class == DirectColor ||
+       vinfo->c_class == GrayScale)
+       status = readwrite_map(dpy, vinfo, colormap);
+    else if (vinfo->c_class == TrueColor)
+       status = TRUEMATCH(red_mult, red_max, red_mask) &&
+                TRUEMATCH(green_mult, green_max, green_mask) &&
+                TRUEMATCH(blue_mult, blue_max, blue_mask);
+    else 
+       status = readonly_map(dpy, vinfo, colormap);
+    
+    XFree((char *) vpointer);
+    return status;
+}
+
+/****************************************************************************/
+static Status
+readwrite_map(Display *dpy, XVisualInfo *vinfo, XStandardColormap *colormap)
+{
+    register unsigned long i, n;       /* index counters */
+    unsigned long      ncolors;        /* number of colors to be defined */
+    int                        npixels;        /* number of pixels allocated R/W */
+    int                        first_index;    /* first index of pixels to use */
+    int                        remainder;      /* first index of remainder */
+    XColor             color;          /* the definition of a color */
+    unsigned long      *pixels;        /* array of colormap pixels */
+    unsigned long      delta;
+
+    
+    /* Determine ncolors, the number of colors to be defined.
+     * Insure that 1 < ncolors <= the colormap size.
+     */
+    if (vinfo->c_class == DirectColor) {
+       ncolors = colormap->red_max;
+       if (colormap->green_max > ncolors)
+           ncolors = colormap->green_max;
+       if (colormap->blue_max > ncolors)
+           ncolors = colormap->blue_max;
+       ncolors++;
+       delta = lowbit(vinfo->red_mask) +
+               lowbit(vinfo->green_mask) +
+               lowbit(vinfo->blue_mask);
+    } else {
+       ncolors = colormap->red_max * colormap->red_mult +
+                 colormap->green_max * colormap->green_mult +
+                 colormap->blue_max * colormap->blue_mult + 1;
+       delta = 1;
+    }
+    if (ncolors <= 1 || (int) ncolors > vinfo->colormap_size)  return 0;
+
+    /* Allocate Read/Write as much of the colormap as we can possibly get.
+     * Then insure that the pixels we were allocated are given in 
+     * monotonically increasing order, using a quicksort.  Next, insure
+     * that our allocation includes a subset of contiguous pixels at least
+     * as long as the number of colors to be defined.  Now we know that 
+     * these conditions are met:
+     * 1) There are no free cells in the colormap.
+     *  2) We have a contiguous sequence of pixels, monotonically 
+     *     increasing, of length >= the number of colors requested.
+     *
+     * One cell at a time, we will free, compute the next color value, 
+     * then allocate read only.  This takes a long time.
+     * This is done to insure that cells are allocated read only in the
+     * contiguous order which we prefer.  If the server has a choice of
+     * cells to grant to an allocation request, the server may give us any
+     * cell, so that is why we do these slow gymnastics.
+     */
+
+    if ((pixels = (unsigned long *) calloc((unsigned) vinfo->colormap_size,
+                                     sizeof(unsigned long))) == NULL)
+       return 0;
+
+    if ((npixels = ROmap(dpy, colormap->colormap, pixels,
+                          vinfo->colormap_size, ncolors)) == 0) {
+       free((char *) pixels);
+       return 0;
+    }
+
+    qsort((char *) pixels, npixels, sizeof(unsigned long), compare);
+
+    if (!contiguous(pixels, npixels, ncolors, delta, &first_index, &remainder))
+    {
+       /* can't find enough contiguous cells, give up */
+       XFreeColors(dpy, colormap->colormap, pixels, npixels,
+                   (unsigned long) 0);
+       free((char *) pixels);
+       return 0;
+    }
+    colormap->base_pixel = pixels[first_index];
+
+    /* construct a gray map */
+    if (colormap->red_mult == 1 && colormap->green_mult == 1 &&
+       colormap->blue_mult == 1)
+       for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
+       {
+           color.pixel = n;
+           color.blue = color.green = color.red =
+               (unsigned short) ((i * 65535) / (colormap->red_max +
+                                                colormap->green_max +
+                                                colormap->blue_max));
+
+           if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
+                            first_index + i))
+               return 0;
+       }
+
+    /* construct a red ramp map */
+    else if (colormap->green_max == 0 && colormap->blue_max == 0)
+       for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
+       {
+           color.pixel = n;
+           color.red = (unsigned short) ((i * 65535) / colormap->red_max);
+           color.green = color.blue = 0;
+
+           if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
+                            first_index + i))
+               return 0;
+       }
+
+    /* construct a green ramp map */
+    else if (colormap->red_max == 0 && colormap->blue_max == 0)
+       for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
+       {
+           color.pixel = n;
+           color.green = (unsigned short) ((i * 65535) / colormap->green_max);
+           color.red = color.blue = 0;
+
+           if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
+                            first_index + i))
+               return 0;
+       }
+
+    /* construct a blue ramp map */
+    else if (colormap->red_max == 0 && colormap->green_max == 0)
+       for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
+       {
+           color.pixel = n;
+           color.blue = (unsigned short) ((i * 65535) / colormap->blue_max);
+           color.red = color.green = 0;
+
+           if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
+                            first_index + i))
+               return 0;
+       }
+
+    /* construct a standard red green blue cube map */
+    else
+    {
+#define calc(max,mult) (((n / colormap->mult) % \
+                        (colormap->max + 1)) * 65535) / colormap->max
+
+       for (n=0, i=0; i < ncolors; i++, n += delta)
+       {
+           color.pixel = n + colormap->base_pixel;
+           color.red = calc(red_max, red_mult);
+           color.green = calc(green_max, green_mult);
+           color.blue = calc(blue_max, blue_mult);
+           if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
+                            first_index + i))
+               return 0;
+       }
+#undef calc
+    }
+    /* We have a read-only map defined.  Now free unused cells,
+     * first those occuring before the contiguous sequence begins,
+     * then any following the contiguous sequence.
+     */
+
+    if (first_index)
+       XFreeColors(dpy, colormap->colormap, pixels, first_index, 
+                   (unsigned long) 0);
+    if (remainder)
+       XFreeColors(dpy, colormap->colormap,
+                   &(pixels[first_index + ncolors]), remainder,
+                   (unsigned long) 0);
+
+    free((char *) pixels);
+    return 1;
+}
+
+
+/****************************************************************************/
+static int
+ROmap(Display *dpy, Colormap cmap, unsigned long pixels[], int m, int n)
+     /*
+      * dpy    - the X server connection
+      * cmap   - specifies colormap ID
+      * pixels - returns pixel allocations
+      * m      - specifies colormap size
+      * n      - specifies number of colors
+      */
+{
+    register int       p;
+
+    /* first try to allocate the entire colormap */
+    if (XAllocColorCells(dpy, cmap, 1, (unsigned long *) NULL, 
+                        (unsigned) 0, pixels, (unsigned) m))
+       return m;
+
+    /* Allocate all available cells in the colormap, using a binary
+     * algorithm to discover how many cells we can allocate in the colormap.
+     */
+    m--;
+    while (n <= m) {
+       p = n + ((m - n + 1) / 2);
+       if (XAllocColorCells(dpy, cmap, 1, (unsigned long *) NULL,
+                            (unsigned) 0, pixels, (unsigned) p)) {
+           if (p == m)
+               return p;
+           else {
+               XFreeColors(dpy, cmap, pixels, p, (unsigned long) 0);
+               n = p;
+           }
+       }
+       else
+           m = p - 1;
+    }
+    return 0;
+}
+      
+
+/****************************************************************************/
+static Status
+contiguous(unsigned long pixels[], int npixels, int ncolors,
+          unsigned long delta, int *first, int *rem)
+     /* pixels - specifies allocated pixels
+      * npixels        - specifies count of alloc'd pixels
+      * ncolors - specifies needed sequence length
+      * delta  - between pixels
+      * first  - returns first index of sequence
+      * rem    - returns first index after sequence, or 0, if none follow
+      */
+{
+    register int i = 1;                /* walking index into the pixel array */
+    register int count = 1;    /* length of sequence discovered so far */
+
+    *first = 0;
+    if (npixels == ncolors) {
+       *rem = 0;
+       return 1;
+    }
+    *rem = npixels - 1;
+    while (count < ncolors && ncolors - count <= *rem)
+    {
+       if (pixels[i-1] + delta == pixels[i])
+           count++;
+       else {
+           count = 1;
+           *first = i;
+       }
+       i++;
+       (*rem)--;
+    }
+    if (count != ncolors)
+       return 0;
+    return 1;
+}
+
+
+/****************************************************************************/
+static Status
+ROorRWcell(Display *dpy, Colormap cmap, unsigned long pixels[],
+          int npixels, XColor *color, unsigned long p)
+{
+    unsigned long      pixel;
+    XColor             request;
+
+    /* Free the read/write allocation of one cell in the colormap.
+     * Request a read only allocation of one cell in the colormap.
+     * If the read only allocation cannot be granted, give up, because
+     * there must be no free cells in the colormap.
+     * If the read only allocation is granted, but gives us a cell which
+     * is not the one that we just freed, it is probably the case that
+     * we are trying allocate White or Black or some other color which
+     * already has a read-only allocation in the map.  So we try to 
+     * allocate the previously freed cell with a read/write allocation,
+     * because we want contiguous cells for image processing algorithms.
+     */
+     
+    pixel = color->pixel;
+    request.red = color->red;
+    request.green = color->green;
+    request.blue = color->blue;
+
+    XFreeColors(dpy, cmap, &pixel, 1, (unsigned long) 0);
+    if (! XAllocColor(dpy, cmap, color) 
+       || (color->pixel != pixel &&
+           (!RWcell(dpy, cmap, color, &request, &pixel)))) 
+    {
+       free_cells(dpy, cmap, pixels, npixels, (int)p);
+       return 0;
+    }
+    return 1;
+}
+
+
+/****************************************************************************/
+static void
+free_cells(Display *dpy, Colormap cmap, unsigned long pixels[],
+          int npixels, int p)
+     /*
+      * pixels - to be freed
+      *        npixels - original number allocated
+      */
+{
+    /* One of the npixels allocated has already been freed.
+     * p is the index of the freed pixel.
+     * First free the pixels preceeding p, and there are p of them;
+     * then free the pixels following p, there are npixels - p - 1 of them.
+     */
+    XFreeColors(dpy, cmap, pixels, p, (unsigned long) 0);
+    XFreeColors(dpy, cmap, &(pixels[p+1]), npixels - p - 1, (unsigned long) 0);
+    free((char *) pixels);
+}
+
+
+/****************************************************************************/
+static Status
+RWcell(Display *dpy, Colormap cmap, XColor *color, XColor *request,
+       unsigned long *pixel)
+{
+    unsigned long      n = *pixel;
+
+    XFreeColors(dpy, cmap, &(color->pixel), 1, (unsigned long)0);
+    if (! XAllocColorCells(dpy, cmap, (Bool) 0, (unsigned long *) NULL,
+                          (unsigned) 0, pixel, (unsigned) 1))
+       return 0;
+    if (*pixel != n)
+    {
+       XFreeColors(dpy, cmap, pixel, 1, (unsigned long) 0);
+       return 0;
+    }
+    color->pixel = *pixel;
+    color->flags = DoRed | DoGreen | DoBlue;
+    color->red = request->red;
+    color->green = request->green;
+    color->blue = request->blue;
+    XStoreColors(dpy, cmap, color, 1);
+    return 1;
+}
+
+
+/****************************************************************************/
+static int
+compare(_Xconst void *e1, _Xconst void *e2)
+{
+  return ((int)(*(long *)e1 - *(long *)e2));
+}
+
+
+/****************************************************************************/
+static Status
+readonly_map(Display *dpy, XVisualInfo *vinfo, XStandardColormap *colormap)
+{
+    int                        i, last_pixel;
+    XColor             color;
+
+    last_pixel = (colormap->red_max + 1) * (colormap->green_max + 1) * 
+       (colormap->blue_max + 1) + colormap->base_pixel - 1;
+
+    for(i=colormap->base_pixel; i <= last_pixel; i++) {
+
+       color.pixel = (unsigned long) i;
+       color.red = (unsigned short)
+           (((i/colormap->red_mult) * 65535) / colormap->red_max);
+
+       if (vinfo->c_class == StaticColor) {
+           color.green = (unsigned short)
+               ((((i/colormap->green_mult) % (colormap->green_max + 1)) *
+                 65535) / colormap->green_max);
+           color.blue = (unsigned short)
+               (((i%colormap->green_mult) * 65535) / colormap->blue_max);
+       }
+       else    /* vinfo->c_class == GrayScale, old style allocation XXX */
+           color.green = color.blue = color.red;
+
+       XAllocColor(dpy, colormap->colormap, &color);
+       if (color.pixel != (unsigned long) i)
+           return 0;
+    }
+    return 1;
+}
+
+
+/* $Xorg: DelCmap.c,v 1.4 2001/02/09 02:03:52 xorgcvs Exp $ */
+
+/* 
+Copyright 1989, 1998  The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+*/
+/* $XFree86: xc/lib/Xmu/DelCmap.c,v 1.7 2001/12/14 19:55:40 dawes Exp $ */
+
+/*
+ * Author:  Donna Converse, MIT X Consortium
+ */
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xmu/StdCmap.h>
+
+int ignoreErrorHandler(Display* d, XErrorEvent* e) { }
+
+/* To remove any standard colormap property, use XmuDeleteStandardColormap().
+ * XmuDeleteStandardColormap() will remove the specified property from the
+ * specified screen, releasing any resources used by the colormap(s) of the
+ * property if possible.
+ */
+
+void
+XmuDeleteStandardColormap(Display *dpy, int screen, Atom property)
+     /* dpy;           - specifies the X server to connect to
+      * screen         - specifies the screen of the display
+      * property       - specifies the standard colormap property
+      */
+{
+    XStandardColormap  *stdcmaps, *s;
+    int                        count = 0;
+
+    if (XGetRGBColormaps(dpy, RootWindow(dpy, screen), &stdcmaps, &count,
+                         property))
+        {
+            for (s=stdcmaps; count > 0; count--, s++) {
+                if ((s->killid == ReleaseByFreeingColormap) &&
+                    (s->colormap != None) &&
+                    (s->colormap != DefaultColormap(dpy, screen))) {
+
+                    // UGLY HACK written in by Adam Megacz -- sometimes s->colormap isn't valid, so we do some shuffling
+                    X11ErrorHandler* oldHandler = XSetErrorHandler(ignoreErrorHandler);
+                    XSync(dpy, False);
+                    XFreeColormap(dpy, s->colormap);
+                    XSync(dpy, False);
+                    XSetErrorHandler(oldHandler);
+                    XSync(dpy, False);
+
+                } else if (s->killid != None) {
+                    XKillClient(dpy, s->killid);
+                }
+            }
+            XDeleteProperty(dpy, RootWindow(dpy, screen), property);
+            XFree((char *) stdcmaps);
+            XSync(dpy, False);
+        }
+}
+
diff --git a/src/org/xwt/plat/X11.java b/src/org/xwt/plat/X11.java
new file mode 100644 (file)
index 0000000..a65c41b
--- /dev/null
@@ -0,0 +1,350 @@
+// Copyright 2002 Adam Megacz, see the COPYING file for licensing [LGPL]
+package org.xwt.plat;
+
+import java.awt.*;
+import java.awt.image.*;
+import gnu.gcj.RawData;
+import java.net.*;
+import java.lang.reflect.*;
+import java.io.*;
+import java.util.*;
+import java.awt.peer.*;
+import org.xwt.util.*;
+import org.xwt.*;
+
+/** Platform implementation for POSIX compliant operating systems with an X11 Server */
+public class X11 extends POSIX {
+
+    // Static Data ///////////////////////////////////////////////////////////
+
+    /**
+     *  When the user reads from the clipboard, the main thread blocks
+     *  on this semaphore until we get an X11 SelectionNotify. Crude,
+     *  but effective. We know that only one thread will ever block on
+     *  this, since only one thread can ever be running JavaScript.
+     */
+    public static Semaphore waiting_for_selection_event = new Semaphore();
+
+    /** our local (in-process) copy of the clipboard */
+    public static String clipboard = null;
+
+    /** map from Window's (casted to jlong, wrapped in java.lang.Long) to X11Surface objects */
+    public static Hashtable windowToSurfaceMap = new Hashtable();
+
+
+    // General Methods ///////////////////////////////////////////////////////
+
+    protected String _getAltKeyName() { return System.getProperty("os.name", "").indexOf("SunOS") != -1 ? "Meta" : "Alt"; }
+    protected String[] _listFonts() { return fontList; }
+
+    protected Picture _createPicture(int[] data, int w, int h) { return new POSIX.X11Picture(data, w, h); }
+    protected DoubleBuffer _createDoubleBuffer(int w, int h, Surface owner) { return new POSIX.X11DoubleBuffer(w, h); }
+    protected Surface _createSurface(Box b, boolean framed) { return new X11Surface(b, framed); }
+    protected boolean _needsAutoClick() { return true; }
+    protected native int _getScreenWidth();
+    protected native int _getScreenHeight();
+    protected native String _getClipBoard();
+    protected native void _setClipBoard(String s);
+    protected native int _stringWidth(String font, String text);
+    protected native int _getMaxAscent(String font);
+    protected native int _getMaxDescent(String font);
+    protected boolean _needsAutoDoubleClick() { return true; }
+    protected native void eventThread();
+    private native void natInit();
+
+    public void init() {
+       super.init();
+        (new Thread() { public void run() { eventThread(); } }).start();
+        initFonts();
+    }
+
+    // X11Surface /////////////////////////////////////////////////////
+
+    /** Implements a Surface as an X11 Window */
+    public static class X11Surface extends Surface {
+        
+        gnu.gcj.RawData window;
+        gnu.gcj.RawData gc;
+        boolean framed = false;
+        Semaphore waitForCreation = new Semaphore();
+        
+        public native void setInvisible(boolean i);
+        public void _setMaximized(boolean m) { if (Log.on) Log.log(this, "POSIX/X11 can't maximize windows"); }
+        public native void setIcon(Picture p);
+        public native void _setMinimized(boolean b);
+        public native void setTitleBarText(String s);
+        public native void setSize(int w, int h);
+        public native void setLocation(int x, int y);
+        public native void natInit();
+        public native void toFront();
+        public native void toBack();
+        public native void syncCursor();
+        public native void _dispose();
+        public native void setLimits(int minw, int minh, int maxw, int maxh);
+        public native void blit(DoubleBuffer s, int sx, int sy, int dx, int dy, int dx2, int dy2);
+        public native void dispatchEvent(gnu.gcj.RawData ev);
+
+        public X11Surface(Box root, boolean framed) {
+            super(root);
+            this.framed = framed;
+            natInit();
+        }        
+    
+    }
+
+
+    // Our Subclass of Picture ///////////////////////////////////////////////
+
+    /**
+     *  Implements a Picture. No special X11 structure is created
+     *  unless the image has no alpha (in which case a
+     *  non-shared-pixmap DoubleBuffer is created), or all-or-nothing
+     *  alpha (in which case a non-shared-pixmap DoubleBuffer with a
+     *  stipple bitmap is created).
+     */
+    public static class X11Picture extends Picture {
+        
+        int width;
+        int height;
+        int[] data = null;
+        public X11DoubleBuffer doublebuf = null;
+
+        public int getWidth() { return width; }
+        public int getHeight() { return height; }
+
+        public X11Picture(int[] data, int w, int h) {
+            this.data = data;
+            this.width = w;
+            this.height = h;
+            boolean needsStipple = false;
+
+            // if we have any non-0x00, non-0xFF alphas, we can't double buffer ourselves
+            for(int i=0; i<w*h; i++)
+                if ((data[i] & 0xFF000000) == 0xFF000000)
+                    needsStipple = true;
+                else if ((data[i] & 0xFF000000) != 0x00)
+                    return;
+
+            buildDoubleBuffer(needsStipple);
+        }
+
+        void buildDoubleBuffer(boolean needsStipple) {
+            if (doublebuf != null) return;
+            // no point in using a shared pixmap since we'll only write to this image once
+            X11DoubleBuffer b = new X11DoubleBuffer(width, height, false);
+            b.drawPicture(this, 0, 0);
+            if (needsStipple) b.createStipple(this);
+            doublebuf = b;
+        }
+
+    }
+
+    /**
+     *  An X11DoubleBuffer is implemented as an X11 pixmap. "Normal"
+     *  DoubleBuffers will use XShm shared pixmaps if
+     *  available. X11DoubleBuffers created to accelerate Pictures
+     *  with all-or-nothing alpha will not use shared pixmaps, however
+     *  (since they are only written to once.
+     */
+    public static class X11DoubleBuffer extends DoubleBuffer {
+
+        int clipx, clipy, clipw, cliph;
+        int width;
+        int height;
+
+        /** DoubleBuffers of X11Pictures can have stipples -- the stipple of the Picture */
+        RawData stipple = null;
+
+        /** Sets the DoubleBuffer's internal stipple to the alpha==0x00 regions of xpi */
+        public native void createStipple(X11Picture xpi);
+        
+        RawData pm;                    // Pixmap (if any) representing this Picture
+        boolean shared_pixmap = false; // true if pm is a ShmPixmap
+        RawData fake_ximage = null;    // a 'fake' XImage corresponding to the shared pixmap; gives us the address and depth parameters
+        RawData shm_segment = null;    // XShmSegmentInfo
+
+        RawData gc;                    // Graphics Context on pm (never changes, so it's fast)
+        RawData clipped_gc;            // Graphics Context on pm, use this one if you need a clip/stipple
+
+        /** DoubleBuffer mode */
+        public X11DoubleBuffer(int w, int h) { this(w, h, true); }
+        public X11DoubleBuffer(int w, int h, boolean shared_pixmap) {
+            width = clipw = w;
+            height = cliph = h;
+            clipx = clipy = 0;
+            this.shared_pixmap = shared_pixmap;
+            natInit();
+        }
+
+        public void setClip(int x, int y, int x2, int y2) {
+            clipx = x; if (clipx < 0) clipx = 0;
+            clipy = y; if (clipy < 0) clipy = 0;
+            clipw = x2 - x; if (clipw < 0) clipw = 0;
+            cliph = y2 - y; if (cliph < 0) cliph = 0;
+        }
+        
+        public void drawPicture(Picture source, int x, int y) {
+            drawPicture(source, x, y, x + source.getWidth(), y + source.getHeight(), 0, 0, source.getWidth(), source.getHeight());
+        }
+
+        public void drawPicture(Picture source, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2) {
+            if (!(dx2 - dx1 != sx2 - sx1 || dy2 - dy1 != sy2 - sy1) && ((X11Picture)source).doublebuf != null)
+                fastDrawPicture(source, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2);
+            else 
+                slowDrawPicture(source, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2);
+        }
+
+        /** fast path for image drawing (no scaling, all-or-nothing alpha) */
+        public native void fastDrawPicture(Picture source, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2);
+
+        /** slow path for image drawing */
+        public native void slowDrawPicture(Picture source, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2);
+
+        public int getWidth() { return width; }
+        public int getHeight() { return height; }
+        public native void natInit();
+        public native void fillRect(int x, int y, int x2, int y2, int color);
+        public native void drawString(String font, String text, int x, int y, int color);
+        public native void finalize();
+
+    }
+
+
+    // Font Handling ////////////////////////////////////////////////////////////////////
+
+    static String[] fontList = null;
+
+    /** hashtable of all built in X11 fonts; key is XWT font spec, value is X11 font string */
+    static Hashtable nativeFontList = new Hashtable();
+
+    /** cache of all already-looked-up X11 fonts; key is XWT font name, value is a WrappedRawData */
+    static Hashtable xwtFontToFontStruct = new Hashtable();
+
+    /** dumps a list of X11 font strings */
+    private native String[] listNativeFonts();
+
+    /** load native font list */
+    public void initFonts() {
+        // use the font list to build nativeFontList
+        String[] fonts = listNativeFonts();
+
+        Vector v = new Vector();
+        for(int k=0; k<fonts.length; k++) {
+
+            String s = fonts[k].toLowerCase();
+            String s2 = s;
+            try {
+                v.setSize(0);
+                s = s.substring(s.indexOf('-') + 1);
+                while (s.indexOf('-') != -1) {
+                    v.addElement(s.substring(0, s.indexOf('-')));
+                    s = s.substring(s.indexOf('-') + 1);
+                }
+                v.addElement(s);
+                String[] font = new String[v.size()];
+                v.copyInto(font);
+
+                // limit to iso8559 until we can do I18N properly....
+                if (font.length > 12) {
+                    if (!font[12].equals("iso8859") && !font[12].equals("")) continue;
+                    if (font.length < 14 || !font[13].equals("1")) continue;
+                }
+
+                String name = font[1];
+                String size = font[6];
+                String slant = (font[3].equals("i") || font[3].equals("o")) ? "i" : "";
+                String bold = font[2].equals("bold") ? "b" : "";
+                String tail = s2.substring(1 + font[0].length() + 1 + font[1].length() + 1 + font[2].length() + 1 +
+                                           font[3].length() + 1 + font[4].length() + 1);
+                
+                if (bold.equals("*") && slant.equals("*")) {
+                    nativeFontList.put(name + size, font[0] + "-" + font[1] + "-regular-r-" + font[4] + "-" + tail);
+                    nativeFontList.put(name + size + "b", font[0] + "-" + font[1] + "-bold-r-" + font[4] + "-" + tail);
+                    nativeFontList.put(name + size + "i", font[0] + "-" + font[1] + "-regular-i-" + font[4] + "-" + tail);
+                    nativeFontList.put(name + size + "bi", font[0] + "-" + font[1] + "-bold-i-" + font[4] + "-" + tail);
+                    
+                } else if (bold.equals("*")) {
+                    nativeFontList.put(name + size + slant, font[0] + "-" + font[1] + "-regular-" + font[3] + "-" + font[4] + "-" + tail);
+                    nativeFontList.put(name + size + "b" + slant, font[0] + "-" + font[1] + "-bold-" + font[3] + "-" + font[4] + "-" + tail);
+                    
+                } else if (slant.equals("*")) {
+                    nativeFontList.put(name + size + bold, font[0] + "-" + font[1] + "-" + font[2] + "-r-" + font[4] + "-" + tail);
+                    nativeFontList.put(name + size + bold + "i", font[0] + "-" + font[1] + "-" + font[2] + "-i-" + font[4] + "-" + tail);
+                    
+                } else {
+                    nativeFontList.put(name + size + bold + slant, s2);
+                    
+                }
+            } catch (ArrayIndexOutOfBoundsException e) {
+                if (Log.on) Log.log(this, "skipping incomplete font string " + s2);
+                continue;
+            }
+        }
+        fontList = new String[nativeFontList.size()];
+        Enumeration e = nativeFontList.keys();
+        for(int i=0; e.hasMoreElements(); i++) fontList[i] = (String)e.nextElement();
+    }
+
+    /** so we can put XFontStruct's into Hashtables */
+    private static class WrappedRawData {
+        public RawData wrapee = null;
+        public WrappedRawData(RawData r) { wrapee = r; }
+    }
+
+    /** translates an X11 font string into an XFontStruct* */
+    public static native gnu.gcj.RawData fontStringToStruct(String s);
+
+    /** translates an XWT font string into an XFontStruct*, performing caching as well */
+    public static RawData fontToXFont(String s) {
+        if (s == null) s = "sansserif";
+        s = s.toLowerCase();
+        
+        WrappedRawData wrap = (WrappedRawData)xwtFontToFontStruct.get(s);
+        if (wrap != null) return wrap.wrapee;
+
+        String bestmatch = "";
+        int metric = -1 * Integer.MAX_VALUE;
+        ParsedFont arg = new ParsedFont(s);
+        ParsedFont pf = new ParsedFont();
+
+        if (arg.size == -1) arg.size = 10;
+        Enumeration e = nativeFontList.keys();
+        while(e.hasMoreElements()) {
+            String jfont = (String)e.nextElement();
+            pf.parse(jfont);
+            int thismetric = 0;
+            if (!pf.name.equals(arg.name)) {
+                if (pf.name.equals("lucidabright") && arg.name.equals("serif")) thismetric -= 1000;
+                else if (pf.name.equals("times") && arg.name.equals("serif")) thismetric -= 2000;
+                else if (pf.name.equals("helvetica") && arg.name.equals("sansserif")) thismetric -= 1000;
+                else if (pf.name.equals("courier") && arg.name.equals("monospaced")) thismetric -= 1000;
+                else if (pf.name.equals("lucida") && arg.name.equals("dialog")) thismetric -= 1000;
+                else if (pf.name.equals("helvetica") && arg.name.equals("dialog")) thismetric -= 2000;
+                else if (pf.name.equals("fixed") && arg.name.equals("tty")) thismetric -= 1000;
+                else if (pf.name.equals("sansserif")) thismetric -= 4000;
+                else thismetric -= 4004;
+            }
+            if (pf.size != 0) thismetric -= Math.abs(pf.size - arg.size) * 4;
+            if (pf.bold != arg.bold) thismetric -= 1;
+            if (pf.italic != arg.italic) thismetric -= 1;
+            if (thismetric > metric) {
+                metric = thismetric;
+                bestmatch = jfont;
+            }
+        }
+        
+        pf.parse(bestmatch);
+        String target = (String)nativeFontList.get(bestmatch);
+        if (pf.size == 0) {
+            int i = 0;
+            for(int j=0; j<6; j++) i = target.indexOf('-', i + 1);
+            target = target.substring(0, i + 1) + arg.size + target.substring(target.indexOf('-', i+1));
+        }
+        if (Log.on) Log.log(POSIX.class, "mapping font \"" + s + "\" to \"" + target + "\"");
+        RawData ret = fontStringToStruct(target);
+        if (ret == null) ret = fontStringToStruct("fixed");
+        xwtFontToFontStruct.put(s, new WrappedRawData(ret));
+        return ret;
+    }
+
+}