1 // Copyright 2002 Adam Megacz, see the COPYING file for licensing [LGPL]
2 // see below for copyright information on the second portion of this file
7 #include <X11/extensions/XShm.h>
8 #include <X11/keysymdef.h>
9 #include <X11/keysym.h>
10 #include <X11/cursorfont.h>
11 #include <X11/Xutil.h>
12 #include <X11/Xatom.h>
13 #include <X11/Xmu/StdCmap.h>
15 #include <java/lang/String.h>
16 #include <org/xwt/Surface.h>
17 #include <org/xwt/Picture.h>
18 #include <org/xwt/Box.h>
19 #include <org/xwt/plat/X11.h>
20 #include <org/xwt/plat/X11$X11Surface.h>
21 #include <org/xwt/plat/X11$X11Picture.h>
22 #include <org/xwt/plat/X11$X11PixelBuffer.h>
23 #include <org/xwt/util/Semaphore.h>
24 #include <org/xwt/Platform.h>
25 #include <java/lang/Long.h>
26 #include <java/util/Hashtable.h>
27 #include <org/xwt/util/Log.h>
29 #include <java/lang/System.h>
30 #include <java/io/PrintStream.h>
32 // static (per-xserver) data
33 static Visual* visual;
34 static Colormap s_colormap;
35 static XStandardColormap* colormap_info;
36 static XShmSegmentInfo shm_info;
37 static Window selectionWindow;
38 static int shm_supported = 0;
39 static int shm_pixmaps_supported;
40 static int screen_num;
41 static int colorDepth = 0;
42 static Display* display;
43 static int shm_size = 0;
45 #define min(a, b) ((a) < (b) ? (a) : (b))
46 #define max(a, b) ((a) < (b) ? (b) : (a))
48 // X11PixelBuffer //////////////////////////////////////////////////////////////////////
50 // ensures that the shared memory is at least size bytes; if not, allocates 3/2 * size
51 static void ensureShmSize(int size) {
52 if (size > shm_size) {
54 XShmDetach(display, &shm_info);
55 shmdt(shm_info.shmaddr);
56 shmctl(shm_info.shmid, IPC_RMID, 0);
58 shm_size = 3 * size / 2;
59 shm_info.shmid = shmget(IPC_PRIVATE, shm_size, IPC_CREAT | 0777 | IPC_EXCL);
60 shm_info.shmaddr = (char*)shmat(shm_info.shmid, 0, 0);
61 shm_info.readOnly = False;
62 XSync(display, False);
63 shmctl(shm_info.shmid, IPC_RMID, 0);
64 XShmAttach(display, &shm_info);
65 XSync(display, False);
69 void org::xwt::plat::X11$X11PixelBuffer::fastDrawPicture(org::xwt::Picture* s,
70 jint dx, jint dy, jint cx1, jint cy1, jint cx2, jint cy2) {
71 org::xwt::plat::X11$X11Picture* source = (org::xwt::plat::X11$X11Picture*)s;
73 if (source->doublebuf->stipple != NULL) {
74 XSetClipMask(display, (*((GC*)clipped_gc)), *((Pixmap*)source->doublebuf->stipple));
75 XSetClipOrigin(display, (*((GC*)clipped_gc)), cx1 - dx, cy1 - dy);
77 XSetClipMask(display, (*((GC*)clipped_gc)), None);
80 *((Pixmap*)source->doublebuf->pm), (*((Pixmap*)pm)), (*((GC*)clipped_gc)),
81 cx1 - dx, cy2 - cy1, cx2 - cx1, cy2 - cy1, dx, dy);
84 void org::xwt::plat::X11$X11PixelBuffer::slowDrawPicture(org::xwt::Picture* s,
85 jint dx, jint dy, jint cx1, jint cy1, jint cx2, jint cy2,
86 jint rgb, jboolean alphaOnly) {
88 org::xwt::plat::X11$X11Picture* source = (org::xwt::plat::X11$X11Picture*)s;
91 // FASTEST: shared pixmap; twiddle bits in video ram directly
93 XSync(display, False); // ensure that all pending operations have rendered
94 xi = (XImage*)fake_ximage;
96 // MEDIUM: write to a shared ximage, then ask the server to do the blit
97 } else if (shm_supported) {
98 xi = XShmCreateImage(display, visual, colorDepth, ZPixmap, NULL, &shm_info, cx2 - cx1, cy2 - cy1);
99 ensureShmSize(xi->bytes_per_line * xi->height);
100 xi->data = shm_info.shmaddr;
101 XShmGetImage(display, (*((Pixmap*)pm)), xi, cx1, cy1, AllPlanes);
103 // SLOWEST: write to an ximage, copy it through the TCP connection, ask the server to do the blit
105 xi = XGetImage(display, (*((Pixmap*)pm)), cx1, cy1, cx2 - cx1, cy2 - cy1, AllPlanes, ZPixmap);
108 int* sourcedata = (int*)elements(source->data);
109 for(int y=cy1; y < cy2; y++) {
111 char* current_pixel = (xi->data + y * xi->bytes_per_line) +
112 (shared_pixmap ? cx1 * (xi->bits_per_pixel / 8) : - 1 * cy1 * xi->bytes_per_line);
114 for(int x=cx1; x < cx1; x++, current_pixel += xi->bits_per_pixel / 8) {
115 int source_x = x - dx;
116 int source_y = y - dy;
118 int sourcepixel = sourcedata[source_x + source_y * source->getWidth()];
119 int alpha = (sourcepixel & 0xFF000000) >> 24;
121 // FEATURE: be smarter here; can we do something better for the alphaonly case?
122 if (alphaOnly) sourcepixel = rgb;
123 int source_red = (sourcepixel & 0x00FF0000) >> 16;
124 int source_green = (sourcepixel & 0x0000FF00) >> 8;
125 int source_blue = (sourcepixel & 0x000000FF);
126 int red = 0, blue = 0, green = 0;
128 if (alpha == 0x00) continue;
131 switch (xi->bits_per_pixel) {
132 case 8: targetpixel = (int)(*current_pixel); break;
133 case 16: targetpixel = (int)(*((uint16_t*)current_pixel)); break;
134 case 24: targetpixel = (((int)*current_pixel) << 16) | (((int)*(current_pixel + 1)) << 8) | (((int)*(current_pixel + 2))); break;
135 case 32: targetpixel = *((int*)current_pixel); break;
136 default: org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: bpp not a multiple of 8!"));
139 targetpixel -= colormap_info->base_pixel;
141 // if you're on some wierd display that isn't either RGB or BGR, that's your problem, not mine
142 if (colormap_info->red_mult > colormap_info->green_mult && colormap_info->green_mult > colormap_info->blue_mult) {
143 red = targetpixel / colormap_info->red_mult;
144 green = (targetpixel - red * colormap_info->red_mult) / colormap_info->green_mult;
145 blue = (targetpixel - red * colormap_info->red_mult - green * colormap_info->green_mult) / colormap_info->blue_mult;
147 blue = targetpixel / colormap_info->blue_mult;
148 green = (targetpixel - blue * colormap_info->blue_mult) / colormap_info->green_mult;
149 red = (targetpixel - blue * colormap_info->blue_mult - green * colormap_info->green_mult) / colormap_info->red_mult;
153 red = ((source_red * colormap_info->red_max * alpha) + (red * 0xFF * (0xFF - alpha))) / (0xFF * 0xFF);
154 green = ((source_green * colormap_info->green_max * alpha) + (green * 0xFF * (0xFF - alpha))) / (0xFF * 0xFF);
155 blue = ((source_blue * colormap_info->blue_max * alpha) + (blue * 0xFF * (0xFF - alpha))) / (0xFF * 0xFF);
156 uint32_t destpixel = red * colormap_info->red_mult + green * colormap_info->green_mult +
157 blue * colormap_info->blue_mult + colormap_info->base_pixel;
159 switch (xi->bits_per_pixel) {
160 case 8: *current_pixel = (char)(destpixel & 0xFF); break;
161 case 16: *((uint16_t*)current_pixel) = (uint16_t)destpixel; break;
163 int offset = (int)current_pixel & 0x3;
164 uint64_t dest = ((uint64_t)destpixel) << (8 * offset);
165 uint64_t mask = ((uint64_t)0xffffff) << (8 * offset);
166 uint64_t* base = (uint64_t*)(current_pixel - offset);
167 *base = (*base & ~mask) | dest;
170 case 32: *((uint32_t*)current_pixel) = destpixel; break;
171 default: org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: bpp not a multiple of 8!"));
177 // do nothing, we wrote directly to video memory
179 } else if (shm_supported) {
180 XShmPutImage(display, (*((Pixmap*)pm)), (*((GC*)gc)), xi, 0, 0, cx1, cy1, cx2 - cx1, cy2 - cy1, False);
184 XPutImage(display, (*((Pixmap*)pm)), (*((GC*)gc)), xi, 0, 0, cx1, cy1, cx2 - cx1, cy2 - cy1);
189 void org::xwt::plat::X11$X11PixelBuffer::finalize() {
191 XShmSegmentInfo *sinfo = (XShmSegmentInfo*)shm_segment;
192 XShmDetach(display, sinfo);
193 shmdt(sinfo->shmaddr);
194 shmctl(sinfo->shmid, IPC_RMID, 0);
195 XDestroyImage((XImage*)fake_ximage);
199 XFreePixmap(display, *((Pixmap*)stipple));
202 XFreePixmap(display, *((Pixmap*)pm));
203 XFreeGC(display, *((GC*)gc));
204 XFreeGC(display, *((GC*)clipped_gc));
207 void org::xwt::plat::X11$X11PixelBuffer::natInit() {
209 if (width == 0 || height == 0) return;
210 shared_pixmap &= shm_supported & shm_pixmaps_supported; // refuse to use shared pixmaps if we don't have shm
211 pm = (gnu::gcj::RawData*)malloc(sizeof(Pixmap));
214 (*((Pixmap*)pm)) = XCreatePixmap(display, RootWindow(display, screen_num), width, height, colorDepth);
216 XShmSegmentInfo *sinfo = (XShmSegmentInfo*)malloc(sizeof(XShmSegmentInfo));
217 shm_segment = (gnu::gcj::RawData*)sinfo;
218 ((XImage*)fake_ximage) = XShmCreateImage(display, visual, colorDepth, ZPixmap, NULL, sinfo, width, height);
219 sinfo->shmid = shmget(IPC_PRIVATE, ((XImage*)fake_ximage)->bytes_per_line * height, IPC_CREAT | 0777 | IPC_EXCL);
220 ((XImage*)fake_ximage)->data = sinfo->shmaddr = (char*)shmat(sinfo->shmid, 0, 0);
221 sinfo->readOnly = False;
222 XShmAttach(display, sinfo);
223 XSync(display, False);
224 shmctl(sinfo->shmid, IPC_RMID, 0);
225 (*((Pixmap*)pm)) = XShmCreatePixmap(display, RootWindow(display, screen_num), sinfo->shmaddr, sinfo, width, height, colorDepth);
226 XSync(display, False);
229 gc = (gnu::gcj::RawData*)malloc(sizeof(GC));
230 clipped_gc = (gnu::gcj::RawData*)malloc(sizeof(GC));
231 (*((GC*)gc)) = XCreateGC(display, (*((Pixmap*)pm)), 0, 0);
232 (*((GC*)clipped_gc)) = XCreateGC(display, (*((Pixmap*)pm)), 0, 0);
235 vm.graphics_exposures = 0;
236 XChangeGC(display, (*((GC*)gc)), GCGraphicsExposures, &vm);
237 XChangeGC(display, (*((GC*)clipped_gc)), GCGraphicsExposures, &vm);
240 void org::xwt::plat::X11$X11PixelBuffer::createStipple(org::xwt::plat::X11$X11Picture* xpi) {
242 stipple = (gnu::gcj::RawData*)malloc(sizeof(Pixmap));
243 (*((Pixmap*)stipple)) = XCreatePixmap(display, RootWindow(display, screen_num), width, height, 1);
246 xi.data = (char*)malloc((width + 1) * height);
253 xi.byte_order = LSBFirst;
255 xi.bytes_per_line = (width / 8) + 1;
256 xi.bits_per_pixel = 1;
258 jint* d = (jint*)elements(xpi->data);
259 memset(xi.data, 0xFF, (width + 1) * height);
260 for(int x=0; x<width; x++)
261 for (int y=0; y<height; y++)
262 xi.data[y * xi.bytes_per_line + (x/8)] &= ~(((d[x + y * width] & 0xFF000000) != 0 ? 0 : 1) << (x % 8));
264 GC stipple_gc = XCreateGC(display, (*((Pixmap*)stipple)), 0, 0);
267 vm.graphics_exposures = 0;
268 XChangeGC(display, stipple_gc, GCGraphicsExposures, &vm);
270 XPutImage(display, (*((Pixmap*)stipple)), stipple_gc, &xi, 0, 0, 0, 0, width, height);
273 void org::xwt::plat::X11$X11Surface::blit(org::xwt::PixelBuffer* db, jint sx, jint sy, jint dx, jint dy, jint dx2, jint dy2) {
274 org::xwt::plat::X11$X11PixelBuffer *xdb = (org::xwt::plat::X11$X11PixelBuffer*)db;
275 XCopyArea(display, *((Pixmap*)xdb->pm), *((Window*)window), *((GC*)gc), sx, sy, dx2 - dx, dy2 - dy, dx, dy);
279 void org::xwt::plat::X11$X11PixelBuffer::fillRect (jint x, jint y, jint x2, jint y2, jint argb) {
284 if (x < clipx) { w -= (clipx - x); x = clipx; }
285 if (y < clipy) { h -= (clipy - y); y = clipy; }
286 if (x + w > clipx + clipw) w = (clipx + clipw - x);
287 if (y + h > clipy + cliph) h = (cliph + clipy - y);
289 XSetForeground(display, (*((GC*)gc)),
290 ((((argb & 0x00FF0000) >> 16) * colormap_info->red_max) / 0xFF) * colormap_info->red_mult +
291 ((((argb & 0x0000FF00) >> 8) * colormap_info->green_max) / 0xFF) * colormap_info->green_mult +
292 ((((argb & 0x000000FF)) * colormap_info->blue_max) / 0xFF) * colormap_info->blue_mult +
293 colormap_info->base_pixel
296 XFillRectangle(display, (*((Pixmap*)pm)), (*((GC*)gc)), x, y, w, h);
300 // X11Surface //////////////////////////////////////////////////////////////////////
302 void org::xwt::plat::X11$X11Surface::setIcon(org::xwt::Picture* pic) {
303 org::xwt::plat::X11$X11Picture* p = ((org::xwt::plat::X11$X11Picture*)pic);
304 org::xwt::plat::X11$X11PixelBuffer* old_dbuf = p->doublebuf;
305 p->buildPixelBuffer(1);
307 memset(&xwmh, 0, sizeof(XWMHints));
308 xwmh.flags |= IconPixmapHint | IconMaskHint;
309 xwmh.icon_pixmap = *((Pixmap*)p->doublebuf->pm);
310 xwmh.icon_mask = *((Pixmap*)p->doublebuf->stipple);
311 XSetWMHints(display, (*((Window*)window)), &xwmh);
312 p->doublebuf = old_dbuf;
315 void org::xwt::plat::X11$X11Surface::setTitleBarText(java::lang::String* s) {
316 int len = min(JvGetStringUTFLength(s), 1024);
318 JvGetStringUTFRegion(s, 0, len, buf);
322 tp.value = (unsigned char*)buf;
324 tp.encoding = XA_STRING;
326 XSetTextProperty(display, (*((Window*)window)), &tp, XA_WM_NAME);
327 XSetTextProperty(display, (*((Window*)window)), &tp, XA_WM_ICON_NAME);
330 void org::xwt::plat::X11$X11Surface::setLimits(jint minw, jint minh, jint maxw, jint maxh) {
332 hints.min_width = minw;
333 hints.min_height = minh;
334 hints.max_width = maxw;
335 hints.max_height = maxh;
336 hints.flags = PMinSize | PMaxSize;
337 XSetWMNormalHints(display, (*((Window*)window)), &hints);
340 void org::xwt::plat::X11$X11Surface::_setSize (jint width, jint height) {
341 if (width <= 0 || height <= 0) return;
342 XResizeWindow(display, (*((Window*)window)), width, height);
346 void org::xwt::plat::X11$X11Surface::setLocation () { XMoveWindow(display, (*((Window*)window)), root->x, root->y); }
347 void org::xwt::plat::X11$X11Surface::toFront() { XRaiseWindow(display, (*((Window*)window))); }
348 void org::xwt::plat::X11$X11Surface::toBack() { XLowerWindow(display, (*((Window*)window))); }
350 void org::xwt::plat::X11$X11Surface::_dispose() {
351 // without this we get phantom messages after the window is gone
352 org::xwt::plat::X11::windowToSurfaceMap->remove(new java::lang::Long(*((Window*)window)));
353 XDestroyWindow(display, (*((Window*)window)));
356 void org::xwt::plat::X11$X11Surface::setInvisible(jboolean i) {
357 if (i) XUnmapWindow(display, (*((Window*)window)));
358 else XMapRaised(display, (*((Window*)window)));
362 void org::xwt::plat::X11$X11Surface::_setMinimized(jboolean b) {
363 if (b) XIconifyWindow(display, (*((Window*)window)), screen_num);
364 else XMapRaised(display, (*((Window*)window)));
368 void org::xwt::plat::X11$X11Surface::natInit() {
369 XSetWindowAttributes xswa;
370 window = (gnu::gcj::RawData*)malloc(sizeof(Window));
371 xswa.bit_gravity = NorthWestGravity;
372 xswa.colormap = s_colormap;
373 xswa.event_mask = ExposureMask | ButtonPressMask | StructureNotifyMask |
374 KeyPressMask | KeyReleaseMask | ButtonPressMask |
375 ButtonReleaseMask | EnterWindowMask | LeaveWindowMask |
376 PointerMotionMask | ButtonMotionMask | ConfigureNotify | FocusChangeMask;
377 *((Window*)window) = XCreateWindow(display, RootWindow(display, screen_num), 10, 10, 10, 10, 0,
378 colorDepth, InputOutput, CopyFromParent,
379 CWColormap | CWBitGravity | CWEventMask, &xswa);
382 // I don't know why this works....
383 int dat[5] = { 0x2, 0xbffff804, 0x0, 0x817f560, 0x8110694 };
384 XChangeProperty(display, (*((Window*)window)),
385 XInternAtom(display, "_MOTIF_WM_HINTS", False),
386 XInternAtom(display, "_MOTIF_WM_HINTS", False),
394 tp.value = (unsigned char*)"XWT";
396 tp.encoding = XA_STRING;
398 XSetTextProperty(display, (*((Window*)window)), &tp, XA_WM_CLASS);
400 Atom proto = XInternAtom(display, "WM_DELETE_WINDOW", False);
401 XSetWMProtocols(display, (*((Window*)window)), &proto, 1);
403 XSelectInput(display, (*((Window*)window)), StructureNotifyMask);
404 org::xwt::plat::X11::windowToSurfaceMap->put(new java::lang::Long(*((Window*)window)), this);
407 XMapRaised(display, (*((Window*)window)));
410 waitForCreation->block();
411 XSelectInput(display, (*((Window*)window)), xswa.event_mask);
414 gc = (gnu::gcj::RawData*)malloc(sizeof(GC));
415 *((GC*)gc) = XCreateGC(display, (*((Window*)window)), 0, 0);
418 vm.graphics_exposures = 0;
419 XChangeGC(display, *((GC*)gc), GCGraphicsExposures, &vm);
423 void org::xwt::plat::X11$X11Surface::dispatchEvent(gnu::gcj::RawData* ev) {
425 XEvent* e = (XEvent*)ev;
426 if (e->type == Expose) {
427 XExposeEvent *expose = (XExposeEvent*)(e);
428 Dirty(expose->x, expose->y, expose->width, expose->height);
430 } else if (e->type == MapNotify) { Minimized(0); waitForCreation->release();
431 } else if (e->type == UnmapNotify) { Minimized(1);
432 } else if (e->type == FocusIn) { Focused(1);
433 } else if (e->type == FocusOut) { Focused(0);
434 } else if (e->type == ClientMessage) {
435 if (((XClientMessageEvent*)(e))->data.l[0] == XInternAtom(display, "WM_DELETE_WINDOW", False)) Close();
437 } else if (e->type == KeyPress || e->type == KeyRelease) {
438 XKeyEvent *xbe = (XKeyEvent*)(e);
440 // drop faked KeyRelease events generated by the X server's autorepeat
441 if (e->type == KeyRelease) {
443 XQueryKeymap(display, depressed);
444 if ((depressed[(xbe->keycode & 0xff) / 8] & (0x1 << (xbe->keycode % 8))) >> (xbe->keycode % 8)) return;
450 unsigned int savestate = xbe->state;
451 xbe->state = xbe->state & ShiftMask; // ignore everything except shiftmask
452 XLookupString(xbe, s, 20, NULL, NULL);
453 xbe->state = savestate;
455 if (s != NULL && s[0] != '\0' && s[1] == '\0' && s[0] >= 0x20 && s[0] <= 0x7E) {
459 KeySym ks = XKeycodeToKeysym(display, xbe->keycode, 0);
461 case XK_BackSpace: s = "back_space"; break;
462 case XK_Tab: s = "tab"; break;
463 case XK_Linefeed: s = "enter"; break;
464 case XK_Return: s = "enter"; break;
465 case XK_Scroll_Lock: s = "scroll_lock"; break;
466 case XK_Escape: s = "escape"; break;
467 case XK_Insert: s = "insert"; break;
468 case XK_Delete: s = "delete"; break;
469 case XK_Home: s = "home"; break;
470 case XK_Left: s = "left"; break;
471 case XK_Up: s = "up"; break;
472 case XK_Right: s = "right"; break;
473 case XK_Down: s = "down"; break;
474 case XK_Page_Up: s = "page_up"; break;
475 case XK_Page_Down: s = "page_down"; break;
476 case XK_End: s = "end"; break;
477 case XK_Num_Lock: s = "num_lock"; break;
478 case XK_KP_Tab: s = "tab"; break;
479 case XK_KP_Enter: s = "enter"; break;
480 case XK_KP_F1: s = "f1"; break;
481 case XK_KP_F2: s = "f2"; break;
482 case XK_KP_F3: s = "f3"; break;
483 case XK_KP_F4: s = "f4"; break;
484 case XK_KP_Home: s = "home"; break;
485 case XK_KP_Left: s = "left"; break;
486 case XK_KP_Up: s = "up"; break;
487 case XK_KP_Right: s = "right"; break;
488 case XK_KP_Down: s = "down"; break;
489 case XK_KP_Page_Up: s = "page_up"; break;
490 case XK_KP_Page_Down: s = "page_down"; break;
491 case XK_KP_End: s = "end"; break;
492 case XK_KP_Insert: s = "insert"; break;
493 case XK_KP_Delete: s = "delete"; break;
494 case XK_F1: s = "f1"; break;
495 case XK_F2: s = "f2"; break;
496 case XK_F3: s = "f3"; break;
497 case XK_F4: s = "f4"; break;
498 case XK_F5: s = "f5"; break;
499 case XK_F6: s = "f6"; break;
500 case XK_F7: s = "f7"; break;
501 case XK_F8: s = "f8"; break;
502 case XK_F9: s = "f9"; break;
503 case XK_F10: s = "f10"; break;
504 case XK_F11: s = "f11"; break;
505 case XK_F12: s = "f12"; break;
506 case XK_Shift_L: s = "shift"; break;
507 case XK_Shift_R: s = "shift"; break;
508 case XK_Control_L: s = "control"; break;
509 case XK_Control_R: s = "control"; break;
510 case XK_Meta_L: s = "alt"; break;
511 case XK_Meta_R: s = "alt"; break;
512 case XK_Alt_L: s = "alt"; break;
513 case XK_Alt_R: s = "alt"; break;
518 jstring s2 = JvNewStringLatin1(s);
519 if (e->type == KeyPress) KeyPressed((xbe->state & LockMask) ? s2->toUpperCase() : s2);
520 if (e->type == KeyRelease) KeyReleased(s2);
522 } else if (e->type == ButtonPress) {
523 XButtonEvent* xbe = (XButtonEvent*)(e);
524 if (xbe->button == 2) xbe->button = 3;
525 else if (xbe->button == 3) xbe->button = 2;
528 } else if (e->type == ButtonRelease) {
529 XButtonEvent* xbe = (XButtonEvent*)(e);
530 if (xbe->button == 2) xbe->button = 3;
531 else if (xbe->button == 3) xbe->button = 2;
532 Release(xbe->button);
534 } else if (e->type == MotionNotify) {
535 XMotionEvent* xme = (XMotionEvent*)(e);
536 Move(xme->x, xme->y);
538 } else if (e->type == EnterNotify || e->type == LeaveNotify) {
539 XCrossingEvent* xce = (XCrossingEvent*)(e);
540 Move(xce->x, xce->y);
542 } else if (e->type == ConfigureNotify) {
545 XConfigureEvent* xce = (XConfigureEvent*)(e);
546 XTranslateCoordinates(display, (*((Window*)window)), RootWindow(display, screen_num), 0, 0, &x_out, &y_out, &child);
547 if (xce->width != root->width || xce->height != root->height) SizeChange(xce->width, xce->height);
548 if (x_out != root->x || y_out != root->y) PosChange(x_out, y_out);
553 static jstring crosshair, east, hand, move, north, northeast, northwest,
554 south, southeast, southwest, text, west, wait_string;
555 static Cursor crosshair_cursor, east_cursor, hand_cursor, move_cursor, north_cursor,
556 northeast_cursor, northwest_cursor, south_cursor, southeast_cursor,
557 southwest_cursor, text_cursor, west_cursor, wait_cursor, default_cursor;
559 void org::xwt::plat::X11$X11Surface::syncCursor() {
562 if (cursor->equals(crosshair)) curs = crosshair_cursor;
563 else if (cursor->equals(east)) curs = east_cursor;
564 else if (cursor->equals(hand)) curs = hand_cursor;
565 else if (cursor->equals(move)) curs = move_cursor;
566 else if (cursor->equals(north)) curs = north_cursor;
567 else if (cursor->equals(northeast)) curs = northeast_cursor;
568 else if (cursor->equals(northwest)) curs = northwest_cursor;
569 else if (cursor->equals(south)) curs = south_cursor;
570 else if (cursor->equals(southeast)) curs = southeast_cursor;
571 else if (cursor->equals(southwest)) curs = southwest_cursor;
572 else if (cursor->equals(text)) curs = text_cursor;
573 else if (cursor->equals(west)) curs = west_cursor;
574 else if (cursor->equals(wait_string)) curs = wait_cursor;
575 else curs = default_cursor;
577 XDefineCursor(display, (*((Window*)window)), curs);
582 // X11 ///////////////////////////////////////////////////////////////////
584 jint org::xwt::plat::X11::_getScreenWidth() { return WidthOfScreen(DefaultScreenOfDisplay(display)); }
585 jint org::xwt::plat::X11::_getScreenHeight() { return HeightOfScreen(DefaultScreenOfDisplay(display)); }
587 static void dispatchSelectionEvent(XEvent* e) {
588 if (e->type == SelectionNotify) {
589 XSelectionEvent* xsn = (XSelectionEvent*)(e);
590 if (xsn->property == None) org::xwt::plat::X11::clipboard = JvNewStringLatin1("", 0);
594 unsigned long numitems;
596 unsigned long bytes_after;
597 XGetWindowProperty(display, xsn->requestor, xsn->property, 0, 4096,
598 True, AnyPropertyType, &returntype, &returnformat,
599 &numitems, &bytes_after, &ret);
600 org::xwt::plat::X11::clipboard =
601 (returntype == None ? JvNewStringLatin1("", 0) : JvNewStringLatin1((char*)ret, strlen((char*)ret)));
603 org::xwt::plat::X11::waiting_for_selection_event->release();
605 } else if (e->type == SelectionRequest) {
606 XSelectionRequestEvent* xsr = (XSelectionRequestEvent*)(e);
608 xsn.type = SelectionNotify;
609 xsn.serial = xsr->serial;
610 xsn.send_event = True;
611 xsn.display = display;
612 xsn.requestor = xsr->requestor;
613 xsn.selection = xsr->selection;
614 xsn.target = xsr->target;
615 xsn.property = xsr->property;
616 xsn.time = xsr->time;
618 int len = min(1024, JvGetStringUTFLength(org::xwt::plat::X11::clipboard));
620 JvGetStringUTFRegion(org::xwt::plat::X11::clipboard, 0, len, buf);
623 XChangeProperty(display, xsr->requestor, xsr->property, xsr->target, 8, PropModeReplace, (unsigned char*)buf, len + 1);
624 XSendEvent(display, xsr->requestor, True, 0, (XEvent*)(&xsn));
628 void org::xwt::plat::X11::eventThread() {
631 XNextEvent(display, &e);
632 if (e.type == SelectionNotify || e.type == SelectionRequest) {
633 dispatchSelectionEvent(&e);
635 org::xwt::plat::X11$X11Surface* surface =
636 (org::xwt::plat::X11$X11Surface*)windowToSurfaceMap->get(new java::lang::Long(((XAnyEvent*)&e)->window));
637 if (surface != NULL) surface->dispatchEvent((gnu::gcj::RawData*)&e);
642 jstring org::xwt::plat::X11::_getClipBoard() {
643 XConvertSelection(display, XA_PRIMARY, XA_STRING, XInternAtom(display, "VT_SELECTION", False), selectionWindow, CurrentTime);
645 org::xwt::plat::X11::waiting_for_selection_event->block();
649 void org::xwt::plat::X11::_setClipBoard(jstring s) {
651 int len = JvGetStringUTFLength(clipboard);
653 JvGetStringUTFRegion(clipboard, 0, len, buf);
655 XSetSelectionOwner(display, XInternAtom(display, "PRIMARY", 0), selectionWindow, CurrentTime);
658 typedef int (X11ErrorHandler)(Display*, XErrorEvent*);
659 int errorHandler(Display* d, XErrorEvent* e) {
660 // this error handler is only installed during the initial
661 // test to see if shm is present
665 void org::xwt::plat::X11::natInit() {
668 org::xwt::Platform::criticalAbort(JvNewStringLatin1("Your X11 libraries do not support multithreaded programs"));
670 char* DISPLAY = getenv("DISPLAY");
671 if (DISPLAY == NULL || strlen(DISPLAY) == 0) DISPLAY = ":0.0";
672 display = XOpenDisplay(DISPLAY);
675 org::xwt::Platform::criticalAbort(JvNewStringLatin1("Unable to connect to X11 display server"));
677 screen_num = XDefaultScreen(display);
678 colorDepth = (jint)(DefaultDepth(((Display*)display), 0));
679 shm_info.shmaddr = NULL;
681 // FIXME: SHM doesn't work on Darwin
682 //shm_supported = (XShmQueryExtension(display) == True);
684 X11ErrorHandler* oldHandler = XSetErrorHandler(errorHandler);
685 XShmSegmentInfo sinfo;
686 sinfo.shmid = shmget(IPC_PRIVATE, 1, IPC_CREAT | 0777 | IPC_EXCL);
687 sinfo.readOnly = False;
688 // if the server is remote, this will trigger the error handler
689 XShmAttach(display, &sinfo);
690 XSync(display, False);
691 XSetErrorHandler(oldHandler);
695 shm_pixmaps_supported = (XShmPixmapFormat(display) == ZPixmap);
697 crosshair = JvNewStringLatin1("crosshair");
698 east = JvNewStringLatin1("east");
699 hand = JvNewStringLatin1("hand");
700 move = JvNewStringLatin1("move");
701 north = JvNewStringLatin1("north");
702 northeast = JvNewStringLatin1("northeast");
703 northwest = JvNewStringLatin1("northwest");
704 south = JvNewStringLatin1("south");
705 southeast = JvNewStringLatin1("southeast");
706 southwest = JvNewStringLatin1("southwest");
707 text = JvNewStringLatin1("text");
708 west = JvNewStringLatin1("west");
709 wait_string = JvNewStringLatin1("wait");
710 crosshair_cursor = XCreateFontCursor(display, XC_tcross);
711 east_cursor = XCreateFontCursor(display, XC_right_side);
712 hand_cursor = XCreateFontCursor(display, XC_hand2);
713 move_cursor = XCreateFontCursor(display, XC_fleur);
714 north_cursor = XCreateFontCursor(display, XC_top_side);
715 northeast_cursor = XCreateFontCursor(display, XC_top_right_corner);
716 northwest_cursor = XCreateFontCursor(display, XC_left_side);
717 south_cursor = XCreateFontCursor(display, XC_bottom_side);
718 southeast_cursor = XCreateFontCursor(display, XC_bottom_right_corner);
719 southwest_cursor = XCreateFontCursor(display, XC_bottom_left_corner);
720 text_cursor = XCreateFontCursor(display, XC_xterm);
721 west_cursor = XCreateFontCursor(display, XC_right_side);
722 wait_cursor = XCreateFontCursor(display, XC_watch);
723 default_cursor = XCreateFontCursor(display, XC_left_ptr);
725 selectionWindow = XCreateWindow(display, RootWindow(display, screen_num), 0, 0, 1, 1, 0, colorDepth, InputOutput, CopyFromParent, 0, NULL);
726 visual = DefaultVisual(display, screen_num);
728 sprintf(buf, "X11 DISPLAY: %s", XDisplayString(display));
729 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
730 sprintf(buf, "X11 SHM: %s", shm_supported ? "enabled" : "disabled");
731 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
732 sprintf(buf, "X11 Visual: %x %x %x bits: %i visualid: %i depth: %i",
733 visual->red_mask, visual->green_mask, visual->blue_mask, visual->bits_per_rgb, visual->visualid, colorDepth);
734 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
736 // FIXME: don't know why (True, False) is the best solution...
737 if(XmuLookupStandardColormap(display, screen_num, visual->visualid, colorDepth, XA_RGB_BEST_MAP, True, False) == 0)
738 org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: XmuLookupStandardColormap failed"));
740 XStandardColormap* best_map_info = NULL;
742 if (XGetRGBColormaps(display, RootWindow(display, screen_num), &best_map_info, &count, XA_RGB_BEST_MAP) == 0)
743 org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: couldn't allocate a standard colormap"));
744 if (!best_map_info->colormap)
745 org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: XmuLookupStandardColomap succeded, but no colormap was found on the root window"));
746 if (best_map_info->red_max == 0)
747 org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: standard colormap exists, but was improperly allocated"));
748 s_colormap = best_map_info->colormap;
749 colormap_info = best_map_info;
751 sprintf(buf, " red_max / red_mult: %x %x", colormap_info->red_max, colormap_info->red_mult);
752 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
753 sprintf(buf, " green_max / green_mult: %x %x", colormap_info->green_max, colormap_info->green_mult);
754 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
755 sprintf(buf, " blue_max / blue_mult: %x %x", colormap_info->blue_max, colormap_info->blue_mult);
756 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
757 sprintf(buf, " base_pixel: %x", colormap_info->base_pixel);
758 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
763 //////////////////////////////////////////////////////////////////////////////
764 //////////////////////////////////////////////////////////////////////////////
765 //////////////////////////////////////////////////////////////////////////////
766 //////////////////////////////////////////////////////////////////////////////
768 // Everything below this point was taken, cut-and-paste, from the //
769 // source for libXmu. It implements the official 'standard colormap //
770 // creation algorithm. I made some small changes to //
771 // XmuDeleteStandardColormap //
773 //////////////////////////////////////////////////////////////////////////////
774 //////////////////////////////////////////////////////////////////////////////
775 //////////////////////////////////////////////////////////////////////////////
776 //////////////////////////////////////////////////////////////////////////////
778 /* $Xorg: LookupCmap.c,v 1.4 2001/02/09 02:03:53 xorgcvs Exp $ */
782 Copyright 1989, 1998 The Open Group
784 Permission to use, copy, modify, distribute, and sell this software and its
785 documentation for any purpose is hereby granted without fee, provided that
786 the above copyright notice appear in all copies and that both that
787 copyright notice and this permission notice appear in supporting
790 The above copyright notice and this permission notice shall be included in
791 all copies or substantial portions of the Software.
793 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
794 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
795 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
796 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
797 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
798 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
800 Except as contained in this notice, the name of The Open Group shall not be
801 used in advertising or otherwise to promote the sale, use or other dealings
802 in this Software without prior written authorization from The Open Group.
805 /* $XFree86: xc/lib/Xmu/LookupCmap.c,v 1.8 2001/12/14 19:55:47 dawes Exp $ */
808 * Author: Donna Converse, MIT X Consortium
812 #include <X11/Xlib.h>
813 #include <X11/Xatom.h>
814 #include <X11/Xutil.h>
815 #include <X11/Xmu/StdCmap.h>
821 static Status lookup(Display*, int, VisualID, Atom, XStandardColormap*, Bool);
824 * To create a standard colormap if one does not currently exist, or
825 * replace the currently existing standard colormap, use
826 * XmuLookupStandardColormap().
828 * Given a screen, a visual, and a property, XmuLookupStandardColormap()
829 * will determine the best allocation for the property under the specified
830 * visual, and determine the whether to create a new colormap or to use
831 * the default colormap of the screen. It will call XmuStandardColormap()
832 * to create the standard colormap.
834 * If replace is true, any previous definition of the property will be
835 * replaced. If retain is true, the property and the colormap will be
836 * made permanent for the duration of the server session. However,
837 * pre-existing property definitions which are not replaced cannot be made
838 * permanent by a call to XmuLookupStandardColormap(); a request to retain
839 * resources pertains to newly created resources.
841 * Returns 0 on failure, non-zero on success. A request to create a
842 * standard colormap upon a visual which cannot support such a map is
843 * considered a failure. An example of this would be requesting any
844 * standard colormap property on a monochrome visual, or, requesting an
845 * RGB_BEST_MAP on a display whose colormap size is 16.
849 XmuLookupStandardColormap(Display *dpy, int screen, VisualID visualid,
850 unsigned int depth, Atom property,
851 Bool replace, Bool retain)
853 * dpy - specifies X server connection
854 * screen - specifies screen of display
855 * visualid - specifies the visual type
856 * depth - specifies the visual type
857 * property - a standard colormap property
858 * replace - specifies whether to replace
859 * retain - specifies whether to retain
862 Display *odpy; /* original display connection */
863 XStandardColormap *colormap;
864 XVisualInfo vinfo_template, *vinfo; /* visual */
866 unsigned long r_max, g_max, b_max; /* allocation */
868 Colormap cmap; /* colormap ID */
872 /* Match the requested visual */
874 vinfo_template.visualid = visualid;
875 vinfo_template.screen = screen;
876 vinfo_template.depth = depth;
877 vinfo_mask = VisualIDMask | VisualScreenMask | VisualDepthMask;
878 if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &count)) ==
882 /* Monochrome visuals have no standard maps */
884 if (vinfo->colormap_size <= 2) {
885 XFree((char *) vinfo);
889 /* If the requested property already exists on this screen, and,
890 * if the replace flag has not been set to true, return success.
891 * lookup() will remove a pre-existing map if replace is true.
894 if (lookup(dpy, screen, visualid, property, (XStandardColormap *) NULL,
895 replace) && !replace) {
896 XFree((char *) vinfo);
900 /* Determine the best allocation for this property under the requested
901 * visualid and depth, and determine whether or not to use the default
902 * colormap of the screen.
905 if (!XmuGetColormapAllocation(vinfo, property, &r_max, &g_max, &b_max)) {
906 XFree((char *) vinfo);
910 cmap = (property == XA_RGB_DEFAULT_MAP &&
911 visualid == XVisualIDFromVisual(DefaultVisual(dpy, screen)))
912 ? DefaultColormap(dpy, screen) : None;
914 /* If retaining resources, open a new connection to the same server */
918 if ((dpy = XOpenDisplay(XDisplayString(odpy))) == NULL) {
919 XFree((char *) vinfo);
924 /* Create the standard colormap */
926 colormap = XmuStandardColormap(dpy, screen, visualid, depth, property,
927 cmap, r_max, g_max, b_max);
929 /* Set the standard colormap property */
934 if (lookup(dpy, screen, visualid, property, colormap, replace) &&
936 /* Someone has defined the property since we last looked.
937 * Since we will not replace it, release our own resources.
938 * If this is the default map, our allocations will be freed
939 * when this connection closes.
941 if (colormap->killid == ReleaseByFreeingColormap)
942 XFreeColormap(dpy, colormap->colormap);
944 XSetCloseDownMode(dpy, RetainPermanent);
947 XFree((char *) colormap);
953 XFree((char *) vinfo);
957 /***************************************************************************/
959 /* Lookup a standard colormap property. If the property is RGB_DEFAULT_MAP,
960 * the visualid is used to determine whether the indicated standard colormap
961 * exists. If the map exists and replace is true, delete the resources used
962 * by the map and remove the property. Return true if the map exists,
963 * or did exist and was deleted; return false if the map was not found.
965 * Note that this is not the way that a Status return is normally used.
967 * If new is not NULL, new points to an XStandardColormap structure which
968 * describes a standard colormap of the specified property. It will be made
969 * a standard colormap of the screen if none already exists, or if replace
974 lookup(Display *dpy, int screen, VisualID visualid, Atom property,
975 XStandardColormap *cnew, Bool replace)
977 * dpy - specifies display connection
978 * screen - specifies screen number
979 * visualid - specifies visualid for std map
980 * property - specifies colormap property name
981 * cnew - specifies a standard colormap
982 * replace - specifies whether to replace
987 XStandardColormap *stdcmaps, *s;
988 Window win = RootWindow(dpy, screen);
990 /* The property does not already exist */
992 if (! XGetRGBColormaps(dpy, win, &stdcmaps, &count, property)) {
994 XSetRGBColormaps(dpy, win, cnew, 1, property);
998 /* The property exists and is not describing the RGB_DEFAULT_MAP */
1000 if (property != XA_RGB_DEFAULT_MAP) {
1002 XmuDeleteStandardColormap(dpy, screen, property);
1004 XSetRGBColormaps(dpy, win, cnew, 1, property);
1006 XFree((char *)stdcmaps);
1010 /* The property exists and is RGB_DEFAULT_MAP */
1012 for (i=0, s=stdcmaps; (i < count) && (s->visualid != visualid); i++, s++)
1015 /* No RGB_DEFAULT_MAP property matches the given visualid */
1019 XStandardColormap *m, *maps;
1021 s = (XStandardColormap *) malloc((unsigned) ((count+1) * sizeof
1022 (XStandardColormap)));
1024 for (i = 0, m = s, maps = stdcmaps; i < count; i++, m++, maps++) {
1025 m->colormap = maps->colormap;
1026 m->red_max = maps->red_max;
1027 m->red_mult = maps->red_mult;
1028 m->green_max = maps->green_max;
1029 m->green_mult = maps->green_mult;
1030 m->blue_max = maps->blue_max;
1031 m->blue_mult = maps->blue_mult;
1032 m->base_pixel = maps->base_pixel;
1033 m->visualid = maps->visualid;
1034 m->killid = maps->killid;
1036 m->colormap = cnew->colormap;
1037 m->red_max = cnew->red_max;
1038 m->red_mult = cnew->red_mult;
1039 m->green_max = cnew->green_max;
1040 m->green_mult = cnew->green_mult;
1041 m->blue_max = cnew->blue_max;
1042 m->blue_mult = cnew->blue_mult;
1043 m->base_pixel = cnew->base_pixel;
1044 m->visualid = cnew->visualid;
1045 m->killid = cnew->killid;
1047 XSetRGBColormaps(dpy, win, s, ++count, property);
1050 XFree((char *) stdcmaps);
1054 /* Found an RGB_DEFAULT_MAP property with a matching visualid */
1057 /* Free old resources first - we may need them, particularly in
1058 * the default colormap of the screen. However, because of this,
1059 * it is possible that we will destroy the old resource and fail
1060 * to create a new one if XmuStandardColormap() fails.
1064 XmuDeleteStandardColormap(dpy, screen, property);
1066 XSetRGBColormaps(dpy, win, cnew, 1, property);
1069 XStandardColormap *map;
1071 /* s still points to the matching standard colormap */
1073 if (s->killid == ReleaseByFreeingColormap) {
1074 if ((s->colormap != None) &&
1075 (s->colormap != DefaultColormap(dpy, screen)))
1076 XFreeColormap(dpy, s->colormap);
1078 else if (s->killid != None)
1079 XKillClient(dpy, s->killid);
1081 map = (cnew) ? cnew : stdcmaps + --count;
1083 s->colormap = map->colormap;
1084 s->red_max = map->red_max;
1085 s->red_mult = map->red_mult;
1086 s->green_max = map->green_max;
1087 s->green_mult = map->green_mult;
1088 s->blue_max = map->blue_max;
1089 s->blue_mult = map->blue_mult;
1090 s->visualid = map->visualid;
1091 s->killid = map->killid;
1093 XSetRGBColormaps(dpy, win, stdcmaps, count, property);
1096 XFree((char *) stdcmaps);
1100 /* $Xorg: CmapAlloc.c,v 1.4 2001/02/09 02:03:51 xorgcvs Exp $ */
1104 Copyright 1989, 1994, 1998 The Open Group
1106 Permission to use, copy, modify, distribute, and sell this software and its
1107 documentation for any purpose is hereby granted without fee, provided that
1108 the above copyright notice appear in all copies and that both that
1109 copyright notice and this permission notice appear in supporting
1112 The above copyright notice and this permission notice shall be included in
1113 all copies or substantial portions of the Software.
1115 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1116 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1117 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1118 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1119 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1120 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1122 Except as contained in this notice, the name of The Open Group shall not be
1123 used in advertising or otherwise to promote the sale, use or other dealings
1124 in this Software without prior written authorization from The Open Group.
1127 /* $XFree86: xc/lib/Xmu/CmapAlloc.c,v 1.7 2001/12/14 19:55:35 dawes Exp $ */
1130 * Author: Donna Converse, MIT X Consortium
1133 #include <X11/Xlib.h>
1134 #include <X11/Xatom.h>
1135 #include <X11/Xutil.h>
1136 #include <X11/Xmu/StdCmap.h>
1139 #define lowbit(x) ((x) & (~(x) + 1))
1144 static void best_allocation(XVisualInfo*, unsigned long*, unsigned long*,
1146 static int default_allocation(XVisualInfo*, unsigned long*,
1147 unsigned long*, unsigned long*);
1148 static void gray_allocation(int, unsigned long*, unsigned long*,
1150 static int icbrt(int);
1151 static int icbrt_with_bits(int, int);
1152 static int icbrt_with_guess(int, int);
1154 /* To determine the best allocation of reds, greens, and blues in a
1155 * standard colormap, use XmuGetColormapAllocation.
1156 * vinfo specifies visual information for a chosen visual
1157 * property specifies one of the standard colormap property names
1158 * red_max returns maximum red value
1159 * green_max returns maximum green value
1160 * blue_max returns maximum blue value
1162 * XmuGetColormapAllocation returns 0 on failure, non-zero on success.
1163 * It is assumed that the visual is appropriate for the colormap property.
1167 XmuGetColormapAllocation(XVisualInfo *vinfo, Atom property,
1168 unsigned long *red_max,
1169 unsigned long *green_max,
1170 unsigned long *blue_max)
1174 if (vinfo->colormap_size <= 2)
1179 case XA_RGB_DEFAULT_MAP:
1180 status = default_allocation(vinfo, red_max, green_max, blue_max);
1182 case XA_RGB_BEST_MAP:
1183 best_allocation(vinfo, red_max, green_max, blue_max);
1185 case XA_RGB_GRAY_MAP:
1186 gray_allocation(vinfo->colormap_size, red_max, green_max, blue_max);
1188 case XA_RGB_RED_MAP:
1189 *red_max = vinfo->colormap_size - 1;
1190 *green_max = *blue_max = 0;
1192 case XA_RGB_GREEN_MAP:
1193 *green_max = vinfo->colormap_size - 1;
1194 *red_max = *blue_max = 0;
1196 case XA_RGB_BLUE_MAP:
1197 *blue_max = vinfo->colormap_size - 1;
1198 *red_max = *green_max = 0;
1206 /****************************************************************************/
1207 /* Determine the appropriate color allocations of a gray scale.
1209 * Keith Packard, MIT X Consortium
1213 gray_allocation(int n, unsigned long *red_max, unsigned long *green_max,
1214 unsigned long *blue_max)
1216 *red_max = (n * 30) / 100;
1217 *green_max = (n * 59) / 100;
1218 *blue_max = (n * 11) / 100;
1219 *green_max += ((n - 1) - (*red_max + *green_max + *blue_max));
1222 /****************************************************************************/
1223 /* Determine an appropriate color allocation for the RGB_DEFAULT_MAP.
1224 * If a map has less than a minimum number of definable entries, we do not
1225 * produce an allocation for an RGB_DEFAULT_MAP.
1227 * For 16 planes, the default colormap will have 27 each RGB; for 12 planes,
1228 * 12 each. For 8 planes, let n = the number of colormap entries, which may
1229 * be 256 or 254. Then, maximum red value = floor(cube_root(n - 125)) - 1.
1230 * Maximum green and maximum blue values are identical to maximum red.
1231 * This leaves at least 125 cells which clients can allocate.
1233 * Return 0 if an allocation has been determined, non-zero otherwise.
1237 default_allocation(XVisualInfo *vinfo, unsigned long *red,
1238 unsigned long *green, unsigned long *blue)
1240 int ngrays; /* number of gray cells */
1242 switch (vinfo->c_class)
1246 if (vinfo->colormap_size > 65000)
1247 /* intended for displays with 16 planes */
1248 *red = *green = *blue = (unsigned long) 27;
1249 else if (vinfo->colormap_size > 4000)
1250 /* intended for displays with 12 planes */
1251 *red = *green = *blue = (unsigned long) 12;
1252 else if (vinfo->colormap_size < 250)
1255 /* intended for displays with 8 planes */
1256 *red = *green = *blue = (unsigned long)
1257 (icbrt(vinfo->colormap_size - 125) - 1);
1262 if (vinfo->colormap_size < 10)
1264 *red = *green = *blue = vinfo->colormap_size / 2 - 1;
1269 *red = vinfo->red_mask / lowbit(vinfo->red_mask);
1270 *green = vinfo->green_mask / lowbit(vinfo->green_mask);
1271 *blue = vinfo->blue_mask / lowbit(vinfo->blue_mask);
1276 if (vinfo->colormap_size > 65000)
1278 else if (vinfo->colormap_size > 4000)
1280 else if (vinfo->colormap_size < 250)
1284 gray_allocation(ngrays, red, green, blue);
1293 /****************************************************************************/
1294 /* Determine an appropriate color allocation for the RGB_BEST_MAP.
1296 * For a DirectColor or TrueColor visual, the allocation is determined
1297 * by the red_mask, green_mask, and blue_mask members of the visual info.
1299 * Otherwise, if the colormap size is an integral power of 2, determine
1300 * the allocation according to the number of bits given to each color,
1301 * with green getting more than red, and red more than blue, if there
1302 * are to be inequities in the distribution. If the colormap size is
1303 * not an integral power of 2, let n = the number of colormap entries.
1304 * Then maximum red value = floor(cube_root(n)) - 1;
1305 * maximum blue value = floor(cube_root(n)) - 1;
1306 * maximum green value = n / ((# red values) * (# blue values)) - 1;
1307 * Which, on a GPX, allows for 252 entries in the best map, out of 254
1308 * defineable colormap entries.
1312 best_allocation(XVisualInfo *vinfo, unsigned long *red, unsigned long *green,
1313 unsigned long *blue)
1316 if (vinfo->c_class == DirectColor || vinfo->c_class == TrueColor)
1318 *red = vinfo->red_mask;
1319 while ((*red & 01) == 0)
1321 *green = vinfo->green_mask;
1322 while ((*green & 01) == 0)
1324 *blue = vinfo->blue_mask;
1325 while ((*blue & 01) == 0)
1330 register int bits, n;
1332 /* Determine n such that n is the least integral power of 2 which is
1333 * greater than or equal to the number of entries in the colormap.
1337 while (vinfo->colormap_size > n)
1343 /* If the number of entries in the colormap is a power of 2, determine
1344 * the allocation by "dealing" the bits, first to green, then red, then
1345 * blue. If not, find the maximum integral red, green, and blue values
1346 * which, when multiplied together, do not exceed the number of
1350 if (n == vinfo->colormap_size)
1352 register int r, g, b;
1354 g = b + ((bits % 3) ? 1 : 0);
1355 r = b + (((bits % 3) == 2) ? 1 : 0);
1362 *red = icbrt_with_bits(vinfo->colormap_size, bits);
1364 *green = (vinfo->colormap_size / ((*red) * (*blue)));
1374 * integer cube roots by Newton's method
1376 * Stephen Gildea, MIT X Consortium, July 1991
1382 register int bits = 0;
1383 register unsigned n = a;
1390 return icbrt_with_bits(a, bits);
1395 icbrt_with_bits(int a, int bits)
1396 /* bits - log 2 of a */
1398 return icbrt_with_guess(a, a>>2*bits/3);
1401 #ifdef _X_ROOT_STATS
1402 int icbrt_loopcount;
1405 /* Newton's Method: x_n+1 = x_n - ( f(x_n) / f'(x_n) ) */
1407 /* for cube roots, x^3 - a = 0, x_new = x - 1/3 (x - a/x^2) */
1410 * Quick and dirty cube roots. Nothing fancy here, just Newton's method.
1411 * Only works for positive integers (since that's all we need).
1412 * We actually return floor(cbrt(a)) because that's what we need here, too.
1416 icbrt_with_guess(int a, int guess)
1420 #ifdef _X_ROOT_STATS
1421 icbrt_loopcount = 0;
1429 #ifdef _X_ROOT_STATS
1432 delta = (guess - a/(guess*guess))/3;
1434 printf("pass %d: guess=%d, delta=%d\n", icbrt_loopcount, guess, delta);
1437 } while (delta != 0);
1439 if (guess*guess*guess > a)
1446 /* $Xorg: StdCmap.c,v 1.4 2001/02/09 02:03:53 xorgcvs Exp $ */
1450 Copyright 1989, 1998 The Open Group
1452 Permission to use, copy, modify, distribute, and sell this software and its
1453 documentation for any purpose is hereby granted without fee, provided that
1454 the above copyright notice appear in all copies and that both that
1455 copyright notice and this permission notice appear in supporting
1458 The above copyright notice and this permission notice shall be included in
1459 all copies or substantial portions of the Software.
1461 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1462 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1463 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1464 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1465 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1466 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1468 Except as contained in this notice, the name of The Open Group shall not be
1469 used in advertising or otherwise to promote the sale, use or other dealings
1470 in this Software without prior written authorization from The Open Group.
1473 /* $XFree86: xc/lib/Xmu/StdCmap.c,v 1.6 2001/12/14 19:55:48 dawes Exp $ */
1476 * Author: Donna Converse, MIT X Consortium
1480 #include <X11/Xlib.h>
1481 #include <X11/Xatom.h>
1482 #include <X11/Xutil.h>
1483 #include <X11/Xmu/StdCmap.h>
1485 #define lowbit(x) ((x) & (~(x) + 1))
1490 /* argument restrictions */
1491 static Status valid_args(XVisualInfo*, unsigned long, unsigned long,
1492 unsigned long, Atom);
1495 * To create any one standard colormap, use XmuStandardColormap().
1497 * Create a standard colormap for the given screen, visualid, and visual
1498 * depth, with the given red, green, and blue maximum values, with the
1499 * given standard property name. Return a pointer to an XStandardColormap
1500 * structure which describes the newly created colormap, upon success.
1501 * Upon failure, return NULL.
1503 * XmuStandardColormap() calls XmuCreateColormap() to create the map.
1505 * Resources created by this function are not made permanent; that is the
1506 * caller's responsibility.
1510 XmuStandardColormap(Display *dpy, int screen, VisualID visualid,
1511 unsigned int depth, Atom property, Colormap cmap,
1512 unsigned long red_max, unsigned long green_max,
1513 unsigned long blue_max)
1515 * dpy - specifies X server connection
1516 * screen - specifies display screen
1517 * visualid - identifies the visual type
1518 * depth - identifies the visual type
1519 * property - a standard colormap property
1520 * cmap - specifies colormap ID or None
1521 * red_max, green_max, blue_max - allocations
1524 XStandardColormap *stdcmap;
1526 XVisualInfo vinfo_template, *vinfo;
1530 /* Match the required visual information to an actual visual */
1531 vinfo_template.visualid = visualid;
1532 vinfo_template.screen = screen;
1533 vinfo_template.depth = depth;
1534 vinfo_mask = VisualIDMask | VisualScreenMask | VisualDepthMask;
1535 if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &n)) == NULL)
1538 /* Check the validity of the combination of visual characteristics,
1539 * allocation, and colormap property. Create an XStandardColormap
1543 if (! valid_args(vinfo, red_max, green_max, blue_max, property)
1544 || ((stdcmap = XAllocStandardColormap()) == NULL)) {
1545 XFree((char *) vinfo);
1549 /* Fill in the XStandardColormap structure */
1551 if (cmap == DefaultColormap(dpy, screen)) {
1552 /* Allocating out of the default map, cannot use XFreeColormap() */
1553 Window win = XCreateWindow(dpy, RootWindow(dpy, screen), 1, 1, 1, 1,
1554 0, 0, InputOnly, vinfo->visual,
1556 (XSetWindowAttributes *)NULL);
1557 stdcmap->killid = (XID) XCreatePixmap(dpy, win, 1, 1, depth);
1558 XDestroyWindow(dpy, win);
1559 stdcmap->colormap = cmap;
1561 stdcmap->killid = ReleaseByFreeingColormap;
1562 stdcmap->colormap = XCreateColormap(dpy, RootWindow(dpy, screen),
1563 vinfo->visual, AllocNone);
1565 stdcmap->red_max = red_max;
1566 stdcmap->green_max = green_max;
1567 stdcmap->blue_max = blue_max;
1568 if (property == XA_RGB_GRAY_MAP)
1569 stdcmap->red_mult = stdcmap->green_mult = stdcmap->blue_mult = 1;
1570 else if (vinfo->c_class == TrueColor || vinfo->c_class == DirectColor) {
1571 stdcmap->red_mult = lowbit(vinfo->red_mask);
1572 stdcmap->green_mult = lowbit(vinfo->green_mask);
1573 stdcmap->blue_mult = lowbit(vinfo->blue_mask);
1575 stdcmap->red_mult = (red_max > 0)
1576 ? (green_max + 1) * (blue_max + 1) : 0;
1577 stdcmap->green_mult = (green_max > 0) ? blue_max + 1 : 0;
1578 stdcmap->blue_mult = (blue_max > 0) ? 1 : 0;
1580 stdcmap->base_pixel = 0; /* base pixel may change */
1581 stdcmap->visualid = vinfo->visualid;
1583 /* Make the colormap */
1585 status = XmuCreateColormap(dpy, stdcmap);
1589 XFree((char *) vinfo);
1592 /* Free the colormap or the pixmap, if we created one */
1593 if (stdcmap->killid == ReleaseByFreeingColormap)
1594 XFreeColormap(dpy, stdcmap->colormap);
1595 else if (stdcmap->killid != None)
1596 XFreePixmap(dpy, stdcmap->killid);
1598 XFree((char *) stdcmap);
1599 return (XStandardColormap *) NULL;
1604 /****************************************************************************/
1606 valid_args(XVisualInfo *vinfo, unsigned long red_max, unsigned long green_max,
1607 unsigned long blue_max, Atom property)
1609 * vinfo - specifies visual
1610 * red_max, green_max, blue_max - specifies alloc
1611 * property - specifies property name
1614 unsigned long ncolors; /* number of colors requested */
1616 /* Determine that the number of colors requested is <= map size */
1618 if ((vinfo->c_class == DirectColor) || (vinfo->c_class == TrueColor)) {
1621 mask = vinfo->red_mask;
1626 mask = vinfo->green_mask;
1629 if (green_max > mask)
1631 mask = vinfo->blue_mask;
1634 if (blue_max > mask)
1636 } else if (property == XA_RGB_GRAY_MAP) {
1637 ncolors = red_max + green_max + blue_max + 1;
1638 if (ncolors > vinfo->colormap_size)
1641 ncolors = (red_max + 1) * (green_max + 1) * (blue_max + 1);
1642 if (ncolors > vinfo->colormap_size)
1646 /* Determine that the allocation and visual make sense for the property */
1650 case XA_RGB_DEFAULT_MAP:
1651 if (red_max == 0 || green_max == 0 || blue_max == 0)
1654 case XA_RGB_RED_MAP:
1658 case XA_RGB_GREEN_MAP:
1662 case XA_RGB_BLUE_MAP:
1666 case XA_RGB_BEST_MAP:
1667 if (red_max == 0 || green_max == 0 || blue_max == 0)
1670 case XA_RGB_GRAY_MAP:
1671 if (red_max == 0 || blue_max == 0 || green_max == 0)
1681 /* $Xorg: CrCmap.c,v 1.4 2001/02/09 02:03:51 xorgcvs Exp $ */
1685 Copyright 1989, 1998 The Open Group
1687 Permission to use, copy, modify, distribute, and sell this software and its
1688 documentation for any purpose is hereby granted without fee, provided that
1689 the above copyright notice appear in all copies and that both that
1690 copyright notice and this permission notice appear in supporting
1693 The above copyright notice and this permission notice shall be included in
1694 all copies or substantial portions of the Software.
1696 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1697 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1698 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1699 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1700 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1701 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1703 Except as contained in this notice, the name of The Open Group shall not be
1704 used in advertising or otherwise to promote the sale, use or other dealings
1705 in this Software without prior written authorization from The Open Group.
1708 /* $XFree86: xc/lib/Xmu/CrCmap.c,v 3.7 2001/12/14 19:55:36 dawes Exp $ */
1711 * Author: Donna Converse, MIT X Consortium
1715 * CreateCmap.c - given a standard colormap description, make the map.
1720 #include <X11/Xlib.h>
1721 #include <X11/Xutil.h>
1722 #include <X11/Xmu/StdCmap.h>
1727 /* allocate entire map Read Only */
1728 static int ROmap(Display*, Colormap, unsigned long[], int, int);
1730 /* allocate a cell, prefer Read Only */
1731 static Status ROorRWcell(Display*, Colormap, unsigned long[], int,
1732 XColor*, unsigned long);
1734 /* allocate a cell Read Write */
1735 static Status RWcell(Display*, Colormap, XColor*, XColor*, unsigned long*);
1738 static int compare(_Xconst void*, _Xconst void*);
1740 /* find contiguous sequence of cells */
1741 static Status contiguous(unsigned long[], int, int, unsigned long, int*, int*);
1743 /* frees resources before quitting */
1744 static void free_cells(Display*, Colormap, unsigned long[], int, int);
1746 /* create a map in a RO visual type */
1747 static Status readonly_map(Display*, XVisualInfo*, XStandardColormap*);
1749 /* create a map in a RW visual type */
1750 static Status readwrite_map(Display*, XVisualInfo*, XStandardColormap*);
1752 #define lowbit(x) ((x) & (~(x) + 1))
1753 #define TRUEMATCH(mult,max,mask) \
1754 (colormap->max * colormap->mult <= vinfo->mask && \
1755 lowbit(vinfo->mask) == colormap->mult)
1758 * To create any one colormap which is described by an XStandardColormap
1759 * structure, use XmuCreateColormap().
1761 * Return 0 on failure, non-zero on success.
1762 * Resources created by this function are not made permanent.
1763 * No argument error checking is provided. Use at your own risk.
1765 * All colormaps are created with read only allocations, with the exception
1766 * of read only allocations of colors in the default map or otherwise
1767 * which fail to return the expected pixel value, and these are individually
1768 * defined as read/write allocations. This is done so that all the cells
1769 * defined in the default map are contiguous, for use in image processing.
1770 * This typically happens with White and Black in the default map.
1772 * Colormaps of static visuals are considered to be successfully created if
1773 * the map of the static visual matches the definition given in the
1774 * standard colormap structure.
1778 XmuCreateColormap(Display *dpy, XStandardColormap *colormap)
1779 /* dpy - specifies the connection under which the map is created
1780 * colormap - specifies the map to be created, and returns, particularly
1781 * if the map is created as a subset of the default colormap
1782 * of the screen, the base_pixel of the map.
1785 XVisualInfo vinfo_template; /* template visual information */
1786 XVisualInfo *vinfo; /* matching visual information */
1787 XVisualInfo *vpointer; /* for freeing the entire list */
1788 long vinfo_mask; /* specifies the visual mask value */
1789 int n; /* number of matching visuals */
1792 vinfo_template.visualid = colormap->visualid;
1793 vinfo_mask = VisualIDMask;
1794 if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &n)) == NULL)
1797 /* A visual id may be valid on multiple screens. Also, there may
1798 * be multiple visuals with identical visual ids at different depths.
1799 * If the colormap is the Default Colormap, use the Default Visual.
1800 * Otherwise, arbitrarily, use the deepest visual.
1806 register int screen_number;
1810 for (screen_number = ScreenCount(dpy); --screen_number >= 0; )
1811 if (colormap->colormap == DefaultColormap(dpy, screen_number)) {
1817 for (i=0; i < n; i++, vinfo++) {
1818 if (vinfo->visual == DefaultVisual(dpy, screen_number))
1823 XVisualInfo *v = NULL;
1825 for (i=0; i < n; i++, vinfo++)
1826 if (vinfo->depth > maxdepth) {
1827 maxdepth = vinfo->depth;
1834 if (vinfo->c_class == PseudoColor || vinfo->c_class == DirectColor ||
1835 vinfo->c_class == GrayScale)
1836 status = readwrite_map(dpy, vinfo, colormap);
1837 else if (vinfo->c_class == TrueColor)
1838 status = TRUEMATCH(red_mult, red_max, red_mask) &&
1839 TRUEMATCH(green_mult, green_max, green_mask) &&
1840 TRUEMATCH(blue_mult, blue_max, blue_mask);
1842 status = readonly_map(dpy, vinfo, colormap);
1844 XFree((char *) vpointer);
1848 /****************************************************************************/
1850 readwrite_map(Display *dpy, XVisualInfo *vinfo, XStandardColormap *colormap)
1852 register unsigned long i, n; /* index counters */
1853 unsigned long ncolors; /* number of colors to be defined */
1854 int npixels; /* number of pixels allocated R/W */
1855 int first_index; /* first index of pixels to use */
1856 int remainder; /* first index of remainder */
1857 XColor color; /* the definition of a color */
1858 unsigned long *pixels; /* array of colormap pixels */
1859 unsigned long delta;
1862 /* Determine ncolors, the number of colors to be defined.
1863 * Insure that 1 < ncolors <= the colormap size.
1865 if (vinfo->c_class == DirectColor) {
1866 ncolors = colormap->red_max;
1867 if (colormap->green_max > ncolors)
1868 ncolors = colormap->green_max;
1869 if (colormap->blue_max > ncolors)
1870 ncolors = colormap->blue_max;
1872 delta = lowbit(vinfo->red_mask) +
1873 lowbit(vinfo->green_mask) +
1874 lowbit(vinfo->blue_mask);
1876 ncolors = colormap->red_max * colormap->red_mult +
1877 colormap->green_max * colormap->green_mult +
1878 colormap->blue_max * colormap->blue_mult + 1;
1881 if (ncolors <= 1 || (int) ncolors > vinfo->colormap_size) return 0;
1883 /* Allocate Read/Write as much of the colormap as we can possibly get.
1884 * Then insure that the pixels we were allocated are given in
1885 * monotonically increasing order, using a quicksort. Next, insure
1886 * that our allocation includes a subset of contiguous pixels at least
1887 * as long as the number of colors to be defined. Now we know that
1888 * these conditions are met:
1889 * 1) There are no free cells in the colormap.
1890 * 2) We have a contiguous sequence of pixels, monotonically
1891 * increasing, of length >= the number of colors requested.
1893 * One cell at a time, we will free, compute the next color value,
1894 * then allocate read only. This takes a long time.
1895 * This is done to insure that cells are allocated read only in the
1896 * contiguous order which we prefer. If the server has a choice of
1897 * cells to grant to an allocation request, the server may give us any
1898 * cell, so that is why we do these slow gymnastics.
1901 if ((pixels = (unsigned long *) calloc((unsigned) vinfo->colormap_size,
1902 sizeof(unsigned long))) == NULL)
1905 if ((npixels = ROmap(dpy, colormap->colormap, pixels,
1906 vinfo->colormap_size, ncolors)) == 0) {
1907 free((char *) pixels);
1911 qsort((char *) pixels, npixels, sizeof(unsigned long), compare);
1913 if (!contiguous(pixels, npixels, ncolors, delta, &first_index, &remainder))
1915 /* can't find enough contiguous cells, give up */
1916 XFreeColors(dpy, colormap->colormap, pixels, npixels,
1918 free((char *) pixels);
1921 colormap->base_pixel = pixels[first_index];
1923 /* construct a gray map */
1924 if (colormap->red_mult == 1 && colormap->green_mult == 1 &&
1925 colormap->blue_mult == 1)
1926 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
1929 color.blue = color.green = color.red =
1930 (unsigned short) ((i * 65535) / (colormap->red_max +
1931 colormap->green_max +
1932 colormap->blue_max));
1934 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
1939 /* construct a red ramp map */
1940 else if (colormap->green_max == 0 && colormap->blue_max == 0)
1941 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
1944 color.red = (unsigned short) ((i * 65535) / colormap->red_max);
1945 color.green = color.blue = 0;
1947 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
1952 /* construct a green ramp map */
1953 else if (colormap->red_max == 0 && colormap->blue_max == 0)
1954 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
1957 color.green = (unsigned short) ((i * 65535) / colormap->green_max);
1958 color.red = color.blue = 0;
1960 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
1965 /* construct a blue ramp map */
1966 else if (colormap->red_max == 0 && colormap->green_max == 0)
1967 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
1970 color.blue = (unsigned short) ((i * 65535) / colormap->blue_max);
1971 color.red = color.green = 0;
1973 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
1978 /* construct a standard red green blue cube map */
1981 #define calc(max,mult) (((n / colormap->mult) % \
1982 (colormap->max + 1)) * 65535) / colormap->max
1984 for (n=0, i=0; i < ncolors; i++, n += delta)
1986 color.pixel = n + colormap->base_pixel;
1987 color.red = calc(red_max, red_mult);
1988 color.green = calc(green_max, green_mult);
1989 color.blue = calc(blue_max, blue_mult);
1990 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
1996 /* We have a read-only map defined. Now free unused cells,
1997 * first those occuring before the contiguous sequence begins,
1998 * then any following the contiguous sequence.
2002 XFreeColors(dpy, colormap->colormap, pixels, first_index,
2005 XFreeColors(dpy, colormap->colormap,
2006 &(pixels[first_index + ncolors]), remainder,
2009 free((char *) pixels);
2014 /****************************************************************************/
2016 ROmap(Display *dpy, Colormap cmap, unsigned long pixels[], int m, int n)
2018 * dpy - the X server connection
2019 * cmap - specifies colormap ID
2020 * pixels - returns pixel allocations
2021 * m - specifies colormap size
2022 * n - specifies number of colors
2027 /* first try to allocate the entire colormap */
2028 if (XAllocColorCells(dpy, cmap, 1, (unsigned long *) NULL,
2029 (unsigned) 0, pixels, (unsigned) m))
2032 /* Allocate all available cells in the colormap, using a binary
2033 * algorithm to discover how many cells we can allocate in the colormap.
2037 p = n + ((m - n + 1) / 2);
2038 if (XAllocColorCells(dpy, cmap, 1, (unsigned long *) NULL,
2039 (unsigned) 0, pixels, (unsigned) p)) {
2043 XFreeColors(dpy, cmap, pixels, p, (unsigned long) 0);
2054 /****************************************************************************/
2056 contiguous(unsigned long pixels[], int npixels, int ncolors,
2057 unsigned long delta, int *first, int *rem)
2058 /* pixels - specifies allocated pixels
2059 * npixels - specifies count of alloc'd pixels
2060 * ncolors - specifies needed sequence length
2061 * delta - between pixels
2062 * first - returns first index of sequence
2063 * rem - returns first index after sequence, or 0, if none follow
2066 register int i = 1; /* walking index into the pixel array */
2067 register int count = 1; /* length of sequence discovered so far */
2070 if (npixels == ncolors) {
2075 while (count < ncolors && ncolors - count <= *rem)
2077 if (pixels[i-1] + delta == pixels[i])
2086 if (count != ncolors)
2092 /****************************************************************************/
2094 ROorRWcell(Display *dpy, Colormap cmap, unsigned long pixels[],
2095 int npixels, XColor *color, unsigned long p)
2097 unsigned long pixel;
2100 /* Free the read/write allocation of one cell in the colormap.
2101 * Request a read only allocation of one cell in the colormap.
2102 * If the read only allocation cannot be granted, give up, because
2103 * there must be no free cells in the colormap.
2104 * If the read only allocation is granted, but gives us a cell which
2105 * is not the one that we just freed, it is probably the case that
2106 * we are trying allocate White or Black or some other color which
2107 * already has a read-only allocation in the map. So we try to
2108 * allocate the previously freed cell with a read/write allocation,
2109 * because we want contiguous cells for image processing algorithms.
2112 pixel = color->pixel;
2113 request.red = color->red;
2114 request.green = color->green;
2115 request.blue = color->blue;
2117 XFreeColors(dpy, cmap, &pixel, 1, (unsigned long) 0);
2118 if (! XAllocColor(dpy, cmap, color)
2119 || (color->pixel != pixel &&
2120 (!RWcell(dpy, cmap, color, &request, &pixel))))
2122 free_cells(dpy, cmap, pixels, npixels, (int)p);
2129 /****************************************************************************/
2131 free_cells(Display *dpy, Colormap cmap, unsigned long pixels[],
2134 * pixels - to be freed
2135 * npixels - original number allocated
2138 /* One of the npixels allocated has already been freed.
2139 * p is the index of the freed pixel.
2140 * First free the pixels preceeding p, and there are p of them;
2141 * then free the pixels following p, there are npixels - p - 1 of them.
2143 XFreeColors(dpy, cmap, pixels, p, (unsigned long) 0);
2144 XFreeColors(dpy, cmap, &(pixels[p+1]), npixels - p - 1, (unsigned long) 0);
2145 free((char *) pixels);
2149 /****************************************************************************/
2151 RWcell(Display *dpy, Colormap cmap, XColor *color, XColor *request,
2152 unsigned long *pixel)
2154 unsigned long n = *pixel;
2156 XFreeColors(dpy, cmap, &(color->pixel), 1, (unsigned long)0);
2157 if (! XAllocColorCells(dpy, cmap, (Bool) 0, (unsigned long *) NULL,
2158 (unsigned) 0, pixel, (unsigned) 1))
2162 XFreeColors(dpy, cmap, pixel, 1, (unsigned long) 0);
2165 color->pixel = *pixel;
2166 color->flags = DoRed | DoGreen | DoBlue;
2167 color->red = request->red;
2168 color->green = request->green;
2169 color->blue = request->blue;
2170 XStoreColors(dpy, cmap, color, 1);
2175 /****************************************************************************/
2177 compare(_Xconst void *e1, _Xconst void *e2)
2179 return ((int)(*(long *)e1 - *(long *)e2));
2183 /****************************************************************************/
2185 readonly_map(Display *dpy, XVisualInfo *vinfo, XStandardColormap *colormap)
2190 last_pixel = (colormap->red_max + 1) * (colormap->green_max + 1) *
2191 (colormap->blue_max + 1) + colormap->base_pixel - 1;
2193 for(i=colormap->base_pixel; i <= last_pixel; i++) {
2195 color.pixel = (unsigned long) i;
2196 color.red = (unsigned short)
2197 (((i/colormap->red_mult) * 65535) / colormap->red_max);
2199 if (vinfo->c_class == StaticColor) {
2200 color.green = (unsigned short)
2201 ((((i/colormap->green_mult) % (colormap->green_max + 1)) *
2202 65535) / colormap->green_max);
2203 color.blue = (unsigned short)
2204 (((i%colormap->green_mult) * 65535) / colormap->blue_max);
2206 else /* vinfo->c_class == GrayScale, old style allocation XXX */
2207 color.green = color.blue = color.red;
2209 XAllocColor(dpy, colormap->colormap, &color);
2210 if (color.pixel != (unsigned long) i)
2217 /* $Xorg: DelCmap.c,v 1.4 2001/02/09 02:03:52 xorgcvs Exp $ */
2221 Copyright 1989, 1998 The Open Group
2223 Permission to use, copy, modify, distribute, and sell this software and its
2224 documentation for any purpose is hereby granted without fee, provided that
2225 the above copyright notice appear in all copies and that both that
2226 copyright notice and this permission notice appear in supporting
2229 The above copyright notice and this permission notice shall be included in
2230 all copies or substantial portions of the Software.
2232 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2233 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2234 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2235 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
2236 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
2237 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2239 Except as contained in this notice, the name of The Open Group shall not be
2240 used in advertising or otherwise to promote the sale, use or other dealings
2241 in this Software without prior written authorization from The Open Group.
2244 /* $XFree86: xc/lib/Xmu/DelCmap.c,v 1.7 2001/12/14 19:55:40 dawes Exp $ */
2247 * Author: Donna Converse, MIT X Consortium
2250 #include <X11/Xlib.h>
2251 #include <X11/Xutil.h>
2252 #include <X11/Xmu/StdCmap.h>
2254 int ignoreErrorHandler(Display* d, XErrorEvent* e) { }
2256 /* To remove any standard colormap property, use XmuDeleteStandardColormap().
2257 * XmuDeleteStandardColormap() will remove the specified property from the
2258 * specified screen, releasing any resources used by the colormap(s) of the
2259 * property if possible.
2263 XmuDeleteStandardColormap(Display *dpy, int screen, Atom property)
2264 /* dpy; - specifies the X server to connect to
2265 * screen - specifies the screen of the display
2266 * property - specifies the standard colormap property
2269 XStandardColormap *stdcmaps, *s;
2272 if (XGetRGBColormaps(dpy, RootWindow(dpy, screen), &stdcmaps, &count,
2275 for (s=stdcmaps; count > 0; count--, s++) {
2276 if ((s->killid == ReleaseByFreeingColormap) &&
2277 (s->colormap != None) &&
2278 (s->colormap != DefaultColormap(dpy, screen))) {
2280 // UGLY HACK written in by Adam Megacz -- sometimes s->colormap isn't valid, so we do some shuffling
2281 X11ErrorHandler* oldHandler = XSetErrorHandler(ignoreErrorHandler);
2283 XFreeColormap(dpy, s->colormap);
2285 XSetErrorHandler(oldHandler);
2288 } else if (s->killid != None) {
2289 XKillClient(dpy, s->killid);
2292 XDeleteProperty(dpy, RootWindow(dpy, screen), property);
2293 XFree((char *) stdcmaps);