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/ibex/Surface.h>
17 #include <org/ibex/Picture.h>
18 #include <org/ibex/Box.h>
19 #include <org/ibex/plat/X11.h>
20 #include <org/ibex/plat/X11$X11Surface.h>
21 #include <org/ibex/plat/X11$X11Picture.h>
22 #include <org/ibex/plat/X11$X11PixelBuffer.h>
23 #include <org/ibex/util/Semaphore.h>
24 #include <org/ibex/Platform.h>
25 #include <java/lang/Long.h>
26 #include <java/util/Hashtable.h>
27 #include <org/ibex/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::ibex::plat::X11$X11PixelBuffer::fastDrawPicture(org::ibex::Picture* s,
70 jint dx, jint dy, jint cx1, jint cy1, jint cx2, jint cy2) {
71 org::ibex::plat::X11$X11Picture* source = (org::ibex::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)), dx, dy);
77 XSetClipMask(display, (*((GC*)clipped_gc)), None);
81 *((Pixmap*)source->doublebuf->pm), (*((Pixmap*)pm)), (*((GC*)clipped_gc)),
82 cx1 - dx, cy1 - dy, cx2 - cx1, cy2 - cy1, cx1, cy1);
85 void org::ibex::plat::X11$X11PixelBuffer::slowDrawPicture(org::ibex::Picture* s,
86 jint dx, jint dy, jint cx1, jint cy1, jint cx2, jint cy2,
87 jint rgb, jboolean alphaOnly) {
89 org::ibex::plat::X11$X11Picture* source = (org::ibex::plat::X11$X11Picture*)s;
92 // FASTEST: shared pixmap; twiddle bits in video ram directly
94 XSync(display, False); // ensure that all pending operations have rendered
95 xi = (XImage*)fake_ximage;
97 // MEDIUM: write to a shared ximage, then ask the server to do the blit
98 } else if (shm_supported) {
99 xi = XShmCreateImage(display, visual, colorDepth, ZPixmap, NULL, &shm_info, cx2 - cx1, cy2 - cy1);
100 ensureShmSize(xi->bytes_per_line * xi->height);
101 xi->data = shm_info.shmaddr;
102 XShmGetImage(display, (*((Pixmap*)pm)), xi, cx1, cy1, AllPlanes);
104 // SLOWEST: write to an ximage, copy it through the TCP connection, ask the server to do the blit
106 xi = XGetImage(display, (*((Pixmap*)pm)), cx1, cy1, cx2 - cx1, cy2 - cy1, AllPlanes, ZPixmap);
109 int* sourcedata = (int*)elements(source->data);
110 for(int y=cy1; y < cy2; y++) {
112 char* current_pixel = (xi->data + y * xi->bytes_per_line) +
113 (shared_pixmap ? cx1 * (xi->bits_per_pixel / 8) : - 1 * cy1 * xi->bytes_per_line);
115 for(int x=cx1; x < cx2; x++, current_pixel += xi->bits_per_pixel / 8) {
116 int source_x = x - dx;
117 int source_y = y - dy;
119 // FEATURE: be smarter here; can we do something better for the alphaonly case?
120 int sourcepixel = sourcedata[source_x + source_y * source->getWidth()];
121 int alpha = (sourcepixel & 0xFF000000) >> 24;
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;
130 switch (xi->bits_per_pixel) {
131 case 8: targetpixel = (int)(*current_pixel); break;
133 case 16: targetpixel = (int)(*((uint16_t*)current_pixel)); break;
135 // FIXME assumes endianness...
136 case 24: targetpixel =
137 (((int)*current_pixel) << 16) |
138 (((int)*(current_pixel + 1)) << 8) |
139 (((int)*(current_pixel + 2))); break;
140 case 32: targetpixel = *((int*)current_pixel); break;
141 default: org::ibex::Platform::criticalAbort(JvNewStringLatin1("ERROR: bpp not a multiple of 8!"));
143 targetpixel -= colormap_info->base_pixel;
145 // if you're on some wierd display that isn't either RGB or BGR, that's your problem, not mine
146 if (colormap_info->red_mult > colormap_info->green_mult && colormap_info->green_mult > colormap_info->blue_mult) {
147 red = targetpixel / colormap_info->red_mult;
148 green = (targetpixel - red * colormap_info->red_mult) / colormap_info->green_mult;
149 blue = (targetpixel-red * colormap_info->red_mult-green * colormap_info->green_mult)/colormap_info->blue_mult;
151 blue = targetpixel / colormap_info->blue_mult;
152 green = (targetpixel - blue * colormap_info->blue_mult) / colormap_info->green_mult;
153 red = (targetpixel-blue * colormap_info->blue_mult-green * colormap_info->green_mult)/colormap_info->red_mult;
156 red = ((source_red * (colormap_info->red_max) * alpha) + (red * 0xFF * (0xFF - alpha))) / (0xFF * 0xFF);
157 green = ((source_green * (colormap_info->green_max) * alpha)+(green * 0xFF * (0xFF - alpha))) / (0xFF * 0xFF);
158 blue = ((source_blue * (colormap_info->blue_max) * alpha) + (blue * 0xFF * (0xFF - alpha))) / (0xFF * 0xFF);
160 (red * colormap_info->red_mult) +
161 (green * colormap_info->green_mult) +
162 (blue * colormap_info->blue_mult) +
163 colormap_info->base_pixel;
164 switch (xi->bits_per_pixel) {
165 case 8: *current_pixel = (char)(destpixel & 0xFF); break;
166 case 16: *((uint16_t*)current_pixel) = (uint16_t)destpixel; break;
168 int offset = (int)current_pixel & 0x3;
169 uint64_t dest = ((uint64_t)destpixel) << (8 * offset);
170 uint64_t mask = ((uint64_t)0xffffff) << (8 * offset);
171 uint64_t* base = (uint64_t*)(current_pixel - offset);
172 *base = (*base & ~mask) | dest;
175 case 32: *((uint32_t*)current_pixel) = destpixel; break;
176 default: org::ibex::Platform::criticalAbort(JvNewStringLatin1("ERROR: bpp not a multiple of 8!"));
182 // do nothing, we wrote directly to video memory
184 } else if (shm_supported) {
185 XShmPutImage(display, (*((Pixmap*)pm)), (*((GC*)gc)), xi, 0, 0, cx1, cy1, cx2 - cx1, cy2 - cy1, False);
189 XPutImage(display, (*((Pixmap*)pm)), (*((GC*)gc)), xi, 0, 0, cx1, cy1, cx2 - cx1, cy2 - cy1);
194 void org::ibex::plat::X11$X11PixelBuffer::finalize() {
196 XShmSegmentInfo *sinfo = (XShmSegmentInfo*)shm_segment;
197 XShmDetach(display, sinfo);
198 shmdt(sinfo->shmaddr);
199 shmctl(sinfo->shmid, IPC_RMID, 0);
200 XDestroyImage((XImage*)fake_ximage);
204 XFreePixmap(display, *((Pixmap*)stipple));
207 XFreePixmap(display, *((Pixmap*)pm));
208 XFreeGC(display, *((GC*)gc));
209 XFreeGC(display, *((GC*)clipped_gc));
212 void org::ibex::plat::X11$X11PixelBuffer::natInit() {
214 if (width == 0 || height == 0) return;
215 shared_pixmap &= shm_supported & shm_pixmaps_supported; // refuse to use shared pixmaps if we don't have shm
216 pm = (gnu::gcj::RawData*)malloc(sizeof(Pixmap));
219 (*((Pixmap*)pm)) = XCreatePixmap(display, RootWindow(display, screen_num), width, height, colorDepth);
221 XShmSegmentInfo *sinfo = (XShmSegmentInfo*)malloc(sizeof(XShmSegmentInfo));
222 shm_segment = (gnu::gcj::RawData*)sinfo;
223 ((XImage*)fake_ximage) = XShmCreateImage(display, visual, colorDepth, ZPixmap, NULL, sinfo, width, height);
224 sinfo->shmid = shmget(IPC_PRIVATE, ((XImage*)fake_ximage)->bytes_per_line * height, IPC_CREAT | 0777 | IPC_EXCL);
225 ((XImage*)fake_ximage)->data = sinfo->shmaddr = (char*)shmat(sinfo->shmid, 0, 0);
226 sinfo->readOnly = False;
227 XShmAttach(display, sinfo);
228 XSync(display, False);
229 shmctl(sinfo->shmid, IPC_RMID, 0);
230 (*((Pixmap*)pm)) = XShmCreatePixmap(display, RootWindow(display, screen_num), sinfo->shmaddr, sinfo, width, height, colorDepth);
231 XSync(display, False);
234 gc = (gnu::gcj::RawData*)malloc(sizeof(GC));
235 clipped_gc = (gnu::gcj::RawData*)malloc(sizeof(GC));
236 (*((GC*)gc)) = XCreateGC(display, (*((Pixmap*)pm)), 0, 0);
237 (*((GC*)clipped_gc)) = XCreateGC(display, (*((Pixmap*)pm)), 0, 0);
240 vm.graphics_exposures = 0;
241 XChangeGC(display, (*((GC*)gc)), GCGraphicsExposures, &vm);
242 XChangeGC(display, (*((GC*)clipped_gc)), GCGraphicsExposures, &vm);
245 void org::ibex::plat::X11$X11PixelBuffer::createStipple(org::ibex::plat::X11$X11Picture* xpi) {
247 stipple = (gnu::gcj::RawData*)malloc(sizeof(Pixmap));
248 (*((Pixmap*)stipple)) = XCreatePixmap(display, RootWindow(display, screen_num), width, height, 1);
251 xi.data = (char*)malloc((width + 1) * height);
258 xi.byte_order = LSBFirst;
260 xi.bytes_per_line = (width / 8) + 1;
261 xi.bits_per_pixel = 1;
263 jint* d = (jint*)elements(xpi->data);
264 memset(xi.data, 0xFF, (width + 1) * height);
265 for(int x=0; x<width; x++)
266 for (int y=0; y<height; y++)
267 xi.data[y * xi.bytes_per_line + (x/8)] &= ~(((d[x + y * width] & 0xFF000000) != 0 ? 0 : 1) << (x % 8));
269 GC stipple_gc = XCreateGC(display, (*((Pixmap*)stipple)), 0, 0);
272 vm.graphics_exposures = 0;
273 XChangeGC(display, stipple_gc, GCGraphicsExposures, &vm);
275 XPutImage(display, (*((Pixmap*)stipple)), stipple_gc, &xi, 0, 0, 0, 0, width, height);
278 void org::ibex::plat::X11$X11Surface::blit(org::ibex::PixelBuffer* db, jint sx, jint sy, jint dx, jint dy, jint dx2, jint dy2) {
279 org::ibex::plat::X11$X11PixelBuffer *xdb = (org::ibex::plat::X11$X11PixelBuffer*)db;
280 XCopyArea(display, *((Pixmap*)xdb->pm), *((Window*)window), *((GC*)gc), sx, sy, dx2 - dx, dy2 - dy, dx, dy);
284 void org::ibex::plat::X11$X11PixelBuffer::fillRect (jint x, jint y, jint x2, jint y2, jint argb) {
289 if (x < clipx) { w -= (clipx - x); x = clipx; }
290 if (y < clipy) { h -= (clipy - y); y = clipy; }
291 if (x + w > clipx + clipw) w = (clipx + clipw - x);
292 if (y + h > clipy + cliph) h = (cliph + clipy - y);
294 XSetForeground(display, (*((GC*)gc)),
295 ((((argb & 0x00FF0000) >> 16) * colormap_info->red_max) / 0xFF) * colormap_info->red_mult +
296 ((((argb & 0x0000FF00) >> 8) * colormap_info->green_max) / 0xFF) * colormap_info->green_mult +
297 ((((argb & 0x000000FF)) * colormap_info->blue_max) / 0xFF) * colormap_info->blue_mult +
298 colormap_info->base_pixel
301 XFillRectangle(display, (*((Pixmap*)pm)), (*((GC*)gc)), x, y, w, h);
305 // X11Surface //////////////////////////////////////////////////////////////////////
307 void org::ibex::plat::X11$X11Surface::setIcon(org::ibex::Picture* pic) {
308 org::ibex::plat::X11$X11Picture* p = ((org::ibex::plat::X11$X11Picture*)pic);
309 org::ibex::plat::X11$X11PixelBuffer* old_dbuf = p->doublebuf;
310 p->buildPixelBuffer(1);
312 memset(&xwmh, 0, sizeof(XWMHints));
313 xwmh.flags |= IconPixmapHint | IconMaskHint;
314 xwmh.icon_pixmap = *((Pixmap*)p->doublebuf->pm);
315 xwmh.icon_mask = *((Pixmap*)p->doublebuf->stipple);
316 XSetWMHints(display, (*((Window*)window)), &xwmh);
317 p->doublebuf = old_dbuf;
320 void org::ibex::plat::X11$X11Surface::setTitleBarText(java::lang::String* s) {
321 int len = min(JvGetStringUTFLength(s), 1024);
323 JvGetStringUTFRegion(s, 0, len, buf);
327 tp.value = (unsigned char*)buf;
329 tp.encoding = XA_STRING;
331 XSetTextProperty(display, (*((Window*)window)), &tp, XA_WM_NAME);
332 XSetTextProperty(display, (*((Window*)window)), &tp, XA_WM_ICON_NAME);
335 void org::ibex::plat::X11$X11Surface::setLimits(jint minw, jint minh, jint maxw, jint maxh) {
337 hints.min_width = minw;
338 hints.min_height = minh;
339 hints.max_width = maxw;
340 hints.max_height = maxh;
341 hints.flags = PMinSize | PMaxSize;
342 XSetWMNormalHints(display, (*((Window*)window)), &hints);
345 void org::ibex::plat::X11$X11Surface::_setSize (jint width, jint height) {
346 if (width <= 0 || height <= 0) return;
347 XResizeWindow(display, (*((Window*)window)), width, height);
351 void org::ibex::plat::X11$X11Surface::setLocation () { XMoveWindow(display, (*((Window*)window)), root->x, root->y); }
352 void org::ibex::plat::X11$X11Surface::toFront() { XRaiseWindow(display, (*((Window*)window))); }
353 void org::ibex::plat::X11$X11Surface::toBack() { XLowerWindow(display, (*((Window*)window))); }
355 void org::ibex::plat::X11$X11Surface::_dispose() {
356 // without this we get phantom messages after the window is gone
357 org::ibex::plat::X11::windowToSurfaceMap->remove(new java::lang::Long(*((Window*)window)));
358 XDestroyWindow(display, (*((Window*)window)));
361 void org::ibex::plat::X11$X11Surface::setInvisible(jboolean i) {
362 if (i) XUnmapWindow(display, (*((Window*)window)));
363 else XMapRaised(display, (*((Window*)window)));
367 void org::ibex::plat::X11$X11Surface::_setMinimized(jboolean b) {
368 if (b) XIconifyWindow(display, (*((Window*)window)), screen_num);
369 else XMapRaised(display, (*((Window*)window)));
373 void org::ibex::plat::X11$X11Surface::natInit() {
374 XSetWindowAttributes xswa;
375 window = (gnu::gcj::RawData*)malloc(sizeof(Window));
376 xswa.bit_gravity = NorthWestGravity;
377 xswa.colormap = s_colormap;
378 xswa.event_mask = ExposureMask | ButtonPressMask | StructureNotifyMask |
379 KeyPressMask | KeyReleaseMask | ButtonPressMask |
380 ButtonReleaseMask | EnterWindowMask | LeaveWindowMask |
381 PointerMotionMask | ButtonMotionMask | ConfigureNotify | FocusChangeMask;
382 *((Window*)window) = XCreateWindow(display, RootWindow(display, screen_num), 10, 10, 10, 10, 0,
383 colorDepth, InputOutput, CopyFromParent,
384 CWColormap | CWBitGravity | CWEventMask, &xswa);
387 // I don't know why this works....
388 int dat[5] = { 0x2, 0xbffff804, 0x0, 0x817f560, 0x8110694 };
389 XChangeProperty(display, (*((Window*)window)),
390 XInternAtom(display, "_MOTIF_WM_HINTS", False),
391 XInternAtom(display, "_MOTIF_WM_HINTS", False),
399 tp.value = (unsigned char*)"Ibex";
401 tp.encoding = XA_STRING;
403 XSetTextProperty(display, (*((Window*)window)), &tp, XA_WM_CLASS);
405 Atom proto = XInternAtom(display, "WM_DELETE_WINDOW", False);
406 XSetWMProtocols(display, (*((Window*)window)), &proto, 1);
408 XSelectInput(display, (*((Window*)window)), StructureNotifyMask);
409 org::ibex::plat::X11::windowToSurfaceMap->put(new java::lang::Long(*((Window*)window)), this);
412 XMapRaised(display, (*((Window*)window)));
415 waitForCreation->block();
416 XSelectInput(display, (*((Window*)window)), xswa.event_mask);
419 gc = (gnu::gcj::RawData*)malloc(sizeof(GC));
420 *((GC*)gc) = XCreateGC(display, (*((Window*)window)), 0, 0);
423 vm.graphics_exposures = 0;
424 XChangeGC(display, *((GC*)gc), GCGraphicsExposures, &vm);
428 void org::ibex::plat::X11$X11Surface::dispatchEvent(gnu::gcj::RawData* ev) {
430 XEvent* e = (XEvent*)ev;
431 if (e->type == Expose) {
432 XExposeEvent *expose = (XExposeEvent*)(e);
433 Dirty(expose->x, expose->y, expose->width, expose->height);
435 } else if (e->type == MapNotify) { Minimized(0); waitForCreation->release();
436 } else if (e->type == UnmapNotify) { Minimized(1);
437 } else if (e->type == FocusIn) { Focused(1);
438 } else if (e->type == FocusOut) { Focused(0);
439 } else if (e->type == ClientMessage) {
440 if (((XClientMessageEvent*)(e))->data.l[0] == XInternAtom(display, "WM_DELETE_WINDOW", False)) Close();
442 } else if (e->type == KeyPress || e->type == KeyRelease) {
443 XKeyEvent *xbe = (XKeyEvent*)(e);
445 // drop faked KeyRelease events generated by the X server's autorepeat
446 if (e->type == KeyRelease) {
448 XQueryKeymap(display, depressed);
449 if ((depressed[(xbe->keycode & 0xff) / 8] & (0x1 << (xbe->keycode % 8))) >> (xbe->keycode % 8)) return;
455 unsigned int savestate = xbe->state;
456 xbe->state = xbe->state & ShiftMask; // ignore everything except shiftmask
457 XLookupString(xbe, s, 20, NULL, NULL);
458 xbe->state = savestate;
460 if (s != NULL && s[0] != '\0' && s[1] == '\0' && s[0] >= 0x20 && s[0] <= 0x7E) {
464 KeySym ks = XKeycodeToKeysym(display, xbe->keycode, 0);
466 case XK_BackSpace: s = "back_space"; break;
467 case XK_Tab: s = "tab"; break;
468 case XK_Linefeed: s = "enter"; break;
469 case XK_Return: s = "enter"; break;
470 case XK_Scroll_Lock: s = "scroll_lock"; break;
471 case XK_Escape: s = "escape"; break;
472 case XK_Insert: s = "insert"; break;
473 case XK_Delete: s = "delete"; break;
474 case XK_Home: s = "home"; break;
475 case XK_Left: s = "left"; break;
476 case XK_Up: s = "up"; break;
477 case XK_Right: s = "right"; break;
478 case XK_Down: s = "down"; break;
479 case XK_Page_Up: s = "page_up"; break;
480 case XK_Page_Down: s = "page_down"; break;
481 case XK_End: s = "end"; break;
482 case XK_Num_Lock: s = "num_lock"; break;
483 case XK_KP_Tab: s = "tab"; break;
484 case XK_KP_Enter: s = "enter"; break;
485 case XK_KP_F1: s = "f1"; break;
486 case XK_KP_F2: s = "f2"; break;
487 case XK_KP_F3: s = "f3"; break;
488 case XK_KP_F4: s = "f4"; break;
489 case XK_KP_Home: s = "home"; break;
490 case XK_KP_Left: s = "left"; break;
491 case XK_KP_Up: s = "up"; break;
492 case XK_KP_Right: s = "right"; break;
493 case XK_KP_Down: s = "down"; break;
494 case XK_KP_Page_Up: s = "page_up"; break;
495 case XK_KP_Page_Down: s = "page_down"; break;
496 case XK_KP_End: s = "end"; break;
497 case XK_KP_Insert: s = "insert"; break;
498 case XK_KP_Delete: s = "delete"; break;
499 case XK_F1: s = "f1"; break;
500 case XK_F2: s = "f2"; break;
501 case XK_F3: s = "f3"; break;
502 case XK_F4: s = "f4"; break;
503 case XK_F5: s = "f5"; break;
504 case XK_F6: s = "f6"; break;
505 case XK_F7: s = "f7"; break;
506 case XK_F8: s = "f8"; break;
507 case XK_F9: s = "f9"; break;
508 case XK_F10: s = "f10"; break;
509 case XK_F11: s = "f11"; break;
510 case XK_F12: s = "f12"; break;
511 case XK_Shift_L: s = "shift"; break;
512 case XK_Shift_R: s = "shift"; break;
513 case XK_Control_L: s = "control"; break;
514 case XK_Control_R: s = "control"; break;
515 case XK_Meta_L: s = "alt"; break;
516 case XK_Meta_R: s = "alt"; break;
517 case XK_Alt_L: s = "alt"; break;
518 case XK_Alt_R: s = "alt"; break;
523 jstring s2 = JvNewStringLatin1(s);
524 if (e->type == KeyPress) KeyPressed((xbe->state & LockMask) ? s2->toUpperCase() : s2);
525 if (e->type == KeyRelease) KeyReleased(s2);
527 } else if (e->type == ButtonPress) {
528 XButtonEvent* xbe = (XButtonEvent*)(e);
529 if (xbe->button == 2) xbe->button = 3;
530 else if (xbe->button == 3) xbe->button = 2;
533 } else if (e->type == ButtonRelease) {
534 XButtonEvent* xbe = (XButtonEvent*)(e);
535 if (xbe->button == 2) xbe->button = 3;
536 else if (xbe->button == 3) xbe->button = 2;
537 Release(xbe->button);
539 } else if (e->type == MotionNotify) {
540 XMotionEvent* xme = (XMotionEvent*)(e);
541 Move(xme->x, xme->y);
543 } else if (e->type == EnterNotify || e->type == LeaveNotify) {
544 XCrossingEvent* xce = (XCrossingEvent*)(e);
545 Move(xce->x, xce->y);
547 } else if (e->type == ConfigureNotify) {
550 XConfigureEvent* xce = (XConfigureEvent*)(e);
551 XTranslateCoordinates(display, (*((Window*)window)), RootWindow(display, screen_num), 0, 0, &x_out, &y_out, &child);
552 if (xce->width != root->width || xce->height != root->height) SizeChange(xce->width, xce->height);
553 if (x_out != root->x || y_out != root->y) PosChange(x_out, y_out);
558 static jstring crosshair, east, hand, move, north, northeast, northwest,
559 south, southeast, southwest, text, west, wait_string;
560 static Cursor crosshair_cursor, east_cursor, hand_cursor, move_cursor, north_cursor,
561 northeast_cursor, northwest_cursor, south_cursor, southeast_cursor,
562 southwest_cursor, text_cursor, west_cursor, wait_cursor, default_cursor;
564 void org::ibex::plat::X11$X11Surface::syncCursor() {
567 if (cursor->equals(crosshair)) curs = crosshair_cursor;
568 else if (cursor->equals(east)) curs = east_cursor;
569 else if (cursor->equals(hand)) curs = hand_cursor;
570 else if (cursor->equals(move)) curs = move_cursor;
571 else if (cursor->equals(north)) curs = north_cursor;
572 else if (cursor->equals(northeast)) curs = northeast_cursor;
573 else if (cursor->equals(northwest)) curs = northwest_cursor;
574 else if (cursor->equals(south)) curs = south_cursor;
575 else if (cursor->equals(southeast)) curs = southeast_cursor;
576 else if (cursor->equals(southwest)) curs = southwest_cursor;
577 else if (cursor->equals(text)) curs = text_cursor;
578 else if (cursor->equals(west)) curs = west_cursor;
579 else if (cursor->equals(wait_string)) curs = wait_cursor;
580 else curs = default_cursor;
582 XDefineCursor(display, (*((Window*)window)), curs);
587 // X11 ///////////////////////////////////////////////////////////////////
589 jint org::ibex::plat::X11::_getScreenWidth() { return WidthOfScreen(DefaultScreenOfDisplay(display)); }
590 jint org::ibex::plat::X11::_getScreenHeight() { return HeightOfScreen(DefaultScreenOfDisplay(display)); }
592 static void dispatchSelectionEvent(XEvent* e) {
593 if (e->type == SelectionNotify) {
594 XSelectionEvent* xsn = (XSelectionEvent*)(e);
595 if (xsn->property == None) org::ibex::plat::X11::clipboard = JvNewStringLatin1("", 0);
599 unsigned long numitems;
601 unsigned long bytes_after;
602 XGetWindowProperty(display, xsn->requestor, xsn->property, 0, 4096,
603 True, AnyPropertyType, &returntype, &returnformat,
604 &numitems, &bytes_after, &ret);
605 org::ibex::plat::X11::clipboard =
606 (returntype == None ? JvNewStringLatin1("", 0) : JvNewStringLatin1((char*)ret, strlen((char*)ret)));
608 org::ibex::plat::X11::waiting_for_selection_event->release();
610 } else if (e->type == SelectionRequest) {
611 XSelectionRequestEvent* xsr = (XSelectionRequestEvent*)(e);
613 xsn.type = SelectionNotify;
614 xsn.serial = xsr->serial;
615 xsn.send_event = True;
616 xsn.display = display;
617 xsn.requestor = xsr->requestor;
618 xsn.selection = xsr->selection;
619 xsn.target = xsr->target;
620 xsn.property = xsr->property;
621 xsn.time = xsr->time;
623 int len = min(1024, JvGetStringUTFLength(org::ibex::plat::X11::clipboard));
625 JvGetStringUTFRegion(org::ibex::plat::X11::clipboard, 0, len, buf);
628 XChangeProperty(display, xsr->requestor, xsr->property, xsr->target, 8, PropModeReplace, (unsigned char*)buf, len + 1);
629 XSendEvent(display, xsr->requestor, True, 0, (XEvent*)(&xsn));
633 void org::ibex::plat::X11::eventThread() {
636 XNextEvent(display, &e);
637 if (e.type == SelectionNotify || e.type == SelectionRequest) {
638 dispatchSelectionEvent(&e);
640 org::ibex::plat::X11$X11Surface* surface =
641 (org::ibex::plat::X11$X11Surface*)windowToSurfaceMap->get(new java::lang::Long(((XAnyEvent*)&e)->window));
642 if (surface != NULL) surface->dispatchEvent((gnu::gcj::RawData*)&e);
647 jstring org::ibex::plat::X11::_getClipBoard() {
648 XConvertSelection(display, XA_PRIMARY, XA_STRING, XInternAtom(display, "VT_SELECTION", False), selectionWindow, CurrentTime);
650 org::ibex::plat::X11::waiting_for_selection_event->block();
654 void org::ibex::plat::X11::_setClipBoard(jstring s) {
656 int len = JvGetStringUTFLength(clipboard);
658 JvGetStringUTFRegion(clipboard, 0, len, buf);
660 XSetSelectionOwner(display, XInternAtom(display, "PRIMARY", 0), selectionWindow, CurrentTime);
663 typedef int (X11ErrorHandler)(Display*, XErrorEvent*);
664 int errorHandler(Display* d, XErrorEvent* e) {
665 // this error handler is only installed during the initial
666 // test to see if shm is present
670 void org::ibex::plat::X11::natInit() {
673 org::ibex::Platform::criticalAbort(JvNewStringLatin1("Your X11 libraries do not support multithreaded programs"));
675 char* DISPLAY = getenv("DISPLAY");
676 if (DISPLAY == NULL || strlen(DISPLAY) == 0) DISPLAY = ":0.0";
677 display = XOpenDisplay(DISPLAY);
680 org::ibex::Platform::criticalAbort(JvNewStringLatin1("Unable to connect to X11 display server"));
682 screen_num = XDefaultScreen(display);
683 colorDepth = (jint)(DefaultDepth(((Display*)display), 0));
684 shm_info.shmaddr = NULL;
686 // FIXME: SHM doesn't work on Darwin
687 //shm_supported = (XShmQueryExtension(display) == True);
689 X11ErrorHandler* oldHandler = XSetErrorHandler(errorHandler);
690 XShmSegmentInfo sinfo;
691 sinfo.shmid = shmget(IPC_PRIVATE, 1, IPC_CREAT | 0777 | IPC_EXCL);
692 sinfo.readOnly = False;
693 // if the server is remote, this will trigger the error handler
694 XShmAttach(display, &sinfo);
695 XSync(display, False);
696 XSetErrorHandler(oldHandler);
700 shm_pixmaps_supported = (XShmPixmapFormat(display) == ZPixmap);
702 crosshair = JvNewStringLatin1("crosshair");
703 east = JvNewStringLatin1("east");
704 hand = JvNewStringLatin1("hand");
705 move = JvNewStringLatin1("move");
706 north = JvNewStringLatin1("north");
707 northeast = JvNewStringLatin1("northeast");
708 northwest = JvNewStringLatin1("northwest");
709 south = JvNewStringLatin1("south");
710 southeast = JvNewStringLatin1("southeast");
711 southwest = JvNewStringLatin1("southwest");
712 text = JvNewStringLatin1("text");
713 west = JvNewStringLatin1("west");
714 wait_string = JvNewStringLatin1("wait");
715 crosshair_cursor = XCreateFontCursor(display, XC_tcross);
716 east_cursor = XCreateFontCursor(display, XC_right_side);
717 hand_cursor = XCreateFontCursor(display, XC_hand2);
718 move_cursor = XCreateFontCursor(display, XC_fleur);
719 north_cursor = XCreateFontCursor(display, XC_top_side);
720 northeast_cursor = XCreateFontCursor(display, XC_top_right_corner);
721 northwest_cursor = XCreateFontCursor(display, XC_left_side);
722 south_cursor = XCreateFontCursor(display, XC_bottom_side);
723 southeast_cursor = XCreateFontCursor(display, XC_bottom_right_corner);
724 southwest_cursor = XCreateFontCursor(display, XC_bottom_left_corner);
725 text_cursor = XCreateFontCursor(display, XC_xterm);
726 west_cursor = XCreateFontCursor(display, XC_right_side);
727 wait_cursor = XCreateFontCursor(display, XC_watch);
728 default_cursor = XCreateFontCursor(display, XC_left_ptr);
730 selectionWindow = XCreateWindow(display, RootWindow(display, screen_num), 0, 0, 1, 1, 0, colorDepth, InputOutput, CopyFromParent, 0, NULL);
731 visual = DefaultVisual(display, screen_num);
733 sprintf(buf, "X11 DISPLAY: %s", XDisplayString(display));
734 org::ibex::util::Log::info(this->getClass(), JvNewStringLatin1(buf));
735 sprintf(buf, "X11 SHM: %s", shm_supported ? "enabled" : "disabled");
736 org::ibex::util::Log::info(this->getClass(), JvNewStringLatin1(buf));
737 sprintf(buf, "X11 Visual: %x %x %x bits: %i visualid: %i depth: %i",
738 visual->red_mask, visual->green_mask, visual->blue_mask, visual->bits_per_rgb, visual->visualid, colorDepth);
739 org::ibex::util::Log::info(this->getClass(), JvNewStringLatin1(buf));
741 // FIXME: don't know why (True, False) is the best solution...
742 if(XmuLookupStandardColormap(display, screen_num, visual->visualid, colorDepth, XA_RGB_BEST_MAP, True, False) == 0)
743 org::ibex::Platform::criticalAbort(JvNewStringLatin1("ERROR: XmuLookupStandardColormap failed"));
745 XStandardColormap* best_map_info = NULL;
747 if (XGetRGBColormaps(display, RootWindow(display, screen_num), &best_map_info, &count, XA_RGB_BEST_MAP) == 0)
748 org::ibex::Platform::criticalAbort(JvNewStringLatin1("ERROR: couldn't allocate a standard colormap"));
749 if (!best_map_info->colormap)
750 org::ibex::Platform::criticalAbort(JvNewStringLatin1("ERROR: XmuLookupStandardColomap succeded, but no colormap was found on the root window"));
751 if (best_map_info->red_max == 0)
752 org::ibex::Platform::criticalAbort(JvNewStringLatin1("ERROR: standard colormap exists, but was improperly allocated"));
753 s_colormap = best_map_info->colormap;
754 colormap_info = best_map_info;
756 sprintf(buf, " red_max / red_mult: %x %x", colormap_info->red_max, colormap_info->red_mult);
757 org::ibex::util::Log::info(this->getClass(), JvNewStringLatin1(buf));
758 sprintf(buf, " green_max / green_mult: %x %x", colormap_info->green_max, colormap_info->green_mult);
759 org::ibex::util::Log::info(this->getClass(), JvNewStringLatin1(buf));
760 sprintf(buf, " blue_max / blue_mult: %x %x", colormap_info->blue_max, colormap_info->blue_mult);
761 org::ibex::util::Log::info(this->getClass(), JvNewStringLatin1(buf));
762 sprintf(buf, " base_pixel: %x", colormap_info->base_pixel);
763 org::ibex::util::Log::info(this->getClass(), JvNewStringLatin1(buf));
768 //////////////////////////////////////////////////////////////////////////////
769 //////////////////////////////////////////////////////////////////////////////
770 //////////////////////////////////////////////////////////////////////////////
771 //////////////////////////////////////////////////////////////////////////////
773 // Everything below this point was taken, cut-and-paste, from the //
774 // source for libXmu. It implements the official 'standard colormap //
775 // creation algorithm. I made some small changes to //
776 // XmuDeleteStandardColormap //
778 //////////////////////////////////////////////////////////////////////////////
779 //////////////////////////////////////////////////////////////////////////////
780 //////////////////////////////////////////////////////////////////////////////
781 //////////////////////////////////////////////////////////////////////////////
783 /* $Xorg: LookupCmap.c,v 1.4 2001/02/09 02:03:53 xorgcvs Exp $ */
787 Copyright 1989, 1998 The Open Group
789 Permission to use, copy, modify, distribute, and sell this software and its
790 documentation for any purpose is hereby granted without fee, provided that
791 the above copyright notice appear in all copies and that both that
792 copyright notice and this permission notice appear in supporting
795 The above copyright notice and this permission notice shall be included in
796 all copies or substantial portions of the Software.
798 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
799 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
800 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
801 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
802 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
803 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
805 Except as contained in this notice, the name of The Open Group shall not be
806 used in advertising or otherwise to promote the sale, use or other dealings
807 in this Software without prior written authorization from The Open Group.
810 /* $XFree86: xc/lib/Xmu/LookupCmap.c,v 1.8 2001/12/14 19:55:47 dawes Exp $ */
813 * Author: Donna Converse, MIT X Consortium
817 #include <X11/Xlib.h>
818 #include <X11/Xatom.h>
819 #include <X11/Xutil.h>
820 #include <X11/Xmu/StdCmap.h>
826 static Status lookup(Display*, int, VisualID, Atom, XStandardColormap*, Bool);
829 * To create a standard colormap if one does not currently exist, or
830 * replace the currently existing standard colormap, use
831 * XmuLookupStandardColormap().
833 * Given a screen, a visual, and a property, XmuLookupStandardColormap()
834 * will determine the best allocation for the property under the specified
835 * visual, and determine the whether to create a new colormap or to use
836 * the default colormap of the screen. It will call XmuStandardColormap()
837 * to create the standard colormap.
839 * If replace is true, any previous definition of the property will be
840 * replaced. If retain is true, the property and the colormap will be
841 * made permanent for the duration of the server session. However,
842 * pre-existing property definitions which are not replaced cannot be made
843 * permanent by a call to XmuLookupStandardColormap(); a request to retain
844 * resources pertains to newly created resources.
846 * Returns 0 on failure, non-zero on success. A request to create a
847 * standard colormap upon a visual which cannot support such a map is
848 * considered a failure. An example of this would be requesting any
849 * standard colormap property on a monochrome visual, or, requesting an
850 * RGB_BEST_MAP on a display whose colormap size is 16.
854 XmuLookupStandardColormap(Display *dpy, int screen, VisualID visualid,
855 unsigned int depth, Atom property,
856 Bool replace, Bool retain)
858 * dpy - specifies X server connection
859 * screen - specifies screen of display
860 * visualid - specifies the visual type
861 * depth - specifies the visual type
862 * property - a standard colormap property
863 * replace - specifies whether to replace
864 * retain - specifies whether to retain
867 Display *odpy; /* original display connection */
868 XStandardColormap *colormap;
869 XVisualInfo vinfo_template, *vinfo; /* visual */
871 unsigned long r_max, g_max, b_max; /* allocation */
873 Colormap cmap; /* colormap ID */
877 /* Match the requested visual */
879 vinfo_template.visualid = visualid;
880 vinfo_template.screen = screen;
881 vinfo_template.depth = depth;
882 vinfo_mask = VisualIDMask | VisualScreenMask | VisualDepthMask;
883 if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &count)) ==
887 /* Monochrome visuals have no standard maps */
889 if (vinfo->colormap_size <= 2) {
890 XFree((char *) vinfo);
894 /* If the requested property already exists on this screen, and,
895 * if the replace flag has not been set to true, return success.
896 * lookup() will remove a pre-existing map if replace is true.
899 if (lookup(dpy, screen, visualid, property, (XStandardColormap *) NULL,
900 replace) && !replace) {
901 XFree((char *) vinfo);
905 /* Determine the best allocation for this property under the requested
906 * visualid and depth, and determine whether or not to use the default
907 * colormap of the screen.
910 if (!XmuGetColormapAllocation(vinfo, property, &r_max, &g_max, &b_max)) {
911 XFree((char *) vinfo);
915 cmap = (property == XA_RGB_DEFAULT_MAP &&
916 visualid == XVisualIDFromVisual(DefaultVisual(dpy, screen)))
917 ? DefaultColormap(dpy, screen) : None;
919 /* If retaining resources, open a new connection to the same server */
923 if ((dpy = XOpenDisplay(XDisplayString(odpy))) == NULL) {
924 XFree((char *) vinfo);
929 /* Create the standard colormap */
931 colormap = XmuStandardColormap(dpy, screen, visualid, depth, property,
932 cmap, r_max, g_max, b_max);
934 /* Set the standard colormap property */
939 if (lookup(dpy, screen, visualid, property, colormap, replace) &&
941 /* Someone has defined the property since we last looked.
942 * Since we will not replace it, release our own resources.
943 * If this is the default map, our allocations will be freed
944 * when this connection closes.
946 if (colormap->killid == ReleaseByFreeingColormap)
947 XFreeColormap(dpy, colormap->colormap);
949 XSetCloseDownMode(dpy, RetainPermanent);
952 XFree((char *) colormap);
958 XFree((char *) vinfo);
962 /***************************************************************************/
964 /* Lookup a standard colormap property. If the property is RGB_DEFAULT_MAP,
965 * the visualid is used to determine whether the indicated standard colormap
966 * exists. If the map exists and replace is true, delete the resources used
967 * by the map and remove the property. Return true if the map exists,
968 * or did exist and was deleted; return false if the map was not found.
970 * Note that this is not the way that a Status return is normally used.
972 * If new is not NULL, new points to an XStandardColormap structure which
973 * describes a standard colormap of the specified property. It will be made
974 * a standard colormap of the screen if none already exists, or if replace
979 lookup(Display *dpy, int screen, VisualID visualid, Atom property,
980 XStandardColormap *cnew, Bool replace)
982 * dpy - specifies display connection
983 * screen - specifies screen number
984 * visualid - specifies visualid for std map
985 * property - specifies colormap property name
986 * cnew - specifies a standard colormap
987 * replace - specifies whether to replace
992 XStandardColormap *stdcmaps, *s;
993 Window win = RootWindow(dpy, screen);
995 /* The property does not already exist */
997 if (! XGetRGBColormaps(dpy, win, &stdcmaps, &count, property)) {
999 XSetRGBColormaps(dpy, win, cnew, 1, property);
1003 /* The property exists and is not describing the RGB_DEFAULT_MAP */
1005 if (property != XA_RGB_DEFAULT_MAP) {
1007 XmuDeleteStandardColormap(dpy, screen, property);
1009 XSetRGBColormaps(dpy, win, cnew, 1, property);
1011 XFree((char *)stdcmaps);
1015 /* The property exists and is RGB_DEFAULT_MAP */
1017 for (i=0, s=stdcmaps; (i < count) && (s->visualid != visualid); i++, s++)
1020 /* No RGB_DEFAULT_MAP property matches the given visualid */
1024 XStandardColormap *m, *maps;
1026 s = (XStandardColormap *) malloc((unsigned) ((count+1) * sizeof
1027 (XStandardColormap)));
1029 for (i = 0, m = s, maps = stdcmaps; i < count; i++, m++, maps++) {
1030 m->colormap = maps->colormap;
1031 m->red_max = maps->red_max;
1032 m->red_mult = maps->red_mult;
1033 m->green_max = maps->green_max;
1034 m->green_mult = maps->green_mult;
1035 m->blue_max = maps->blue_max;
1036 m->blue_mult = maps->blue_mult;
1037 m->base_pixel = maps->base_pixel;
1038 m->visualid = maps->visualid;
1039 m->killid = maps->killid;
1041 m->colormap = cnew->colormap;
1042 m->red_max = cnew->red_max;
1043 m->red_mult = cnew->red_mult;
1044 m->green_max = cnew->green_max;
1045 m->green_mult = cnew->green_mult;
1046 m->blue_max = cnew->blue_max;
1047 m->blue_mult = cnew->blue_mult;
1048 m->base_pixel = cnew->base_pixel;
1049 m->visualid = cnew->visualid;
1050 m->killid = cnew->killid;
1052 XSetRGBColormaps(dpy, win, s, ++count, property);
1055 XFree((char *) stdcmaps);
1059 /* Found an RGB_DEFAULT_MAP property with a matching visualid */
1062 /* Free old resources first - we may need them, particularly in
1063 * the default colormap of the screen. However, because of this,
1064 * it is possible that we will destroy the old resource and fail
1065 * to create a new one if XmuStandardColormap() fails.
1069 XmuDeleteStandardColormap(dpy, screen, property);
1071 XSetRGBColormaps(dpy, win, cnew, 1, property);
1074 XStandardColormap *map;
1076 /* s still points to the matching standard colormap */
1078 if (s->killid == ReleaseByFreeingColormap) {
1079 if ((s->colormap != None) &&
1080 (s->colormap != DefaultColormap(dpy, screen)))
1081 XFreeColormap(dpy, s->colormap);
1083 else if (s->killid != None)
1084 XKillClient(dpy, s->killid);
1086 map = (cnew) ? cnew : stdcmaps + --count;
1088 s->colormap = map->colormap;
1089 s->red_max = map->red_max;
1090 s->red_mult = map->red_mult;
1091 s->green_max = map->green_max;
1092 s->green_mult = map->green_mult;
1093 s->blue_max = map->blue_max;
1094 s->blue_mult = map->blue_mult;
1095 s->visualid = map->visualid;
1096 s->killid = map->killid;
1098 XSetRGBColormaps(dpy, win, stdcmaps, count, property);
1101 XFree((char *) stdcmaps);
1105 /* $Xorg: CmapAlloc.c,v 1.4 2001/02/09 02:03:51 xorgcvs Exp $ */
1109 Copyright 1989, 1994, 1998 The Open Group
1111 Permission to use, copy, modify, distribute, and sell this software and its
1112 documentation for any purpose is hereby granted without fee, provided that
1113 the above copyright notice appear in all copies and that both that
1114 copyright notice and this permission notice appear in supporting
1117 The above copyright notice and this permission notice shall be included in
1118 all copies or substantial portions of the Software.
1120 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1121 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1122 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1123 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1124 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1125 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1127 Except as contained in this notice, the name of The Open Group shall not be
1128 used in advertising or otherwise to promote the sale, use or other dealings
1129 in this Software without prior written authorization from The Open Group.
1132 /* $XFree86: xc/lib/Xmu/CmapAlloc.c,v 1.7 2001/12/14 19:55:35 dawes Exp $ */
1135 * Author: Donna Converse, MIT X Consortium
1138 #include <X11/Xlib.h>
1139 #include <X11/Xatom.h>
1140 #include <X11/Xutil.h>
1141 #include <X11/Xmu/StdCmap.h>
1144 #define lowbit(x) ((x) & (~(x) + 1))
1149 static void best_allocation(XVisualInfo*, unsigned long*, unsigned long*,
1151 static int default_allocation(XVisualInfo*, unsigned long*,
1152 unsigned long*, unsigned long*);
1153 static void gray_allocation(int, unsigned long*, unsigned long*,
1155 static int icbrt(int);
1156 static int icbrt_with_bits(int, int);
1157 static int icbrt_with_guess(int, int);
1159 /* To determine the best allocation of reds, greens, and blues in a
1160 * standard colormap, use XmuGetColormapAllocation.
1161 * vinfo specifies visual information for a chosen visual
1162 * property specifies one of the standard colormap property names
1163 * red_max returns maximum red value
1164 * green_max returns maximum green value
1165 * blue_max returns maximum blue value
1167 * XmuGetColormapAllocation returns 0 on failure, non-zero on success.
1168 * It is assumed that the visual is appropriate for the colormap property.
1172 XmuGetColormapAllocation(XVisualInfo *vinfo, Atom property,
1173 unsigned long *red_max,
1174 unsigned long *green_max,
1175 unsigned long *blue_max)
1179 if (vinfo->colormap_size <= 2)
1184 case XA_RGB_DEFAULT_MAP:
1185 status = default_allocation(vinfo, red_max, green_max, blue_max);
1187 case XA_RGB_BEST_MAP:
1188 best_allocation(vinfo, red_max, green_max, blue_max);
1190 case XA_RGB_GRAY_MAP:
1191 gray_allocation(vinfo->colormap_size, red_max, green_max, blue_max);
1193 case XA_RGB_RED_MAP:
1194 *red_max = vinfo->colormap_size - 1;
1195 *green_max = *blue_max = 0;
1197 case XA_RGB_GREEN_MAP:
1198 *green_max = vinfo->colormap_size - 1;
1199 *red_max = *blue_max = 0;
1201 case XA_RGB_BLUE_MAP:
1202 *blue_max = vinfo->colormap_size - 1;
1203 *red_max = *green_max = 0;
1211 /****************************************************************************/
1212 /* Determine the appropriate color allocations of a gray scale.
1214 * Keith Packard, MIT X Consortium
1218 gray_allocation(int n, unsigned long *red_max, unsigned long *green_max,
1219 unsigned long *blue_max)
1221 *red_max = (n * 30) / 100;
1222 *green_max = (n * 59) / 100;
1223 *blue_max = (n * 11) / 100;
1224 *green_max += ((n - 1) - (*red_max + *green_max + *blue_max));
1227 /****************************************************************************/
1228 /* Determine an appropriate color allocation for the RGB_DEFAULT_MAP.
1229 * If a map has less than a minimum number of definable entries, we do not
1230 * produce an allocation for an RGB_DEFAULT_MAP.
1232 * For 16 planes, the default colormap will have 27 each RGB; for 12 planes,
1233 * 12 each. For 8 planes, let n = the number of colormap entries, which may
1234 * be 256 or 254. Then, maximum red value = floor(cube_root(n - 125)) - 1.
1235 * Maximum green and maximum blue values are identical to maximum red.
1236 * This leaves at least 125 cells which clients can allocate.
1238 * Return 0 if an allocation has been determined, non-zero otherwise.
1242 default_allocation(XVisualInfo *vinfo, unsigned long *red,
1243 unsigned long *green, unsigned long *blue)
1245 int ngrays; /* number of gray cells */
1247 switch (vinfo->c_class)
1251 if (vinfo->colormap_size > 65000)
1252 /* intended for displays with 16 planes */
1253 *red = *green = *blue = (unsigned long) 27;
1254 else if (vinfo->colormap_size > 4000)
1255 /* intended for displays with 12 planes */
1256 *red = *green = *blue = (unsigned long) 12;
1257 else if (vinfo->colormap_size < 250)
1260 /* intended for displays with 8 planes */
1261 *red = *green = *blue = (unsigned long)
1262 (icbrt(vinfo->colormap_size - 125) - 1);
1267 if (vinfo->colormap_size < 10)
1269 *red = *green = *blue = vinfo->colormap_size / 2 - 1;
1274 *red = vinfo->red_mask / lowbit(vinfo->red_mask);
1275 *green = vinfo->green_mask / lowbit(vinfo->green_mask);
1276 *blue = vinfo->blue_mask / lowbit(vinfo->blue_mask);
1281 if (vinfo->colormap_size > 65000)
1283 else if (vinfo->colormap_size > 4000)
1285 else if (vinfo->colormap_size < 250)
1289 gray_allocation(ngrays, red, green, blue);
1298 /****************************************************************************/
1299 /* Determine an appropriate color allocation for the RGB_BEST_MAP.
1301 * For a DirectColor or TrueColor visual, the allocation is determined
1302 * by the red_mask, green_mask, and blue_mask members of the visual info.
1304 * Otherwise, if the colormap size is an integral power of 2, determine
1305 * the allocation according to the number of bits given to each color,
1306 * with green getting more than red, and red more than blue, if there
1307 * are to be inequities in the distribution. If the colormap size is
1308 * not an integral power of 2, let n = the number of colormap entries.
1309 * Then maximum red value = floor(cube_root(n)) - 1;
1310 * maximum blue value = floor(cube_root(n)) - 1;
1311 * maximum green value = n / ((# red values) * (# blue values)) - 1;
1312 * Which, on a GPX, allows for 252 entries in the best map, out of 254
1313 * defineable colormap entries.
1317 best_allocation(XVisualInfo *vinfo, unsigned long *red, unsigned long *green,
1318 unsigned long *blue)
1321 if (vinfo->c_class == DirectColor || vinfo->c_class == TrueColor)
1323 *red = vinfo->red_mask;
1324 while ((*red & 01) == 0)
1326 *green = vinfo->green_mask;
1327 while ((*green & 01) == 0)
1329 *blue = vinfo->blue_mask;
1330 while ((*blue & 01) == 0)
1335 register int bits, n;
1337 /* Determine n such that n is the least integral power of 2 which is
1338 * greater than or equal to the number of entries in the colormap.
1342 while (vinfo->colormap_size > n)
1348 /* If the number of entries in the colormap is a power of 2, determine
1349 * the allocation by "dealing" the bits, first to green, then red, then
1350 * blue. If not, find the maximum integral red, green, and blue values
1351 * which, when multiplied together, do not exceed the number of
1355 if (n == vinfo->colormap_size)
1357 register int r, g, b;
1359 g = b + ((bits % 3) ? 1 : 0);
1360 r = b + (((bits % 3) == 2) ? 1 : 0);
1367 *red = icbrt_with_bits(vinfo->colormap_size, bits);
1369 *green = (vinfo->colormap_size / ((*red) * (*blue)));
1379 * integer cube roots by Newton's method
1381 * Stephen Gildea, MIT X Consortium, July 1991
1387 register int bits = 0;
1388 register unsigned n = a;
1395 return icbrt_with_bits(a, bits);
1400 icbrt_with_bits(int a, int bits)
1401 /* bits - log 2 of a */
1403 return icbrt_with_guess(a, a>>2*bits/3);
1406 #ifdef _X_ROOT_STATS
1407 int icbrt_loopcount;
1410 /* Newton's Method: x_n+1 = x_n - ( f(x_n) / f'(x_n) ) */
1412 /* for cube roots, x^3 - a = 0, x_new = x - 1/3 (x - a/x^2) */
1415 * Quick and dirty cube roots. Nothing fancy here, just Newton's method.
1416 * Only works for positive integers (since that's all we need).
1417 * We actually return floor(cbrt(a)) because that's what we need here, too.
1421 icbrt_with_guess(int a, int guess)
1425 #ifdef _X_ROOT_STATS
1426 icbrt_loopcount = 0;
1434 #ifdef _X_ROOT_STATS
1437 delta = (guess - a/(guess*guess))/3;
1439 printf("pass %d: guess=%d, delta=%d\n", icbrt_loopcount, guess, delta);
1442 } while (delta != 0);
1444 if (guess*guess*guess > a)
1451 /* $Xorg: StdCmap.c,v 1.4 2001/02/09 02:03:53 xorgcvs Exp $ */
1455 Copyright 1989, 1998 The Open Group
1457 Permission to use, copy, modify, distribute, and sell this software and its
1458 documentation for any purpose is hereby granted without fee, provided that
1459 the above copyright notice appear in all copies and that both that
1460 copyright notice and this permission notice appear in supporting
1463 The above copyright notice and this permission notice shall be included in
1464 all copies or substantial portions of the Software.
1466 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1467 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1468 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1469 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1470 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1471 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1473 Except as contained in this notice, the name of The Open Group shall not be
1474 used in advertising or otherwise to promote the sale, use or other dealings
1475 in this Software without prior written authorization from The Open Group.
1478 /* $XFree86: xc/lib/Xmu/StdCmap.c,v 1.6 2001/12/14 19:55:48 dawes Exp $ */
1481 * Author: Donna Converse, MIT X Consortium
1485 #include <X11/Xlib.h>
1486 #include <X11/Xatom.h>
1487 #include <X11/Xutil.h>
1488 #include <X11/Xmu/StdCmap.h>
1490 #define lowbit(x) ((x) & (~(x) + 1))
1495 /* argument restrictions */
1496 static Status valid_args(XVisualInfo*, unsigned long, unsigned long,
1497 unsigned long, Atom);
1500 * To create any one standard colormap, use XmuStandardColormap().
1502 * Create a standard colormap for the given screen, visualid, and visual
1503 * depth, with the given red, green, and blue maximum values, with the
1504 * given standard property name. Return a pointer to an XStandardColormap
1505 * structure which describes the newly created colormap, upon success.
1506 * Upon failure, return NULL.
1508 * XmuStandardColormap() calls XmuCreateColormap() to create the map.
1510 * Resources created by this function are not made permanent; that is the
1511 * caller's responsibility.
1515 XmuStandardColormap(Display *dpy, int screen, VisualID visualid,
1516 unsigned int depth, Atom property, Colormap cmap,
1517 unsigned long red_max, unsigned long green_max,
1518 unsigned long blue_max)
1520 * dpy - specifies X server connection
1521 * screen - specifies display screen
1522 * visualid - identifies the visual type
1523 * depth - identifies the visual type
1524 * property - a standard colormap property
1525 * cmap - specifies colormap ID or None
1526 * red_max, green_max, blue_max - allocations
1529 XStandardColormap *stdcmap;
1531 XVisualInfo vinfo_template, *vinfo;
1535 /* Match the required visual information to an actual visual */
1536 vinfo_template.visualid = visualid;
1537 vinfo_template.screen = screen;
1538 vinfo_template.depth = depth;
1539 vinfo_mask = VisualIDMask | VisualScreenMask | VisualDepthMask;
1540 if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &n)) == NULL)
1543 /* Check the validity of the combination of visual characteristics,
1544 * allocation, and colormap property. Create an XStandardColormap
1548 if (! valid_args(vinfo, red_max, green_max, blue_max, property)
1549 || ((stdcmap = XAllocStandardColormap()) == NULL)) {
1550 XFree((char *) vinfo);
1554 /* Fill in the XStandardColormap structure */
1556 if (cmap == DefaultColormap(dpy, screen)) {
1557 /* Allocating out of the default map, cannot use XFreeColormap() */
1558 Window win = XCreateWindow(dpy, RootWindow(dpy, screen), 1, 1, 1, 1,
1559 0, 0, InputOnly, vinfo->visual,
1561 (XSetWindowAttributes *)NULL);
1562 stdcmap->killid = (XID) XCreatePixmap(dpy, win, 1, 1, depth);
1563 XDestroyWindow(dpy, win);
1564 stdcmap->colormap = cmap;
1566 stdcmap->killid = ReleaseByFreeingColormap;
1567 stdcmap->colormap = XCreateColormap(dpy, RootWindow(dpy, screen),
1568 vinfo->visual, AllocNone);
1570 stdcmap->red_max = red_max;
1571 stdcmap->green_max = green_max;
1572 stdcmap->blue_max = blue_max;
1573 if (property == XA_RGB_GRAY_MAP)
1574 stdcmap->red_mult = stdcmap->green_mult = stdcmap->blue_mult = 1;
1575 else if (vinfo->c_class == TrueColor || vinfo->c_class == DirectColor) {
1576 stdcmap->red_mult = lowbit(vinfo->red_mask);
1577 stdcmap->green_mult = lowbit(vinfo->green_mask);
1578 stdcmap->blue_mult = lowbit(vinfo->blue_mask);
1580 stdcmap->red_mult = (red_max > 0)
1581 ? (green_max + 1) * (blue_max + 1) : 0;
1582 stdcmap->green_mult = (green_max > 0) ? blue_max + 1 : 0;
1583 stdcmap->blue_mult = (blue_max > 0) ? 1 : 0;
1585 stdcmap->base_pixel = 0; /* base pixel may change */
1586 stdcmap->visualid = vinfo->visualid;
1588 /* Make the colormap */
1590 status = XmuCreateColormap(dpy, stdcmap);
1594 XFree((char *) vinfo);
1597 /* Free the colormap or the pixmap, if we created one */
1598 if (stdcmap->killid == ReleaseByFreeingColormap)
1599 XFreeColormap(dpy, stdcmap->colormap);
1600 else if (stdcmap->killid != None)
1601 XFreePixmap(dpy, stdcmap->killid);
1603 XFree((char *) stdcmap);
1604 return (XStandardColormap *) NULL;
1609 /****************************************************************************/
1611 valid_args(XVisualInfo *vinfo, unsigned long red_max, unsigned long green_max,
1612 unsigned long blue_max, Atom property)
1614 * vinfo - specifies visual
1615 * red_max, green_max, blue_max - specifies alloc
1616 * property - specifies property name
1619 unsigned long ncolors; /* number of colors requested */
1621 /* Determine that the number of colors requested is <= map size */
1623 if ((vinfo->c_class == DirectColor) || (vinfo->c_class == TrueColor)) {
1626 mask = vinfo->red_mask;
1631 mask = vinfo->green_mask;
1634 if (green_max > mask)
1636 mask = vinfo->blue_mask;
1639 if (blue_max > mask)
1641 } else if (property == XA_RGB_GRAY_MAP) {
1642 ncolors = red_max + green_max + blue_max + 1;
1643 if (ncolors > vinfo->colormap_size)
1646 ncolors = (red_max + 1) * (green_max + 1) * (blue_max + 1);
1647 if (ncolors > vinfo->colormap_size)
1651 /* Determine that the allocation and visual make sense for the property */
1655 case XA_RGB_DEFAULT_MAP:
1656 if (red_max == 0 || green_max == 0 || blue_max == 0)
1659 case XA_RGB_RED_MAP:
1663 case XA_RGB_GREEN_MAP:
1667 case XA_RGB_BLUE_MAP:
1671 case XA_RGB_BEST_MAP:
1672 if (red_max == 0 || green_max == 0 || blue_max == 0)
1675 case XA_RGB_GRAY_MAP:
1676 if (red_max == 0 || blue_max == 0 || green_max == 0)
1686 /* $Xorg: CrCmap.c,v 1.4 2001/02/09 02:03:51 xorgcvs Exp $ */
1690 Copyright 1989, 1998 The Open Group
1692 Permission to use, copy, modify, distribute, and sell this software and its
1693 documentation for any purpose is hereby granted without fee, provided that
1694 the above copyright notice appear in all copies and that both that
1695 copyright notice and this permission notice appear in supporting
1698 The above copyright notice and this permission notice shall be included in
1699 all copies or substantial portions of the Software.
1701 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1702 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1703 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1704 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1705 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1706 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1708 Except as contained in this notice, the name of The Open Group shall not be
1709 used in advertising or otherwise to promote the sale, use or other dealings
1710 in this Software without prior written authorization from The Open Group.
1713 /* $XFree86: xc/lib/Xmu/CrCmap.c,v 3.7 2001/12/14 19:55:36 dawes Exp $ */
1716 * Author: Donna Converse, MIT X Consortium
1720 * CreateCmap.c - given a standard colormap description, make the map.
1725 #include <X11/Xlib.h>
1726 #include <X11/Xutil.h>
1727 #include <X11/Xmu/StdCmap.h>
1732 /* allocate entire map Read Only */
1733 static int ROmap(Display*, Colormap, unsigned long[], int, int);
1735 /* allocate a cell, prefer Read Only */
1736 static Status ROorRWcell(Display*, Colormap, unsigned long[], int,
1737 XColor*, unsigned long);
1739 /* allocate a cell Read Write */
1740 static Status RWcell(Display*, Colormap, XColor*, XColor*, unsigned long*);
1743 static int compare(_Xconst void*, _Xconst void*);
1745 /* find contiguous sequence of cells */
1746 static Status contiguous(unsigned long[], int, int, unsigned long, int*, int*);
1748 /* frees resources before quitting */
1749 static void free_cells(Display*, Colormap, unsigned long[], int, int);
1751 /* create a map in a RO visual type */
1752 static Status readonly_map(Display*, XVisualInfo*, XStandardColormap*);
1754 /* create a map in a RW visual type */
1755 static Status readwrite_map(Display*, XVisualInfo*, XStandardColormap*);
1757 #define lowbit(x) ((x) & (~(x) + 1))
1758 #define TRUEMATCH(mult,max,mask) \
1759 (colormap->max * colormap->mult <= vinfo->mask && \
1760 lowbit(vinfo->mask) == colormap->mult)
1763 * To create any one colormap which is described by an XStandardColormap
1764 * structure, use XmuCreateColormap().
1766 * Return 0 on failure, non-zero on success.
1767 * Resources created by this function are not made permanent.
1768 * No argument error checking is provided. Use at your own risk.
1770 * All colormaps are created with read only allocations, with the exception
1771 * of read only allocations of colors in the default map or otherwise
1772 * which fail to return the expected pixel value, and these are individually
1773 * defined as read/write allocations. This is done so that all the cells
1774 * defined in the default map are contiguous, for use in image processing.
1775 * This typically happens with White and Black in the default map.
1777 * Colormaps of static visuals are considered to be successfully created if
1778 * the map of the static visual matches the definition given in the
1779 * standard colormap structure.
1783 XmuCreateColormap(Display *dpy, XStandardColormap *colormap)
1784 /* dpy - specifies the connection under which the map is created
1785 * colormap - specifies the map to be created, and returns, particularly
1786 * if the map is created as a subset of the default colormap
1787 * of the screen, the base_pixel of the map.
1790 XVisualInfo vinfo_template; /* template visual information */
1791 XVisualInfo *vinfo; /* matching visual information */
1792 XVisualInfo *vpointer; /* for freeing the entire list */
1793 long vinfo_mask; /* specifies the visual mask value */
1794 int n; /* number of matching visuals */
1797 vinfo_template.visualid = colormap->visualid;
1798 vinfo_mask = VisualIDMask;
1799 if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &n)) == NULL)
1802 /* A visual id may be valid on multiple screens. Also, there may
1803 * be multiple visuals with identical visual ids at different depths.
1804 * If the colormap is the Default Colormap, use the Default Visual.
1805 * Otherwise, arbitrarily, use the deepest visual.
1811 register int screen_number;
1815 for (screen_number = ScreenCount(dpy); --screen_number >= 0; )
1816 if (colormap->colormap == DefaultColormap(dpy, screen_number)) {
1822 for (i=0; i < n; i++, vinfo++) {
1823 if (vinfo->visual == DefaultVisual(dpy, screen_number))
1828 XVisualInfo *v = NULL;
1830 for (i=0; i < n; i++, vinfo++)
1831 if (vinfo->depth > maxdepth) {
1832 maxdepth = vinfo->depth;
1839 if (vinfo->c_class == PseudoColor || vinfo->c_class == DirectColor ||
1840 vinfo->c_class == GrayScale)
1841 status = readwrite_map(dpy, vinfo, colormap);
1842 else if (vinfo->c_class == TrueColor)
1843 status = TRUEMATCH(red_mult, red_max, red_mask) &&
1844 TRUEMATCH(green_mult, green_max, green_mask) &&
1845 TRUEMATCH(blue_mult, blue_max, blue_mask);
1847 status = readonly_map(dpy, vinfo, colormap);
1849 XFree((char *) vpointer);
1853 /****************************************************************************/
1855 readwrite_map(Display *dpy, XVisualInfo *vinfo, XStandardColormap *colormap)
1857 register unsigned long i, n; /* index counters */
1858 unsigned long ncolors; /* number of colors to be defined */
1859 int npixels; /* number of pixels allocated R/W */
1860 int first_index; /* first index of pixels to use */
1861 int remainder; /* first index of remainder */
1862 XColor color; /* the definition of a color */
1863 unsigned long *pixels; /* array of colormap pixels */
1864 unsigned long delta;
1867 /* Determine ncolors, the number of colors to be defined.
1868 * Insure that 1 < ncolors <= the colormap size.
1870 if (vinfo->c_class == DirectColor) {
1871 ncolors = colormap->red_max;
1872 if (colormap->green_max > ncolors)
1873 ncolors = colormap->green_max;
1874 if (colormap->blue_max > ncolors)
1875 ncolors = colormap->blue_max;
1877 delta = lowbit(vinfo->red_mask) +
1878 lowbit(vinfo->green_mask) +
1879 lowbit(vinfo->blue_mask);
1881 ncolors = colormap->red_max * colormap->red_mult +
1882 colormap->green_max * colormap->green_mult +
1883 colormap->blue_max * colormap->blue_mult + 1;
1886 if (ncolors <= 1 || (int) ncolors > vinfo->colormap_size) return 0;
1888 /* Allocate Read/Write as much of the colormap as we can possibly get.
1889 * Then insure that the pixels we were allocated are given in
1890 * monotonically increasing order, using a quicksort. Next, insure
1891 * that our allocation includes a subset of contiguous pixels at least
1892 * as long as the number of colors to be defined. Now we know that
1893 * these conditions are met:
1894 * 1) There are no free cells in the colormap.
1895 * 2) We have a contiguous sequence of pixels, monotonically
1896 * increasing, of length >= the number of colors requested.
1898 * One cell at a time, we will free, compute the next color value,
1899 * then allocate read only. This takes a long time.
1900 * This is done to insure that cells are allocated read only in the
1901 * contiguous order which we prefer. If the server has a choice of
1902 * cells to grant to an allocation request, the server may give us any
1903 * cell, so that is why we do these slow gymnastics.
1906 if ((pixels = (unsigned long *) calloc((unsigned) vinfo->colormap_size,
1907 sizeof(unsigned long))) == NULL)
1910 if ((npixels = ROmap(dpy, colormap->colormap, pixels,
1911 vinfo->colormap_size, ncolors)) == 0) {
1912 free((char *) pixels);
1916 qsort((char *) pixels, npixels, sizeof(unsigned long), compare);
1918 if (!contiguous(pixels, npixels, ncolors, delta, &first_index, &remainder))
1920 /* can't find enough contiguous cells, give up */
1921 XFreeColors(dpy, colormap->colormap, pixels, npixels,
1923 free((char *) pixels);
1926 colormap->base_pixel = pixels[first_index];
1928 /* construct a gray map */
1929 if (colormap->red_mult == 1 && colormap->green_mult == 1 &&
1930 colormap->blue_mult == 1)
1931 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
1934 color.blue = color.green = color.red =
1935 (unsigned short) ((i * 65535) / (colormap->red_max +
1936 colormap->green_max +
1937 colormap->blue_max));
1939 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
1944 /* construct a red ramp map */
1945 else if (colormap->green_max == 0 && colormap->blue_max == 0)
1946 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
1949 color.red = (unsigned short) ((i * 65535) / colormap->red_max);
1950 color.green = color.blue = 0;
1952 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
1957 /* construct a green ramp map */
1958 else if (colormap->red_max == 0 && colormap->blue_max == 0)
1959 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
1962 color.green = (unsigned short) ((i * 65535) / colormap->green_max);
1963 color.red = color.blue = 0;
1965 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
1970 /* construct a blue ramp map */
1971 else if (colormap->red_max == 0 && colormap->green_max == 0)
1972 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
1975 color.blue = (unsigned short) ((i * 65535) / colormap->blue_max);
1976 color.red = color.green = 0;
1978 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
1983 /* construct a standard red green blue cube map */
1986 #define calc(max,mult) (((n / colormap->mult) % \
1987 (colormap->max + 1)) * 65535) / colormap->max
1989 for (n=0, i=0; i < ncolors; i++, n += delta)
1991 color.pixel = n + colormap->base_pixel;
1992 color.red = calc(red_max, red_mult);
1993 color.green = calc(green_max, green_mult);
1994 color.blue = calc(blue_max, blue_mult);
1995 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
2001 /* We have a read-only map defined. Now free unused cells,
2002 * first those occuring before the contiguous sequence begins,
2003 * then any following the contiguous sequence.
2007 XFreeColors(dpy, colormap->colormap, pixels, first_index,
2010 XFreeColors(dpy, colormap->colormap,
2011 &(pixels[first_index + ncolors]), remainder,
2014 free((char *) pixels);
2019 /****************************************************************************/
2021 ROmap(Display *dpy, Colormap cmap, unsigned long pixels[], int m, int n)
2023 * dpy - the X server connection
2024 * cmap - specifies colormap ID
2025 * pixels - returns pixel allocations
2026 * m - specifies colormap size
2027 * n - specifies number of colors
2032 /* first try to allocate the entire colormap */
2033 if (XAllocColorCells(dpy, cmap, 1, (unsigned long *) NULL,
2034 (unsigned) 0, pixels, (unsigned) m))
2037 /* Allocate all available cells in the colormap, using a binary
2038 * algorithm to discover how many cells we can allocate in the colormap.
2042 p = n + ((m - n + 1) / 2);
2043 if (XAllocColorCells(dpy, cmap, 1, (unsigned long *) NULL,
2044 (unsigned) 0, pixels, (unsigned) p)) {
2048 XFreeColors(dpy, cmap, pixels, p, (unsigned long) 0);
2059 /****************************************************************************/
2061 contiguous(unsigned long pixels[], int npixels, int ncolors,
2062 unsigned long delta, int *first, int *rem)
2063 /* pixels - specifies allocated pixels
2064 * npixels - specifies count of alloc'd pixels
2065 * ncolors - specifies needed sequence length
2066 * delta - between pixels
2067 * first - returns first index of sequence
2068 * rem - returns first index after sequence, or 0, if none follow
2071 register int i = 1; /* walking index into the pixel array */
2072 register int count = 1; /* length of sequence discovered so far */
2075 if (npixels == ncolors) {
2080 while (count < ncolors && ncolors - count <= *rem)
2082 if (pixels[i-1] + delta == pixels[i])
2091 if (count != ncolors)
2097 /****************************************************************************/
2099 ROorRWcell(Display *dpy, Colormap cmap, unsigned long pixels[],
2100 int npixels, XColor *color, unsigned long p)
2102 unsigned long pixel;
2105 /* Free the read/write allocation of one cell in the colormap.
2106 * Request a read only allocation of one cell in the colormap.
2107 * If the read only allocation cannot be granted, give up, because
2108 * there must be no free cells in the colormap.
2109 * If the read only allocation is granted, but gives us a cell which
2110 * is not the one that we just freed, it is probably the case that
2111 * we are trying allocate White or Black or some other color which
2112 * already has a read-only allocation in the map. So we try to
2113 * allocate the previously freed cell with a read/write allocation,
2114 * because we want contiguous cells for image processing algorithms.
2117 pixel = color->pixel;
2118 request.red = color->red;
2119 request.green = color->green;
2120 request.blue = color->blue;
2122 XFreeColors(dpy, cmap, &pixel, 1, (unsigned long) 0);
2123 if (! XAllocColor(dpy, cmap, color)
2124 || (color->pixel != pixel &&
2125 (!RWcell(dpy, cmap, color, &request, &pixel))))
2127 free_cells(dpy, cmap, pixels, npixels, (int)p);
2134 /****************************************************************************/
2136 free_cells(Display *dpy, Colormap cmap, unsigned long pixels[],
2139 * pixels - to be freed
2140 * npixels - original number allocated
2143 /* One of the npixels allocated has already been freed.
2144 * p is the index of the freed pixel.
2145 * First free the pixels preceeding p, and there are p of them;
2146 * then free the pixels following p, there are npixels - p - 1 of them.
2148 XFreeColors(dpy, cmap, pixels, p, (unsigned long) 0);
2149 XFreeColors(dpy, cmap, &(pixels[p+1]), npixels - p - 1, (unsigned long) 0);
2150 free((char *) pixels);
2154 /****************************************************************************/
2156 RWcell(Display *dpy, Colormap cmap, XColor *color, XColor *request,
2157 unsigned long *pixel)
2159 unsigned long n = *pixel;
2161 XFreeColors(dpy, cmap, &(color->pixel), 1, (unsigned long)0);
2162 if (! XAllocColorCells(dpy, cmap, (Bool) 0, (unsigned long *) NULL,
2163 (unsigned) 0, pixel, (unsigned) 1))
2167 XFreeColors(dpy, cmap, pixel, 1, (unsigned long) 0);
2170 color->pixel = *pixel;
2171 color->flags = DoRed | DoGreen | DoBlue;
2172 color->red = request->red;
2173 color->green = request->green;
2174 color->blue = request->blue;
2175 XStoreColors(dpy, cmap, color, 1);
2180 /****************************************************************************/
2182 compare(_Xconst void *e1, _Xconst void *e2)
2184 return ((int)(*(long *)e1 - *(long *)e2));
2188 /****************************************************************************/
2190 readonly_map(Display *dpy, XVisualInfo *vinfo, XStandardColormap *colormap)
2195 last_pixel = (colormap->red_max + 1) * (colormap->green_max + 1) *
2196 (colormap->blue_max + 1) + colormap->base_pixel - 1;
2198 for(i=colormap->base_pixel; i <= last_pixel; i++) {
2200 color.pixel = (unsigned long) i;
2201 color.red = (unsigned short)
2202 (((i/colormap->red_mult) * 65535) / colormap->red_max);
2204 if (vinfo->c_class == StaticColor) {
2205 color.green = (unsigned short)
2206 ((((i/colormap->green_mult) % (colormap->green_max + 1)) *
2207 65535) / colormap->green_max);
2208 color.blue = (unsigned short)
2209 (((i%colormap->green_mult) * 65535) / colormap->blue_max);
2211 else /* vinfo->c_class == GrayScale, old style allocation XXX */
2212 color.green = color.blue = color.red;
2214 XAllocColor(dpy, colormap->colormap, &color);
2215 if (color.pixel != (unsigned long) i)
2222 /* $Xorg: DelCmap.c,v 1.4 2001/02/09 02:03:52 xorgcvs Exp $ */
2226 Copyright 1989, 1998 The Open Group
2228 Permission to use, copy, modify, distribute, and sell this software and its
2229 documentation for any purpose is hereby granted without fee, provided that
2230 the above copyright notice appear in all copies and that both that
2231 copyright notice and this permission notice appear in supporting
2234 The above copyright notice and this permission notice shall be included in
2235 all copies or substantial portions of the Software.
2237 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2238 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2239 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2240 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
2241 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
2242 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2244 Except as contained in this notice, the name of The Open Group shall not be
2245 used in advertising or otherwise to promote the sale, use or other dealings
2246 in this Software without prior written authorization from The Open Group.
2249 /* $XFree86: xc/lib/Xmu/DelCmap.c,v 1.7 2001/12/14 19:55:40 dawes Exp $ */
2252 * Author: Donna Converse, MIT X Consortium
2255 #include <X11/Xlib.h>
2256 #include <X11/Xutil.h>
2257 #include <X11/Xmu/StdCmap.h>
2259 int ignoreErrorHandler(Display* d, XErrorEvent* e) { }
2261 /* To remove any standard colormap property, use XmuDeleteStandardColormap().
2262 * XmuDeleteStandardColormap() will remove the specified property from the
2263 * specified screen, releasing any resources used by the colormap(s) of the
2264 * property if possible.
2268 XmuDeleteStandardColormap(Display *dpy, int screen, Atom property)
2269 /* dpy; - specifies the X server to connect to
2270 * screen - specifies the screen of the display
2271 * property - specifies the standard colormap property
2274 XStandardColormap *stdcmaps, *s;
2277 if (XGetRGBColormaps(dpy, RootWindow(dpy, screen), &stdcmaps, &count,
2280 for (s=stdcmaps; count > 0; count--, s++) {
2281 if ((s->killid == ReleaseByFreeingColormap) &&
2282 (s->colormap != None) &&
2283 (s->colormap != DefaultColormap(dpy, screen))) {
2285 // UGLY HACK written in by Adam Megacz -- sometimes s->colormap isn't valid, so we do some shuffling
2286 X11ErrorHandler* oldHandler = XSetErrorHandler(ignoreErrorHandler);
2288 XFreeColormap(dpy, s->colormap);
2290 XSetErrorHandler(oldHandler);
2293 } else if (s->killid != None) {
2294 XKillClient(dpy, s->killid);
2297 XDeleteProperty(dpy, RootWindow(dpy, screen), property);
2298 XFree((char *) stdcmaps);