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
5 #include <X11/extensions/XShm.h>
6 #include <X11/keysymdef.h>
7 #include <X11/keysym.h>
8 #include <X11/cursorfont.h>
10 #include <X11/Xatom.h>
11 #include <X11/Xmu/StdCmap.h>
13 #include <java/lang/String.h>
14 #include <org/ibex/graphics/Surface.h>
15 #include <org/ibex/graphics/Picture.h>
16 #include <org/ibex/core/Box.h>
17 #include <org/ibex/plat/X11.h>
18 #include <org/ibex/plat/X11$X11Surface.h>
19 #include <org/ibex/plat/X11$X11Picture.h>
20 #include <org/ibex/plat/X11$X11PixelBuffer.h>
21 #include <org/ibex/util/Semaphore.h>
22 #include <org/ibex/plat/Platform.h>
23 #include <java/lang/Long.h>
24 #include <java/util/Hashtable.h>
25 #include <org/ibex/util/Log.h>
27 #include <java/lang/System.h>
28 #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::graphics::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::graphics::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::plat::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::plat::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::graphics::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::graphics::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 switch(xbe->button) {
530 case 4: VScroll((jfloat)-1.0); return;
531 case 5: VScroll((jfloat)1.0); return;
532 case 6: HScroll((jfloat)-1.0); return;
533 case 7: HScroll((jfloat)1.0); return;
535 if (xbe->button == 2) xbe->button = 3;
536 else if (xbe->button == 3) xbe->button = 2;
539 } else if (e->type == ButtonRelease) {
540 XButtonEvent* xbe = (XButtonEvent*)(e);
541 if (xbe->button == 2) xbe->button = 3;
542 else if (xbe->button == 3) xbe->button = 2;
543 Release(xbe->button);
545 } else if (e->type == MotionNotify) {
546 XMotionEvent* xme = (XMotionEvent*)(e);
547 Move(xme->x, xme->y);
549 } else if (e->type == EnterNotify || e->type == LeaveNotify) {
550 XCrossingEvent* xce = (XCrossingEvent*)(e);
551 Move(xce->x, xce->y);
553 } else if (e->type == ConfigureNotify) {
556 XConfigureEvent* xce = (XConfigureEvent*)(e);
557 XTranslateCoordinates(display, (*((Window*)window)), RootWindow(display, screen_num), 0, 0, &x_out, &y_out, &child);
558 if (xce->width != root->width || xce->height != root->height) SizeChange(xce->width, xce->height);
559 if (x_out != root->x || y_out != root->y) PosChange(x_out, y_out);
564 static jstring crosshair, east, hand, move, north, northeast, northwest,
565 south, southeast, southwest, text, west, wait_string;
566 static Cursor crosshair_cursor, east_cursor, hand_cursor, move_cursor, north_cursor,
567 northeast_cursor, northwest_cursor, south_cursor, southeast_cursor,
568 southwest_cursor, text_cursor, west_cursor, wait_cursor, default_cursor;
570 void org::ibex::plat::X11$X11Surface::syncCursor() {
573 if (cursor->equals(crosshair)) curs = crosshair_cursor;
574 else if (cursor->equals(east)) curs = east_cursor;
575 else if (cursor->equals(hand)) curs = hand_cursor;
576 else if (cursor->equals(move)) curs = move_cursor;
577 else if (cursor->equals(north)) curs = north_cursor;
578 else if (cursor->equals(northeast)) curs = northeast_cursor;
579 else if (cursor->equals(northwest)) curs = northwest_cursor;
580 else if (cursor->equals(south)) curs = south_cursor;
581 else if (cursor->equals(southeast)) curs = southeast_cursor;
582 else if (cursor->equals(southwest)) curs = southwest_cursor;
583 else if (cursor->equals(text)) curs = text_cursor;
584 else if (cursor->equals(west)) curs = west_cursor;
585 else if (cursor->equals(wait_string)) curs = wait_cursor;
586 else curs = default_cursor;
588 XDefineCursor(display, (*((Window*)window)), curs);
593 // X11 ///////////////////////////////////////////////////////////////////
595 jint org::ibex::plat::X11::_getScreenWidth() { return WidthOfScreen(DefaultScreenOfDisplay(display)); }
596 jint org::ibex::plat::X11::_getScreenHeight() { return HeightOfScreen(DefaultScreenOfDisplay(display)); }
598 static void dispatchSelectionEvent(XEvent* e) {
599 if (e->type == SelectionNotify) {
600 XSelectionEvent* xsn = (XSelectionEvent*)(e);
601 if (xsn->property == None) org::ibex::plat::X11::clipboard = JvNewStringLatin1("", 0);
605 unsigned long numitems;
607 unsigned long bytes_after;
608 XGetWindowProperty(display, xsn->requestor, xsn->property, 0, 4096,
609 True, AnyPropertyType, &returntype, &returnformat,
610 &numitems, &bytes_after, &ret);
611 org::ibex::plat::X11::clipboard =
612 (returntype == None ? JvNewStringLatin1("", 0) : JvNewStringLatin1((char*)ret, strlen((char*)ret)));
614 org::ibex::plat::X11::waiting_for_selection_event->release();
616 } else if (e->type == SelectionRequest) {
617 XSelectionRequestEvent* xsr = (XSelectionRequestEvent*)(e);
619 xsn.type = SelectionNotify;
620 xsn.serial = xsr->serial;
621 xsn.send_event = True;
622 xsn.display = display;
623 xsn.requestor = xsr->requestor;
624 xsn.selection = xsr->selection;
625 xsn.target = xsr->target;
626 xsn.property = xsr->property;
627 xsn.time = xsr->time;
629 int len = min(1024, JvGetStringUTFLength(org::ibex::plat::X11::clipboard));
631 JvGetStringUTFRegion(org::ibex::plat::X11::clipboard, 0, len, buf);
634 XChangeProperty(display, xsr->requestor, xsr->property, xsr->target, 8, PropModeReplace, (unsigned char*)buf, len + 1);
635 XSendEvent(display, xsr->requestor, True, 0, (XEvent*)(&xsn));
639 void org::ibex::plat::X11::eventThread() {
642 XNextEvent(display, &e);
643 if (e.type == SelectionNotify || e.type == SelectionRequest) {
644 dispatchSelectionEvent(&e);
646 org::ibex::plat::X11$X11Surface* surface =
647 (org::ibex::plat::X11$X11Surface*)windowToSurfaceMap->get(new java::lang::Long(((XAnyEvent*)&e)->window));
648 if (surface != NULL) surface->dispatchEvent((gnu::gcj::RawData*)&e);
653 jstring org::ibex::plat::X11::_getClipBoard() {
654 XConvertSelection(display, XA_PRIMARY, XA_STRING, XInternAtom(display, "VT_SELECTION", False), selectionWindow, CurrentTime);
656 org::ibex::plat::X11::waiting_for_selection_event->block();
660 void org::ibex::plat::X11::_setClipBoard(jstring s) {
662 int len = JvGetStringUTFLength(clipboard);
664 JvGetStringUTFRegion(clipboard, 0, len, buf);
666 XSetSelectionOwner(display, XInternAtom(display, "PRIMARY", 0), selectionWindow, CurrentTime);
669 typedef int (X11ErrorHandler)(Display*, XErrorEvent*);
670 int errorHandler(Display* d, XErrorEvent* e) {
671 // this error handler is only installed during the initial
672 // test to see if shm is present
676 void org::ibex::plat::X11::natInit() {
679 org::ibex::plat::Platform::criticalAbort(JvNewStringLatin1("Your X11 libraries do not support multithreaded programs"));
681 char* DISPLAY = getenv("DISPLAY");
682 if (DISPLAY == NULL || strlen(DISPLAY) == 0) DISPLAY = ":0.0";
683 display = XOpenDisplay(DISPLAY);
686 org::ibex::plat::Platform::criticalAbort(JvNewStringLatin1("Unable to connect to X11 display server"));
688 screen_num = XDefaultScreen(display);
689 colorDepth = (jint)(DefaultDepth(((Display*)display), 0));
690 shm_info.shmaddr = NULL;
692 // FIXME: SHM doesn't work on Darwin
693 //shm_supported = (XShmQueryExtension(display) == True);
695 X11ErrorHandler* oldHandler = XSetErrorHandler(errorHandler);
696 XShmSegmentInfo sinfo;
697 sinfo.shmid = shmget(IPC_PRIVATE, 1, IPC_CREAT | 0777 | IPC_EXCL);
698 sinfo.readOnly = False;
699 // if the server is remote, this will trigger the error handler
700 XShmAttach(display, &sinfo);
701 XSync(display, False);
702 XSetErrorHandler(oldHandler);
706 shm_pixmaps_supported = (XShmPixmapFormat(display) == ZPixmap);
708 crosshair = JvNewStringLatin1("crosshair");
709 east = JvNewStringLatin1("east");
710 hand = JvNewStringLatin1("hand");
711 move = JvNewStringLatin1("move");
712 north = JvNewStringLatin1("north");
713 northeast = JvNewStringLatin1("northeast");
714 northwest = JvNewStringLatin1("northwest");
715 south = JvNewStringLatin1("south");
716 southeast = JvNewStringLatin1("southeast");
717 southwest = JvNewStringLatin1("southwest");
718 text = JvNewStringLatin1("text");
719 west = JvNewStringLatin1("west");
720 wait_string = JvNewStringLatin1("wait");
721 crosshair_cursor = XCreateFontCursor(display, XC_tcross);
722 east_cursor = XCreateFontCursor(display, XC_right_side);
723 hand_cursor = XCreateFontCursor(display, XC_hand2);
724 move_cursor = XCreateFontCursor(display, XC_fleur);
725 north_cursor = XCreateFontCursor(display, XC_top_side);
726 northeast_cursor = XCreateFontCursor(display, XC_top_right_corner);
727 northwest_cursor = XCreateFontCursor(display, XC_left_side);
728 south_cursor = XCreateFontCursor(display, XC_bottom_side);
729 southeast_cursor = XCreateFontCursor(display, XC_bottom_right_corner);
730 southwest_cursor = XCreateFontCursor(display, XC_bottom_left_corner);
731 text_cursor = XCreateFontCursor(display, XC_xterm);
732 west_cursor = XCreateFontCursor(display, XC_right_side);
733 wait_cursor = XCreateFontCursor(display, XC_watch);
734 default_cursor = XCreateFontCursor(display, XC_left_ptr);
736 selectionWindow = XCreateWindow(display, RootWindow(display, screen_num), 0, 0, 1, 1, 0, colorDepth, InputOutput, CopyFromParent, 0, NULL);
737 visual = DefaultVisual(display, screen_num);
739 sprintf(buf, "X11 DISPLAY: %s", XDisplayString(display));
740 org::ibex::util::Log::info(this->getClass(), JvNewStringLatin1(buf));
741 sprintf(buf, "X11 SHM: %s", shm_supported ? "enabled" : "disabled");
742 org::ibex::util::Log::info(this->getClass(), JvNewStringLatin1(buf));
743 sprintf(buf, "X11 Visual: %x %x %x bits: %i visualid: %i depth: %i",
744 visual->red_mask, visual->green_mask, visual->blue_mask, visual->bits_per_rgb, visual->visualid, colorDepth);
745 org::ibex::util::Log::info(this->getClass(), JvNewStringLatin1(buf));
747 // FIXME: don't know why (True, False) is the best solution...
748 if(XmuLookupStandardColormap(display, screen_num, visual->visualid, colorDepth, XA_RGB_BEST_MAP, True, False) == 0)
749 org::ibex::plat::Platform::criticalAbort(JvNewStringLatin1("ERROR: XmuLookupStandardColormap failed"));
750 XStandardColormap* best_map_info = NULL;
752 if (XGetRGBColormaps(display, RootWindow(display, screen_num), &best_map_info, &count, XA_RGB_BEST_MAP) == 0)
753 org::ibex::plat::Platform::criticalAbort(JvNewStringLatin1("ERROR: couldn't allocate a standard colormap"));
754 if (!best_map_info->colormap)
755 org::ibex::plat::Platform::criticalAbort(JvNewStringLatin1("ERROR: XmuLookupStandardColomap succeded, but no colormap was found on the root window"));
756 if (best_map_info->red_max == 0)
757 org::ibex::plat::Platform::criticalAbort(JvNewStringLatin1("ERROR: standard colormap exists, but was improperly allocated"));
758 s_colormap = best_map_info->colormap;
759 colormap_info = best_map_info;
761 sprintf(buf, " red_max / red_mult: %x %x", colormap_info->red_max, colormap_info->red_mult);
762 org::ibex::util::Log::info(this->getClass(), JvNewStringLatin1(buf));
763 sprintf(buf, " green_max / green_mult: %x %x", colormap_info->green_max, colormap_info->green_mult);
764 org::ibex::util::Log::info(this->getClass(), JvNewStringLatin1(buf));
765 sprintf(buf, " blue_max / blue_mult: %x %x", colormap_info->blue_max, colormap_info->blue_mult);
766 org::ibex::util::Log::info(this->getClass(), JvNewStringLatin1(buf));
767 sprintf(buf, " base_pixel: %x", colormap_info->base_pixel);
768 org::ibex::util::Log::info(this->getClass(), JvNewStringLatin1(buf));
771 #include "WINGs/WINGs.h"
772 jstring org::ibex::plat::X11::_fileDialog(jstring suggestedFileName, jboolean write) {
777 // FIXME see WINGs/Tests/filedialog.c for more info... need an icon
778 WMInitializeApplication("Ibex", &argc, argv);
779 WMScreen *scr = WMCreateSimpleApplicationScreen(display);
780 int len = min(1024, JvGetStringUTFLength(suggestedFileName));
782 JvGetStringUTFRegion(suggestedFileName, 0, len, buf);
786 sPanel = WMGetSavePanel(scr);
787 if (WMRunModalFilePanelForDirectory(sPanel, NULL, buf, /*title*/ NULL, NULL) != True) return NULL;
788 return JvNewStringLatin1(WMGetFilePanelFileName(sPanel));
791 oPanel = WMGetOpenPanel(scr);
792 if (WMRunModalFilePanelForDirectory(oPanel, NULL, buf, /*title*/ NULL, NULL) != True) return NULL;
793 return JvNewStringLatin1(WMGetFilePanelFileName(oPanel));
798 //////////////////////////////////////////////////////////////////////////////
799 //////////////////////////////////////////////////////////////////////////////
800 //////////////////////////////////////////////////////////////////////////////
801 //////////////////////////////////////////////////////////////////////////////
803 // Everything below this point was taken, cut-and-paste, from the //
804 // source for libXmu. It implements the official 'standard colormap //
805 // creation algorithm. I made some small changes to //
806 // XmuDeleteStandardColormap //
808 //////////////////////////////////////////////////////////////////////////////
809 //////////////////////////////////////////////////////////////////////////////
810 //////////////////////////////////////////////////////////////////////////////
811 //////////////////////////////////////////////////////////////////////////////
813 /* $Xorg: LookupCmap.c,v 1.4 2001/02/09 02:03:53 xorgcvs Exp $ */
817 Copyright 1989, 1998 The Open Group
819 Permission to use, copy, modify, distribute, and sell this software and its
820 documentation for any purpose is hereby granted without fee, provided that
821 the above copyright notice appear in all copies and that both that
822 copyright notice and this permission notice appear in supporting
825 The above copyright notice and this permission notice shall be included in
826 all copies or substantial portions of the Software.
828 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
829 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
830 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
831 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
832 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
833 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
835 Except as contained in this notice, the name of The Open Group shall not be
836 used in advertising or otherwise to promote the sale, use or other dealings
837 in this Software without prior written authorization from The Open Group.
840 /* $XFree86: xc/lib/Xmu/LookupCmap.c,v 1.8 2001/12/14 19:55:47 dawes Exp $ */
843 * Author: Donna Converse, MIT X Consortium
847 #include <X11/Xlib.h>
848 #include <X11/Xatom.h>
849 #include <X11/Xutil.h>
850 #include <X11/Xmu/StdCmap.h>
856 static Status lookup(Display*, int, VisualID, Atom, XStandardColormap*, Bool);
859 * To create a standard colormap if one does not currently exist, or
860 * replace the currently existing standard colormap, use
861 * XmuLookupStandardColormap().
863 * Given a screen, a visual, and a property, XmuLookupStandardColormap()
864 * will determine the best allocation for the property under the specified
865 * visual, and determine the whether to create a new colormap or to use
866 * the default colormap of the screen. It will call XmuStandardColormap()
867 * to create the standard colormap.
869 * If replace is true, any previous definition of the property will be
870 * replaced. If retain is true, the property and the colormap will be
871 * made permanent for the duration of the server session. However,
872 * pre-existing property definitions which are not replaced cannot be made
873 * permanent by a call to XmuLookupStandardColormap(); a request to retain
874 * resources pertains to newly created resources.
876 * Returns 0 on failure, non-zero on success. A request to create a
877 * standard colormap upon a visual which cannot support such a map is
878 * considered a failure. An example of this would be requesting any
879 * standard colormap property on a monochrome visual, or, requesting an
880 * RGB_BEST_MAP on a display whose colormap size is 16.
884 XmuLookupStandardColormap(Display *dpy, int screen, VisualID visualid,
885 unsigned int depth, Atom property,
886 Bool replace, Bool retain)
888 * dpy - specifies X server connection
889 * screen - specifies screen of display
890 * visualid - specifies the visual type
891 * depth - specifies the visual type
892 * property - a standard colormap property
893 * replace - specifies whether to replace
894 * retain - specifies whether to retain
897 Display *odpy; /* original display connection */
898 XStandardColormap *colormap;
899 XVisualInfo vinfo_template, *vinfo; /* visual */
901 unsigned long r_max, g_max, b_max; /* allocation */
903 Colormap cmap; /* colormap ID */
907 /* Match the requested visual */
909 vinfo_template.visualid = visualid;
910 vinfo_template.screen = screen;
911 vinfo_template.depth = depth;
912 vinfo_mask = VisualIDMask | VisualScreenMask | VisualDepthMask;
913 if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &count)) ==
917 /* Monochrome visuals have no standard maps */
919 if (vinfo->colormap_size <= 2) {
920 XFree((char *) vinfo);
924 /* If the requested property already exists on this screen, and,
925 * if the replace flag has not been set to true, return success.
926 * lookup() will remove a pre-existing map if replace is true.
929 if (lookup(dpy, screen, visualid, property, (XStandardColormap *) NULL,
930 replace) && !replace) {
931 XFree((char *) vinfo);
935 /* Determine the best allocation for this property under the requested
936 * visualid and depth, and determine whether or not to use the default
937 * colormap of the screen.
940 if (!XmuGetColormapAllocation(vinfo, property, &r_max, &g_max, &b_max)) {
941 XFree((char *) vinfo);
945 cmap = (property == XA_RGB_DEFAULT_MAP &&
946 visualid == XVisualIDFromVisual(DefaultVisual(dpy, screen)))
947 ? DefaultColormap(dpy, screen) : None;
949 /* If retaining resources, open a new connection to the same server */
953 if ((dpy = XOpenDisplay(XDisplayString(odpy))) == NULL) {
954 XFree((char *) vinfo);
959 /* Create the standard colormap */
961 colormap = XmuStandardColormap(dpy, screen, visualid, depth, property,
962 cmap, r_max, g_max, b_max);
964 /* Set the standard colormap property */
969 if (lookup(dpy, screen, visualid, property, colormap, replace) &&
971 /* Someone has defined the property since we last looked.
972 * Since we will not replace it, release our own resources.
973 * If this is the default map, our allocations will be freed
974 * when this connection closes.
976 if (colormap->killid == ReleaseByFreeingColormap)
977 XFreeColormap(dpy, colormap->colormap);
979 XSetCloseDownMode(dpy, RetainPermanent);
982 XFree((char *) colormap);
988 XFree((char *) vinfo);
992 /***************************************************************************/
994 /* Lookup a standard colormap property. If the property is RGB_DEFAULT_MAP,
995 * the visualid is used to determine whether the indicated standard colormap
996 * exists. If the map exists and replace is true, delete the resources used
997 * by the map and remove the property. Return true if the map exists,
998 * or did exist and was deleted; return false if the map was not found.
1000 * Note that this is not the way that a Status return is normally used.
1002 * If new is not NULL, new points to an XStandardColormap structure which
1003 * describes a standard colormap of the specified property. It will be made
1004 * a standard colormap of the screen if none already exists, or if replace
1009 lookup(Display *dpy, int screen, VisualID visualid, Atom property,
1010 XStandardColormap *cnew, Bool replace)
1012 * dpy - specifies display connection
1013 * screen - specifies screen number
1014 * visualid - specifies visualid for std map
1015 * property - specifies colormap property name
1016 * cnew - specifies a standard colormap
1017 * replace - specifies whether to replace
1022 XStandardColormap *stdcmaps, *s;
1023 Window win = RootWindow(dpy, screen);
1025 /* The property does not already exist */
1027 if (! XGetRGBColormaps(dpy, win, &stdcmaps, &count, property)) {
1029 XSetRGBColormaps(dpy, win, cnew, 1, property);
1033 /* The property exists and is not describing the RGB_DEFAULT_MAP */
1035 if (property != XA_RGB_DEFAULT_MAP) {
1037 XmuDeleteStandardColormap(dpy, screen, property);
1039 XSetRGBColormaps(dpy, win, cnew, 1, property);
1041 XFree((char *)stdcmaps);
1045 /* The property exists and is RGB_DEFAULT_MAP */
1047 for (i=0, s=stdcmaps; (i < count) && (s->visualid != visualid); i++, s++)
1050 /* No RGB_DEFAULT_MAP property matches the given visualid */
1054 XStandardColormap *m, *maps;
1056 s = (XStandardColormap *) malloc((unsigned) ((count+1) * sizeof
1057 (XStandardColormap)));
1059 for (i = 0, m = s, maps = stdcmaps; i < count; i++, m++, maps++) {
1060 m->colormap = maps->colormap;
1061 m->red_max = maps->red_max;
1062 m->red_mult = maps->red_mult;
1063 m->green_max = maps->green_max;
1064 m->green_mult = maps->green_mult;
1065 m->blue_max = maps->blue_max;
1066 m->blue_mult = maps->blue_mult;
1067 m->base_pixel = maps->base_pixel;
1068 m->visualid = maps->visualid;
1069 m->killid = maps->killid;
1071 m->colormap = cnew->colormap;
1072 m->red_max = cnew->red_max;
1073 m->red_mult = cnew->red_mult;
1074 m->green_max = cnew->green_max;
1075 m->green_mult = cnew->green_mult;
1076 m->blue_max = cnew->blue_max;
1077 m->blue_mult = cnew->blue_mult;
1078 m->base_pixel = cnew->base_pixel;
1079 m->visualid = cnew->visualid;
1080 m->killid = cnew->killid;
1082 XSetRGBColormaps(dpy, win, s, ++count, property);
1085 XFree((char *) stdcmaps);
1089 /* Found an RGB_DEFAULT_MAP property with a matching visualid */
1092 /* Free old resources first - we may need them, particularly in
1093 * the default colormap of the screen. However, because of this,
1094 * it is possible that we will destroy the old resource and fail
1095 * to create a new one if XmuStandardColormap() fails.
1099 XmuDeleteStandardColormap(dpy, screen, property);
1101 XSetRGBColormaps(dpy, win, cnew, 1, property);
1104 XStandardColormap *map;
1106 /* s still points to the matching standard colormap */
1108 if (s->killid == ReleaseByFreeingColormap) {
1109 if ((s->colormap != None) &&
1110 (s->colormap != DefaultColormap(dpy, screen)))
1111 XFreeColormap(dpy, s->colormap);
1113 else if (s->killid != None)
1114 XKillClient(dpy, s->killid);
1116 map = (cnew) ? cnew : stdcmaps + --count;
1118 s->colormap = map->colormap;
1119 s->red_max = map->red_max;
1120 s->red_mult = map->red_mult;
1121 s->green_max = map->green_max;
1122 s->green_mult = map->green_mult;
1123 s->blue_max = map->blue_max;
1124 s->blue_mult = map->blue_mult;
1125 s->visualid = map->visualid;
1126 s->killid = map->killid;
1128 XSetRGBColormaps(dpy, win, stdcmaps, count, property);
1131 XFree((char *) stdcmaps);
1135 /* $Xorg: CmapAlloc.c,v 1.4 2001/02/09 02:03:51 xorgcvs Exp $ */
1139 Copyright 1989, 1994, 1998 The Open Group
1141 Permission to use, copy, modify, distribute, and sell this software and its
1142 documentation for any purpose is hereby granted without fee, provided that
1143 the above copyright notice appear in all copies and that both that
1144 copyright notice and this permission notice appear in supporting
1147 The above copyright notice and this permission notice shall be included in
1148 all copies or substantial portions of the Software.
1150 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1151 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1152 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1153 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1154 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1155 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1157 Except as contained in this notice, the name of The Open Group shall not be
1158 used in advertising or otherwise to promote the sale, use or other dealings
1159 in this Software without prior written authorization from The Open Group.
1162 /* $XFree86: xc/lib/Xmu/CmapAlloc.c,v 1.7 2001/12/14 19:55:35 dawes Exp $ */
1165 * Author: Donna Converse, MIT X Consortium
1168 #include <X11/Xlib.h>
1169 #include <X11/Xatom.h>
1170 #include <X11/Xutil.h>
1171 #include <X11/Xmu/StdCmap.h>
1174 #define lowbit(x) ((x) & (~(x) + 1))
1179 static void best_allocation(XVisualInfo*, unsigned long*, unsigned long*,
1181 static int default_allocation(XVisualInfo*, unsigned long*,
1182 unsigned long*, unsigned long*);
1183 static void gray_allocation(int, unsigned long*, unsigned long*,
1185 static int icbrt(int);
1186 static int icbrt_with_bits(int, int);
1187 static int icbrt_with_guess(int, int);
1189 /* To determine the best allocation of reds, greens, and blues in a
1190 * standard colormap, use XmuGetColormapAllocation.
1191 * vinfo specifies visual information for a chosen visual
1192 * property specifies one of the standard colormap property names
1193 * red_max returns maximum red value
1194 * green_max returns maximum green value
1195 * blue_max returns maximum blue value
1197 * XmuGetColormapAllocation returns 0 on failure, non-zero on success.
1198 * It is assumed that the visual is appropriate for the colormap property.
1202 XmuGetColormapAllocation(XVisualInfo *vinfo, Atom property,
1203 unsigned long *red_max,
1204 unsigned long *green_max,
1205 unsigned long *blue_max)
1209 if (vinfo->colormap_size <= 2)
1214 case XA_RGB_DEFAULT_MAP:
1215 status = default_allocation(vinfo, red_max, green_max, blue_max);
1217 case XA_RGB_BEST_MAP:
1218 best_allocation(vinfo, red_max, green_max, blue_max);
1220 case XA_RGB_GRAY_MAP:
1221 gray_allocation(vinfo->colormap_size, red_max, green_max, blue_max);
1223 case XA_RGB_RED_MAP:
1224 *red_max = vinfo->colormap_size - 1;
1225 *green_max = *blue_max = 0;
1227 case XA_RGB_GREEN_MAP:
1228 *green_max = vinfo->colormap_size - 1;
1229 *red_max = *blue_max = 0;
1231 case XA_RGB_BLUE_MAP:
1232 *blue_max = vinfo->colormap_size - 1;
1233 *red_max = *green_max = 0;
1241 /****************************************************************************/
1242 /* Determine the appropriate color allocations of a gray scale.
1244 * Keith Packard, MIT X Consortium
1248 gray_allocation(int n, unsigned long *red_max, unsigned long *green_max,
1249 unsigned long *blue_max)
1251 *red_max = (n * 30) / 100;
1252 *green_max = (n * 59) / 100;
1253 *blue_max = (n * 11) / 100;
1254 *green_max += ((n - 1) - (*red_max + *green_max + *blue_max));
1257 /****************************************************************************/
1258 /* Determine an appropriate color allocation for the RGB_DEFAULT_MAP.
1259 * If a map has less than a minimum number of definable entries, we do not
1260 * produce an allocation for an RGB_DEFAULT_MAP.
1262 * For 16 planes, the default colormap will have 27 each RGB; for 12 planes,
1263 * 12 each. For 8 planes, let n = the number of colormap entries, which may
1264 * be 256 or 254. Then, maximum red value = floor(cube_root(n - 125)) - 1.
1265 * Maximum green and maximum blue values are identical to maximum red.
1266 * This leaves at least 125 cells which clients can allocate.
1268 * Return 0 if an allocation has been determined, non-zero otherwise.
1272 default_allocation(XVisualInfo *vinfo, unsigned long *red,
1273 unsigned long *green, unsigned long *blue)
1275 int ngrays; /* number of gray cells */
1277 switch (vinfo->c_class)
1281 if (vinfo->colormap_size > 65000)
1282 /* intended for displays with 16 planes */
1283 *red = *green = *blue = (unsigned long) 27;
1284 else if (vinfo->colormap_size > 4000)
1285 /* intended for displays with 12 planes */
1286 *red = *green = *blue = (unsigned long) 12;
1287 else if (vinfo->colormap_size < 250)
1290 /* intended for displays with 8 planes */
1291 *red = *green = *blue = (unsigned long)
1292 (icbrt(vinfo->colormap_size - 125) - 1);
1297 if (vinfo->colormap_size < 10)
1299 *red = *green = *blue = vinfo->colormap_size / 2 - 1;
1304 *red = vinfo->red_mask / lowbit(vinfo->red_mask);
1305 *green = vinfo->green_mask / lowbit(vinfo->green_mask);
1306 *blue = vinfo->blue_mask / lowbit(vinfo->blue_mask);
1311 if (vinfo->colormap_size > 65000)
1313 else if (vinfo->colormap_size > 4000)
1315 else if (vinfo->colormap_size < 250)
1319 gray_allocation(ngrays, red, green, blue);
1328 /****************************************************************************/
1329 /* Determine an appropriate color allocation for the RGB_BEST_MAP.
1331 * For a DirectColor or TrueColor visual, the allocation is determined
1332 * by the red_mask, green_mask, and blue_mask members of the visual info.
1334 * Otherwise, if the colormap size is an integral power of 2, determine
1335 * the allocation according to the number of bits given to each color,
1336 * with green getting more than red, and red more than blue, if there
1337 * are to be inequities in the distribution. If the colormap size is
1338 * not an integral power of 2, let n = the number of colormap entries.
1339 * Then maximum red value = floor(cube_root(n)) - 1;
1340 * maximum blue value = floor(cube_root(n)) - 1;
1341 * maximum green value = n / ((# red values) * (# blue values)) - 1;
1342 * Which, on a GPX, allows for 252 entries in the best map, out of 254
1343 * defineable colormap entries.
1347 best_allocation(XVisualInfo *vinfo, unsigned long *red, unsigned long *green,
1348 unsigned long *blue)
1351 if (vinfo->c_class == DirectColor || vinfo->c_class == TrueColor)
1353 *red = vinfo->red_mask;
1354 while ((*red & 01) == 0)
1356 *green = vinfo->green_mask;
1357 while ((*green & 01) == 0)
1359 *blue = vinfo->blue_mask;
1360 while ((*blue & 01) == 0)
1365 register int bits, n;
1367 /* Determine n such that n is the least integral power of 2 which is
1368 * greater than or equal to the number of entries in the colormap.
1372 while (vinfo->colormap_size > n)
1378 /* If the number of entries in the colormap is a power of 2, determine
1379 * the allocation by "dealing" the bits, first to green, then red, then
1380 * blue. If not, find the maximum integral red, green, and blue values
1381 * which, when multiplied together, do not exceed the number of
1385 if (n == vinfo->colormap_size)
1387 register int r, g, b;
1389 g = b + ((bits % 3) ? 1 : 0);
1390 r = b + (((bits % 3) == 2) ? 1 : 0);
1397 *red = icbrt_with_bits(vinfo->colormap_size, bits);
1399 *green = (vinfo->colormap_size / ((*red) * (*blue)));
1409 * integer cube roots by Newton's method
1411 * Stephen Gildea, MIT X Consortium, July 1991
1417 register int bits = 0;
1418 register unsigned n = a;
1425 return icbrt_with_bits(a, bits);
1430 icbrt_with_bits(int a, int bits)
1431 /* bits - log 2 of a */
1433 return icbrt_with_guess(a, a>>2*bits/3);
1436 #ifdef _X_ROOT_STATS
1437 int icbrt_loopcount;
1440 /* Newton's Method: x_n+1 = x_n - ( f(x_n) / f'(x_n) ) */
1442 /* for cube roots, x^3 - a = 0, x_new = x - 1/3 (x - a/x^2) */
1445 * Quick and dirty cube roots. Nothing fancy here, just Newton's method.
1446 * Only works for positive integers (since that's all we need).
1447 * We actually return floor(cbrt(a)) because that's what we need here, too.
1451 icbrt_with_guess(int a, int guess)
1455 #ifdef _X_ROOT_STATS
1456 icbrt_loopcount = 0;
1464 #ifdef _X_ROOT_STATS
1467 delta = (guess - a/(guess*guess))/3;
1469 printf("pass %d: guess=%d, delta=%d\n", icbrt_loopcount, guess, delta);
1472 } while (delta != 0);
1474 if (guess*guess*guess > a)
1481 /* $Xorg: StdCmap.c,v 1.4 2001/02/09 02:03:53 xorgcvs Exp $ */
1485 Copyright 1989, 1998 The Open Group
1487 Permission to use, copy, modify, distribute, and sell this software and its
1488 documentation for any purpose is hereby granted without fee, provided that
1489 the above copyright notice appear in all copies and that both that
1490 copyright notice and this permission notice appear in supporting
1493 The above copyright notice and this permission notice shall be included in
1494 all copies or substantial portions of the Software.
1496 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1497 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1498 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1499 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1500 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1501 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1503 Except as contained in this notice, the name of The Open Group shall not be
1504 used in advertising or otherwise to promote the sale, use or other dealings
1505 in this Software without prior written authorization from The Open Group.
1508 /* $XFree86: xc/lib/Xmu/StdCmap.c,v 1.6 2001/12/14 19:55:48 dawes Exp $ */
1511 * Author: Donna Converse, MIT X Consortium
1515 #include <X11/Xlib.h>
1516 #include <X11/Xatom.h>
1517 #include <X11/Xutil.h>
1518 #include <X11/Xmu/StdCmap.h>
1520 #define lowbit(x) ((x) & (~(x) + 1))
1525 /* argument restrictions */
1526 static Status valid_args(XVisualInfo*, unsigned long, unsigned long,
1527 unsigned long, Atom);
1530 * To create any one standard colormap, use XmuStandardColormap().
1532 * Create a standard colormap for the given screen, visualid, and visual
1533 * depth, with the given red, green, and blue maximum values, with the
1534 * given standard property name. Return a pointer to an XStandardColormap
1535 * structure which describes the newly created colormap, upon success.
1536 * Upon failure, return NULL.
1538 * XmuStandardColormap() calls XmuCreateColormap() to create the map.
1540 * Resources created by this function are not made permanent; that is the
1541 * caller's responsibility.
1545 XmuStandardColormap(Display *dpy, int screen, VisualID visualid,
1546 unsigned int depth, Atom property, Colormap cmap,
1547 unsigned long red_max, unsigned long green_max,
1548 unsigned long blue_max)
1550 * dpy - specifies X server connection
1551 * screen - specifies display screen
1552 * visualid - identifies the visual type
1553 * depth - identifies the visual type
1554 * property - a standard colormap property
1555 * cmap - specifies colormap ID or None
1556 * red_max, green_max, blue_max - allocations
1559 XStandardColormap *stdcmap;
1561 XVisualInfo vinfo_template, *vinfo;
1565 /* Match the required visual information to an actual visual */
1566 vinfo_template.visualid = visualid;
1567 vinfo_template.screen = screen;
1568 vinfo_template.depth = depth;
1569 vinfo_mask = VisualIDMask | VisualScreenMask | VisualDepthMask;
1570 if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &n)) == NULL)
1573 /* Check the validity of the combination of visual characteristics,
1574 * allocation, and colormap property. Create an XStandardColormap
1578 if (! valid_args(vinfo, red_max, green_max, blue_max, property)
1579 || ((stdcmap = XAllocStandardColormap()) == NULL)) {
1580 XFree((char *) vinfo);
1584 /* Fill in the XStandardColormap structure */
1586 if (cmap == DefaultColormap(dpy, screen)) {
1587 /* Allocating out of the default map, cannot use XFreeColormap() */
1588 Window win = XCreateWindow(dpy, RootWindow(dpy, screen), 1, 1, 1, 1,
1589 0, 0, InputOnly, vinfo->visual,
1591 (XSetWindowAttributes *)NULL);
1592 stdcmap->killid = (XID) XCreatePixmap(dpy, win, 1, 1, depth);
1593 XDestroyWindow(dpy, win);
1594 stdcmap->colormap = cmap;
1596 stdcmap->killid = ReleaseByFreeingColormap;
1597 stdcmap->colormap = XCreateColormap(dpy, RootWindow(dpy, screen),
1598 vinfo->visual, AllocNone);
1600 stdcmap->red_max = red_max;
1601 stdcmap->green_max = green_max;
1602 stdcmap->blue_max = blue_max;
1603 if (property == XA_RGB_GRAY_MAP)
1604 stdcmap->red_mult = stdcmap->green_mult = stdcmap->blue_mult = 1;
1605 else if (vinfo->c_class == TrueColor || vinfo->c_class == DirectColor) {
1606 stdcmap->red_mult = lowbit(vinfo->red_mask);
1607 stdcmap->green_mult = lowbit(vinfo->green_mask);
1608 stdcmap->blue_mult = lowbit(vinfo->blue_mask);
1610 stdcmap->red_mult = (red_max > 0)
1611 ? (green_max + 1) * (blue_max + 1) : 0;
1612 stdcmap->green_mult = (green_max > 0) ? blue_max + 1 : 0;
1613 stdcmap->blue_mult = (blue_max > 0) ? 1 : 0;
1615 stdcmap->base_pixel = 0; /* base pixel may change */
1616 stdcmap->visualid = vinfo->visualid;
1618 /* Make the colormap */
1620 status = XmuCreateColormap(dpy, stdcmap);
1624 XFree((char *) vinfo);
1627 /* Free the colormap or the pixmap, if we created one */
1628 if (stdcmap->killid == ReleaseByFreeingColormap)
1629 XFreeColormap(dpy, stdcmap->colormap);
1630 else if (stdcmap->killid != None)
1631 XFreePixmap(dpy, stdcmap->killid);
1633 XFree((char *) stdcmap);
1634 return (XStandardColormap *) NULL;
1639 /****************************************************************************/
1641 valid_args(XVisualInfo *vinfo, unsigned long red_max, unsigned long green_max,
1642 unsigned long blue_max, Atom property)
1644 * vinfo - specifies visual
1645 * red_max, green_max, blue_max - specifies alloc
1646 * property - specifies property name
1649 unsigned long ncolors; /* number of colors requested */
1651 /* Determine that the number of colors requested is <= map size */
1653 if ((vinfo->c_class == DirectColor) || (vinfo->c_class == TrueColor)) {
1656 mask = vinfo->red_mask;
1661 mask = vinfo->green_mask;
1664 if (green_max > mask)
1666 mask = vinfo->blue_mask;
1669 if (blue_max > mask)
1671 } else if (property == XA_RGB_GRAY_MAP) {
1672 ncolors = red_max + green_max + blue_max + 1;
1673 if (ncolors > vinfo->colormap_size)
1676 ncolors = (red_max + 1) * (green_max + 1) * (blue_max + 1);
1677 if (ncolors > vinfo->colormap_size)
1681 /* Determine that the allocation and visual make sense for the property */
1685 case XA_RGB_DEFAULT_MAP:
1686 if (red_max == 0 || green_max == 0 || blue_max == 0)
1689 case XA_RGB_RED_MAP:
1693 case XA_RGB_GREEN_MAP:
1697 case XA_RGB_BLUE_MAP:
1701 case XA_RGB_BEST_MAP:
1702 if (red_max == 0 || green_max == 0 || blue_max == 0)
1705 case XA_RGB_GRAY_MAP:
1706 if (red_max == 0 || blue_max == 0 || green_max == 0)
1716 /* $Xorg: CrCmap.c,v 1.4 2001/02/09 02:03:51 xorgcvs Exp $ */
1720 Copyright 1989, 1998 The Open Group
1722 Permission to use, copy, modify, distribute, and sell this software and its
1723 documentation for any purpose is hereby granted without fee, provided that
1724 the above copyright notice appear in all copies and that both that
1725 copyright notice and this permission notice appear in supporting
1728 The above copyright notice and this permission notice shall be included in
1729 all copies or substantial portions of the Software.
1731 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1732 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1733 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1734 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1735 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1736 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1738 Except as contained in this notice, the name of The Open Group shall not be
1739 used in advertising or otherwise to promote the sale, use or other dealings
1740 in this Software without prior written authorization from The Open Group.
1743 /* $XFree86: xc/lib/Xmu/CrCmap.c,v 3.7 2001/12/14 19:55:36 dawes Exp $ */
1746 * Author: Donna Converse, MIT X Consortium
1750 * CreateCmap.c - given a standard colormap description, make the map.
1755 #include <X11/Xlib.h>
1756 #include <X11/Xutil.h>
1757 #include <X11/Xmu/StdCmap.h>
1762 /* allocate entire map Read Only */
1763 static int ROmap(Display*, Colormap, unsigned long[], int, int);
1765 /* allocate a cell, prefer Read Only */
1766 static Status ROorRWcell(Display*, Colormap, unsigned long[], int,
1767 XColor*, unsigned long);
1769 /* allocate a cell Read Write */
1770 static Status RWcell(Display*, Colormap, XColor*, XColor*, unsigned long*);
1773 static int compare(_Xconst void*, _Xconst void*);
1775 /* find contiguous sequence of cells */
1776 static Status contiguous(unsigned long[], int, int, unsigned long, int*, int*);
1778 /* frees resources before quitting */
1779 static void free_cells(Display*, Colormap, unsigned long[], int, int);
1781 /* create a map in a RO visual type */
1782 static Status readonly_map(Display*, XVisualInfo*, XStandardColormap*);
1784 /* create a map in a RW visual type */
1785 static Status readwrite_map(Display*, XVisualInfo*, XStandardColormap*);
1787 #define lowbit(x) ((x) & (~(x) + 1))
1788 #define TRUEMATCH(mult,max,mask) \
1789 (colormap->max * colormap->mult <= vinfo->mask && \
1790 lowbit(vinfo->mask) == colormap->mult)
1793 * To create any one colormap which is described by an XStandardColormap
1794 * structure, use XmuCreateColormap().
1796 * Return 0 on failure, non-zero on success.
1797 * Resources created by this function are not made permanent.
1798 * No argument error checking is provided. Use at your own risk.
1800 * All colormaps are created with read only allocations, with the exception
1801 * of read only allocations of colors in the default map or otherwise
1802 * which fail to return the expected pixel value, and these are individually
1803 * defined as read/write allocations. This is done so that all the cells
1804 * defined in the default map are contiguous, for use in image processing.
1805 * This typically happens with White and Black in the default map.
1807 * Colormaps of static visuals are considered to be successfully created if
1808 * the map of the static visual matches the definition given in the
1809 * standard colormap structure.
1813 XmuCreateColormap(Display *dpy, XStandardColormap *colormap)
1814 /* dpy - specifies the connection under which the map is created
1815 * colormap - specifies the map to be created, and returns, particularly
1816 * if the map is created as a subset of the default colormap
1817 * of the screen, the base_pixel of the map.
1820 XVisualInfo vinfo_template; /* template visual information */
1821 XVisualInfo *vinfo; /* matching visual information */
1822 XVisualInfo *vpointer; /* for freeing the entire list */
1823 long vinfo_mask; /* specifies the visual mask value */
1824 int n; /* number of matching visuals */
1827 vinfo_template.visualid = colormap->visualid;
1828 vinfo_mask = VisualIDMask;
1829 if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &n)) == NULL)
1832 /* A visual id may be valid on multiple screens. Also, there may
1833 * be multiple visuals with identical visual ids at different depths.
1834 * If the colormap is the Default Colormap, use the Default Visual.
1835 * Otherwise, arbitrarily, use the deepest visual.
1841 register int screen_number;
1845 for (screen_number = ScreenCount(dpy); --screen_number >= 0; )
1846 if (colormap->colormap == DefaultColormap(dpy, screen_number)) {
1852 for (i=0; i < n; i++, vinfo++) {
1853 if (vinfo->visual == DefaultVisual(dpy, screen_number))
1858 XVisualInfo *v = NULL;
1860 for (i=0; i < n; i++, vinfo++)
1861 if (vinfo->depth > maxdepth) {
1862 maxdepth = vinfo->depth;
1869 if (vinfo->c_class == PseudoColor || vinfo->c_class == DirectColor ||
1870 vinfo->c_class == GrayScale)
1871 status = readwrite_map(dpy, vinfo, colormap);
1872 else if (vinfo->c_class == TrueColor)
1873 status = TRUEMATCH(red_mult, red_max, red_mask) &&
1874 TRUEMATCH(green_mult, green_max, green_mask) &&
1875 TRUEMATCH(blue_mult, blue_max, blue_mask);
1877 status = readonly_map(dpy, vinfo, colormap);
1879 XFree((char *) vpointer);
1883 /****************************************************************************/
1885 readwrite_map(Display *dpy, XVisualInfo *vinfo, XStandardColormap *colormap)
1887 register unsigned long i, n; /* index counters */
1888 unsigned long ncolors; /* number of colors to be defined */
1889 int npixels; /* number of pixels allocated R/W */
1890 int first_index; /* first index of pixels to use */
1891 int remainder; /* first index of remainder */
1892 XColor color; /* the definition of a color */
1893 unsigned long *pixels; /* array of colormap pixels */
1894 unsigned long delta;
1897 /* Determine ncolors, the number of colors to be defined.
1898 * Insure that 1 < ncolors <= the colormap size.
1900 if (vinfo->c_class == DirectColor) {
1901 ncolors = colormap->red_max;
1902 if (colormap->green_max > ncolors)
1903 ncolors = colormap->green_max;
1904 if (colormap->blue_max > ncolors)
1905 ncolors = colormap->blue_max;
1907 delta = lowbit(vinfo->red_mask) +
1908 lowbit(vinfo->green_mask) +
1909 lowbit(vinfo->blue_mask);
1911 ncolors = colormap->red_max * colormap->red_mult +
1912 colormap->green_max * colormap->green_mult +
1913 colormap->blue_max * colormap->blue_mult + 1;
1916 if (ncolors <= 1 || (int) ncolors > vinfo->colormap_size) return 0;
1918 /* Allocate Read/Write as much of the colormap as we can possibly get.
1919 * Then insure that the pixels we were allocated are given in
1920 * monotonically increasing order, using a quicksort. Next, insure
1921 * that our allocation includes a subset of contiguous pixels at least
1922 * as long as the number of colors to be defined. Now we know that
1923 * these conditions are met:
1924 * 1) There are no free cells in the colormap.
1925 * 2) We have a contiguous sequence of pixels, monotonically
1926 * increasing, of length >= the number of colors requested.
1928 * One cell at a time, we will free, compute the next color value,
1929 * then allocate read only. This takes a long time.
1930 * This is done to insure that cells are allocated read only in the
1931 * contiguous order which we prefer. If the server has a choice of
1932 * cells to grant to an allocation request, the server may give us any
1933 * cell, so that is why we do these slow gymnastics.
1936 if ((pixels = (unsigned long *) calloc((unsigned) vinfo->colormap_size,
1937 sizeof(unsigned long))) == NULL)
1940 if ((npixels = ROmap(dpy, colormap->colormap, pixels,
1941 vinfo->colormap_size, ncolors)) == 0) {
1942 free((char *) pixels);
1946 qsort((char *) pixels, npixels, sizeof(unsigned long), compare);
1948 if (!contiguous(pixels, npixels, ncolors, delta, &first_index, &remainder))
1950 /* can't find enough contiguous cells, give up */
1951 XFreeColors(dpy, colormap->colormap, pixels, npixels,
1953 free((char *) pixels);
1956 colormap->base_pixel = pixels[first_index];
1958 /* construct a gray map */
1959 if (colormap->red_mult == 1 && colormap->green_mult == 1 &&
1960 colormap->blue_mult == 1)
1961 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
1964 color.blue = color.green = color.red =
1965 (unsigned short) ((i * 65535) / (colormap->red_max +
1966 colormap->green_max +
1967 colormap->blue_max));
1969 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
1974 /* construct a red ramp map */
1975 else if (colormap->green_max == 0 && colormap->blue_max == 0)
1976 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
1979 color.red = (unsigned short) ((i * 65535) / colormap->red_max);
1980 color.green = color.blue = 0;
1982 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
1987 /* construct a green ramp map */
1988 else if (colormap->red_max == 0 && colormap->blue_max == 0)
1989 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
1992 color.green = (unsigned short) ((i * 65535) / colormap->green_max);
1993 color.red = color.blue = 0;
1995 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
2000 /* construct a blue ramp map */
2001 else if (colormap->red_max == 0 && colormap->green_max == 0)
2002 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
2005 color.blue = (unsigned short) ((i * 65535) / colormap->blue_max);
2006 color.red = color.green = 0;
2008 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
2013 /* construct a standard red green blue cube map */
2016 #define calc(max,mult) (((n / colormap->mult) % \
2017 (colormap->max + 1)) * 65535) / colormap->max
2019 for (n=0, i=0; i < ncolors; i++, n += delta)
2021 color.pixel = n + colormap->base_pixel;
2022 color.red = calc(red_max, red_mult);
2023 color.green = calc(green_max, green_mult);
2024 color.blue = calc(blue_max, blue_mult);
2025 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
2031 /* We have a read-only map defined. Now free unused cells,
2032 * first those occuring before the contiguous sequence begins,
2033 * then any following the contiguous sequence.
2037 XFreeColors(dpy, colormap->colormap, pixels, first_index,
2040 XFreeColors(dpy, colormap->colormap,
2041 &(pixels[first_index + ncolors]), remainder,
2044 free((char *) pixels);
2049 /****************************************************************************/
2051 ROmap(Display *dpy, Colormap cmap, unsigned long pixels[], int m, int n)
2053 * dpy - the X server connection
2054 * cmap - specifies colormap ID
2055 * pixels - returns pixel allocations
2056 * m - specifies colormap size
2057 * n - specifies number of colors
2062 /* first try to allocate the entire colormap */
2063 if (XAllocColorCells(dpy, cmap, 1, (unsigned long *) NULL,
2064 (unsigned) 0, pixels, (unsigned) m))
2067 /* Allocate all available cells in the colormap, using a binary
2068 * algorithm to discover how many cells we can allocate in the colormap.
2072 p = n + ((m - n + 1) / 2);
2073 if (XAllocColorCells(dpy, cmap, 1, (unsigned long *) NULL,
2074 (unsigned) 0, pixels, (unsigned) p)) {
2078 XFreeColors(dpy, cmap, pixels, p, (unsigned long) 0);
2089 /****************************************************************************/
2091 contiguous(unsigned long pixels[], int npixels, int ncolors,
2092 unsigned long delta, int *first, int *rem)
2093 /* pixels - specifies allocated pixels
2094 * npixels - specifies count of alloc'd pixels
2095 * ncolors - specifies needed sequence length
2096 * delta - between pixels
2097 * first - returns first index of sequence
2098 * rem - returns first index after sequence, or 0, if none follow
2101 register int i = 1; /* walking index into the pixel array */
2102 register int count = 1; /* length of sequence discovered so far */
2105 if (npixels == ncolors) {
2110 while (count < ncolors && ncolors - count <= *rem)
2112 if (pixels[i-1] + delta == pixels[i])
2121 if (count != ncolors)
2127 /****************************************************************************/
2129 ROorRWcell(Display *dpy, Colormap cmap, unsigned long pixels[],
2130 int npixels, XColor *color, unsigned long p)
2132 unsigned long pixel;
2135 /* Free the read/write allocation of one cell in the colormap.
2136 * Request a read only allocation of one cell in the colormap.
2137 * If the read only allocation cannot be granted, give up, because
2138 * there must be no free cells in the colormap.
2139 * If the read only allocation is granted, but gives us a cell which
2140 * is not the one that we just freed, it is probably the case that
2141 * we are trying allocate White or Black or some other color which
2142 * already has a read-only allocation in the map. So we try to
2143 * allocate the previously freed cell with a read/write allocation,
2144 * because we want contiguous cells for image processing algorithms.
2147 pixel = color->pixel;
2148 request.red = color->red;
2149 request.green = color->green;
2150 request.blue = color->blue;
2152 XFreeColors(dpy, cmap, &pixel, 1, (unsigned long) 0);
2153 if (! XAllocColor(dpy, cmap, color)
2154 || (color->pixel != pixel &&
2155 (!RWcell(dpy, cmap, color, &request, &pixel))))
2157 free_cells(dpy, cmap, pixels, npixels, (int)p);
2164 /****************************************************************************/
2166 free_cells(Display *dpy, Colormap cmap, unsigned long pixels[],
2169 * pixels - to be freed
2170 * npixels - original number allocated
2173 /* One of the npixels allocated has already been freed.
2174 * p is the index of the freed pixel.
2175 * First free the pixels preceeding p, and there are p of them;
2176 * then free the pixels following p, there are npixels - p - 1 of them.
2178 XFreeColors(dpy, cmap, pixels, p, (unsigned long) 0);
2179 XFreeColors(dpy, cmap, &(pixels[p+1]), npixels - p - 1, (unsigned long) 0);
2180 free((char *) pixels);
2184 /****************************************************************************/
2186 RWcell(Display *dpy, Colormap cmap, XColor *color, XColor *request,
2187 unsigned long *pixel)
2189 unsigned long n = *pixel;
2191 XFreeColors(dpy, cmap, &(color->pixel), 1, (unsigned long)0);
2192 if (! XAllocColorCells(dpy, cmap, (Bool) 0, (unsigned long *) NULL,
2193 (unsigned) 0, pixel, (unsigned) 1))
2197 XFreeColors(dpy, cmap, pixel, 1, (unsigned long) 0);
2200 color->pixel = *pixel;
2201 color->flags = DoRed | DoGreen | DoBlue;
2202 color->red = request->red;
2203 color->green = request->green;
2204 color->blue = request->blue;
2205 XStoreColors(dpy, cmap, color, 1);
2210 /****************************************************************************/
2212 compare(_Xconst void *e1, _Xconst void *e2)
2214 return ((int)(*(long *)e1 - *(long *)e2));
2218 /****************************************************************************/
2220 readonly_map(Display *dpy, XVisualInfo *vinfo, XStandardColormap *colormap)
2225 last_pixel = (colormap->red_max + 1) * (colormap->green_max + 1) *
2226 (colormap->blue_max + 1) + colormap->base_pixel - 1;
2228 for(i=colormap->base_pixel; i <= last_pixel; i++) {
2230 color.pixel = (unsigned long) i;
2231 color.red = (unsigned short)
2232 (((i/colormap->red_mult) * 65535) / colormap->red_max);
2234 if (vinfo->c_class == StaticColor) {
2235 color.green = (unsigned short)
2236 ((((i/colormap->green_mult) % (colormap->green_max + 1)) *
2237 65535) / colormap->green_max);
2238 color.blue = (unsigned short)
2239 (((i%colormap->green_mult) * 65535) / colormap->blue_max);
2241 else /* vinfo->c_class == GrayScale, old style allocation XXX */
2242 color.green = color.blue = color.red;
2244 XAllocColor(dpy, colormap->colormap, &color);
2245 if (color.pixel != (unsigned long) i)
2252 /* $Xorg: DelCmap.c,v 1.4 2001/02/09 02:03:52 xorgcvs Exp $ */
2256 Copyright 1989, 1998 The Open Group
2258 Permission to use, copy, modify, distribute, and sell this software and its
2259 documentation for any purpose is hereby granted without fee, provided that
2260 the above copyright notice appear in all copies and that both that
2261 copyright notice and this permission notice appear in supporting
2264 The above copyright notice and this permission notice shall be included in
2265 all copies or substantial portions of the Software.
2267 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2268 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2269 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2270 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
2271 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
2272 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2274 Except as contained in this notice, the name of The Open Group shall not be
2275 used in advertising or otherwise to promote the sale, use or other dealings
2276 in this Software without prior written authorization from The Open Group.
2279 /* $XFree86: xc/lib/Xmu/DelCmap.c,v 1.7 2001/12/14 19:55:40 dawes Exp $ */
2282 * Author: Donna Converse, MIT X Consortium
2285 #include <X11/Xlib.h>
2286 #include <X11/Xutil.h>
2287 #include <X11/Xmu/StdCmap.h>
2289 int ignoreErrorHandler(Display* d, XErrorEvent* e) { }
2291 /* To remove any standard colormap property, use XmuDeleteStandardColormap().
2292 * XmuDeleteStandardColormap() will remove the specified property from the
2293 * specified screen, releasing any resources used by the colormap(s) of the
2294 * property if possible.
2298 XmuDeleteStandardColormap(Display *dpy, int screen, Atom property)
2299 /* dpy; - specifies the X server to connect to
2300 * screen - specifies the screen of the display
2301 * property - specifies the standard colormap property
2304 XStandardColormap *stdcmaps, *s;
2307 if (XGetRGBColormaps(dpy, RootWindow(dpy, screen), &stdcmaps, &count,
2310 for (s=stdcmaps; count > 0; count--, s++) {
2311 if ((s->killid == ReleaseByFreeingColormap) &&
2312 (s->colormap != None) &&
2313 (s->colormap != DefaultColormap(dpy, screen))) {
2315 // UGLY HACK written in by Adam Megacz -- sometimes s->colormap isn't valid, so we do some shuffling
2316 X11ErrorHandler* oldHandler = XSetErrorHandler(ignoreErrorHandler);
2318 XFreeColormap(dpy, s->colormap);
2320 XSetErrorHandler(oldHandler);
2323 } else if (s->killid != None) {
2324 XKillClient(dpy, s->killid);
2327 XDeleteProperty(dpy, RootWindow(dpy, screen), property);
2328 XFree((char *) stdcmaps);