From fa437b8b1bdf01b3bbdabec990b60833cd6c68f0 Mon Sep 17 00:00:00 2001 From: megacz Date: Fri, 30 Jan 2004 06:51:10 +0000 Subject: [PATCH] 2003/02/05 21:51:50 darcs-hash:20040130065110-2ba56-bf357911c0b7e04ff3ac4a1d51765bbf32cce87e.gz --- src/org/xwt/plat/Linux.xml | 4 +- src/org/xwt/plat/POSIX.cc | 2346 ------------------------------------------ src/org/xwt/plat/POSIX.java | 330 +----- src/org/xwt/plat/X11.cc | 2357 +++++++++++++++++++++++++++++++++++++++++++ src/org/xwt/plat/X11.java | 350 +++++++ 5 files changed, 2712 insertions(+), 2675 deletions(-) create mode 100644 src/org/xwt/plat/X11.cc create mode 100644 src/org/xwt/plat/X11.java diff --git a/src/org/xwt/plat/Linux.xml b/src/org/xwt/plat/Linux.xml index 1bb1630..36ae917 100644 --- a/src/org/xwt/plat/Linux.xml +++ b/src/org/xwt/plat/Linux.xml @@ -4,9 +4,9 @@ - + - + diff --git a/src/org/xwt/plat/POSIX.cc b/src/org/xwt/plat/POSIX.cc index f34fbdf..203ac8a 100644 --- a/src/org/xwt/plat/POSIX.cc +++ b/src/org/xwt/plat/POSIX.cc @@ -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 -#include -#include -#include -#include -#include -#include -#include -#include -#include #include #include #include @@ -18,610 +8,6 @@ #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -// 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); ydata + 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); xbits_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; xpm), *((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* 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* org::xwt::plat::POSIX::listNativeFonts() { - int numfonts; - char** xfonts = XListFonts(display, "-*-*-*-*-normal-*-*-*-*-*-*-*-*-*", 0xFFFFFFFF, &numfonts); - JArray* fonts = (JArray*)JvNewObjectArray(numfonts, &(::java::lang::String::class$), NULL); - java::lang::String** jfonts = (java::lang::String**)(elements(fonts)); - for(int i=0; imax_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 -#include -#include -#include -#include -#include - -/* - * 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 -#include -#include -#include -#include - -#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 -#include -#include -#include -#include - -#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 -#include -#include -#include -#include - -/* - * 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 -#include -#include - -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/POSIX.java b/src/org/xwt/plat/POSIX.java index e47cc9b..1733572 100644 --- a/src/org/xwt/plat/POSIX.java +++ b/src/org/xwt/plat/POSIX.java @@ -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 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 index 0000000..9fd2ac3 --- /dev/null +++ b/src/org/xwt/plat/X11.cc @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +// 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); ydata + 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); xbits_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; xpm), *((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* org::xwt::plat::X11::listNativeFonts() { + int numfonts; + char** xfonts = XListFonts(display, "-*-*-*-*-normal-*-*-*-*-*-*-*-*-*", 0xFFFFFFFF, &numfonts); + JArray* fonts = (JArray*)JvNewObjectArray(numfonts, &(::java::lang::String::class$), NULL); + java::lang::String** jfonts = (java::lang::String**)(elements(fonts)); + for(int i=0; imax_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 +#include +#include +#include +#include +#include + +/* + * 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 +#include +#include +#include +#include + +#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 +#include +#include +#include +#include + +#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 +#include +#include +#include +#include + +/* + * 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 +#include +#include + +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 index 0000000..a65c41b --- /dev/null +++ b/src/org/xwt/plat/X11.java @@ -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 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; + } + +} -- 1.7.10.4