X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=src%2Forg%2Fxwt%2Fplat%2FPOSIX.cc;fp=src%2Forg%2Fxwt%2Fplat%2FPOSIX.cc;h=b5d466227b4fc3748bc6e3c170b277a22b8f3e19;hb=027607da259f292060d80e0ed90d2b0e896acd86;hp=0000000000000000000000000000000000000000;hpb=55a705adbd2e74b771d6cbd161ee5e6f90bd5dac;p=org.ibex.core.git diff --git a/src/org/xwt/plat/POSIX.cc b/src/org/xwt/plat/POSIX.cc new file mode 100644 index 0000000..b5d4662 --- /dev/null +++ b/src/org/xwt/plat/POSIX.cc @@ -0,0 +1,2299 @@ +#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 colormap; +static XStandardColormap* colormap_info; +static XShmSegmentInfo shm_info; +static Window selectionWindow; +static int shm_supported; +static int screen_num; +static int colorDepth = 0; +static Display* display; + +#define min(a, b) (a < b ? a : b) + +// X11DoubleBuffer ////////////////////////////////////////////////////////////////////// + +void org::xwt::plat::POSIX$X11DoubleBuffer::drawPicture(org::xwt::Picture* s, + jint dx1, jint dy1, jint dx2, jint dy2, jint sx1, jint sy1, jint sx2, jint sy2) { + + if (pm == NULL) return; + org::xwt::plat::POSIX$X11Picture* source = (org::xwt::plat::POSIX$X11Picture*)s; + + int scaling = dx2 - dx1 != sx2 - sx1 || dy2 - dy1 != sy2 - sy1; + + // FIXME: this needs to be moved into the fastpath-only to prevent image wriggling + 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; + + // fastpath: if the X11Picture has a pixmap, and no scaling, and all-or-nothing alpha + if (!scaling && source->doublebuf != NULL) { + 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); + return; + } + + // slowpath: true alpha or scaling + + // the following optimizations were abandoned because they don't + // improve performance in the presence of XSHM extensions, and + // therefore aren't worth the code-bloat: + // - scaling clipmask bitmaps (and caching them) + // - caching pre-scaled XImages + + // ximage from our destination -- if true_alpha is false, we can use malloc() instead of XGetImage + XImage* xi; + + if (force_slowpath && shm_supported) { + + // if the shared memory area is unsuitable, destroy it + + if (((XImage*)shm_ximage) != NULL && (dx2 - dx1 != ((XImage*)shm_ximage)->width || dy2 - dy1 != ((XImage*)shm_ximage)->height)) { + XShmDetach(display, &shm_info); + XDestroyImage(((XImage*)shm_ximage)); + } + + // FIXME: replace 4 with something sensible + if (((XImage*)shm_ximage) != NULL && (dx2 - dx1) * (dy2 - dy1) * 4 < old_shmsize) { + shmdt(shm_info.shmaddr); + shmctl(shm_info.shmid, IPC_RMID, 0); + memset(&shm_info, 0, sizeof(XShmSegmentInfo)); + shm_info.shmaddr = NULL; + } + + // if we need to recreate the shared memory area + if (shm_info.shmaddr == NULL) { + old_shmsize = xi->bytes_per_line * xi->height; + memset(&shm_info, 0, sizeof(XShmSegmentInfo)); + shm_info.shmid = shmget(IPC_PRIVATE, xi->bytes_per_line * xi->height, IPC_CREAT | 0777 | IPC_EXCL); + shm_info.shmaddr = xi->data = (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); + } + + xi = ((XImage*)shm_ximage) = XShmCreateImage(display, visual, colorDepth, ZPixmap, shm_info.shmaddr, &shm_info, dx2 - dx1, dy2 - dy1); + + } else if (shared_pixmap && shm_supported) { + xi = ((XImage*)mxi); + + } else { + xi = XGetImage(display, (*((Pixmap*)pm)), dx1, dy1, dx2 - dx1, dy2 - dy1, AllPlanes, ZPixmap); + + } + + // FIXME: xoffset? + // FIXME: optimize pixels that have 0xFF or 0x00 alpha + // endian issues + + + // further assumption: the only time source->data will be null is + // if we're drawing from a bordercache -- but those don't get + // stretched. + if (source->data == NULL || elements(source->data) == NULL) { + printf("AIEEEEE %i %i %i %i\n", dx2 - dx1, dy2 - dy1, sx2 - sx1, sy2 - sy1); + return; + } + int* sourcedata = (int*)elements(source->data); + + for(int y=dy1; y= clipy + cliph) continue; + + char* bitstart; + if (shared_pixmap && shm_supported) { + // FIXME: not sure if bitmap_unit is the right thing + bitstart = xi->data + y * xi->bytes_per_line + dx1 * (xi->bits_per_pixel / 8); + } else { + bitstart = xi->data + (y - dy1) * xi->bytes_per_line; + } + + for(int x=dx1; xbits_per_pixel / 8) { + + if (x < clipx || x >= clipx + clipw) continue; + + int source_x = ((x - dx1) * (sx2 - sx1)) / (dx2 - dx1) + sx1; + int source_y = ((y - dy1) * (sy2 - sy1)) / (dy2 - dy1) + sy1; + + // note that we can assume that source->data exists here, since writeable PixelGrids (ie + // doublebuffers) never have true_alpha, and are never scaled. + 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 != 0xFF) { + int targetpixel; + switch (xi->bits_per_pixel) { + case 8: targetpixel = (int)(*bitstart); break; + case 16: targetpixel = (int)(*((u_int16_t*)bitstart)); break; + case 24: targetpixel = (((int)*bitstart) << 16) | (((int)*(bitstart + 1)) << 8) | (((int)*(bitstart + 2))); break; + case 32: targetpixel = *((int*)bitstart); 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); + + int 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: *bitstart = (char)(destpixel & 0xFF); break; + case 16: *((u_int16_t*)bitstart) = (u_int16_t)destpixel; break; + case 24: break; // FIXME, unimplemented + case 32: *((int*)bitstart) = destpixel; break; + default: org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: bpp not a multiple of 8!")); + } + + } + } + + if (force_slowpath && shm_supported) { + // watch for concurrency issues if we're going to keep the shm region around + XShmPutImage(display, (*((Pixmap*)pm)), (*((GC*)gc)), xi, 0, 0, dx1, dy1, dx2 - dx1, dy2 - dy1, False); + + } if (shared_pixmap && shm_supported) { + // do nothing, it's all taken care of + + } else { + XPutImage(display, (*((Pixmap*)pm)), (*((GC*)gc)), xi, 0, 0, dx1, dy1, dx2 - dx1, dy2 - dy1); + + } +} + +void org::xwt::plat::POSIX$X11DoubleBuffer::natInit() { + + if (width == 0 || height == 0) return; + + pm = (gnu::gcj::RawData*)malloc(sizeof(Pixmap)); + + if (shared_pixmap && shm_supported) { + + // FIXME: check if server pixmaps are XYPixmaps + printf("CREATING SHARED (*((Pixmap*)pm)) %i %i\n", width, height); + + XShmSegmentInfo *sinfo = (XShmSegmentInfo*)malloc(sizeof(XShmSegmentInfo)); + ((XImage*)mxi) = XShmCreateImage(display, visual, colorDepth, ZPixmap, NULL, sinfo, width, height); + + memset(sinfo, 0, sizeof(XShmSegmentInfo)); + + sinfo->shmid = shmget(IPC_PRIVATE, ((XImage*)mxi)->bytes_per_line * height, IPC_CREAT | 0777 | IPC_EXCL); + ((XImage*)mxi)->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, 0), sinfo->shmaddr, sinfo, width, height, colorDepth); + XSync(display, False); + + } else { + (*((Pixmap*)pm)) = XCreatePixmap(display, RootWindow(display, 0), width, height, colorDepth); + + } + 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, 0), 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 + char buf[text->length() + 1]; + JvGetStringUTFRegion(text, 0, text->length(), buf); + buf[text->length()] = '\0'; + + // Build the XTextItem structure + XTextItem textitem; + textitem.chars = buf; + textitem.nchars = text->length(); + 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::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::_dispose() { XDestroyWindow(display, (*((Window*)window))); } +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::_setMinimized(jboolean b) { + if (b) XIconifyWindow(display, (*((Window*)window)), screen_num); + else XMapRaised(display, (*((Window*)window))); +} + +void org::xwt::plat::POSIX$X11Surface::natInit() { + XSetWindowAttributes xswa; + window = (gnu::gcj::RawData*)malloc(sizeof(Window)); + xswa.bit_gravity = NorthWestGravity; + xswa.colormap = colormap; + xswa.event_mask = ExposureMask | ButtonPressMask | StructureNotifyMask | + KeyPressMask | KeyReleaseMask | ButtonPressMask | + ButtonReleaseMask | EnterWindowMask | LeaveWindowMask | + PointerMotionMask | ButtonMotionMask | ConfigureNotify | FocusChangeMask; + *((Window*)window) = XCreateWindow(display, DefaultRootWindow(display), 10, 10, 500, 300, 0, + colorDepth, InputOutput, CopyFromParent, + CWColormap | CWBitGravity | CWEventMask, &xswa); + + if (!framed) { + // FIXME: figure out why this works and make it elegant + 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 == 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)); + + } 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_Caps_Lock: s = "caps_lock"; 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; + } + } + + if (e->type == KeyPress) KeyPressed(JvNewStringLatin1(s)); + if (e->type == KeyRelease) KeyReleased(JvNewStringLatin1(s)); + + } 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)), DefaultRootWindow(display), 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)); } + +void org::xwt::plat::POSIX::eventThread() { + XEvent e; + while(true) { + XNextEvent(display, &e); + 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); +} + +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); + //shm_supported = 0; + + 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, DefaultRootWindow(display), 0, 0, 1, 1, 0, colorDepth, InputOutput, CopyFromParent, 0, NULL); + visual = DefaultVisual(display, screen_num); + char buf[255]; + 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)); + + if(XmuLookupStandardColormap(display, screen_num, visual->visualid, colorDepth, XA_RGB_BEST_MAP, False, True) == 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")); + 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, "-*-*-*-*-*-*-*-*-*-*-*-*-*-*", 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); +} + + +////////////////////////////////////////////////////////////////////////////// + +/* $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 + +/* 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))) + XFreeColormap(dpy, s->colormap); + else if (s->killid != None) + XKillClient(dpy, s->killid); + } + XDeleteProperty(dpy, RootWindow(dpy, screen), property); + XFree((char *) stdcmaps); + XSync(dpy, False); + } +} +