1 // Copyright 2000-2005 the Contributors, as shown in the revision logs.
2 // Licensed under the GNU General Public License version 2 ("the License").
3 // You may not use this file except in compliance with the License.
6 #include <X11/extensions/XShm.h>
7 #include <X11/keysymdef.h>
8 #include <X11/keysym.h>
9 #include <X11/cursorfont.h>
10 #include <X11/Xutil.h>
11 #include <X11/Xatom.h>
12 #include <X11/Xmu/StdCmap.h>
14 #include <java/lang/String.h>
15 #include <org/ibex/graphics/Surface.h>
16 #include <org/ibex/graphics/Picture.h>
17 #include <org/ibex/core/Box.h>
18 #include <org/ibex/plat/X11.h>
19 #include <org/ibex/plat/X11$X11Surface.h>
20 #include <org/ibex/plat/X11$X11Picture.h>
21 #include <org/ibex/plat/X11$X11PixelBuffer.h>
22 #include <org/ibex/util/Semaphore.h>
23 #include <org/ibex/plat/Platform.h>
24 #include <java/lang/Long.h>
25 #include <java/util/Hashtable.h>
26 #include <org/ibex/util/Log.h>
28 #include <java/lang/System.h>
29 #include <java/io/PrintStream.h>
33 // static (per-xserver) data
34 static Visual* visual;
35 static Colormap s_colormap;
36 static XStandardColormap* colormap_info;
37 static XShmSegmentInfo shm_info;
38 static Window selectionWindow;
39 static int shm_supported = 0;
40 static int shm_pixmaps_supported;
41 static int screen_num;
42 static int colorDepth = 0;
43 static Display* display;
44 static int shm_size = 0;
46 #define min(a, b) ((a) < (b) ? (a) : (b))
47 #define max(a, b) ((a) < (b) ? (b) : (a))
49 // X11PixelBuffer //////////////////////////////////////////////////////////////////////
51 // ensures that the shared memory is at least size bytes; if not, allocates 3/2 * size
52 static void ensureShmSize(int size) {
53 if (size > shm_size) {
55 XShmDetach(display, &shm_info);
56 shmdt(shm_info.shmaddr);
57 shmctl(shm_info.shmid, IPC_RMID, 0);
59 shm_size = 3 * size / 2;
60 shm_info.shmid = shmget(IPC_PRIVATE, shm_size, IPC_CREAT | 0777 | IPC_EXCL);
61 shm_info.shmaddr = (char*)shmat(shm_info.shmid, 0, 0);
62 shm_info.readOnly = False;
63 XSync(display, False);
64 shmctl(shm_info.shmid, IPC_RMID, 0);
65 XShmAttach(display, &shm_info);
66 XSync(display, False);
70 void org::ibex::plat::X11$X11PixelBuffer::fastDrawPicture(org::ibex::graphics::Picture* s,
71 jint dx, jint dy, jint cx1, jint cy1, jint cx2, jint cy2) {
72 org::ibex::plat::X11$X11Picture* source = (org::ibex::plat::X11$X11Picture*)s;
74 if (source->doublebuf->stipple != NULL) {
75 XSetClipMask(display, (*((GC*)clipped_gc)), *((Pixmap*)source->doublebuf->stipple));
76 XSetClipOrigin(display, (*((GC*)clipped_gc)), dx, dy);
78 XSetClipMask(display, (*((GC*)clipped_gc)), None);
82 *((Pixmap*)source->doublebuf->pm), (*((Pixmap*)pm)), (*((GC*)clipped_gc)),
83 cx1 - dx, cy1 - dy, cx2 - cx1, cy2 - cy1, cx1, cy1);
86 void org::ibex::plat::X11$X11PixelBuffer::slowDrawPicture(org::ibex::graphics::Picture* s,
87 jint dx, jint dy, jint cx1, jint cy1, jint cx2, jint cy2,
88 jint rgb, jboolean alphaOnly) {
90 org::ibex::plat::X11$X11Picture* source = (org::ibex::plat::X11$X11Picture*)s;
93 // FASTEST: shared pixmap; twiddle bits in video ram directly
95 XSync(display, False); // ensure that all pending operations have rendered
96 xi = (XImage*)fake_ximage;
98 // MEDIUM: write to a shared ximage, then ask the server to do the blit
99 } else if (shm_supported) {
100 xi = XShmCreateImage(display, visual, colorDepth, ZPixmap, NULL, &shm_info, cx2 - cx1, cy2 - cy1);
101 ensureShmSize(xi->bytes_per_line * xi->height);
102 xi->data = shm_info.shmaddr;
103 XShmGetImage(display, (*((Pixmap*)pm)), xi, cx1, cy1, AllPlanes);
105 // SLOWEST: write to an ximage, copy it through the TCP connection, ask the server to do the blit
107 xi = XGetImage(display, (*((Pixmap*)pm)), cx1, cy1, cx2 - cx1, cy2 - cy1, AllPlanes, ZPixmap);
110 int* sourcedata = (int*)elements(source->data);
111 for(int y=cy1; y < cy2; y++) {
113 char* current_pixel = (xi->data + y * xi->bytes_per_line) +
114 (shared_pixmap ? cx1 * (xi->bits_per_pixel / 8) : - 1 * cy1 * xi->bytes_per_line);
116 for(int x=cx1; x < cx2; x++, current_pixel += xi->bits_per_pixel / 8) {
117 int source_x = x - dx;
118 int source_y = y - dy;
120 // FEATURE: be smarter here; can we do something better for the alphaonly case?
121 int sourcepixel = sourcedata[source_x + source_y * source->getWidth()];
122 int alpha = (sourcepixel & 0xFF000000) >> 24;
123 if (alphaOnly) sourcepixel = rgb;
124 int source_red = (sourcepixel & 0x00FF0000) >> 16;
125 int source_green = (sourcepixel & 0x0000FF00) >> 8;
126 int source_blue = (sourcepixel & 0x000000FF);
127 int red = 0, blue = 0, green = 0;
129 if (alpha == 0x00) continue;
131 switch (xi->bits_per_pixel) {
132 case 8: targetpixel = (int)(*current_pixel); break;
134 case 16: targetpixel = (int)(*((uint16_t*)current_pixel)); break;
136 // FIXME assumes endianness...
137 case 24: targetpixel =
138 (((int)*current_pixel) << 16) |
139 (((int)*(current_pixel + 1)) << 8) |
140 (((int)*(current_pixel + 2))); break;
141 case 32: targetpixel = *((int*)current_pixel); break;
142 default: org::ibex::plat::Platform::criticalAbort(JvNewStringLatin1("ERROR: bpp not a multiple of 8!"));
144 targetpixel -= colormap_info->base_pixel;
146 // if you're on some wierd display that isn't either RGB or BGR, that's your problem, not mine
147 if (colormap_info->red_mult > colormap_info->green_mult && colormap_info->green_mult > colormap_info->blue_mult) {
148 red = targetpixel / colormap_info->red_mult;
149 green = (targetpixel - red * colormap_info->red_mult) / colormap_info->green_mult;
150 blue = (targetpixel-red * colormap_info->red_mult-green * colormap_info->green_mult)/colormap_info->blue_mult;
152 blue = targetpixel / colormap_info->blue_mult;
153 green = (targetpixel - blue * colormap_info->blue_mult) / colormap_info->green_mult;
154 red = (targetpixel-blue * colormap_info->blue_mult-green * colormap_info->green_mult)/colormap_info->red_mult;
157 red = ((source_red * (colormap_info->red_max) * alpha) + (red * 0xFF * (0xFF - alpha))) / (0xFF * 0xFF);
158 green = ((source_green * (colormap_info->green_max) * alpha)+(green * 0xFF * (0xFF - alpha))) / (0xFF * 0xFF);
159 blue = ((source_blue * (colormap_info->blue_max) * alpha) + (blue * 0xFF * (0xFF - alpha))) / (0xFF * 0xFF);
161 (red * colormap_info->red_mult) +
162 (green * colormap_info->green_mult) +
163 (blue * colormap_info->blue_mult) +
164 colormap_info->base_pixel;
165 switch (xi->bits_per_pixel) {
166 case 8: *current_pixel = (char)(destpixel & 0xFF); break;
167 case 16: *((uint16_t*)current_pixel) = (uint16_t)destpixel; break;
169 int offset = (int)current_pixel & 0x3;
170 uint64_t dest = ((uint64_t)destpixel) << (8 * offset);
171 uint64_t mask = ((uint64_t)0xffffff) << (8 * offset);
172 uint64_t* base = (uint64_t*)(current_pixel - offset);
173 *base = (*base & ~mask) | dest;
176 case 32: *((uint32_t*)current_pixel) = destpixel; break;
177 default: org::ibex::plat::Platform::criticalAbort(JvNewStringLatin1("ERROR: bpp not a multiple of 8!"));
183 // do nothing, we wrote directly to video memory
185 } else if (shm_supported) {
186 XShmPutImage(display, (*((Pixmap*)pm)), (*((GC*)gc)), xi, 0, 0, cx1, cy1, cx2 - cx1, cy2 - cy1, False);
190 XPutImage(display, (*((Pixmap*)pm)), (*((GC*)gc)), xi, 0, 0, cx1, cy1, cx2 - cx1, cy2 - cy1);
195 void org::ibex::plat::X11$X11PixelBuffer::finalize() {
197 XShmSegmentInfo *sinfo = (XShmSegmentInfo*)shm_segment;
198 XShmDetach(display, sinfo);
199 shmdt(sinfo->shmaddr);
200 shmctl(sinfo->shmid, IPC_RMID, 0);
201 XDestroyImage((XImage*)fake_ximage);
205 XFreePixmap(display, *((Pixmap*)stipple));
208 XFreePixmap(display, *((Pixmap*)pm));
209 XFreeGC(display, *((GC*)gc));
210 XFreeGC(display, *((GC*)clipped_gc));
213 void org::ibex::plat::X11$X11PixelBuffer::natInit() {
215 if (width == 0 || height == 0) return;
216 shared_pixmap &= shm_supported & shm_pixmaps_supported; // refuse to use shared pixmaps if we don't have shm
217 pm = (gnu::gcj::RawData*)malloc(sizeof(Pixmap));
220 (*((Pixmap*)pm)) = XCreatePixmap(display, RootWindow(display, screen_num), width, height, colorDepth);
222 XShmSegmentInfo *sinfo = (XShmSegmentInfo*)malloc(sizeof(XShmSegmentInfo));
223 shm_segment = (gnu::gcj::RawData*)sinfo;
224 ((XImage*)fake_ximage) = XShmCreateImage(display, visual, colorDepth, ZPixmap, NULL, sinfo, width, height);
225 sinfo->shmid = shmget(IPC_PRIVATE, ((XImage*)fake_ximage)->bytes_per_line * height, IPC_CREAT | 0777 | IPC_EXCL);
226 ((XImage*)fake_ximage)->data = sinfo->shmaddr = (char*)shmat(sinfo->shmid, 0, 0);
227 sinfo->readOnly = False;
228 XShmAttach(display, sinfo);
229 XSync(display, False);
230 shmctl(sinfo->shmid, IPC_RMID, 0);
231 (*((Pixmap*)pm)) = XShmCreatePixmap(display, RootWindow(display, screen_num), sinfo->shmaddr, sinfo, width, height, colorDepth);
232 XSync(display, False);
235 gc = (gnu::gcj::RawData*)malloc(sizeof(GC));
236 clipped_gc = (gnu::gcj::RawData*)malloc(sizeof(GC));
237 (*((GC*)gc)) = XCreateGC(display, (*((Pixmap*)pm)), 0, 0);
238 (*((GC*)clipped_gc)) = XCreateGC(display, (*((Pixmap*)pm)), 0, 0);
241 vm.graphics_exposures = 0;
242 XChangeGC(display, (*((GC*)gc)), GCGraphicsExposures, &vm);
243 XChangeGC(display, (*((GC*)clipped_gc)), GCGraphicsExposures, &vm);
246 void org::ibex::plat::X11$X11PixelBuffer::createStipple(org::ibex::plat::X11$X11Picture* xpi) {
248 stipple = (gnu::gcj::RawData*)malloc(sizeof(Pixmap));
249 (*((Pixmap*)stipple)) = XCreatePixmap(display, RootWindow(display, screen_num), width, height, 1);
252 xi.data = (char*)malloc((width + 1) * height);
259 xi.byte_order = LSBFirst;
261 xi.bytes_per_line = (width / 8) + 1;
262 xi.bits_per_pixel = 1;
264 jint* d = (jint*)elements(xpi->data);
265 memset(xi.data, 0xFF, (width + 1) * height);
266 for(int x=0; x<width; x++)
267 for (int y=0; y<height; y++)
268 xi.data[y * xi.bytes_per_line + (x/8)] &= ~(((d[x + y * width] & 0xFF000000) != 0 ? 0 : 1) << (x % 8));
270 GC stipple_gc = XCreateGC(display, (*((Pixmap*)stipple)), 0, 0);
273 vm.graphics_exposures = 0;
274 XChangeGC(display, stipple_gc, GCGraphicsExposures, &vm);
276 XPutImage(display, (*((Pixmap*)stipple)), stipple_gc, &xi, 0, 0, 0, 0, width, height);
279 void org::ibex::plat::X11$X11Surface::blit(org::ibex::graphics::PixelBuffer* db, jint sx, jint sy, jint dx, jint dy, jint dx2, jint dy2) {
280 org::ibex::plat::X11$X11PixelBuffer *xdb = (org::ibex::plat::X11$X11PixelBuffer*)db;
281 XCopyArea(display, *((Pixmap*)xdb->pm), *((Window*)window), *((GC*)gc), sx, sy, dx2 - dx, dy2 - dy, dx, dy);
285 void org::ibex::plat::X11$X11PixelBuffer::fillRect (jint x, jint y, jint x2, jint y2, jint argb) {
290 if (x < clipx) { w -= (clipx - x); x = clipx; }
291 if (y < clipy) { h -= (clipy - y); y = clipy; }
292 if (x + w > clipx + clipw) w = (clipx + clipw - x);
293 if (y + h > clipy + cliph) h = (cliph + clipy - y);
295 XSetForeground(display, (*((GC*)gc)),
296 ((((argb & 0x00FF0000) >> 16) * colormap_info->red_max) / 0xFF) * colormap_info->red_mult +
297 ((((argb & 0x0000FF00) >> 8) * colormap_info->green_max) / 0xFF) * colormap_info->green_mult +
298 ((((argb & 0x000000FF)) * colormap_info->blue_max) / 0xFF) * colormap_info->blue_mult +
299 colormap_info->base_pixel
302 XFillRectangle(display, (*((Pixmap*)pm)), (*((GC*)gc)), x, y, w, h);
306 // X11Surface //////////////////////////////////////////////////////////////////////
308 void org::ibex::plat::X11$X11Surface::setIcon(org::ibex::graphics::Picture* pic) {
309 org::ibex::plat::X11$X11Picture* p = ((org::ibex::plat::X11$X11Picture*)pic);
310 org::ibex::plat::X11$X11PixelBuffer* old_dbuf = p->doublebuf;
311 p->buildPixelBuffer(1);
313 memset(&xwmh, 0, sizeof(XWMHints));
314 xwmh.flags |= IconPixmapHint | IconMaskHint;
315 xwmh.icon_pixmap = *((Pixmap*)p->doublebuf->pm);
316 xwmh.icon_mask = *((Pixmap*)p->doublebuf->stipple);
317 XSetWMHints(display, (*((Window*)window)), &xwmh);
318 p->doublebuf = old_dbuf;
321 void org::ibex::plat::X11$X11Surface::setTitleBarText(java::lang::String* s) {
322 int len = min(JvGetStringUTFLength(s), 1024);
324 JvGetStringUTFRegion(s, 0, len, buf);
328 tp.value = (unsigned char*)buf;
330 tp.encoding = XA_STRING;
332 XSetTextProperty(display, (*((Window*)window)), &tp, XA_WM_NAME);
333 XSetTextProperty(display, (*((Window*)window)), &tp, XA_WM_ICON_NAME);
336 void org::ibex::plat::X11$X11Surface::setLimits(jint minw, jint minh, jint maxw, jint maxh) {
338 hints.min_width = minw;
339 hints.min_height = minh;
340 hints.max_width = maxw;
341 hints.max_height = maxh;
342 hints.flags = PMinSize | PMaxSize;
343 XSetWMNormalHints(display, (*((Window*)window)), &hints);
346 void org::ibex::plat::X11$X11Surface::_setSize (jint width, jint height) {
347 if (width <= 0 || height <= 0) return;
348 XResizeWindow(display, (*((Window*)window)), width, height);
352 void org::ibex::plat::X11$X11Surface::setLocation () { XMoveWindow(display, (*((Window*)window)), root->x, root->y); }
353 void org::ibex::plat::X11$X11Surface::toFront() { XRaiseWindow(display, (*((Window*)window))); }
354 void org::ibex::plat::X11$X11Surface::toBack() { XLowerWindow(display, (*((Window*)window))); }
356 void org::ibex::plat::X11$X11Surface::_dispose() {
357 // without this we get phantom messages after the window is gone
358 org::ibex::plat::X11::windowToSurfaceMap->remove(new java::lang::Long(*((Window*)window)));
359 XDestroyWindow(display, (*((Window*)window)));
362 void org::ibex::plat::X11$X11Surface::setInvisible(jboolean i) {
363 if (i) XUnmapWindow(display, (*((Window*)window)));
364 else XMapRaised(display, (*((Window*)window)));
368 void org::ibex::plat::X11$X11Surface::_setMinimized(jboolean b) {
369 if (b) XIconifyWindow(display, (*((Window*)window)), screen_num);
370 else XMapRaised(display, (*((Window*)window)));
374 void org::ibex::plat::X11$X11Surface::natInit() {
375 XSetWindowAttributes xswa;
376 window = (gnu::gcj::RawData*)malloc(sizeof(Window));
377 xswa.bit_gravity = NorthWestGravity;
378 xswa.colormap = s_colormap;
379 xswa.event_mask = ExposureMask | ButtonPressMask | StructureNotifyMask |
380 KeyPressMask | KeyReleaseMask | ButtonPressMask |
381 ButtonReleaseMask | EnterWindowMask | LeaveWindowMask |
382 PointerMotionMask | ButtonMotionMask | ConfigureNotify | FocusChangeMask;
383 *((Window*)window) = XCreateWindow(display, RootWindow(display, screen_num), 10, 10, 10, 10, 0,
384 colorDepth, InputOutput, CopyFromParent,
385 CWColormap | CWBitGravity | CWEventMask, &xswa);
388 // I don't know why this works....
389 int dat[5] = { 0x2, 0xbffff804, 0x0, 0x817f560, 0x8110694 };
390 XChangeProperty(display, (*((Window*)window)),
391 XInternAtom(display, "_MOTIF_WM_HINTS", False),
392 XInternAtom(display, "_MOTIF_WM_HINTS", False),
400 tp.value = (unsigned char*)"Ibex";
402 tp.encoding = XA_STRING;
404 XSetTextProperty(display, (*((Window*)window)), &tp, XA_WM_CLASS);
406 Atom proto = XInternAtom(display, "WM_DELETE_WINDOW", False);
407 XSetWMProtocols(display, (*((Window*)window)), &proto, 1);
409 XSelectInput(display, (*((Window*)window)), StructureNotifyMask);
410 org::ibex::plat::X11::windowToSurfaceMap->put(new java::lang::Long(*((Window*)window)), this);
413 XMapRaised(display, (*((Window*)window)));
416 waitForCreation->block();
417 XSelectInput(display, (*((Window*)window)), xswa.event_mask);
420 gc = (gnu::gcj::RawData*)malloc(sizeof(GC));
421 *((GC*)gc) = XCreateGC(display, (*((Window*)window)), 0, 0);
424 vm.graphics_exposures = 0;
425 XChangeGC(display, *((GC*)gc), GCGraphicsExposures, &vm);
429 void org::ibex::plat::X11$X11Surface::dispatchEvent(gnu::gcj::RawData* ev) {
431 XEvent* e = (XEvent*)ev;
432 if (e->type == Expose) {
433 XExposeEvent *expose = (XExposeEvent*)(e);
434 Dirty(expose->x, expose->y, expose->width, expose->height);
436 } else if (e->type == MapNotify) { Minimized(0); waitForCreation->release();
437 } else if (e->type == UnmapNotify) { Minimized(1);
438 } else if (e->type == FocusIn) { Focused(1);
439 } else if (e->type == FocusOut) { Focused(0);
440 } else if (e->type == ClientMessage) {
441 if (((XClientMessageEvent*)(e))->data.l[0] == XInternAtom(display, "WM_DELETE_WINDOW", False)) Close();
443 } else if (e->type == KeyPress || e->type == KeyRelease) {
444 XKeyEvent *xbe = (XKeyEvent*)(e);
446 // drop faked KeyRelease events generated by the X server's autorepeat
447 if (e->type == KeyRelease) {
449 XQueryKeymap(display, depressed);
450 if ((depressed[(xbe->keycode & 0xff) / 8] & (0x1 << (xbe->keycode % 8))) >> (xbe->keycode % 8)) return;
456 unsigned int savestate = xbe->state;
457 xbe->state = xbe->state & ShiftMask; // ignore everything except shiftmask
458 XLookupString(xbe, s, 20, NULL, NULL);
459 xbe->state = savestate;
461 if (s != NULL && s[0] != '\0' && s[1] == '\0' && s[0] >= 0x20 && s[0] <= 0x7E) {
465 KeySym ks = XKeycodeToKeysym(display, xbe->keycode, 0);
467 case XK_BackSpace: s = "back_space"; break;
468 case XK_Tab: s = "tab"; break;
469 case XK_Linefeed: s = "enter"; break;
470 case XK_Return: s = "enter"; break;
471 case XK_Scroll_Lock: s = "scroll_lock"; break;
472 case XK_Escape: s = "escape"; break;
473 case XK_Insert: s = "insert"; break;
474 case XK_Delete: s = "delete"; break;
475 case XK_Home: s = "home"; break;
476 case XK_Left: s = "left"; break;
477 case XK_Up: s = "up"; break;
478 case XK_Right: s = "right"; break;
479 case XK_Down: s = "down"; break;
480 case XK_Page_Up: s = "page_up"; break;
481 case XK_Page_Down: s = "page_down"; break;
482 case XK_End: s = "end"; break;
483 case XK_Num_Lock: s = "num_lock"; break;
484 case XK_KP_Tab: s = "tab"; break;
485 case XK_KP_Enter: s = "enter"; break;
486 case XK_KP_F1: s = "f1"; break;
487 case XK_KP_F2: s = "f2"; break;
488 case XK_KP_F3: s = "f3"; break;
489 case XK_KP_F4: s = "f4"; break;
490 case XK_KP_Home: s = "home"; break;
491 case XK_KP_Left: s = "left"; break;
492 case XK_KP_Up: s = "up"; break;
493 case XK_KP_Right: s = "right"; break;
494 case XK_KP_Down: s = "down"; break;
495 case XK_KP_Page_Up: s = "page_up"; break;
496 case XK_KP_Page_Down: s = "page_down"; break;
497 case XK_KP_End: s = "end"; break;
498 case XK_KP_Insert: s = "insert"; break;
499 case XK_KP_Delete: s = "delete"; break;
500 case XK_F1: s = "f1"; break;
501 case XK_F2: s = "f2"; break;
502 case XK_F3: s = "f3"; break;
503 case XK_F4: s = "f4"; break;
504 case XK_F5: s = "f5"; break;
505 case XK_F6: s = "f6"; break;
506 case XK_F7: s = "f7"; break;
507 case XK_F8: s = "f8"; break;
508 case XK_F9: s = "f9"; break;
509 case XK_F10: s = "f10"; break;
510 case XK_F11: s = "f11"; break;
511 case XK_F12: s = "f12"; break;
512 case XK_Shift_L: s = "shift"; break;
513 case XK_Shift_R: s = "shift"; break;
514 case XK_Control_L: s = "control"; break;
515 case XK_Control_R: s = "control"; break;
516 case XK_Meta_L: s = "alt"; break;
517 case XK_Meta_R: s = "alt"; break;
518 case XK_Alt_L: s = "alt"; break;
519 case XK_Alt_R: s = "alt"; break;
524 jstring s2 = JvNewStringLatin1(s);
525 if (e->type == KeyPress) KeyPressed((xbe->state & LockMask) ? s2->toUpperCase() : s2);
526 if (e->type == KeyRelease) KeyReleased(s2);
528 } else if (e->type == ButtonPress) {
529 XButtonEvent* xbe = (XButtonEvent*)(e);
530 switch(xbe->button) {
531 case 4: VScroll((jfloat)-1.0); return;
532 case 5: VScroll((jfloat)1.0); return;
533 case 6: HScroll((jfloat)-1.0); return;
534 case 7: HScroll((jfloat)1.0); return;
536 if (xbe->button == 2) xbe->button = 3;
537 else if (xbe->button == 3) xbe->button = 2;
540 } else if (e->type == ButtonRelease) {
541 XButtonEvent* xbe = (XButtonEvent*)(e);
542 if (xbe->button == 2) xbe->button = 3;
543 else if (xbe->button == 3) xbe->button = 2;
544 Release(xbe->button);
546 } else if (e->type == MotionNotify) {
547 XMotionEvent* xme = (XMotionEvent*)(e);
548 Move(xme->x, xme->y);
550 } else if (e->type == EnterNotify || e->type == LeaveNotify) {
551 XCrossingEvent* xce = (XCrossingEvent*)(e);
552 Move(xce->x, xce->y);
554 } else if (e->type == ConfigureNotify) {
557 XConfigureEvent* xce = (XConfigureEvent*)(e);
558 XTranslateCoordinates(display, (*((Window*)window)), RootWindow(display, screen_num), 0, 0, &x_out, &y_out, &child);
559 if (xce->width != root->width || xce->height != root->height) SizeChange(xce->width, xce->height);
560 if (x_out != root->x || y_out != root->y) PosChange(x_out, y_out);
565 static jstring crosshair, east, hand, move, north, northeast, northwest,
566 south, southeast, southwest, text, west, wait_string;
567 static Cursor crosshair_cursor, east_cursor, hand_cursor, move_cursor, north_cursor,
568 northeast_cursor, northwest_cursor, south_cursor, southeast_cursor,
569 southwest_cursor, text_cursor, west_cursor, wait_cursor, default_cursor;
571 void org::ibex::plat::X11$X11Surface::syncCursor() {
574 if (cursor->equals(crosshair)) curs = crosshair_cursor;
575 else if (cursor->equals(east)) curs = east_cursor;
576 else if (cursor->equals(hand)) curs = hand_cursor;
577 else if (cursor->equals(move)) curs = move_cursor;
578 else if (cursor->equals(north)) curs = north_cursor;
579 else if (cursor->equals(northeast)) curs = northeast_cursor;
580 else if (cursor->equals(northwest)) curs = northwest_cursor;
581 else if (cursor->equals(south)) curs = south_cursor;
582 else if (cursor->equals(southeast)) curs = southeast_cursor;
583 else if (cursor->equals(southwest)) curs = southwest_cursor;
584 else if (cursor->equals(text)) curs = text_cursor;
585 else if (cursor->equals(west)) curs = west_cursor;
586 else if (cursor->equals(wait_string)) curs = wait_cursor;
587 else curs = default_cursor;
589 XDefineCursor(display, (*((Window*)window)), curs);
594 // X11 ///////////////////////////////////////////////////////////////////
596 jint org::ibex::plat::X11::_getScreenWidth() { return WidthOfScreen(DefaultScreenOfDisplay(display)); }
597 jint org::ibex::plat::X11::_getScreenHeight() { return HeightOfScreen(DefaultScreenOfDisplay(display)); }
599 static void dispatchSelectionEvent(XEvent* e) {
600 if (e->type == SelectionNotify) {
601 XSelectionEvent* xsn = (XSelectionEvent*)(e);
602 if (xsn->property == None) org::ibex::plat::X11::clipboard = JvNewStringLatin1("", 0);
606 unsigned long numitems;
608 unsigned long bytes_after;
609 XGetWindowProperty(display, xsn->requestor, xsn->property, 0, 4096,
610 True, AnyPropertyType, &returntype, &returnformat,
611 &numitems, &bytes_after, &ret);
612 org::ibex::plat::X11::clipboard =
613 (returntype == None ? JvNewStringLatin1("", 0) : JvNewStringLatin1((char*)ret, strlen((char*)ret)));
615 org::ibex::plat::X11::waiting_for_selection_event->release();
617 } else if (e->type == SelectionRequest) {
618 XSelectionRequestEvent* xsr = (XSelectionRequestEvent*)(e);
620 xsn.type = SelectionNotify;
621 xsn.serial = xsr->serial;
622 xsn.send_event = True;
623 xsn.display = display;
624 xsn.requestor = xsr->requestor;
625 xsn.selection = xsr->selection;
626 xsn.target = xsr->target;
627 xsn.property = xsr->property;
628 xsn.time = xsr->time;
630 int len = min(1024, JvGetStringUTFLength(org::ibex::plat::X11::clipboard));
632 JvGetStringUTFRegion(org::ibex::plat::X11::clipboard, 0, len, buf);
635 XChangeProperty(display, xsr->requestor, xsr->property, xsr->target, 8, PropModeReplace, (unsigned char*)buf, len + 1);
636 XSendEvent(display, xsr->requestor, True, 0, (XEvent*)(&xsn));
640 void org::ibex::plat::X11::eventThread() {
643 XNextEvent(display, &e);
644 if (e.type == SelectionNotify || e.type == SelectionRequest) {
645 dispatchSelectionEvent(&e);
647 org::ibex::plat::X11$X11Surface* surface =
648 (org::ibex::plat::X11$X11Surface*)windowToSurfaceMap->get(new java::lang::Long(((XAnyEvent*)&e)->window));
649 if (surface != NULL) surface->dispatchEvent((gnu::gcj::RawData*)&e);
654 jstring org::ibex::plat::X11::_getClipBoard() {
655 XConvertSelection(display, XA_PRIMARY, XA_STRING, XInternAtom(display, "VT_SELECTION", False), selectionWindow, CurrentTime);
657 org::ibex::plat::X11::waiting_for_selection_event->block();
661 void org::ibex::plat::X11::_setClipBoard(jstring s) {
663 int len = JvGetStringUTFLength(clipboard);
665 JvGetStringUTFRegion(clipboard, 0, len, buf);
667 XSetSelectionOwner(display, XInternAtom(display, "PRIMARY", 0), selectionWindow, CurrentTime);
670 typedef int (X11ErrorHandler)(Display*, XErrorEvent*);
671 int errorHandler(Display* d, XErrorEvent* e) {
672 // this error handler is only installed during the initial
673 // test to see if shm is present
677 void org::ibex::plat::X11::natInit() {
680 org::ibex::plat::Platform::criticalAbort(JvNewStringLatin1("Your X11 libraries do not support multithreaded programs"));
682 char* DISPLAY = getenv("DISPLAY");
683 if (DISPLAY == NULL || strlen(DISPLAY) == 0) DISPLAY = ":0.0";
684 display = XOpenDisplay(DISPLAY);
687 org::ibex::plat::Platform::criticalAbort(JvNewStringLatin1("Unable to connect to X11 display server"));
689 screen_num = XDefaultScreen(display);
690 colorDepth = (jint)(DefaultDepth(((Display*)display), 0));
691 shm_info.shmaddr = NULL;
693 // FIXME: SHM doesn't work on Darwin
694 //shm_supported = (XShmQueryExtension(display) == True);
696 X11ErrorHandler* oldHandler = XSetErrorHandler(errorHandler);
697 XShmSegmentInfo sinfo;
698 sinfo.shmid = shmget(IPC_PRIVATE, 1, IPC_CREAT | 0777 | IPC_EXCL);
699 sinfo.readOnly = False;
700 // if the server is remote, this will trigger the error handler
701 XShmAttach(display, &sinfo);
702 XSync(display, False);
703 XSetErrorHandler(oldHandler);
707 shm_pixmaps_supported = (XShmPixmapFormat(display) == ZPixmap);
709 crosshair = JvNewStringLatin1("crosshair");
710 east = JvNewStringLatin1("east");
711 hand = JvNewStringLatin1("hand");
712 move = JvNewStringLatin1("move");
713 north = JvNewStringLatin1("north");
714 northeast = JvNewStringLatin1("northeast");
715 northwest = JvNewStringLatin1("northwest");
716 south = JvNewStringLatin1("south");
717 southeast = JvNewStringLatin1("southeast");
718 southwest = JvNewStringLatin1("southwest");
719 text = JvNewStringLatin1("text");
720 west = JvNewStringLatin1("west");
721 wait_string = JvNewStringLatin1("wait");
722 crosshair_cursor = XCreateFontCursor(display, XC_tcross);
723 east_cursor = XCreateFontCursor(display, XC_right_side);
724 hand_cursor = XCreateFontCursor(display, XC_hand2);
725 move_cursor = XCreateFontCursor(display, XC_fleur);
726 north_cursor = XCreateFontCursor(display, XC_top_side);
727 northeast_cursor = XCreateFontCursor(display, XC_top_right_corner);
728 northwest_cursor = XCreateFontCursor(display, XC_left_side);
729 south_cursor = XCreateFontCursor(display, XC_bottom_side);
730 southeast_cursor = XCreateFontCursor(display, XC_bottom_right_corner);
731 southwest_cursor = XCreateFontCursor(display, XC_bottom_left_corner);
732 text_cursor = XCreateFontCursor(display, XC_xterm);
733 west_cursor = XCreateFontCursor(display, XC_right_side);
734 wait_cursor = XCreateFontCursor(display, XC_watch);
735 default_cursor = XCreateFontCursor(display, XC_left_ptr);
737 selectionWindow = XCreateWindow(display, RootWindow(display, screen_num), 0, 0, 1, 1, 0, colorDepth, InputOutput, CopyFromParent, 0, NULL);
738 visual = DefaultVisual(display, screen_num);
740 sprintf(buf, "X11 DISPLAY: %s", XDisplayString(display));
741 org::ibex::util::Log::info(this->getClass(), JvNewStringLatin1(buf));
742 sprintf(buf, "X11 SHM: %s", shm_supported ? "enabled" : "disabled");
743 org::ibex::util::Log::info(this->getClass(), JvNewStringLatin1(buf));
744 sprintf(buf, "X11 Visual: %x %x %x bits: %i visualid: %i depth: %i",
745 visual->red_mask, visual->green_mask, visual->blue_mask, visual->bits_per_rgb, visual->visualid, colorDepth);
746 org::ibex::util::Log::info(this->getClass(), JvNewStringLatin1(buf));
748 // FIXME: don't know why (True, False) is the best solution...
749 if(XmuLookupStandardColormap(display, screen_num, visual->visualid, colorDepth, XA_RGB_BEST_MAP, True, False) == 0)
750 org::ibex::plat::Platform::criticalAbort(JvNewStringLatin1("ERROR: XmuLookupStandardColormap failed"));
751 XStandardColormap* best_map_info = NULL;
753 if (XGetRGBColormaps(display, RootWindow(display, screen_num), &best_map_info, &count, XA_RGB_BEST_MAP) == 0)
754 org::ibex::plat::Platform::criticalAbort(JvNewStringLatin1("ERROR: couldn't allocate a standard colormap"));
755 if (!best_map_info->colormap)
756 org::ibex::plat::Platform::criticalAbort(JvNewStringLatin1("ERROR: XmuLookupStandardColomap succeded, but no colormap was found on the root window"));
757 if (best_map_info->red_max == 0)
758 org::ibex::plat::Platform::criticalAbort(JvNewStringLatin1("ERROR: standard colormap exists, but was improperly allocated"));
759 s_colormap = best_map_info->colormap;
760 colormap_info = best_map_info;
762 sprintf(buf, " red_max / red_mult: %x %x", colormap_info->red_max, colormap_info->red_mult);
763 org::ibex::util::Log::info(this->getClass(), JvNewStringLatin1(buf));
764 sprintf(buf, " green_max / green_mult: %x %x", colormap_info->green_max, colormap_info->green_mult);
765 org::ibex::util::Log::info(this->getClass(), JvNewStringLatin1(buf));
766 sprintf(buf, " blue_max / blue_mult: %x %x", colormap_info->blue_max, colormap_info->blue_mult);
767 org::ibex::util::Log::info(this->getClass(), JvNewStringLatin1(buf));
768 sprintf(buf, " base_pixel: %x", colormap_info->base_pixel);
769 org::ibex::util::Log::info(this->getClass(), JvNewStringLatin1(buf));
772 #include "WINGs/WINGs.h"
773 jstring org::ibex::plat::X11::_fileDialog(jstring suggestedFileName, jboolean write) {
778 // FIXME see WINGs/Tests/filedialog.c for more info... need an icon
779 WMInitializeApplication("Ibex", &argc, argv);
780 WMScreen *scr = WMCreateSimpleApplicationScreen(display);
781 int len = min(1024, JvGetStringUTFLength(suggestedFileName));
783 JvGetStringUTFRegion(suggestedFileName, 0, len, buf);
787 sPanel = WMGetSavePanel(scr);
788 if (WMRunModalFilePanelForDirectory(sPanel, NULL, buf, /*title*/ NULL, NULL) != True) return NULL;
789 return JvNewStringLatin1(WMGetFilePanelFileName(sPanel));
792 oPanel = WMGetOpenPanel(scr);
793 if (WMRunModalFilePanelForDirectory(oPanel, NULL, buf, /*title*/ NULL, NULL) != True) return NULL;
794 return JvNewStringLatin1(WMGetFilePanelFileName(oPanel));
799 //////////////////////////////////////////////////////////////////////////////
800 //////////////////////////////////////////////////////////////////////////////
801 //////////////////////////////////////////////////////////////////////////////
802 //////////////////////////////////////////////////////////////////////////////
804 // Everything below this point was taken, cut-and-paste, from the //
805 // source for libXmu. It implements the official 'standard colormap //
806 // creation algorithm. I made some small changes to //
807 // XmuDeleteStandardColormap //
809 //////////////////////////////////////////////////////////////////////////////
810 //////////////////////////////////////////////////////////////////////////////
811 //////////////////////////////////////////////////////////////////////////////
812 //////////////////////////////////////////////////////////////////////////////
814 /* $Xorg: LookupCmap.c,v 1.4 2001/02/09 02:03:53 xorgcvs Exp $ */
818 Copyright 1989, 1998 The Open Group
820 Permission to use, copy, modify, distribute, and sell this software and its
821 documentation for any purpose is hereby granted without fee, provided that
822 the above copyright notice appear in all copies and that both that
823 copyright notice and this permission notice appear in supporting
826 The above copyright notice and this permission notice shall be included in
827 all copies or substantial portions of the Software.
829 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
830 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
831 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
832 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
833 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
834 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
836 Except as contained in this notice, the name of The Open Group shall not be
837 used in advertising or otherwise to promote the sale, use or other dealings
838 in this Software without prior written authorization from The Open Group.
841 /* $XFree86: xc/lib/Xmu/LookupCmap.c,v 1.8 2001/12/14 19:55:47 dawes Exp $ */
844 * Author: Donna Converse, MIT X Consortium
848 #include <X11/Xlib.h>
849 #include <X11/Xatom.h>
850 #include <X11/Xutil.h>
851 #include <X11/Xmu/StdCmap.h>
857 static Status lookup(Display*, int, VisualID, Atom, XStandardColormap*, Bool);
860 * To create a standard colormap if one does not currently exist, or
861 * replace the currently existing standard colormap, use
862 * XmuLookupStandardColormap().
864 * Given a screen, a visual, and a property, XmuLookupStandardColormap()
865 * will determine the best allocation for the property under the specified
866 * visual, and determine the whether to create a new colormap or to use
867 * the default colormap of the screen. It will call XmuStandardColormap()
868 * to create the standard colormap.
870 * If replace is true, any previous definition of the property will be
871 * replaced. If retain is true, the property and the colormap will be
872 * made permanent for the duration of the server session. However,
873 * pre-existing property definitions which are not replaced cannot be made
874 * permanent by a call to XmuLookupStandardColormap(); a request to retain
875 * resources pertains to newly created resources.
877 * Returns 0 on failure, non-zero on success. A request to create a
878 * standard colormap upon a visual which cannot support such a map is
879 * considered a failure. An example of this would be requesting any
880 * standard colormap property on a monochrome visual, or, requesting an
881 * RGB_BEST_MAP on a display whose colormap size is 16.
885 XmuLookupStandardColormap(Display *dpy, int screen, VisualID visualid,
886 unsigned int depth, Atom property,
887 Bool replace, Bool retain)
889 * dpy - specifies X server connection
890 * screen - specifies screen of display
891 * visualid - specifies the visual type
892 * depth - specifies the visual type
893 * property - a standard colormap property
894 * replace - specifies whether to replace
895 * retain - specifies whether to retain
898 Display *odpy; /* original display connection */
899 XStandardColormap *colormap;
900 XVisualInfo vinfo_template, *vinfo; /* visual */
902 unsigned long r_max, g_max, b_max; /* allocation */
904 Colormap cmap; /* colormap ID */
908 /* Match the requested visual */
910 vinfo_template.visualid = visualid;
911 vinfo_template.screen = screen;
912 vinfo_template.depth = depth;
913 vinfo_mask = VisualIDMask | VisualScreenMask | VisualDepthMask;
914 if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &count)) ==
918 /* Monochrome visuals have no standard maps */
920 if (vinfo->colormap_size <= 2) {
921 XFree((char *) vinfo);
925 /* If the requested property already exists on this screen, and,
926 * if the replace flag has not been set to true, return success.
927 * lookup() will remove a pre-existing map if replace is true.
930 if (lookup(dpy, screen, visualid, property, (XStandardColormap *) NULL,
931 replace) && !replace) {
932 XFree((char *) vinfo);
936 /* Determine the best allocation for this property under the requested
937 * visualid and depth, and determine whether or not to use the default
938 * colormap of the screen.
941 if (!XmuGetColormapAllocation(vinfo, property, &r_max, &g_max, &b_max)) {
942 XFree((char *) vinfo);
946 cmap = (property == XA_RGB_DEFAULT_MAP &&
947 visualid == XVisualIDFromVisual(DefaultVisual(dpy, screen)))
948 ? DefaultColormap(dpy, screen) : None;
950 /* If retaining resources, open a new connection to the same server */
954 if ((dpy = XOpenDisplay(XDisplayString(odpy))) == NULL) {
955 XFree((char *) vinfo);
960 /* Create the standard colormap */
962 colormap = XmuStandardColormap(dpy, screen, visualid, depth, property,
963 cmap, r_max, g_max, b_max);
965 /* Set the standard colormap property */
970 if (lookup(dpy, screen, visualid, property, colormap, replace) &&
972 /* Someone has defined the property since we last looked.
973 * Since we will not replace it, release our own resources.
974 * If this is the default map, our allocations will be freed
975 * when this connection closes.
977 if (colormap->killid == ReleaseByFreeingColormap)
978 XFreeColormap(dpy, colormap->colormap);
980 XSetCloseDownMode(dpy, RetainPermanent);
983 XFree((char *) colormap);
989 XFree((char *) vinfo);
993 /***************************************************************************/
995 /* Lookup a standard colormap property. If the property is RGB_DEFAULT_MAP,
996 * the visualid is used to determine whether the indicated standard colormap
997 * exists. If the map exists and replace is true, delete the resources used
998 * by the map and remove the property. Return true if the map exists,
999 * or did exist and was deleted; return false if the map was not found.
1001 * Note that this is not the way that a Status return is normally used.
1003 * If new is not NULL, new points to an XStandardColormap structure which
1004 * describes a standard colormap of the specified property. It will be made
1005 * a standard colormap of the screen if none already exists, or if replace
1010 lookup(Display *dpy, int screen, VisualID visualid, Atom property,
1011 XStandardColormap *cnew, Bool replace)
1013 * dpy - specifies display connection
1014 * screen - specifies screen number
1015 * visualid - specifies visualid for std map
1016 * property - specifies colormap property name
1017 * cnew - specifies a standard colormap
1018 * replace - specifies whether to replace
1023 XStandardColormap *stdcmaps, *s;
1024 Window win = RootWindow(dpy, screen);
1026 /* The property does not already exist */
1028 if (! XGetRGBColormaps(dpy, win, &stdcmaps, &count, property)) {
1030 XSetRGBColormaps(dpy, win, cnew, 1, property);
1034 /* The property exists and is not describing the RGB_DEFAULT_MAP */
1036 if (property != XA_RGB_DEFAULT_MAP) {
1038 XmuDeleteStandardColormap(dpy, screen, property);
1040 XSetRGBColormaps(dpy, win, cnew, 1, property);
1042 XFree((char *)stdcmaps);
1046 /* The property exists and is RGB_DEFAULT_MAP */
1048 for (i=0, s=stdcmaps; (i < count) && (s->visualid != visualid); i++, s++)
1051 /* No RGB_DEFAULT_MAP property matches the given visualid */
1055 XStandardColormap *m, *maps;
1057 s = (XStandardColormap *) malloc((unsigned) ((count+1) * sizeof
1058 (XStandardColormap)));
1060 for (i = 0, m = s, maps = stdcmaps; i < count; i++, m++, maps++) {
1061 m->colormap = maps->colormap;
1062 m->red_max = maps->red_max;
1063 m->red_mult = maps->red_mult;
1064 m->green_max = maps->green_max;
1065 m->green_mult = maps->green_mult;
1066 m->blue_max = maps->blue_max;
1067 m->blue_mult = maps->blue_mult;
1068 m->base_pixel = maps->base_pixel;
1069 m->visualid = maps->visualid;
1070 m->killid = maps->killid;
1072 m->colormap = cnew->colormap;
1073 m->red_max = cnew->red_max;
1074 m->red_mult = cnew->red_mult;
1075 m->green_max = cnew->green_max;
1076 m->green_mult = cnew->green_mult;
1077 m->blue_max = cnew->blue_max;
1078 m->blue_mult = cnew->blue_mult;
1079 m->base_pixel = cnew->base_pixel;
1080 m->visualid = cnew->visualid;
1081 m->killid = cnew->killid;
1083 XSetRGBColormaps(dpy, win, s, ++count, property);
1086 XFree((char *) stdcmaps);
1090 /* Found an RGB_DEFAULT_MAP property with a matching visualid */
1093 /* Free old resources first - we may need them, particularly in
1094 * the default colormap of the screen. However, because of this,
1095 * it is possible that we will destroy the old resource and fail
1096 * to create a new one if XmuStandardColormap() fails.
1100 XmuDeleteStandardColormap(dpy, screen, property);
1102 XSetRGBColormaps(dpy, win, cnew, 1, property);
1105 XStandardColormap *map;
1107 /* s still points to the matching standard colormap */
1109 if (s->killid == ReleaseByFreeingColormap) {
1110 if ((s->colormap != None) &&
1111 (s->colormap != DefaultColormap(dpy, screen)))
1112 XFreeColormap(dpy, s->colormap);
1114 else if (s->killid != None)
1115 XKillClient(dpy, s->killid);
1117 map = (cnew) ? cnew : stdcmaps + --count;
1119 s->colormap = map->colormap;
1120 s->red_max = map->red_max;
1121 s->red_mult = map->red_mult;
1122 s->green_max = map->green_max;
1123 s->green_mult = map->green_mult;
1124 s->blue_max = map->blue_max;
1125 s->blue_mult = map->blue_mult;
1126 s->visualid = map->visualid;
1127 s->killid = map->killid;
1129 XSetRGBColormaps(dpy, win, stdcmaps, count, property);
1132 XFree((char *) stdcmaps);
1136 /* $Xorg: CmapAlloc.c,v 1.4 2001/02/09 02:03:51 xorgcvs Exp $ */
1140 Copyright 1989, 1994, 1998 The Open Group
1142 Permission to use, copy, modify, distribute, and sell this software and its
1143 documentation for any purpose is hereby granted without fee, provided that
1144 the above copyright notice appear in all copies and that both that
1145 copyright notice and this permission notice appear in supporting
1148 The above copyright notice and this permission notice shall be included in
1149 all copies or substantial portions of the Software.
1151 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1152 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1153 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1154 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1155 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1156 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1158 Except as contained in this notice, the name of The Open Group shall not be
1159 used in advertising or otherwise to promote the sale, use or other dealings
1160 in this Software without prior written authorization from The Open Group.
1163 /* $XFree86: xc/lib/Xmu/CmapAlloc.c,v 1.7 2001/12/14 19:55:35 dawes Exp $ */
1166 * Author: Donna Converse, MIT X Consortium
1169 #include <X11/Xlib.h>
1170 #include <X11/Xatom.h>
1171 #include <X11/Xutil.h>
1172 #include <X11/Xmu/StdCmap.h>
1175 #define lowbit(x) ((x) & (~(x) + 1))
1180 static void best_allocation(XVisualInfo*, unsigned long*, unsigned long*,
1182 static int default_allocation(XVisualInfo*, unsigned long*,
1183 unsigned long*, unsigned long*);
1184 static void gray_allocation(int, unsigned long*, unsigned long*,
1186 static int icbrt(int);
1187 static int icbrt_with_bits(int, int);
1188 static int icbrt_with_guess(int, int);
1190 /* To determine the best allocation of reds, greens, and blues in a
1191 * standard colormap, use XmuGetColormapAllocation.
1192 * vinfo specifies visual information for a chosen visual
1193 * property specifies one of the standard colormap property names
1194 * red_max returns maximum red value
1195 * green_max returns maximum green value
1196 * blue_max returns maximum blue value
1198 * XmuGetColormapAllocation returns 0 on failure, non-zero on success.
1199 * It is assumed that the visual is appropriate for the colormap property.
1203 XmuGetColormapAllocation(XVisualInfo *vinfo, Atom property,
1204 unsigned long *red_max,
1205 unsigned long *green_max,
1206 unsigned long *blue_max)
1210 if (vinfo->colormap_size <= 2)
1215 case XA_RGB_DEFAULT_MAP:
1216 status = default_allocation(vinfo, red_max, green_max, blue_max);
1218 case XA_RGB_BEST_MAP:
1219 best_allocation(vinfo, red_max, green_max, blue_max);
1221 case XA_RGB_GRAY_MAP:
1222 gray_allocation(vinfo->colormap_size, red_max, green_max, blue_max);
1224 case XA_RGB_RED_MAP:
1225 *red_max = vinfo->colormap_size - 1;
1226 *green_max = *blue_max = 0;
1228 case XA_RGB_GREEN_MAP:
1229 *green_max = vinfo->colormap_size - 1;
1230 *red_max = *blue_max = 0;
1232 case XA_RGB_BLUE_MAP:
1233 *blue_max = vinfo->colormap_size - 1;
1234 *red_max = *green_max = 0;
1242 /****************************************************************************/
1243 /* Determine the appropriate color allocations of a gray scale.
1245 * Keith Packard, MIT X Consortium
1249 gray_allocation(int n, unsigned long *red_max, unsigned long *green_max,
1250 unsigned long *blue_max)
1252 *red_max = (n * 30) / 100;
1253 *green_max = (n * 59) / 100;
1254 *blue_max = (n * 11) / 100;
1255 *green_max += ((n - 1) - (*red_max + *green_max + *blue_max));
1258 /****************************************************************************/
1259 /* Determine an appropriate color allocation for the RGB_DEFAULT_MAP.
1260 * If a map has less than a minimum number of definable entries, we do not
1261 * produce an allocation for an RGB_DEFAULT_MAP.
1263 * For 16 planes, the default colormap will have 27 each RGB; for 12 planes,
1264 * 12 each. For 8 planes, let n = the number of colormap entries, which may
1265 * be 256 or 254. Then, maximum red value = floor(cube_root(n - 125)) - 1.
1266 * Maximum green and maximum blue values are identical to maximum red.
1267 * This leaves at least 125 cells which clients can allocate.
1269 * Return 0 if an allocation has been determined, non-zero otherwise.
1273 default_allocation(XVisualInfo *vinfo, unsigned long *red,
1274 unsigned long *green, unsigned long *blue)
1276 int ngrays; /* number of gray cells */
1278 switch (vinfo->c_class)
1282 if (vinfo->colormap_size > 65000)
1283 /* intended for displays with 16 planes */
1284 *red = *green = *blue = (unsigned long) 27;
1285 else if (vinfo->colormap_size > 4000)
1286 /* intended for displays with 12 planes */
1287 *red = *green = *blue = (unsigned long) 12;
1288 else if (vinfo->colormap_size < 250)
1291 /* intended for displays with 8 planes */
1292 *red = *green = *blue = (unsigned long)
1293 (icbrt(vinfo->colormap_size - 125) - 1);
1298 if (vinfo->colormap_size < 10)
1300 *red = *green = *blue = vinfo->colormap_size / 2 - 1;
1305 *red = vinfo->red_mask / lowbit(vinfo->red_mask);
1306 *green = vinfo->green_mask / lowbit(vinfo->green_mask);
1307 *blue = vinfo->blue_mask / lowbit(vinfo->blue_mask);
1312 if (vinfo->colormap_size > 65000)
1314 else if (vinfo->colormap_size > 4000)
1316 else if (vinfo->colormap_size < 250)
1320 gray_allocation(ngrays, red, green, blue);
1329 /****************************************************************************/
1330 /* Determine an appropriate color allocation for the RGB_BEST_MAP.
1332 * For a DirectColor or TrueColor visual, the allocation is determined
1333 * by the red_mask, green_mask, and blue_mask members of the visual info.
1335 * Otherwise, if the colormap size is an integral power of 2, determine
1336 * the allocation according to the number of bits given to each color,
1337 * with green getting more than red, and red more than blue, if there
1338 * are to be inequities in the distribution. If the colormap size is
1339 * not an integral power of 2, let n = the number of colormap entries.
1340 * Then maximum red value = floor(cube_root(n)) - 1;
1341 * maximum blue value = floor(cube_root(n)) - 1;
1342 * maximum green value = n / ((# red values) * (# blue values)) - 1;
1343 * Which, on a GPX, allows for 252 entries in the best map, out of 254
1344 * defineable colormap entries.
1348 best_allocation(XVisualInfo *vinfo, unsigned long *red, unsigned long *green,
1349 unsigned long *blue)
1352 if (vinfo->c_class == DirectColor || vinfo->c_class == TrueColor)
1354 *red = vinfo->red_mask;
1355 while ((*red & 01) == 0)
1357 *green = vinfo->green_mask;
1358 while ((*green & 01) == 0)
1360 *blue = vinfo->blue_mask;
1361 while ((*blue & 01) == 0)
1366 register int bits, n;
1368 /* Determine n such that n is the least integral power of 2 which is
1369 * greater than or equal to the number of entries in the colormap.
1373 while (vinfo->colormap_size > n)
1379 /* If the number of entries in the colormap is a power of 2, determine
1380 * the allocation by "dealing" the bits, first to green, then red, then
1381 * blue. If not, find the maximum integral red, green, and blue values
1382 * which, when multiplied together, do not exceed the number of
1386 if (n == vinfo->colormap_size)
1388 register int r, g, b;
1390 g = b + ((bits % 3) ? 1 : 0);
1391 r = b + (((bits % 3) == 2) ? 1 : 0);
1398 *red = icbrt_with_bits(vinfo->colormap_size, bits);
1400 *green = (vinfo->colormap_size / ((*red) * (*blue)));
1410 * integer cube roots by Newton's method
1412 * Stephen Gildea, MIT X Consortium, July 1991
1418 register int bits = 0;
1419 register unsigned n = a;
1426 return icbrt_with_bits(a, bits);
1431 icbrt_with_bits(int a, int bits)
1432 /* bits - log 2 of a */
1434 return icbrt_with_guess(a, a>>2*bits/3);
1437 #ifdef _X_ROOT_STATS
1438 int icbrt_loopcount;
1441 /* Newton's Method: x_n+1 = x_n - ( f(x_n) / f'(x_n) ) */
1443 /* for cube roots, x^3 - a = 0, x_new = x - 1/3 (x - a/x^2) */
1446 * Quick and dirty cube roots. Nothing fancy here, just Newton's method.
1447 * Only works for positive integers (since that's all we need).
1448 * We actually return floor(cbrt(a)) because that's what we need here, too.
1452 icbrt_with_guess(int a, int guess)
1456 #ifdef _X_ROOT_STATS
1457 icbrt_loopcount = 0;
1465 #ifdef _X_ROOT_STATS
1468 delta = (guess - a/(guess*guess))/3;
1470 printf("pass %d: guess=%d, delta=%d\n", icbrt_loopcount, guess, delta);
1473 } while (delta != 0);
1475 if (guess*guess*guess > a)
1482 /* $Xorg: StdCmap.c,v 1.4 2001/02/09 02:03:53 xorgcvs Exp $ */
1486 Copyright 1989, 1998 The Open Group
1488 Permission to use, copy, modify, distribute, and sell this software and its
1489 documentation for any purpose is hereby granted without fee, provided that
1490 the above copyright notice appear in all copies and that both that
1491 copyright notice and this permission notice appear in supporting
1494 The above copyright notice and this permission notice shall be included in
1495 all copies or substantial portions of the Software.
1497 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1498 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1499 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1500 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1501 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1502 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1504 Except as contained in this notice, the name of The Open Group shall not be
1505 used in advertising or otherwise to promote the sale, use or other dealings
1506 in this Software without prior written authorization from The Open Group.
1509 /* $XFree86: xc/lib/Xmu/StdCmap.c,v 1.6 2001/12/14 19:55:48 dawes Exp $ */
1512 * Author: Donna Converse, MIT X Consortium
1516 #include <X11/Xlib.h>
1517 #include <X11/Xatom.h>
1518 #include <X11/Xutil.h>
1519 #include <X11/Xmu/StdCmap.h>
1521 #define lowbit(x) ((x) & (~(x) + 1))
1526 /* argument restrictions */
1527 static Status valid_args(XVisualInfo*, unsigned long, unsigned long,
1528 unsigned long, Atom);
1531 * To create any one standard colormap, use XmuStandardColormap().
1533 * Create a standard colormap for the given screen, visualid, and visual
1534 * depth, with the given red, green, and blue maximum values, with the
1535 * given standard property name. Return a pointer to an XStandardColormap
1536 * structure which describes the newly created colormap, upon success.
1537 * Upon failure, return NULL.
1539 * XmuStandardColormap() calls XmuCreateColormap() to create the map.
1541 * Resources created by this function are not made permanent; that is the
1542 * caller's responsibility.
1546 XmuStandardColormap(Display *dpy, int screen, VisualID visualid,
1547 unsigned int depth, Atom property, Colormap cmap,
1548 unsigned long red_max, unsigned long green_max,
1549 unsigned long blue_max)
1551 * dpy - specifies X server connection
1552 * screen - specifies display screen
1553 * visualid - identifies the visual type
1554 * depth - identifies the visual type
1555 * property - a standard colormap property
1556 * cmap - specifies colormap ID or None
1557 * red_max, green_max, blue_max - allocations
1560 XStandardColormap *stdcmap;
1562 XVisualInfo vinfo_template, *vinfo;
1566 /* Match the required visual information to an actual visual */
1567 vinfo_template.visualid = visualid;
1568 vinfo_template.screen = screen;
1569 vinfo_template.depth = depth;
1570 vinfo_mask = VisualIDMask | VisualScreenMask | VisualDepthMask;
1571 if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &n)) == NULL)
1574 /* Check the validity of the combination of visual characteristics,
1575 * allocation, and colormap property. Create an XStandardColormap
1579 if (! valid_args(vinfo, red_max, green_max, blue_max, property)
1580 || ((stdcmap = XAllocStandardColormap()) == NULL)) {
1581 XFree((char *) vinfo);
1585 /* Fill in the XStandardColormap structure */
1587 if (cmap == DefaultColormap(dpy, screen)) {
1588 /* Allocating out of the default map, cannot use XFreeColormap() */
1589 Window win = XCreateWindow(dpy, RootWindow(dpy, screen), 1, 1, 1, 1,
1590 0, 0, InputOnly, vinfo->visual,
1592 (XSetWindowAttributes *)NULL);
1593 stdcmap->killid = (XID) XCreatePixmap(dpy, win, 1, 1, depth);
1594 XDestroyWindow(dpy, win);
1595 stdcmap->colormap = cmap;
1597 stdcmap->killid = ReleaseByFreeingColormap;
1598 stdcmap->colormap = XCreateColormap(dpy, RootWindow(dpy, screen),
1599 vinfo->visual, AllocNone);
1601 stdcmap->red_max = red_max;
1602 stdcmap->green_max = green_max;
1603 stdcmap->blue_max = blue_max;
1604 if (property == XA_RGB_GRAY_MAP)
1605 stdcmap->red_mult = stdcmap->green_mult = stdcmap->blue_mult = 1;
1606 else if (vinfo->c_class == TrueColor || vinfo->c_class == DirectColor) {
1607 stdcmap->red_mult = lowbit(vinfo->red_mask);
1608 stdcmap->green_mult = lowbit(vinfo->green_mask);
1609 stdcmap->blue_mult = lowbit(vinfo->blue_mask);
1611 stdcmap->red_mult = (red_max > 0)
1612 ? (green_max + 1) * (blue_max + 1) : 0;
1613 stdcmap->green_mult = (green_max > 0) ? blue_max + 1 : 0;
1614 stdcmap->blue_mult = (blue_max > 0) ? 1 : 0;
1616 stdcmap->base_pixel = 0; /* base pixel may change */
1617 stdcmap->visualid = vinfo->visualid;
1619 /* Make the colormap */
1621 status = XmuCreateColormap(dpy, stdcmap);
1625 XFree((char *) vinfo);
1628 /* Free the colormap or the pixmap, if we created one */
1629 if (stdcmap->killid == ReleaseByFreeingColormap)
1630 XFreeColormap(dpy, stdcmap->colormap);
1631 else if (stdcmap->killid != None)
1632 XFreePixmap(dpy, stdcmap->killid);
1634 XFree((char *) stdcmap);
1635 return (XStandardColormap *) NULL;
1640 /****************************************************************************/
1642 valid_args(XVisualInfo *vinfo, unsigned long red_max, unsigned long green_max,
1643 unsigned long blue_max, Atom property)
1645 * vinfo - specifies visual
1646 * red_max, green_max, blue_max - specifies alloc
1647 * property - specifies property name
1650 unsigned long ncolors; /* number of colors requested */
1652 /* Determine that the number of colors requested is <= map size */
1654 if ((vinfo->c_class == DirectColor) || (vinfo->c_class == TrueColor)) {
1657 mask = vinfo->red_mask;
1662 mask = vinfo->green_mask;
1665 if (green_max > mask)
1667 mask = vinfo->blue_mask;
1670 if (blue_max > mask)
1672 } else if (property == XA_RGB_GRAY_MAP) {
1673 ncolors = red_max + green_max + blue_max + 1;
1674 if (ncolors > vinfo->colormap_size)
1677 ncolors = (red_max + 1) * (green_max + 1) * (blue_max + 1);
1678 if (ncolors > vinfo->colormap_size)
1682 /* Determine that the allocation and visual make sense for the property */
1686 case XA_RGB_DEFAULT_MAP:
1687 if (red_max == 0 || green_max == 0 || blue_max == 0)
1690 case XA_RGB_RED_MAP:
1694 case XA_RGB_GREEN_MAP:
1698 case XA_RGB_BLUE_MAP:
1702 case XA_RGB_BEST_MAP:
1703 if (red_max == 0 || green_max == 0 || blue_max == 0)
1706 case XA_RGB_GRAY_MAP:
1707 if (red_max == 0 || blue_max == 0 || green_max == 0)
1717 /* $Xorg: CrCmap.c,v 1.4 2001/02/09 02:03:51 xorgcvs Exp $ */
1721 Copyright 1989, 1998 The Open Group
1723 Permission to use, copy, modify, distribute, and sell this software and its
1724 documentation for any purpose is hereby granted without fee, provided that
1725 the above copyright notice appear in all copies and that both that
1726 copyright notice and this permission notice appear in supporting
1729 The above copyright notice and this permission notice shall be included in
1730 all copies or substantial portions of the Software.
1732 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1733 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1734 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1735 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1736 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1737 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1739 Except as contained in this notice, the name of The Open Group shall not be
1740 used in advertising or otherwise to promote the sale, use or other dealings
1741 in this Software without prior written authorization from The Open Group.
1744 /* $XFree86: xc/lib/Xmu/CrCmap.c,v 3.7 2001/12/14 19:55:36 dawes Exp $ */
1747 * Author: Donna Converse, MIT X Consortium
1751 * CreateCmap.c - given a standard colormap description, make the map.
1756 #include <X11/Xlib.h>
1757 #include <X11/Xutil.h>
1758 #include <X11/Xmu/StdCmap.h>
1763 /* allocate entire map Read Only */
1764 static int ROmap(Display*, Colormap, unsigned long[], int, int);
1766 /* allocate a cell, prefer Read Only */
1767 static Status ROorRWcell(Display*, Colormap, unsigned long[], int,
1768 XColor*, unsigned long);
1770 /* allocate a cell Read Write */
1771 static Status RWcell(Display*, Colormap, XColor*, XColor*, unsigned long*);
1774 static int compare(_Xconst void*, _Xconst void*);
1776 /* find contiguous sequence of cells */
1777 static Status contiguous(unsigned long[], int, int, unsigned long, int*, int*);
1779 /* frees resources before quitting */
1780 static void free_cells(Display*, Colormap, unsigned long[], int, int);
1782 /* create a map in a RO visual type */
1783 static Status readonly_map(Display*, XVisualInfo*, XStandardColormap*);
1785 /* create a map in a RW visual type */
1786 static Status readwrite_map(Display*, XVisualInfo*, XStandardColormap*);
1788 #define lowbit(x) ((x) & (~(x) + 1))
1789 #define TRUEMATCH(mult,max,mask) \
1790 (colormap->max * colormap->mult <= vinfo->mask && \
1791 lowbit(vinfo->mask) == colormap->mult)
1794 * To create any one colormap which is described by an XStandardColormap
1795 * structure, use XmuCreateColormap().
1797 * Return 0 on failure, non-zero on success.
1798 * Resources created by this function are not made permanent.
1799 * No argument error checking is provided. Use at your own risk.
1801 * All colormaps are created with read only allocations, with the exception
1802 * of read only allocations of colors in the default map or otherwise
1803 * which fail to return the expected pixel value, and these are individually
1804 * defined as read/write allocations. This is done so that all the cells
1805 * defined in the default map are contiguous, for use in image processing.
1806 * This typically happens with White and Black in the default map.
1808 * Colormaps of static visuals are considered to be successfully created if
1809 * the map of the static visual matches the definition given in the
1810 * standard colormap structure.
1814 XmuCreateColormap(Display *dpy, XStandardColormap *colormap)
1815 /* dpy - specifies the connection under which the map is created
1816 * colormap - specifies the map to be created, and returns, particularly
1817 * if the map is created as a subset of the default colormap
1818 * of the screen, the base_pixel of the map.
1821 XVisualInfo vinfo_template; /* template visual information */
1822 XVisualInfo *vinfo; /* matching visual information */
1823 XVisualInfo *vpointer; /* for freeing the entire list */
1824 long vinfo_mask; /* specifies the visual mask value */
1825 int n; /* number of matching visuals */
1828 vinfo_template.visualid = colormap->visualid;
1829 vinfo_mask = VisualIDMask;
1830 if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &n)) == NULL)
1833 /* A visual id may be valid on multiple screens. Also, there may
1834 * be multiple visuals with identical visual ids at different depths.
1835 * If the colormap is the Default Colormap, use the Default Visual.
1836 * Otherwise, arbitrarily, use the deepest visual.
1842 register int screen_number;
1846 for (screen_number = ScreenCount(dpy); --screen_number >= 0; )
1847 if (colormap->colormap == DefaultColormap(dpy, screen_number)) {
1853 for (i=0; i < n; i++, vinfo++) {
1854 if (vinfo->visual == DefaultVisual(dpy, screen_number))
1859 XVisualInfo *v = NULL;
1861 for (i=0; i < n; i++, vinfo++)
1862 if (vinfo->depth > maxdepth) {
1863 maxdepth = vinfo->depth;
1870 if (vinfo->c_class == PseudoColor || vinfo->c_class == DirectColor ||
1871 vinfo->c_class == GrayScale)
1872 status = readwrite_map(dpy, vinfo, colormap);
1873 else if (vinfo->c_class == TrueColor)
1874 status = TRUEMATCH(red_mult, red_max, red_mask) &&
1875 TRUEMATCH(green_mult, green_max, green_mask) &&
1876 TRUEMATCH(blue_mult, blue_max, blue_mask);
1878 status = readonly_map(dpy, vinfo, colormap);
1880 XFree((char *) vpointer);
1884 /****************************************************************************/
1886 readwrite_map(Display *dpy, XVisualInfo *vinfo, XStandardColormap *colormap)
1888 register unsigned long i, n; /* index counters */
1889 unsigned long ncolors; /* number of colors to be defined */
1890 int npixels; /* number of pixels allocated R/W */
1891 int first_index; /* first index of pixels to use */
1892 int remainder; /* first index of remainder */
1893 XColor color; /* the definition of a color */
1894 unsigned long *pixels; /* array of colormap pixels */
1895 unsigned long delta;
1898 /* Determine ncolors, the number of colors to be defined.
1899 * Insure that 1 < ncolors <= the colormap size.
1901 if (vinfo->c_class == DirectColor) {
1902 ncolors = colormap->red_max;
1903 if (colormap->green_max > ncolors)
1904 ncolors = colormap->green_max;
1905 if (colormap->blue_max > ncolors)
1906 ncolors = colormap->blue_max;
1908 delta = lowbit(vinfo->red_mask) +
1909 lowbit(vinfo->green_mask) +
1910 lowbit(vinfo->blue_mask);
1912 ncolors = colormap->red_max * colormap->red_mult +
1913 colormap->green_max * colormap->green_mult +
1914 colormap->blue_max * colormap->blue_mult + 1;
1917 if (ncolors <= 1 || (int) ncolors > vinfo->colormap_size) return 0;
1919 /* Allocate Read/Write as much of the colormap as we can possibly get.
1920 * Then insure that the pixels we were allocated are given in
1921 * monotonically increasing order, using a quicksort. Next, insure
1922 * that our allocation includes a subset of contiguous pixels at least
1923 * as long as the number of colors to be defined. Now we know that
1924 * these conditions are met:
1925 * 1) There are no free cells in the colormap.
1926 * 2) We have a contiguous sequence of pixels, monotonically
1927 * increasing, of length >= the number of colors requested.
1929 * One cell at a time, we will free, compute the next color value,
1930 * then allocate read only. This takes a long time.
1931 * This is done to insure that cells are allocated read only in the
1932 * contiguous order which we prefer. If the server has a choice of
1933 * cells to grant to an allocation request, the server may give us any
1934 * cell, so that is why we do these slow gymnastics.
1937 if ((pixels = (unsigned long *) calloc((unsigned) vinfo->colormap_size,
1938 sizeof(unsigned long))) == NULL)
1941 if ((npixels = ROmap(dpy, colormap->colormap, pixels,
1942 vinfo->colormap_size, ncolors)) == 0) {
1943 free((char *) pixels);
1947 qsort((char *) pixels, npixels, sizeof(unsigned long), compare);
1949 if (!contiguous(pixels, npixels, ncolors, delta, &first_index, &remainder))
1951 /* can't find enough contiguous cells, give up */
1952 XFreeColors(dpy, colormap->colormap, pixels, npixels,
1954 free((char *) pixels);
1957 colormap->base_pixel = pixels[first_index];
1959 /* construct a gray map */
1960 if (colormap->red_mult == 1 && colormap->green_mult == 1 &&
1961 colormap->blue_mult == 1)
1962 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
1965 color.blue = color.green = color.red =
1966 (unsigned short) ((i * 65535) / (colormap->red_max +
1967 colormap->green_max +
1968 colormap->blue_max));
1970 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
1975 /* construct a red ramp map */
1976 else if (colormap->green_max == 0 && colormap->blue_max == 0)
1977 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
1980 color.red = (unsigned short) ((i * 65535) / colormap->red_max);
1981 color.green = color.blue = 0;
1983 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
1988 /* construct a green ramp map */
1989 else if (colormap->red_max == 0 && colormap->blue_max == 0)
1990 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
1993 color.green = (unsigned short) ((i * 65535) / colormap->green_max);
1994 color.red = color.blue = 0;
1996 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
2001 /* construct a blue ramp map */
2002 else if (colormap->red_max == 0 && colormap->green_max == 0)
2003 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
2006 color.blue = (unsigned short) ((i * 65535) / colormap->blue_max);
2007 color.red = color.green = 0;
2009 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
2014 /* construct a standard red green blue cube map */
2017 #define calc(max,mult) (((n / colormap->mult) % \
2018 (colormap->max + 1)) * 65535) / colormap->max
2020 for (n=0, i=0; i < ncolors; i++, n += delta)
2022 color.pixel = n + colormap->base_pixel;
2023 color.red = calc(red_max, red_mult);
2024 color.green = calc(green_max, green_mult);
2025 color.blue = calc(blue_max, blue_mult);
2026 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
2032 /* We have a read-only map defined. Now free unused cells,
2033 * first those occuring before the contiguous sequence begins,
2034 * then any following the contiguous sequence.
2038 XFreeColors(dpy, colormap->colormap, pixels, first_index,
2041 XFreeColors(dpy, colormap->colormap,
2042 &(pixels[first_index + ncolors]), remainder,
2045 free((char *) pixels);
2050 /****************************************************************************/
2052 ROmap(Display *dpy, Colormap cmap, unsigned long pixels[], int m, int n)
2054 * dpy - the X server connection
2055 * cmap - specifies colormap ID
2056 * pixels - returns pixel allocations
2057 * m - specifies colormap size
2058 * n - specifies number of colors
2063 /* first try to allocate the entire colormap */
2064 if (XAllocColorCells(dpy, cmap, 1, (unsigned long *) NULL,
2065 (unsigned) 0, pixels, (unsigned) m))
2068 /* Allocate all available cells in the colormap, using a binary
2069 * algorithm to discover how many cells we can allocate in the colormap.
2073 p = n + ((m - n + 1) / 2);
2074 if (XAllocColorCells(dpy, cmap, 1, (unsigned long *) NULL,
2075 (unsigned) 0, pixels, (unsigned) p)) {
2079 XFreeColors(dpy, cmap, pixels, p, (unsigned long) 0);
2090 /****************************************************************************/
2092 contiguous(unsigned long pixels[], int npixels, int ncolors,
2093 unsigned long delta, int *first, int *rem)
2094 /* pixels - specifies allocated pixels
2095 * npixels - specifies count of alloc'd pixels
2096 * ncolors - specifies needed sequence length
2097 * delta - between pixels
2098 * first - returns first index of sequence
2099 * rem - returns first index after sequence, or 0, if none follow
2102 register int i = 1; /* walking index into the pixel array */
2103 register int count = 1; /* length of sequence discovered so far */
2106 if (npixels == ncolors) {
2111 while (count < ncolors && ncolors - count <= *rem)
2113 if (pixels[i-1] + delta == pixels[i])
2122 if (count != ncolors)
2128 /****************************************************************************/
2130 ROorRWcell(Display *dpy, Colormap cmap, unsigned long pixels[],
2131 int npixels, XColor *color, unsigned long p)
2133 unsigned long pixel;
2136 /* Free the read/write allocation of one cell in the colormap.
2137 * Request a read only allocation of one cell in the colormap.
2138 * If the read only allocation cannot be granted, give up, because
2139 * there must be no free cells in the colormap.
2140 * If the read only allocation is granted, but gives us a cell which
2141 * is not the one that we just freed, it is probably the case that
2142 * we are trying allocate White or Black or some other color which
2143 * already has a read-only allocation in the map. So we try to
2144 * allocate the previously freed cell with a read/write allocation,
2145 * because we want contiguous cells for image processing algorithms.
2148 pixel = color->pixel;
2149 request.red = color->red;
2150 request.green = color->green;
2151 request.blue = color->blue;
2153 XFreeColors(dpy, cmap, &pixel, 1, (unsigned long) 0);
2154 if (! XAllocColor(dpy, cmap, color)
2155 || (color->pixel != pixel &&
2156 (!RWcell(dpy, cmap, color, &request, &pixel))))
2158 free_cells(dpy, cmap, pixels, npixels, (int)p);
2165 /****************************************************************************/
2167 free_cells(Display *dpy, Colormap cmap, unsigned long pixels[],
2170 * pixels - to be freed
2171 * npixels - original number allocated
2174 /* One of the npixels allocated has already been freed.
2175 * p is the index of the freed pixel.
2176 * First free the pixels preceeding p, and there are p of them;
2177 * then free the pixels following p, there are npixels - p - 1 of them.
2179 XFreeColors(dpy, cmap, pixels, p, (unsigned long) 0);
2180 XFreeColors(dpy, cmap, &(pixels[p+1]), npixels - p - 1, (unsigned long) 0);
2181 free((char *) pixels);
2185 /****************************************************************************/
2187 RWcell(Display *dpy, Colormap cmap, XColor *color, XColor *request,
2188 unsigned long *pixel)
2190 unsigned long n = *pixel;
2192 XFreeColors(dpy, cmap, &(color->pixel), 1, (unsigned long)0);
2193 if (! XAllocColorCells(dpy, cmap, (Bool) 0, (unsigned long *) NULL,
2194 (unsigned) 0, pixel, (unsigned) 1))
2198 XFreeColors(dpy, cmap, pixel, 1, (unsigned long) 0);
2201 color->pixel = *pixel;
2202 color->flags = DoRed | DoGreen | DoBlue;
2203 color->red = request->red;
2204 color->green = request->green;
2205 color->blue = request->blue;
2206 XStoreColors(dpy, cmap, color, 1);
2211 /****************************************************************************/
2213 compare(_Xconst void *e1, _Xconst void *e2)
2215 return ((int)(*(long *)e1 - *(long *)e2));
2219 /****************************************************************************/
2221 readonly_map(Display *dpy, XVisualInfo *vinfo, XStandardColormap *colormap)
2226 last_pixel = (colormap->red_max + 1) * (colormap->green_max + 1) *
2227 (colormap->blue_max + 1) + colormap->base_pixel - 1;
2229 for(i=colormap->base_pixel; i <= last_pixel; i++) {
2231 color.pixel = (unsigned long) i;
2232 color.red = (unsigned short)
2233 (((i/colormap->red_mult) * 65535) / colormap->red_max);
2235 if (vinfo->c_class == StaticColor) {
2236 color.green = (unsigned short)
2237 ((((i/colormap->green_mult) % (colormap->green_max + 1)) *
2238 65535) / colormap->green_max);
2239 color.blue = (unsigned short)
2240 (((i%colormap->green_mult) * 65535) / colormap->blue_max);
2242 else /* vinfo->c_class == GrayScale, old style allocation XXX */
2243 color.green = color.blue = color.red;
2245 XAllocColor(dpy, colormap->colormap, &color);
2246 if (color.pixel != (unsigned long) i)
2253 /* $Xorg: DelCmap.c,v 1.4 2001/02/09 02:03:52 xorgcvs Exp $ */
2257 Copyright 1989, 1998 The Open Group
2259 Permission to use, copy, modify, distribute, and sell this software and its
2260 documentation for any purpose is hereby granted without fee, provided that
2261 the above copyright notice appear in all copies and that both that
2262 copyright notice and this permission notice appear in supporting
2265 The above copyright notice and this permission notice shall be included in
2266 all copies or substantial portions of the Software.
2268 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2269 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2270 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2271 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
2272 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
2273 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2275 Except as contained in this notice, the name of The Open Group shall not be
2276 used in advertising or otherwise to promote the sale, use or other dealings
2277 in this Software without prior written authorization from The Open Group.
2280 /* $XFree86: xc/lib/Xmu/DelCmap.c,v 1.7 2001/12/14 19:55:40 dawes Exp $ */
2283 * Author: Donna Converse, MIT X Consortium
2286 #include <X11/Xlib.h>
2287 #include <X11/Xutil.h>
2288 #include <X11/Xmu/StdCmap.h>
2290 int ignoreErrorHandler(Display* d, XErrorEvent* e) { }
2292 /* To remove any standard colormap property, use XmuDeleteStandardColormap().
2293 * XmuDeleteStandardColormap() will remove the specified property from the
2294 * specified screen, releasing any resources used by the colormap(s) of the
2295 * property if possible.
2299 XmuDeleteStandardColormap(Display *dpy, int screen, Atom property)
2300 /* dpy; - specifies the X server to connect to
2301 * screen - specifies the screen of the display
2302 * property - specifies the standard colormap property
2305 XStandardColormap *stdcmaps, *s;
2308 if (XGetRGBColormaps(dpy, RootWindow(dpy, screen), &stdcmaps, &count,
2311 for (s=stdcmaps; count > 0; count--, s++) {
2312 if ((s->killid == ReleaseByFreeingColormap) &&
2313 (s->colormap != None) &&
2314 (s->colormap != DefaultColormap(dpy, screen))) {
2316 // UGLY HACK written in by Adam Megacz -- sometimes s->colormap isn't valid, so we do some shuffling
2317 X11ErrorHandler* oldHandler = XSetErrorHandler(ignoreErrorHandler);
2319 XFreeColormap(dpy, s->colormap);
2321 XSetErrorHandler(oldHandler);
2324 } else if (s->killid != None) {
2325 XKillClient(dpy, s->killid);
2328 XDeleteProperty(dpy, RootWindow(dpy, screen), property);
2329 XFree((char *) stdcmaps);