1 // Copyright 2002 Adam Megacz, see the COPYING file for licensing [LGPL]
2 // see below for copyright information on the second portion of this file
7 #include <X11/extensions/XShm.h>
8 #include <X11/keysymdef.h>
9 #include <X11/keysym.h>
10 #include <X11/cursorfont.h>
11 #include <X11/Xutil.h>
12 #include <X11/Xatom.h>
13 #include <X11/Xmu/StdCmap.h>
17 #include <sys/types.h>
21 #include <java/lang/String.h>
22 #include <org/xwt/Surface.h>
23 #include <org/xwt/Picture.h>
24 #include <org/xwt/Box.h>
25 #include <org/xwt/plat/POSIX.h>
26 #include <org/xwt/plat/POSIX$X11Surface.h>
27 #include <org/xwt/plat/POSIX$X11Picture.h>
28 #include <org/xwt/plat/POSIX$X11DoubleBuffer.h>
29 #include <org/xwt/util/Semaphore.h>
30 #include <org/xwt/Platform.h>
31 #include <java/lang/Long.h>
32 #include <java/util/Hashtable.h>
33 #include <org/xwt/util/Log.h>
35 #include <java/lang/System.h>
36 #include <java/io/PrintStream.h>
38 // static (per-xserver) data
39 static Visual* visual;
40 static Colormap s_colormap;
41 static XStandardColormap* colormap_info;
42 static XShmSegmentInfo shm_info;
43 static Window selectionWindow;
44 static int shm_supported;
45 static int shm_pixmaps_supported;
46 static int screen_num;
47 static int colorDepth = 0;
48 static Display* display;
49 static int shm_size = 0;
51 #define min(a, b) ((a) < (b) ? (a) : (b))
52 #define max(a, b) ((a) < (b) ? (b) : (a))
54 // X11DoubleBuffer //////////////////////////////////////////////////////////////////////
56 // ensures that the shared memory is at least size bytes; if not, allocates 3/2 * size
57 static void ensureShmSize(int size) {
58 if (size > shm_size) {
60 XShmDetach(display, &shm_info);
61 shmdt(shm_info.shmaddr);
62 shmctl(shm_info.shmid, IPC_RMID, 0);
64 shm_size = 3 * size / 2;
65 shm_info.shmid = shmget(IPC_PRIVATE, shm_size, IPC_CREAT | 0777 | IPC_EXCL);
66 shm_info.shmaddr = (char*)shmat(shm_info.shmid, 0, 0);
67 shm_info.readOnly = False;
68 XSync(display, False);
69 shmctl(shm_info.shmid, IPC_RMID, 0);
70 XShmAttach(display, &shm_info);
71 XSync(display, False);
75 void org::xwt::plat::POSIX$X11DoubleBuffer::fastDrawPicture(org::xwt::Picture* s,
76 jint dx1, jint dy1, jint dx2, jint dy2, jint sx1, jint sy1, jint sx2, jint sy2) {
77 org::xwt::plat::POSIX$X11Picture* source = (org::xwt::plat::POSIX$X11Picture*)s;
79 // it's safe to clip manually since we no that no scaling will be done
80 if (dx1 < clipx) { sx1 += ((clipx - dx1) * (sx2 - sx1)) / (dx2 - dx1); dx1 = clipx; }
81 if (dy1 < clipy) { sy1 += ((clipy - dy1) * (sy2 - sy1)) / (dy2 - dy1); dy1 = clipy; }
82 if (dx2 > clipx + clipw) { sx2 -= ((dx2 - clipx - clipw) * (sx2 - sx1)) / (dx2 - dx1); dx2 = clipx + clipw; }
83 if (dy2 > clipy + cliph) { sy2 -= ((dy2 - clipy - cliph) * (sy2 - sy1)) / (dy2 - dy1); dy2 = clipy + cliph; }
84 if (dx1 > clipx + clipw) return;
85 if (dy1 > clipy + cliph) return;
86 if (dx2 - dx1 <= 0 || dy2 - dy1 <= 0) return;
88 if (source->doublebuf->stipple != NULL) {
89 XSetClipMask(display, (*((GC*)clipped_gc)), *((Pixmap*)source->doublebuf->stipple));
90 XSetClipOrigin(display, (*((GC*)clipped_gc)), dx1 - sx1, dy1 - sy1);
92 XSetClipMask(display, (*((GC*)clipped_gc)), None);
94 XCopyArea(display, *((Pixmap*)source->doublebuf->pm), (*((Pixmap*)pm)), (*((GC*)clipped_gc)), sx1, sy1, sx2 - sx1, sy2 - sy1, dx1, dy1);
97 void org::xwt::plat::POSIX$X11DoubleBuffer::slowDrawPicture(org::xwt::Picture* s,
98 jint dx1, jint dy1, jint dx2, jint dy2, jint sx1, jint sy1, jint sx2, jint sy2) {
100 org::xwt::plat::POSIX$X11Picture* source = (org::xwt::plat::POSIX$X11Picture*)s;
103 // FASTEST: shared pixmap; twiddle bits in video ram directly
105 XSync(display, False); // ensure that all pending operations have rendered
106 xi = (XImage*)fake_ximage;
108 // MEDIUM: write to a shared ximage, then ask the server to do the blit
109 } else if (shm_supported) {
110 xi = XShmCreateImage(display, visual, colorDepth, ZPixmap, NULL, &shm_info, dx2 - dx1, dy2 - dy1);
111 ensureShmSize(xi->bytes_per_line * xi->height);
112 xi->data = shm_info.shmaddr;
113 XShmGetImage(display, (*((Pixmap*)pm)), xi, dx1, dy1, AllPlanes);
115 // SLOWEST: write to an ximage, copy it through the TCP connection, ask the server to do the blit
117 xi = XGetImage(display, (*((Pixmap*)pm)), dx1, dy1, dx2 - dx1, dy2 - dy1, AllPlanes, ZPixmap);
120 int* sourcedata = (int*)elements(source->data);
121 for(int y=max(dy1, clipy); y<min(dy2, clipy + cliph); y++) {
123 char* current_pixel = (xi->data + y * xi->bytes_per_line) +
124 (shared_pixmap ? max(dx1, clipx) * (xi->bits_per_pixel / 8) : - 1 * dy1 * xi->bytes_per_line);
126 for(int x=max(dx1, clipx); x<min(dx2, clipx + clipw); x++, current_pixel += xi->bits_per_pixel / 8) {
127 int source_x = ((x - dx1) * (sx2 - sx1)) / (dx2 - dx1) + sx1;
128 int source_y = ((y - dy1) * (sy2 - sy1)) / (dy2 - dy1) + sy1;
130 int sourcepixel = sourcedata[source_x + source_y * source->getWidth()];
131 int alpha = (sourcepixel & 0xFF000000) >> 24;
132 int source_red = (sourcepixel & 0x00FF0000) >> 16;
133 int source_green = (sourcepixel & 0x0000FF00) >> 8;
134 int source_blue = (sourcepixel & 0x000000FF);
135 int red = 0, blue = 0, green = 0;
137 if (alpha == 0x00) continue;
140 switch (xi->bits_per_pixel) {
141 case 8: targetpixel = (int)(*current_pixel); break;
142 case 16: targetpixel = (int)(*((u_int16_t*)current_pixel)); break;
143 case 24: targetpixel = (((int)*current_pixel) << 16) | (((int)*(current_pixel + 1)) << 8) | (((int)*(current_pixel + 2))); break;
144 case 32: targetpixel = *((int*)current_pixel); break;
145 default: org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: bpp not a multiple of 8!"));
148 targetpixel -= colormap_info->base_pixel;
150 // if you're on some wierd display that isn't either RGB or BGR, that's your problem, not mine
151 if (colormap_info->red_mult > colormap_info->green_mult && colormap_info->green_mult > colormap_info->blue_mult) {
152 red = targetpixel / colormap_info->red_mult;
153 green = (targetpixel - red * colormap_info->red_mult) / colormap_info->green_mult;
154 blue = (targetpixel - red * colormap_info->red_mult - green * colormap_info->green_mult) / colormap_info->blue_mult;
156 blue = targetpixel / colormap_info->blue_mult;
157 green = (targetpixel - blue * colormap_info->blue_mult) / colormap_info->green_mult;
158 red = (targetpixel - blue * colormap_info->blue_mult - green * colormap_info->green_mult) / colormap_info->red_mult;
162 red = ((source_red * colormap_info->red_max * alpha) + (red * 0xFF * (0xFF - alpha))) / (0xFF * 0xFF);
163 green = ((source_green * colormap_info->green_max * alpha) + (green * 0xFF * (0xFF - alpha))) / (0xFF * 0xFF);
164 blue = ((source_blue * colormap_info->blue_max * alpha) + (blue * 0xFF * (0xFF - alpha))) / (0xFF * 0xFF);
165 u_int32_t destpixel = red * colormap_info->red_mult + green * colormap_info->green_mult +
166 blue * colormap_info->blue_mult + colormap_info->base_pixel;
168 switch (xi->bits_per_pixel) {
169 case 8: *current_pixel = (char)(destpixel & 0xFF); break;
170 case 16: *((u_int16_t*)current_pixel) = (u_int16_t)destpixel; break;
172 int offset = (int)current_pixel & 0x3;
173 u_int64_t dest = ((u_int64_t)destpixel) << (8 * offset);
174 u_int64_t mask = ((u_int64_t)0xffffff) << (8 * offset);
175 u_int64_t* base = (u_int64_t*)(current_pixel - offset);
176 *base = (*base & ~mask) | dest;
179 case 32: *((u_int32_t*)current_pixel) = destpixel; break;
180 default: org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: bpp not a multiple of 8!"));
186 // do nothing, we wrote directly to video memory
188 } else if (shm_supported) {
189 XShmPutImage(display, (*((Pixmap*)pm)), (*((GC*)gc)), xi, 0, 0, dx1, dy1, dx2 - dx1, dy2 - dy1, False);
193 XPutImage(display, (*((Pixmap*)pm)), (*((GC*)gc)), xi, 0, 0, dx1, dy1, dx2 - dx1, dy2 - dy1);
198 void org::xwt::plat::POSIX$X11DoubleBuffer::finalize() {
200 XShmSegmentInfo *sinfo = (XShmSegmentInfo*)shm_segment;
201 XShmDetach(display, sinfo);
202 shmdt(sinfo->shmaddr);
203 shmctl(sinfo->shmid, IPC_RMID, 0);
204 XDestroyImage((XImage*)fake_ximage);
208 XFreePixmap(display, *((Pixmap*)stipple));
211 XFreePixmap(display, *((Pixmap*)pm));
212 XFreeGC(display, *((GC*)gc));
213 XFreeGC(display, *((GC*)clipped_gc));
216 void org::xwt::plat::POSIX$X11DoubleBuffer::natInit() {
218 if (width == 0 || height == 0) return;
219 shared_pixmap &= shm_supported & shm_pixmaps_supported; // refuse to use shared pixmaps if we don't have shm
220 pm = (gnu::gcj::RawData*)malloc(sizeof(Pixmap));
223 (*((Pixmap*)pm)) = XCreatePixmap(display, RootWindow(display, screen_num), width, height, colorDepth);
225 XShmSegmentInfo *sinfo = (XShmSegmentInfo*)malloc(sizeof(XShmSegmentInfo));
226 shm_segment = (gnu::gcj::RawData*)sinfo;
227 ((XImage*)fake_ximage) = XShmCreateImage(display, visual, colorDepth, ZPixmap, NULL, sinfo, width, height);
228 sinfo->shmid = shmget(IPC_PRIVATE, ((XImage*)fake_ximage)->bytes_per_line * height, IPC_CREAT | 0777 | IPC_EXCL);
229 ((XImage*)fake_ximage)->data = sinfo->shmaddr = (char*)shmat(sinfo->shmid, 0, 0);
230 sinfo->readOnly = False;
231 XShmAttach(display, sinfo);
232 XSync(display, False);
233 shmctl(sinfo->shmid, IPC_RMID, 0);
234 (*((Pixmap*)pm)) = XShmCreatePixmap(display, RootWindow(display, screen_num), sinfo->shmaddr, sinfo, width, height, colorDepth);
235 XSync(display, False);
238 gc = (gnu::gcj::RawData*)malloc(sizeof(GC));
239 clipped_gc = (gnu::gcj::RawData*)malloc(sizeof(GC));
240 (*((GC*)gc)) = XCreateGC(display, (*((Pixmap*)pm)), 0, 0);
241 (*((GC*)clipped_gc)) = XCreateGC(display, (*((Pixmap*)pm)), 0, 0);
244 vm.graphics_exposures = 0;
245 XChangeGC(display, (*((GC*)gc)), GCGraphicsExposures, &vm);
246 XChangeGC(display, (*((GC*)clipped_gc)), GCGraphicsExposures, &vm);
249 void org::xwt::plat::POSIX$X11DoubleBuffer::createStipple(org::xwt::plat::POSIX$X11Picture* xpi) {
251 stipple = (gnu::gcj::RawData*)malloc(sizeof(Pixmap));
252 (*((Pixmap*)stipple)) = XCreatePixmap(display, RootWindow(display, screen_num), width, height, 1);
255 xi.data = (char*)malloc((width + 1) * height);
262 xi.byte_order = LSBFirst;
264 xi.bytes_per_line = (width / 8) + 1;
265 xi.bits_per_pixel = 1;
267 jint* d = (jint*)elements(xpi->data);
268 memset(xi.data, 0xFF, (width + 1) * height);
269 for(int x=0; x<width; x++)
270 for (int y=0; y<height; y++)
271 xi.data[y * xi.bytes_per_line + (x/8)] &= ~(((d[x + y * width] & 0xFF000000) != 0 ? 0 : 1) << (x % 8));
273 GC stipple_gc = XCreateGC(display, (*((Pixmap*)stipple)), 0, 0);
276 vm.graphics_exposures = 0;
277 XChangeGC(display, stipple_gc, GCGraphicsExposures, &vm);
279 XPutImage(display, (*((Pixmap*)stipple)), stipple_gc, &xi, 0, 0, 0, 0, width, height);
282 void org::xwt::plat::POSIX$X11Surface::blit(org::xwt::DoubleBuffer* db, jint sx, jint sy, jint dx, jint dy, jint dx2, jint dy2) {
283 org::xwt::plat::POSIX$X11DoubleBuffer *xdb = (org::xwt::plat::POSIX$X11DoubleBuffer*)db;
284 XCopyArea(display, *((Pixmap*)xdb->pm), *((Window*)window), *((GC*)gc), sx, sy, dx2 - dx, dy2 - dy, dx, dy);
288 void org::xwt::plat::POSIX$X11DoubleBuffer::fillRect (jint x, jint y, jint x2, jint y2, jint argb) {
293 if (x < clipx) { w -= (clipx - x); x = clipx; }
294 if (y < clipy) { h -= (clipy - y); y = clipy; }
295 if (x + w > clipx + clipw) w = (clipx + clipw - x);
296 if (y + h > clipy + cliph) h = (cliph + clipy - y);
298 XSetForeground(display, (*((GC*)gc)),
299 ((((argb & 0x00FF0000) >> 16) * colormap_info->red_max) / 0xFF) * colormap_info->red_mult +
300 ((((argb & 0x0000FF00) >> 8) * colormap_info->green_max) / 0xFF) * colormap_info->green_mult +
301 ((((argb & 0x000000FF)) * colormap_info->blue_max) / 0xFF) * colormap_info->blue_mult +
302 colormap_info->base_pixel
305 XFillRectangle(display, (*((Pixmap*)pm)), (*((GC*)gc)), x, y, w, h);
308 void org::xwt::plat::POSIX$X11DoubleBuffer::drawString(::java::lang::String* font, ::java::lang::String* text, jint x, jint y, jint argb) {
311 rect.x = clipx, rect.y = clipy; rect.width = clipw; rect.height = cliph;
312 XSetClipMask(display, (*((GC*)clipped_gc)), None);
313 XSetClipRectangles(display, (*((GC*)clipped_gc)), 0, 0, &rect, 1, YSorted);
314 XSetForeground(display, (*((GC*)clipped_gc)),
315 ((((argb & 0x00FF0000) >> 16) * colormap_info->red_max) / 0xFF) * colormap_info->red_mult +
316 ((((argb & 0x0000FF00) >> 8) * colormap_info->green_max) / 0xFF) * colormap_info->green_mult +
317 ((((argb & 0x000000FF)) * colormap_info->blue_max) / 0xFF) * colormap_info->blue_mult +
318 colormap_info->base_pixel
322 int len = min(1024, JvGetStringUTFLength(text));
324 JvGetStringUTFRegion(text, 0, len, buf);
327 // Build the XTextItem structure
329 textitem.chars = buf;
330 textitem.nchars = len;
332 textitem.font = ((XFontStruct*)org::xwt::plat::POSIX::fontToXFont(font))->fid;
335 XDrawText(display, (*((Pixmap*)pm)), (*((GC*)clipped_gc)), x, y, &textitem, 1);
339 // X11Surface //////////////////////////////////////////////////////////////////////
341 void org::xwt::plat::POSIX$X11Surface::setIcon(org::xwt::Picture* pic) {
342 org::xwt::plat::POSIX$X11Picture* p = ((org::xwt::plat::POSIX$X11Picture*)pic);
343 org::xwt::plat::POSIX$X11DoubleBuffer* old_dbuf = p->doublebuf;
344 p->buildDoubleBuffer(1);
346 memset(&xwmh, 0, sizeof(XWMHints));
347 xwmh.flags |= IconPixmapHint | IconMaskHint;
348 xwmh.icon_pixmap = *((Pixmap*)p->doublebuf->pm);
349 xwmh.icon_mask = *((Pixmap*)p->doublebuf->stipple);
350 XSetWMHints(display, (*((Window*)window)), &xwmh);
351 p->doublebuf = old_dbuf;
354 void org::xwt::plat::POSIX$X11Surface::setTitleBarText(java::lang::String* s) {
355 int len = min(JvGetStringUTFLength(s), 1024);
357 JvGetStringUTFRegion(s, 0, len, buf);
361 tp.value = (unsigned char*)buf;
363 tp.encoding = XA_STRING;
365 XSetTextProperty(display, (*((Window*)window)), &tp, XA_WM_NAME);
366 XSetTextProperty(display, (*((Window*)window)), &tp, XA_WM_ICON_NAME);
369 void org::xwt::plat::POSIX$X11Surface::setLimits(jint minw, jint minh, jint maxw, jint maxh) {
371 hints.min_width = minw;
372 hints.min_height = minh;
373 hints.max_width = maxw;
374 hints.max_height = maxh;
375 hints.flags = PMinSize | PMaxSize;
376 XSetWMNormalHints(display, (*((Window*)window)), &hints);
379 void org::xwt::plat::POSIX$X11Surface::setSize (jint width, jint height) {
380 if (width <= 0 || height <= 0) return;
381 XResizeWindow(display, (*((Window*)window)), width, height);
385 void org::xwt::plat::POSIX$X11Surface::setLocation (jint x, jint y) { XMoveWindow(display, (*((Window*)window)), x, y); }
386 void org::xwt::plat::POSIX$X11Surface::toFront() { XRaiseWindow(display, (*((Window*)window))); }
387 void org::xwt::plat::POSIX$X11Surface::toBack() { XLowerWindow(display, (*((Window*)window))); }
389 void org::xwt::plat::POSIX$X11Surface::_dispose() {
390 // without this we get phantom messages after the window is gone
391 org::xwt::plat::POSIX::windowToSurfaceMap->remove(new java::lang::Long(*((Window*)window)));
392 XDestroyWindow(display, (*((Window*)window)));
395 void org::xwt::plat::POSIX$X11Surface::setInvisible(jboolean i) {
396 if (i) XUnmapWindow(display, (*((Window*)window)));
397 else XMapRaised(display, (*((Window*)window)));
401 void org::xwt::plat::POSIX$X11Surface::_setMinimized(jboolean b) {
402 if (b) XIconifyWindow(display, (*((Window*)window)), screen_num);
403 else XMapRaised(display, (*((Window*)window)));
407 void org::xwt::plat::POSIX$X11Surface::natInit() {
408 XSetWindowAttributes xswa;
409 window = (gnu::gcj::RawData*)malloc(sizeof(Window));
410 xswa.bit_gravity = NorthWestGravity;
411 xswa.colormap = s_colormap;
412 xswa.event_mask = ExposureMask | ButtonPressMask | StructureNotifyMask |
413 KeyPressMask | KeyReleaseMask | ButtonPressMask |
414 ButtonReleaseMask | EnterWindowMask | LeaveWindowMask |
415 PointerMotionMask | ButtonMotionMask | ConfigureNotify | FocusChangeMask;
416 *((Window*)window) = XCreateWindow(display, RootWindow(display, screen_num), 10, 10, 10, 10, 0,
417 colorDepth, InputOutput, CopyFromParent,
418 CWColormap | CWBitGravity | CWEventMask, &xswa);
421 // I don't know why this works....
422 int dat[5] = { 0x2, 0xbffff804, 0x0, 0x817f560, 0x8110694 };
423 XChangeProperty(display, (*((Window*)window)),
424 XInternAtom(display, "_MOTIF_WM_HINTS", False),
425 XInternAtom(display, "_MOTIF_WM_HINTS", False),
433 tp.value = (unsigned char*)"XWT";
435 tp.encoding = XA_STRING;
437 XSetTextProperty(display, (*((Window*)window)), &tp, XA_WM_CLASS);
439 Atom proto = XInternAtom(display, "WM_DELETE_WINDOW", False);
440 XSetWMProtocols(display, (*((Window*)window)), &proto, 1);
442 XSelectInput(display, (*((Window*)window)), StructureNotifyMask);
443 org::xwt::plat::POSIX::windowToSurfaceMap->put(new java::lang::Long(*((Window*)window)), this);
446 XMapRaised(display, (*((Window*)window)));
449 waitForCreation->block();
450 XSelectInput(display, (*((Window*)window)), xswa.event_mask);
453 gc = (gnu::gcj::RawData*)malloc(sizeof(GC));
454 *((GC*)gc) = XCreateGC(display, (*((Window*)window)), 0, 0);
457 vm.graphics_exposures = 0;
458 XChangeGC(display, *((GC*)gc), GCGraphicsExposures, &vm);
462 void org::xwt::plat::POSIX$X11Surface::dispatchEvent(gnu::gcj::RawData* ev) {
464 XEvent* e = (XEvent*)ev;
465 if (e->type == Expose) {
466 XExposeEvent *expose = (XExposeEvent*)(e);
467 Dirty(expose->x, expose->y, expose->width, expose->height);
469 } else if (e->type == ClientMessage) { if (((XClientMessageEvent*)(e))->data.l[0] == XInternAtom(display, "WM_DELETE_WINDOW", False)) Close();
470 } else if (e->type == MapNotify) { Minimized(0); waitForCreation->release();
471 } else if (e->type == UnmapNotify) { Minimized(1);
472 } else if (e->type == FocusIn) { Focused(1);
473 } else if (e->type == FocusOut) { Focused(0);
475 } else if (e->type == KeyPress || e->type == KeyRelease) {
476 XKeyEvent *xbe = (XKeyEvent*)(e);
478 // drop faked KeyRelease events generated by the X server's autorepeat
479 if (e->type == KeyRelease) {
481 XQueryKeymap(display, depressed);
482 if ((depressed[(xbe->keycode & 0xff) / 8] & (0x1 << (xbe->keycode % 8))) >> (xbe->keycode % 8)) return;
488 unsigned int savestate = xbe->state;
489 xbe->state = xbe->state & ShiftMask; // ignore everything except shiftmask
490 XLookupString(xbe, s, 20, NULL, NULL);
491 xbe->state = savestate;
493 if (s != NULL && s[0] != '\0' && s[1] == '\0' && s[0] >= 0x20 && s[0] <= 0x7E) {
497 KeySym ks = XKeycodeToKeysym(display, xbe->keycode, 0);
499 case XK_BackSpace: s = "back_space"; break;
500 case XK_Tab: s = "tab"; break;
501 case XK_Linefeed: s = "enter"; break;
502 case XK_Return: s = "enter"; break;
503 case XK_Scroll_Lock: s = "scroll_lock"; break;
504 case XK_Escape: s = "escape"; break;
505 case XK_Insert: s = "insert"; break;
506 case XK_Delete: s = "delete"; break;
507 case XK_Home: s = "home"; break;
508 case XK_Left: s = "left"; break;
509 case XK_Up: s = "up"; break;
510 case XK_Right: s = "right"; break;
511 case XK_Down: s = "down"; break;
512 case XK_Page_Up: s = "page_up"; break;
513 case XK_Page_Down: s = "page_down"; break;
514 case XK_End: s = "end"; break;
515 case XK_Num_Lock: s = "num_lock"; break;
516 case XK_KP_Tab: s = "tab"; break;
517 case XK_KP_Enter: s = "enter"; break;
518 case XK_KP_F1: s = "f1"; break;
519 case XK_KP_F2: s = "f2"; break;
520 case XK_KP_F3: s = "f3"; break;
521 case XK_KP_F4: s = "f4"; break;
522 case XK_KP_Home: s = "home"; break;
523 case XK_KP_Left: s = "left"; break;
524 case XK_KP_Up: s = "up"; break;
525 case XK_KP_Right: s = "right"; break;
526 case XK_KP_Down: s = "down"; break;
527 case XK_KP_Page_Up: s = "page_up"; break;
528 case XK_KP_Page_Down: s = "page_down"; break;
529 case XK_KP_End: s = "end"; break;
530 case XK_KP_Insert: s = "insert"; break;
531 case XK_KP_Delete: s = "delete"; break;
532 case XK_F1: s = "f1"; break;
533 case XK_F2: s = "f2"; break;
534 case XK_F3: s = "f3"; break;
535 case XK_F4: s = "f4"; break;
536 case XK_F5: s = "f5"; break;
537 case XK_F6: s = "f6"; break;
538 case XK_F7: s = "f7"; break;
539 case XK_F8: s = "f8"; break;
540 case XK_F9: s = "f9"; break;
541 case XK_F10: s = "f10"; break;
542 case XK_F11: s = "f11"; break;
543 case XK_F12: s = "f12"; break;
544 case XK_Shift_L: s = "shift"; break;
545 case XK_Shift_R: s = "shift"; break;
546 case XK_Control_L: s = "control"; break;
547 case XK_Control_R: s = "control"; break;
548 case XK_Meta_L: s = "alt"; break;
549 case XK_Meta_R: s = "alt"; break;
550 case XK_Alt_L: s = "alt"; break;
551 case XK_Alt_R: s = "alt"; break;
556 jstring s2 = JvNewStringLatin1(s);
557 if (e->type == KeyPress) KeyPressed((xbe->state & LockMask) ? s2->toUpperCase() : s2);
558 if (e->type == KeyRelease) KeyReleased(s2);
560 } else if (e->type == ButtonPress) {
561 XButtonEvent* xbe = (XButtonEvent*)(e);
562 if (xbe->button == 2) xbe->button = 3;
563 else if (xbe->button == 3) xbe->button = 2;
566 } else if (e->type == ButtonRelease) {
567 XButtonEvent* xbe = (XButtonEvent*)(e);
568 if (xbe->button == 2) xbe->button = 3;
569 else if (xbe->button == 3) xbe->button = 2;
570 Release(xbe->button);
572 } else if (e->type == MotionNotify) {
573 XMotionEvent* xme = (XMotionEvent*)(e);
574 Move(xme->x, xme->y);
576 } else if (e->type == EnterNotify || e->type == LeaveNotify) {
577 XCrossingEvent* xce = (XCrossingEvent*)(e);
578 Move(xce->x, xce->y);
580 } else if (e->type == ConfigureNotify) {
583 XConfigureEvent* xce = (XConfigureEvent*)(e);
584 XTranslateCoordinates(display, (*((Window*)window)), RootWindow(display, screen_num), 0, 0, &x_out, &y_out, &child);
585 if (xce->width != width || xce->height != height) SizeChange(xce->width, xce->height);
586 if (x_out != root->abs(0) || y_out != root->abs(1)) PosChange(x_out, y_out);
591 static jstring crosshair, east, hand, move, north, northeast, northwest,
592 south, southeast, southwest, text, west, wait_string;
593 static Cursor crosshair_cursor, east_cursor, hand_cursor, move_cursor, north_cursor,
594 northeast_cursor, northwest_cursor, south_cursor, southeast_cursor,
595 southwest_cursor, text_cursor, west_cursor, wait_cursor, default_cursor;
597 void org::xwt::plat::POSIX$X11Surface::syncCursor() {
600 if (cursor->equals(crosshair)) curs = crosshair_cursor;
601 else if (cursor->equals(east)) curs = east_cursor;
602 else if (cursor->equals(hand)) curs = hand_cursor;
603 else if (cursor->equals(move)) curs = move_cursor;
604 else if (cursor->equals(north)) curs = north_cursor;
605 else if (cursor->equals(northeast)) curs = northeast_cursor;
606 else if (cursor->equals(northwest)) curs = northwest_cursor;
607 else if (cursor->equals(south)) curs = south_cursor;
608 else if (cursor->equals(southeast)) curs = southeast_cursor;
609 else if (cursor->equals(southwest)) curs = southwest_cursor;
610 else if (cursor->equals(text)) curs = text_cursor;
611 else if (cursor->equals(west)) curs = west_cursor;
612 else if (cursor->equals(wait_string)) curs = wait_cursor;
613 else curs = default_cursor;
615 XDefineCursor(display, (*((Window*)window)), curs);
620 // POSIX ///////////////////////////////////////////////////////////////////
622 jint org::xwt::plat::POSIX::_getScreenWidth() { return WidthOfScreen(DefaultScreenOfDisplay(display)); }
623 jint org::xwt::plat::POSIX::_getScreenHeight() { return HeightOfScreen(DefaultScreenOfDisplay(display)); }
625 jstring org::xwt::plat::POSIX::_getEnv(jstring key) {
626 int len = JvGetStringUTFLength(key);
628 JvGetStringUTFRegion(key, 0, len, buf);
630 char* envstr = getenv(buf);
631 return envstr == NULL ? NULL : JvNewStringLatin1(envstr);
634 void org::xwt::plat::POSIX::spawnChildProcess(JArray<jstring>* cmd) {
635 jstring* cmdstrings = elements(cmd);
636 char* cmd2[cmd->length + 1];
637 cmd2[cmd->length] = NULL;
638 for(int i=0; i<cmd->length; i++) {
639 cmd2[i] = (char*)malloc(JvGetStringUTFLength(cmdstrings[i]));
640 JvGetStringUTFRegion(cmdstrings[i], 0, JvGetStringUTFLength(cmdstrings[i]), cmd2[i]);
644 signal(SIGHUP, SIG_IGN);
645 signal(SIGQUIT, SIG_IGN);
646 signal(SIGINT, SIG_IGN);
647 signal(SIGTERM, SIG_IGN);
649 // ignore SIGPIPE in case we were launched from a browser and the browser closed
650 signal(SIGPIPE, SIG_IGN);
652 execvp(cmd2[0], cmd2);
656 static void dispatchSelectionEvent(XEvent* e) {
657 if (e->type == SelectionNotify) {
658 XSelectionEvent* xsn = (XSelectionEvent*)(e);
659 if (xsn->property == None) org::xwt::plat::POSIX::clipboard = JvNewStringLatin1("", 0);
663 unsigned long numitems;
665 unsigned long bytes_after;
666 XGetWindowProperty(display, xsn->requestor, xsn->property, 0, 4096,
667 True, AnyPropertyType, &returntype, &returnformat,
668 &numitems, &bytes_after, &ret);
669 org::xwt::plat::POSIX::clipboard =
670 (returntype == None ? JvNewStringLatin1("", 0) : JvNewStringLatin1((char*)ret, strlen((char*)ret)));
672 org::xwt::plat::POSIX::waiting_for_selection_event->release();
674 } else if (e->type == SelectionRequest) {
675 XSelectionRequestEvent* xsr = (XSelectionRequestEvent*)(e);
677 xsn.type = SelectionNotify;
678 xsn.serial = xsr->serial;
679 xsn.send_event = True;
680 xsn.display = display;
681 xsn.requestor = xsr->requestor;
682 xsn.selection = xsr->selection;
683 xsn.target = xsr->target;
684 xsn.property = xsr->property;
685 xsn.time = xsr->time;
687 int len = min(1024, JvGetStringUTFLength(org::xwt::plat::POSIX::clipboard));
689 JvGetStringUTFRegion(org::xwt::plat::POSIX::clipboard, 0, len, buf);
692 XChangeProperty(display, xsr->requestor, xsr->property, xsr->target, 8, PropModeReplace, (unsigned char*)buf, len + 1);
693 XSendEvent(display, xsr->requestor, True, 0, (XEvent*)(&xsn));
697 void org::xwt::plat::POSIX::eventThread() {
700 XNextEvent(display, &e);
701 if (e.type == SelectionNotify || e.type == SelectionRequest) {
702 dispatchSelectionEvent(&e);
704 org::xwt::plat::POSIX$X11Surface* surface =
705 (org::xwt::plat::POSIX$X11Surface*)windowToSurfaceMap->get(new java::lang::Long(((XAnyEvent*)&e)->window));
706 if (surface != NULL) surface->dispatchEvent((gnu::gcj::RawData*)&e);
711 jstring org::xwt::plat::POSIX::_getClipBoard() {
712 XConvertSelection(display, XA_PRIMARY, XA_STRING, XInternAtom(display, "VT_SELECTION", False), selectionWindow, CurrentTime);
714 org::xwt::plat::POSIX::waiting_for_selection_event->block();
718 void org::xwt::plat::POSIX::_setClipBoard(jstring s) {
720 int len = JvGetStringUTFLength(clipboard);
722 JvGetStringUTFRegion(clipboard, 0, len, buf);
724 XSetSelectionOwner(display, XInternAtom(display, "PRIMARY", 0), selectionWindow, CurrentTime);
727 typedef int (X11ErrorHandler)(Display*, XErrorEvent*);
728 int errorHandler(Display* d, XErrorEvent* e) {
729 // this error handler is only installed during the initial
730 // test to see if shm is present
734 void org::xwt::plat::POSIX::natInit() {
737 org::xwt::Platform::criticalAbort(JvNewStringLatin1("Your X11 libraries do not support multithreaded programs"));
739 display = XOpenDisplay(NULL);
740 screen_num = XDefaultScreen(display);
741 colorDepth = (jint)(DefaultDepth(((Display*)display), 0));
742 shm_info.shmaddr = NULL;
744 shm_supported = (XShmQueryExtension(display) == True);
746 X11ErrorHandler* oldHandler = XSetErrorHandler(errorHandler);
747 XShmSegmentInfo sinfo;
748 sinfo.shmid = shmget(IPC_PRIVATE, 1, IPC_CREAT | 0777 | IPC_EXCL);
749 sinfo.readOnly = False;
750 // if the server is remote, this will trigger the error handler
751 XShmAttach(display, &sinfo);
752 XSync(display, False);
753 XSetErrorHandler(oldHandler);
757 shm_pixmaps_supported = (XShmPixmapFormat(display) == ZPixmap);
759 crosshair = JvNewStringLatin1("crosshair");
760 east = JvNewStringLatin1("east");
761 hand = JvNewStringLatin1("hand");
762 move = JvNewStringLatin1("move");
763 north = JvNewStringLatin1("north");
764 northeast = JvNewStringLatin1("northeast");
765 northwest = JvNewStringLatin1("northwest");
766 south = JvNewStringLatin1("south");
767 southeast = JvNewStringLatin1("southeast");
768 southwest = JvNewStringLatin1("southwest");
769 text = JvNewStringLatin1("text");
770 west = JvNewStringLatin1("west");
771 wait_string = JvNewStringLatin1("wait");
772 crosshair_cursor = XCreateFontCursor(display, XC_tcross);
773 east_cursor = XCreateFontCursor(display, XC_right_side);
774 hand_cursor = XCreateFontCursor(display, XC_hand2);
775 move_cursor = XCreateFontCursor(display, XC_fleur);
776 north_cursor = XCreateFontCursor(display, XC_top_side);
777 northeast_cursor = XCreateFontCursor(display, XC_top_right_corner);
778 northwest_cursor = XCreateFontCursor(display, XC_left_side);
779 south_cursor = XCreateFontCursor(display, XC_bottom_side);
780 southeast_cursor = XCreateFontCursor(display, XC_bottom_right_corner);
781 southwest_cursor = XCreateFontCursor(display, XC_bottom_left_corner);
782 text_cursor = XCreateFontCursor(display, XC_xterm);
783 west_cursor = XCreateFontCursor(display, XC_right_side);
784 wait_cursor = XCreateFontCursor(display, XC_watch);
785 default_cursor = XCreateFontCursor(display, XC_left_ptr);
787 selectionWindow = XCreateWindow(display, RootWindow(display, screen_num), 0, 0, 1, 1, 0, colorDepth, InputOutput, CopyFromParent, 0, NULL);
788 visual = DefaultVisual(display, screen_num);
790 sprintf(buf, "X11 DISPLAY: %s", XDisplayString(display));
791 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
792 sprintf(buf, "X11 SHM: %s", shm_supported ? "enabled" : "disabled");
793 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
794 sprintf(buf, "X11 Visual: %x %x %x bits: %i visualid: %i depth: %i",
795 visual->red_mask, visual->green_mask, visual->blue_mask, visual->bits_per_rgb, visual->visualid, colorDepth);
796 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
798 // FIXME: don't know why (True, False) is the best solution...
799 if(XmuLookupStandardColormap(display, screen_num, visual->visualid, colorDepth, XA_RGB_BEST_MAP, True, False) == 0)
800 org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: XmuLookupStandardColormap failed"));
802 XStandardColormap* best_map_info = NULL;
804 if (XGetRGBColormaps(display, RootWindow(display, screen_num), &best_map_info, &count, XA_RGB_BEST_MAP) == 0)
805 org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: couldn't allocate a standard colormap"));
806 if (!best_map_info->colormap)
807 org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: XmuLookupStandardColomap succeded, but no colormap was found on the root window"));
808 if (best_map_info->red_max == 0)
809 org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: standard colormap exists, but was improperly allocated"));
810 s_colormap = best_map_info->colormap;
811 colormap_info = best_map_info;
813 sprintf(buf, " red_max / red_mult: %x %x", colormap_info->red_max, colormap_info->red_mult);
814 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
815 sprintf(buf, " green_max / green_mult: %x %x", colormap_info->green_max, colormap_info->green_mult);
816 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
817 sprintf(buf, " blue_max / blue_mult: %x %x", colormap_info->blue_max, colormap_info->blue_mult);
818 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
819 sprintf(buf, " base_pixel: %x", colormap_info->base_pixel);
820 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
823 JArray<java::lang::String*>* org::xwt::plat::POSIX::listNativeFonts() {
825 char** xfonts = XListFonts(display, "-*-*-*-*-normal-*-*-*-*-*-*-*-*-*", 0xFFFFFFFF, &numfonts);
826 JArray<java::lang::String*>* fonts = (JArray<java::lang::String*>*)JvNewObjectArray(numfonts, &(::java::lang::String::class$), NULL);
827 java::lang::String** jfonts = (java::lang::String**)(elements(fonts));
828 for(int i=0; i<numfonts; i++)
829 jfonts[i] = JvNewStringLatin1(xfonts[i], strlen(xfonts[i]));
833 gnu::gcj::RawData* org::xwt::plat::POSIX::fontStringToStruct(jstring s) {
834 int len = min(1024, JvGetStringUTFLength(s));
836 JvGetStringUTFRegion(s, 0, len, buf);
838 return (gnu::gcj::RawData*)XLoadQueryFont(display, buf);
841 jint org::xwt::plat::POSIX::_getMaxAscent(::java::lang::String* font) { return ((XFontStruct*)fontToXFont(font))->max_bounds.ascent; }
842 jint org::xwt::plat::POSIX::_getMaxDescent(::java::lang::String* font) { return ((XFontStruct*)fontToXFont(font))->max_bounds.descent; }
843 jint org::xwt::plat::POSIX::_stringWidth(::java::lang::String* font, ::java::lang::String* text) {
844 if (text == NULL) return 0;
845 int len = JvGetStringUTFLength(text);
847 JvGetStringUTFRegion(text, 0, len, buf);
849 return XTextWidth((XFontStruct*)fontToXFont(font), buf, len);
853 //////////////////////////////////////////////////////////////////////////////
854 //////////////////////////////////////////////////////////////////////////////
855 //////////////////////////////////////////////////////////////////////////////
856 //////////////////////////////////////////////////////////////////////////////
858 // Everything below this point was taken, cut-and-paste, from the //
859 // source for libXmu. It implements the official 'standard colormap //
860 // creation algorithm. I made some small changes to //
861 // XmuDeleteStandardColormap //
863 //////////////////////////////////////////////////////////////////////////////
864 //////////////////////////////////////////////////////////////////////////////
865 //////////////////////////////////////////////////////////////////////////////
866 //////////////////////////////////////////////////////////////////////////////
868 /* $Xorg: LookupCmap.c,v 1.4 2001/02/09 02:03:53 xorgcvs Exp $ */
872 Copyright 1989, 1998 The Open Group
874 Permission to use, copy, modify, distribute, and sell this software and its
875 documentation for any purpose is hereby granted without fee, provided that
876 the above copyright notice appear in all copies and that both that
877 copyright notice and this permission notice appear in supporting
880 The above copyright notice and this permission notice shall be included in
881 all copies or substantial portions of the Software.
883 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
884 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
885 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
886 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
887 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
888 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
890 Except as contained in this notice, the name of The Open Group shall not be
891 used in advertising or otherwise to promote the sale, use or other dealings
892 in this Software without prior written authorization from The Open Group.
895 /* $XFree86: xc/lib/Xmu/LookupCmap.c,v 1.8 2001/12/14 19:55:47 dawes Exp $ */
898 * Author: Donna Converse, MIT X Consortium
902 #include <X11/Xlib.h>
903 #include <X11/Xatom.h>
904 #include <X11/Xutil.h>
905 #include <X11/Xmu/StdCmap.h>
911 static Status lookup(Display*, int, VisualID, Atom, XStandardColormap*, Bool);
914 * To create a standard colormap if one does not currently exist, or
915 * replace the currently existing standard colormap, use
916 * XmuLookupStandardColormap().
918 * Given a screen, a visual, and a property, XmuLookupStandardColormap()
919 * will determine the best allocation for the property under the specified
920 * visual, and determine the whether to create a new colormap or to use
921 * the default colormap of the screen. It will call XmuStandardColormap()
922 * to create the standard colormap.
924 * If replace is true, any previous definition of the property will be
925 * replaced. If retain is true, the property and the colormap will be
926 * made permanent for the duration of the server session. However,
927 * pre-existing property definitions which are not replaced cannot be made
928 * permanent by a call to XmuLookupStandardColormap(); a request to retain
929 * resources pertains to newly created resources.
931 * Returns 0 on failure, non-zero on success. A request to create a
932 * standard colormap upon a visual which cannot support such a map is
933 * considered a failure. An example of this would be requesting any
934 * standard colormap property on a monochrome visual, or, requesting an
935 * RGB_BEST_MAP on a display whose colormap size is 16.
939 XmuLookupStandardColormap(Display *dpy, int screen, VisualID visualid,
940 unsigned int depth, Atom property,
941 Bool replace, Bool retain)
943 * dpy - specifies X server connection
944 * screen - specifies screen of display
945 * visualid - specifies the visual type
946 * depth - specifies the visual type
947 * property - a standard colormap property
948 * replace - specifies whether to replace
949 * retain - specifies whether to retain
952 Display *odpy; /* original display connection */
953 XStandardColormap *colormap;
954 XVisualInfo vinfo_template, *vinfo; /* visual */
956 unsigned long r_max, g_max, b_max; /* allocation */
958 Colormap cmap; /* colormap ID */
962 /* Match the requested visual */
964 vinfo_template.visualid = visualid;
965 vinfo_template.screen = screen;
966 vinfo_template.depth = depth;
967 vinfo_mask = VisualIDMask | VisualScreenMask | VisualDepthMask;
968 if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &count)) ==
972 /* Monochrome visuals have no standard maps */
974 if (vinfo->colormap_size <= 2) {
975 XFree((char *) vinfo);
979 /* If the requested property already exists on this screen, and,
980 * if the replace flag has not been set to true, return success.
981 * lookup() will remove a pre-existing map if replace is true.
984 if (lookup(dpy, screen, visualid, property, (XStandardColormap *) NULL,
985 replace) && !replace) {
986 XFree((char *) vinfo);
990 /* Determine the best allocation for this property under the requested
991 * visualid and depth, and determine whether or not to use the default
992 * colormap of the screen.
995 if (!XmuGetColormapAllocation(vinfo, property, &r_max, &g_max, &b_max)) {
996 XFree((char *) vinfo);
1000 cmap = (property == XA_RGB_DEFAULT_MAP &&
1001 visualid == XVisualIDFromVisual(DefaultVisual(dpy, screen)))
1002 ? DefaultColormap(dpy, screen) : None;
1004 /* If retaining resources, open a new connection to the same server */
1008 if ((dpy = XOpenDisplay(XDisplayString(odpy))) == NULL) {
1009 XFree((char *) vinfo);
1014 /* Create the standard colormap */
1016 colormap = XmuStandardColormap(dpy, screen, visualid, depth, property,
1017 cmap, r_max, g_max, b_max);
1019 /* Set the standard colormap property */
1024 if (lookup(dpy, screen, visualid, property, colormap, replace) &&
1026 /* Someone has defined the property since we last looked.
1027 * Since we will not replace it, release our own resources.
1028 * If this is the default map, our allocations will be freed
1029 * when this connection closes.
1031 if (colormap->killid == ReleaseByFreeingColormap)
1032 XFreeColormap(dpy, colormap->colormap);
1033 } else if (retain) {
1034 XSetCloseDownMode(dpy, RetainPermanent);
1037 XFree((char *) colormap);
1043 XFree((char *) vinfo);
1047 /***************************************************************************/
1049 /* Lookup a standard colormap property. If the property is RGB_DEFAULT_MAP,
1050 * the visualid is used to determine whether the indicated standard colormap
1051 * exists. If the map exists and replace is true, delete the resources used
1052 * by the map and remove the property. Return true if the map exists,
1053 * or did exist and was deleted; return false if the map was not found.
1055 * Note that this is not the way that a Status return is normally used.
1057 * If new is not NULL, new points to an XStandardColormap structure which
1058 * describes a standard colormap of the specified property. It will be made
1059 * a standard colormap of the screen if none already exists, or if replace
1064 lookup(Display *dpy, int screen, VisualID visualid, Atom property,
1065 XStandardColormap *cnew, Bool replace)
1067 * dpy - specifies display connection
1068 * screen - specifies screen number
1069 * visualid - specifies visualid for std map
1070 * property - specifies colormap property name
1071 * cnew - specifies a standard colormap
1072 * replace - specifies whether to replace
1077 XStandardColormap *stdcmaps, *s;
1078 Window win = RootWindow(dpy, screen);
1080 /* The property does not already exist */
1082 if (! XGetRGBColormaps(dpy, win, &stdcmaps, &count, property)) {
1084 XSetRGBColormaps(dpy, win, cnew, 1, property);
1088 /* The property exists and is not describing the RGB_DEFAULT_MAP */
1090 if (property != XA_RGB_DEFAULT_MAP) {
1092 XmuDeleteStandardColormap(dpy, screen, property);
1094 XSetRGBColormaps(dpy, win, cnew, 1, property);
1096 XFree((char *)stdcmaps);
1100 /* The property exists and is RGB_DEFAULT_MAP */
1102 for (i=0, s=stdcmaps; (i < count) && (s->visualid != visualid); i++, s++)
1105 /* No RGB_DEFAULT_MAP property matches the given visualid */
1109 XStandardColormap *m, *maps;
1111 s = (XStandardColormap *) malloc((unsigned) ((count+1) * sizeof
1112 (XStandardColormap)));
1114 for (i = 0, m = s, maps = stdcmaps; i < count; i++, m++, maps++) {
1115 m->colormap = maps->colormap;
1116 m->red_max = maps->red_max;
1117 m->red_mult = maps->red_mult;
1118 m->green_max = maps->green_max;
1119 m->green_mult = maps->green_mult;
1120 m->blue_max = maps->blue_max;
1121 m->blue_mult = maps->blue_mult;
1122 m->base_pixel = maps->base_pixel;
1123 m->visualid = maps->visualid;
1124 m->killid = maps->killid;
1126 m->colormap = cnew->colormap;
1127 m->red_max = cnew->red_max;
1128 m->red_mult = cnew->red_mult;
1129 m->green_max = cnew->green_max;
1130 m->green_mult = cnew->green_mult;
1131 m->blue_max = cnew->blue_max;
1132 m->blue_mult = cnew->blue_mult;
1133 m->base_pixel = cnew->base_pixel;
1134 m->visualid = cnew->visualid;
1135 m->killid = cnew->killid;
1137 XSetRGBColormaps(dpy, win, s, ++count, property);
1140 XFree((char *) stdcmaps);
1144 /* Found an RGB_DEFAULT_MAP property with a matching visualid */
1147 /* Free old resources first - we may need them, particularly in
1148 * the default colormap of the screen. However, because of this,
1149 * it is possible that we will destroy the old resource and fail
1150 * to create a new one if XmuStandardColormap() fails.
1154 XmuDeleteStandardColormap(dpy, screen, property);
1156 XSetRGBColormaps(dpy, win, cnew, 1, property);
1159 XStandardColormap *map;
1161 /* s still points to the matching standard colormap */
1163 if (s->killid == ReleaseByFreeingColormap) {
1164 if ((s->colormap != None) &&
1165 (s->colormap != DefaultColormap(dpy, screen)))
1166 XFreeColormap(dpy, s->colormap);
1168 else if (s->killid != None)
1169 XKillClient(dpy, s->killid);
1171 map = (cnew) ? cnew : stdcmaps + --count;
1173 s->colormap = map->colormap;
1174 s->red_max = map->red_max;
1175 s->red_mult = map->red_mult;
1176 s->green_max = map->green_max;
1177 s->green_mult = map->green_mult;
1178 s->blue_max = map->blue_max;
1179 s->blue_mult = map->blue_mult;
1180 s->visualid = map->visualid;
1181 s->killid = map->killid;
1183 XSetRGBColormaps(dpy, win, stdcmaps, count, property);
1186 XFree((char *) stdcmaps);
1190 /* $Xorg: CmapAlloc.c,v 1.4 2001/02/09 02:03:51 xorgcvs Exp $ */
1194 Copyright 1989, 1994, 1998 The Open Group
1196 Permission to use, copy, modify, distribute, and sell this software and its
1197 documentation for any purpose is hereby granted without fee, provided that
1198 the above copyright notice appear in all copies and that both that
1199 copyright notice and this permission notice appear in supporting
1202 The above copyright notice and this permission notice shall be included in
1203 all copies or substantial portions of the Software.
1205 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1206 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1207 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1208 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1209 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1210 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1212 Except as contained in this notice, the name of The Open Group shall not be
1213 used in advertising or otherwise to promote the sale, use or other dealings
1214 in this Software without prior written authorization from The Open Group.
1217 /* $XFree86: xc/lib/Xmu/CmapAlloc.c,v 1.7 2001/12/14 19:55:35 dawes Exp $ */
1220 * Author: Donna Converse, MIT X Consortium
1223 #include <X11/Xlib.h>
1224 #include <X11/Xatom.h>
1225 #include <X11/Xutil.h>
1226 #include <X11/Xmu/StdCmap.h>
1229 #define lowbit(x) ((x) & (~(x) + 1))
1234 static void best_allocation(XVisualInfo*, unsigned long*, unsigned long*,
1236 static int default_allocation(XVisualInfo*, unsigned long*,
1237 unsigned long*, unsigned long*);
1238 static void gray_allocation(int, unsigned long*, unsigned long*,
1240 static int icbrt(int);
1241 static int icbrt_with_bits(int, int);
1242 static int icbrt_with_guess(int, int);
1244 /* To determine the best allocation of reds, greens, and blues in a
1245 * standard colormap, use XmuGetColormapAllocation.
1246 * vinfo specifies visual information for a chosen visual
1247 * property specifies one of the standard colormap property names
1248 * red_max returns maximum red value
1249 * green_max returns maximum green value
1250 * blue_max returns maximum blue value
1252 * XmuGetColormapAllocation returns 0 on failure, non-zero on success.
1253 * It is assumed that the visual is appropriate for the colormap property.
1257 XmuGetColormapAllocation(XVisualInfo *vinfo, Atom property,
1258 unsigned long *red_max,
1259 unsigned long *green_max,
1260 unsigned long *blue_max)
1264 if (vinfo->colormap_size <= 2)
1269 case XA_RGB_DEFAULT_MAP:
1270 status = default_allocation(vinfo, red_max, green_max, blue_max);
1272 case XA_RGB_BEST_MAP:
1273 best_allocation(vinfo, red_max, green_max, blue_max);
1275 case XA_RGB_GRAY_MAP:
1276 gray_allocation(vinfo->colormap_size, red_max, green_max, blue_max);
1278 case XA_RGB_RED_MAP:
1279 *red_max = vinfo->colormap_size - 1;
1280 *green_max = *blue_max = 0;
1282 case XA_RGB_GREEN_MAP:
1283 *green_max = vinfo->colormap_size - 1;
1284 *red_max = *blue_max = 0;
1286 case XA_RGB_BLUE_MAP:
1287 *blue_max = vinfo->colormap_size - 1;
1288 *red_max = *green_max = 0;
1296 /****************************************************************************/
1297 /* Determine the appropriate color allocations of a gray scale.
1299 * Keith Packard, MIT X Consortium
1303 gray_allocation(int n, unsigned long *red_max, unsigned long *green_max,
1304 unsigned long *blue_max)
1306 *red_max = (n * 30) / 100;
1307 *green_max = (n * 59) / 100;
1308 *blue_max = (n * 11) / 100;
1309 *green_max += ((n - 1) - (*red_max + *green_max + *blue_max));
1312 /****************************************************************************/
1313 /* Determine an appropriate color allocation for the RGB_DEFAULT_MAP.
1314 * If a map has less than a minimum number of definable entries, we do not
1315 * produce an allocation for an RGB_DEFAULT_MAP.
1317 * For 16 planes, the default colormap will have 27 each RGB; for 12 planes,
1318 * 12 each. For 8 planes, let n = the number of colormap entries, which may
1319 * be 256 or 254. Then, maximum red value = floor(cube_root(n - 125)) - 1.
1320 * Maximum green and maximum blue values are identical to maximum red.
1321 * This leaves at least 125 cells which clients can allocate.
1323 * Return 0 if an allocation has been determined, non-zero otherwise.
1327 default_allocation(XVisualInfo *vinfo, unsigned long *red,
1328 unsigned long *green, unsigned long *blue)
1330 int ngrays; /* number of gray cells */
1332 switch (vinfo->c_class)
1336 if (vinfo->colormap_size > 65000)
1337 /* intended for displays with 16 planes */
1338 *red = *green = *blue = (unsigned long) 27;
1339 else if (vinfo->colormap_size > 4000)
1340 /* intended for displays with 12 planes */
1341 *red = *green = *blue = (unsigned long) 12;
1342 else if (vinfo->colormap_size < 250)
1345 /* intended for displays with 8 planes */
1346 *red = *green = *blue = (unsigned long)
1347 (icbrt(vinfo->colormap_size - 125) - 1);
1352 if (vinfo->colormap_size < 10)
1354 *red = *green = *blue = vinfo->colormap_size / 2 - 1;
1359 *red = vinfo->red_mask / lowbit(vinfo->red_mask);
1360 *green = vinfo->green_mask / lowbit(vinfo->green_mask);
1361 *blue = vinfo->blue_mask / lowbit(vinfo->blue_mask);
1366 if (vinfo->colormap_size > 65000)
1368 else if (vinfo->colormap_size > 4000)
1370 else if (vinfo->colormap_size < 250)
1374 gray_allocation(ngrays, red, green, blue);
1383 /****************************************************************************/
1384 /* Determine an appropriate color allocation for the RGB_BEST_MAP.
1386 * For a DirectColor or TrueColor visual, the allocation is determined
1387 * by the red_mask, green_mask, and blue_mask members of the visual info.
1389 * Otherwise, if the colormap size is an integral power of 2, determine
1390 * the allocation according to the number of bits given to each color,
1391 * with green getting more than red, and red more than blue, if there
1392 * are to be inequities in the distribution. If the colormap size is
1393 * not an integral power of 2, let n = the number of colormap entries.
1394 * Then maximum red value = floor(cube_root(n)) - 1;
1395 * maximum blue value = floor(cube_root(n)) - 1;
1396 * maximum green value = n / ((# red values) * (# blue values)) - 1;
1397 * Which, on a GPX, allows for 252 entries in the best map, out of 254
1398 * defineable colormap entries.
1402 best_allocation(XVisualInfo *vinfo, unsigned long *red, unsigned long *green,
1403 unsigned long *blue)
1406 if (vinfo->c_class == DirectColor || vinfo->c_class == TrueColor)
1408 *red = vinfo->red_mask;
1409 while ((*red & 01) == 0)
1411 *green = vinfo->green_mask;
1412 while ((*green & 01) == 0)
1414 *blue = vinfo->blue_mask;
1415 while ((*blue & 01) == 0)
1420 register int bits, n;
1422 /* Determine n such that n is the least integral power of 2 which is
1423 * greater than or equal to the number of entries in the colormap.
1427 while (vinfo->colormap_size > n)
1433 /* If the number of entries in the colormap is a power of 2, determine
1434 * the allocation by "dealing" the bits, first to green, then red, then
1435 * blue. If not, find the maximum integral red, green, and blue values
1436 * which, when multiplied together, do not exceed the number of
1440 if (n == vinfo->colormap_size)
1442 register int r, g, b;
1444 g = b + ((bits % 3) ? 1 : 0);
1445 r = b + (((bits % 3) == 2) ? 1 : 0);
1452 *red = icbrt_with_bits(vinfo->colormap_size, bits);
1454 *green = (vinfo->colormap_size / ((*red) * (*blue)));
1464 * integer cube roots by Newton's method
1466 * Stephen Gildea, MIT X Consortium, July 1991
1472 register int bits = 0;
1473 register unsigned n = a;
1480 return icbrt_with_bits(a, bits);
1485 icbrt_with_bits(int a, int bits)
1486 /* bits - log 2 of a */
1488 return icbrt_with_guess(a, a>>2*bits/3);
1491 #ifdef _X_ROOT_STATS
1492 int icbrt_loopcount;
1495 /* Newton's Method: x_n+1 = x_n - ( f(x_n) / f'(x_n) ) */
1497 /* for cube roots, x^3 - a = 0, x_new = x - 1/3 (x - a/x^2) */
1500 * Quick and dirty cube roots. Nothing fancy here, just Newton's method.
1501 * Only works for positive integers (since that's all we need).
1502 * We actually return floor(cbrt(a)) because that's what we need here, too.
1506 icbrt_with_guess(int a, int guess)
1510 #ifdef _X_ROOT_STATS
1511 icbrt_loopcount = 0;
1519 #ifdef _X_ROOT_STATS
1522 delta = (guess - a/(guess*guess))/3;
1524 printf("pass %d: guess=%d, delta=%d\n", icbrt_loopcount, guess, delta);
1527 } while (delta != 0);
1529 if (guess*guess*guess > a)
1536 /* $Xorg: StdCmap.c,v 1.4 2001/02/09 02:03:53 xorgcvs Exp $ */
1540 Copyright 1989, 1998 The Open Group
1542 Permission to use, copy, modify, distribute, and sell this software and its
1543 documentation for any purpose is hereby granted without fee, provided that
1544 the above copyright notice appear in all copies and that both that
1545 copyright notice and this permission notice appear in supporting
1548 The above copyright notice and this permission notice shall be included in
1549 all copies or substantial portions of the Software.
1551 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1552 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1553 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1554 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1555 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1556 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1558 Except as contained in this notice, the name of The Open Group shall not be
1559 used in advertising or otherwise to promote the sale, use or other dealings
1560 in this Software without prior written authorization from The Open Group.
1563 /* $XFree86: xc/lib/Xmu/StdCmap.c,v 1.6 2001/12/14 19:55:48 dawes Exp $ */
1566 * Author: Donna Converse, MIT X Consortium
1570 #include <X11/Xlib.h>
1571 #include <X11/Xatom.h>
1572 #include <X11/Xutil.h>
1573 #include <X11/Xmu/StdCmap.h>
1575 #define lowbit(x) ((x) & (~(x) + 1))
1580 /* argument restrictions */
1581 static Status valid_args(XVisualInfo*, unsigned long, unsigned long,
1582 unsigned long, Atom);
1585 * To create any one standard colormap, use XmuStandardColormap().
1587 * Create a standard colormap for the given screen, visualid, and visual
1588 * depth, with the given red, green, and blue maximum values, with the
1589 * given standard property name. Return a pointer to an XStandardColormap
1590 * structure which describes the newly created colormap, upon success.
1591 * Upon failure, return NULL.
1593 * XmuStandardColormap() calls XmuCreateColormap() to create the map.
1595 * Resources created by this function are not made permanent; that is the
1596 * caller's responsibility.
1600 XmuStandardColormap(Display *dpy, int screen, VisualID visualid,
1601 unsigned int depth, Atom property, Colormap cmap,
1602 unsigned long red_max, unsigned long green_max,
1603 unsigned long blue_max)
1605 * dpy - specifies X server connection
1606 * screen - specifies display screen
1607 * visualid - identifies the visual type
1608 * depth - identifies the visual type
1609 * property - a standard colormap property
1610 * cmap - specifies colormap ID or None
1611 * red_max, green_max, blue_max - allocations
1614 XStandardColormap *stdcmap;
1616 XVisualInfo vinfo_template, *vinfo;
1620 /* Match the required visual information to an actual visual */
1621 vinfo_template.visualid = visualid;
1622 vinfo_template.screen = screen;
1623 vinfo_template.depth = depth;
1624 vinfo_mask = VisualIDMask | VisualScreenMask | VisualDepthMask;
1625 if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &n)) == NULL)
1628 /* Check the validity of the combination of visual characteristics,
1629 * allocation, and colormap property. Create an XStandardColormap
1633 if (! valid_args(vinfo, red_max, green_max, blue_max, property)
1634 || ((stdcmap = XAllocStandardColormap()) == NULL)) {
1635 XFree((char *) vinfo);
1639 /* Fill in the XStandardColormap structure */
1641 if (cmap == DefaultColormap(dpy, screen)) {
1642 /* Allocating out of the default map, cannot use XFreeColormap() */
1643 Window win = XCreateWindow(dpy, RootWindow(dpy, screen), 1, 1, 1, 1,
1644 0, 0, InputOnly, vinfo->visual,
1646 (XSetWindowAttributes *)NULL);
1647 stdcmap->killid = (XID) XCreatePixmap(dpy, win, 1, 1, depth);
1648 XDestroyWindow(dpy, win);
1649 stdcmap->colormap = cmap;
1651 stdcmap->killid = ReleaseByFreeingColormap;
1652 stdcmap->colormap = XCreateColormap(dpy, RootWindow(dpy, screen),
1653 vinfo->visual, AllocNone);
1655 stdcmap->red_max = red_max;
1656 stdcmap->green_max = green_max;
1657 stdcmap->blue_max = blue_max;
1658 if (property == XA_RGB_GRAY_MAP)
1659 stdcmap->red_mult = stdcmap->green_mult = stdcmap->blue_mult = 1;
1660 else if (vinfo->c_class == TrueColor || vinfo->c_class == DirectColor) {
1661 stdcmap->red_mult = lowbit(vinfo->red_mask);
1662 stdcmap->green_mult = lowbit(vinfo->green_mask);
1663 stdcmap->blue_mult = lowbit(vinfo->blue_mask);
1665 stdcmap->red_mult = (red_max > 0)
1666 ? (green_max + 1) * (blue_max + 1) : 0;
1667 stdcmap->green_mult = (green_max > 0) ? blue_max + 1 : 0;
1668 stdcmap->blue_mult = (blue_max > 0) ? 1 : 0;
1670 stdcmap->base_pixel = 0; /* base pixel may change */
1671 stdcmap->visualid = vinfo->visualid;
1673 /* Make the colormap */
1675 status = XmuCreateColormap(dpy, stdcmap);
1679 XFree((char *) vinfo);
1682 /* Free the colormap or the pixmap, if we created one */
1683 if (stdcmap->killid == ReleaseByFreeingColormap)
1684 XFreeColormap(dpy, stdcmap->colormap);
1685 else if (stdcmap->killid != None)
1686 XFreePixmap(dpy, stdcmap->killid);
1688 XFree((char *) stdcmap);
1689 return (XStandardColormap *) NULL;
1694 /****************************************************************************/
1696 valid_args(XVisualInfo *vinfo, unsigned long red_max, unsigned long green_max,
1697 unsigned long blue_max, Atom property)
1699 * vinfo - specifies visual
1700 * red_max, green_max, blue_max - specifies alloc
1701 * property - specifies property name
1704 unsigned long ncolors; /* number of colors requested */
1706 /* Determine that the number of colors requested is <= map size */
1708 if ((vinfo->c_class == DirectColor) || (vinfo->c_class == TrueColor)) {
1711 mask = vinfo->red_mask;
1716 mask = vinfo->green_mask;
1719 if (green_max > mask)
1721 mask = vinfo->blue_mask;
1724 if (blue_max > mask)
1726 } else if (property == XA_RGB_GRAY_MAP) {
1727 ncolors = red_max + green_max + blue_max + 1;
1728 if (ncolors > vinfo->colormap_size)
1731 ncolors = (red_max + 1) * (green_max + 1) * (blue_max + 1);
1732 if (ncolors > vinfo->colormap_size)
1736 /* Determine that the allocation and visual make sense for the property */
1740 case XA_RGB_DEFAULT_MAP:
1741 if (red_max == 0 || green_max == 0 || blue_max == 0)
1744 case XA_RGB_RED_MAP:
1748 case XA_RGB_GREEN_MAP:
1752 case XA_RGB_BLUE_MAP:
1756 case XA_RGB_BEST_MAP:
1757 if (red_max == 0 || green_max == 0 || blue_max == 0)
1760 case XA_RGB_GRAY_MAP:
1761 if (red_max == 0 || blue_max == 0 || green_max == 0)
1771 /* $Xorg: CrCmap.c,v 1.4 2001/02/09 02:03:51 xorgcvs Exp $ */
1775 Copyright 1989, 1998 The Open Group
1777 Permission to use, copy, modify, distribute, and sell this software and its
1778 documentation for any purpose is hereby granted without fee, provided that
1779 the above copyright notice appear in all copies and that both that
1780 copyright notice and this permission notice appear in supporting
1783 The above copyright notice and this permission notice shall be included in
1784 all copies or substantial portions of the Software.
1786 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1787 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1788 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1789 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1790 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1791 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1793 Except as contained in this notice, the name of The Open Group shall not be
1794 used in advertising or otherwise to promote the sale, use or other dealings
1795 in this Software without prior written authorization from The Open Group.
1798 /* $XFree86: xc/lib/Xmu/CrCmap.c,v 3.7 2001/12/14 19:55:36 dawes Exp $ */
1801 * Author: Donna Converse, MIT X Consortium
1805 * CreateCmap.c - given a standard colormap description, make the map.
1810 #include <X11/Xlib.h>
1811 #include <X11/Xutil.h>
1812 #include <X11/Xmu/StdCmap.h>
1817 /* allocate entire map Read Only */
1818 static int ROmap(Display*, Colormap, unsigned long[], int, int);
1820 /* allocate a cell, prefer Read Only */
1821 static Status ROorRWcell(Display*, Colormap, unsigned long[], int,
1822 XColor*, unsigned long);
1824 /* allocate a cell Read Write */
1825 static Status RWcell(Display*, Colormap, XColor*, XColor*, unsigned long*);
1828 static int compare(_Xconst void*, _Xconst void*);
1830 /* find contiguous sequence of cells */
1831 static Status contiguous(unsigned long[], int, int, unsigned long, int*, int*);
1833 /* frees resources before quitting */
1834 static void free_cells(Display*, Colormap, unsigned long[], int, int);
1836 /* create a map in a RO visual type */
1837 static Status readonly_map(Display*, XVisualInfo*, XStandardColormap*);
1839 /* create a map in a RW visual type */
1840 static Status readwrite_map(Display*, XVisualInfo*, XStandardColormap*);
1842 #define lowbit(x) ((x) & (~(x) + 1))
1843 #define TRUEMATCH(mult,max,mask) \
1844 (colormap->max * colormap->mult <= vinfo->mask && \
1845 lowbit(vinfo->mask) == colormap->mult)
1848 * To create any one colormap which is described by an XStandardColormap
1849 * structure, use XmuCreateColormap().
1851 * Return 0 on failure, non-zero on success.
1852 * Resources created by this function are not made permanent.
1853 * No argument error checking is provided. Use at your own risk.
1855 * All colormaps are created with read only allocations, with the exception
1856 * of read only allocations of colors in the default map or otherwise
1857 * which fail to return the expected pixel value, and these are individually
1858 * defined as read/write allocations. This is done so that all the cells
1859 * defined in the default map are contiguous, for use in image processing.
1860 * This typically happens with White and Black in the default map.
1862 * Colormaps of static visuals are considered to be successfully created if
1863 * the map of the static visual matches the definition given in the
1864 * standard colormap structure.
1868 XmuCreateColormap(Display *dpy, XStandardColormap *colormap)
1869 /* dpy - specifies the connection under which the map is created
1870 * colormap - specifies the map to be created, and returns, particularly
1871 * if the map is created as a subset of the default colormap
1872 * of the screen, the base_pixel of the map.
1875 XVisualInfo vinfo_template; /* template visual information */
1876 XVisualInfo *vinfo; /* matching visual information */
1877 XVisualInfo *vpointer; /* for freeing the entire list */
1878 long vinfo_mask; /* specifies the visual mask value */
1879 int n; /* number of matching visuals */
1882 vinfo_template.visualid = colormap->visualid;
1883 vinfo_mask = VisualIDMask;
1884 if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &n)) == NULL)
1887 /* A visual id may be valid on multiple screens. Also, there may
1888 * be multiple visuals with identical visual ids at different depths.
1889 * If the colormap is the Default Colormap, use the Default Visual.
1890 * Otherwise, arbitrarily, use the deepest visual.
1896 register int screen_number;
1900 for (screen_number = ScreenCount(dpy); --screen_number >= 0; )
1901 if (colormap->colormap == DefaultColormap(dpy, screen_number)) {
1907 for (i=0; i < n; i++, vinfo++) {
1908 if (vinfo->visual == DefaultVisual(dpy, screen_number))
1913 XVisualInfo *v = NULL;
1915 for (i=0; i < n; i++, vinfo++)
1916 if (vinfo->depth > maxdepth) {
1917 maxdepth = vinfo->depth;
1924 if (vinfo->c_class == PseudoColor || vinfo->c_class == DirectColor ||
1925 vinfo->c_class == GrayScale)
1926 status = readwrite_map(dpy, vinfo, colormap);
1927 else if (vinfo->c_class == TrueColor)
1928 status = TRUEMATCH(red_mult, red_max, red_mask) &&
1929 TRUEMATCH(green_mult, green_max, green_mask) &&
1930 TRUEMATCH(blue_mult, blue_max, blue_mask);
1932 status = readonly_map(dpy, vinfo, colormap);
1934 XFree((char *) vpointer);
1938 /****************************************************************************/
1940 readwrite_map(Display *dpy, XVisualInfo *vinfo, XStandardColormap *colormap)
1942 register unsigned long i, n; /* index counters */
1943 unsigned long ncolors; /* number of colors to be defined */
1944 int npixels; /* number of pixels allocated R/W */
1945 int first_index; /* first index of pixels to use */
1946 int remainder; /* first index of remainder */
1947 XColor color; /* the definition of a color */
1948 unsigned long *pixels; /* array of colormap pixels */
1949 unsigned long delta;
1952 /* Determine ncolors, the number of colors to be defined.
1953 * Insure that 1 < ncolors <= the colormap size.
1955 if (vinfo->c_class == DirectColor) {
1956 ncolors = colormap->red_max;
1957 if (colormap->green_max > ncolors)
1958 ncolors = colormap->green_max;
1959 if (colormap->blue_max > ncolors)
1960 ncolors = colormap->blue_max;
1962 delta = lowbit(vinfo->red_mask) +
1963 lowbit(vinfo->green_mask) +
1964 lowbit(vinfo->blue_mask);
1966 ncolors = colormap->red_max * colormap->red_mult +
1967 colormap->green_max * colormap->green_mult +
1968 colormap->blue_max * colormap->blue_mult + 1;
1971 if (ncolors <= 1 || (int) ncolors > vinfo->colormap_size) return 0;
1973 /* Allocate Read/Write as much of the colormap as we can possibly get.
1974 * Then insure that the pixels we were allocated are given in
1975 * monotonically increasing order, using a quicksort. Next, insure
1976 * that our allocation includes a subset of contiguous pixels at least
1977 * as long as the number of colors to be defined. Now we know that
1978 * these conditions are met:
1979 * 1) There are no free cells in the colormap.
1980 * 2) We have a contiguous sequence of pixels, monotonically
1981 * increasing, of length >= the number of colors requested.
1983 * One cell at a time, we will free, compute the next color value,
1984 * then allocate read only. This takes a long time.
1985 * This is done to insure that cells are allocated read only in the
1986 * contiguous order which we prefer. If the server has a choice of
1987 * cells to grant to an allocation request, the server may give us any
1988 * cell, so that is why we do these slow gymnastics.
1991 if ((pixels = (unsigned long *) calloc((unsigned) vinfo->colormap_size,
1992 sizeof(unsigned long))) == NULL)
1995 if ((npixels = ROmap(dpy, colormap->colormap, pixels,
1996 vinfo->colormap_size, ncolors)) == 0) {
1997 free((char *) pixels);
2001 qsort((char *) pixels, npixels, sizeof(unsigned long), compare);
2003 if (!contiguous(pixels, npixels, ncolors, delta, &first_index, &remainder))
2005 /* can't find enough contiguous cells, give up */
2006 XFreeColors(dpy, colormap->colormap, pixels, npixels,
2008 free((char *) pixels);
2011 colormap->base_pixel = pixels[first_index];
2013 /* construct a gray map */
2014 if (colormap->red_mult == 1 && colormap->green_mult == 1 &&
2015 colormap->blue_mult == 1)
2016 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
2019 color.blue = color.green = color.red =
2020 (unsigned short) ((i * 65535) / (colormap->red_max +
2021 colormap->green_max +
2022 colormap->blue_max));
2024 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
2029 /* construct a red ramp map */
2030 else if (colormap->green_max == 0 && colormap->blue_max == 0)
2031 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
2034 color.red = (unsigned short) ((i * 65535) / colormap->red_max);
2035 color.green = color.blue = 0;
2037 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
2042 /* construct a green ramp map */
2043 else if (colormap->red_max == 0 && colormap->blue_max == 0)
2044 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
2047 color.green = (unsigned short) ((i * 65535) / colormap->green_max);
2048 color.red = color.blue = 0;
2050 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
2055 /* construct a blue ramp map */
2056 else if (colormap->red_max == 0 && colormap->green_max == 0)
2057 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
2060 color.blue = (unsigned short) ((i * 65535) / colormap->blue_max);
2061 color.red = color.green = 0;
2063 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
2068 /* construct a standard red green blue cube map */
2071 #define calc(max,mult) (((n / colormap->mult) % \
2072 (colormap->max + 1)) * 65535) / colormap->max
2074 for (n=0, i=0; i < ncolors; i++, n += delta)
2076 color.pixel = n + colormap->base_pixel;
2077 color.red = calc(red_max, red_mult);
2078 color.green = calc(green_max, green_mult);
2079 color.blue = calc(blue_max, blue_mult);
2080 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
2086 /* We have a read-only map defined. Now free unused cells,
2087 * first those occuring before the contiguous sequence begins,
2088 * then any following the contiguous sequence.
2092 XFreeColors(dpy, colormap->colormap, pixels, first_index,
2095 XFreeColors(dpy, colormap->colormap,
2096 &(pixels[first_index + ncolors]), remainder,
2099 free((char *) pixels);
2104 /****************************************************************************/
2106 ROmap(Display *dpy, Colormap cmap, unsigned long pixels[], int m, int n)
2108 * dpy - the X server connection
2109 * cmap - specifies colormap ID
2110 * pixels - returns pixel allocations
2111 * m - specifies colormap size
2112 * n - specifies number of colors
2117 /* first try to allocate the entire colormap */
2118 if (XAllocColorCells(dpy, cmap, 1, (unsigned long *) NULL,
2119 (unsigned) 0, pixels, (unsigned) m))
2122 /* Allocate all available cells in the colormap, using a binary
2123 * algorithm to discover how many cells we can allocate in the colormap.
2127 p = n + ((m - n + 1) / 2);
2128 if (XAllocColorCells(dpy, cmap, 1, (unsigned long *) NULL,
2129 (unsigned) 0, pixels, (unsigned) p)) {
2133 XFreeColors(dpy, cmap, pixels, p, (unsigned long) 0);
2144 /****************************************************************************/
2146 contiguous(unsigned long pixels[], int npixels, int ncolors,
2147 unsigned long delta, int *first, int *rem)
2148 /* pixels - specifies allocated pixels
2149 * npixels - specifies count of alloc'd pixels
2150 * ncolors - specifies needed sequence length
2151 * delta - between pixels
2152 * first - returns first index of sequence
2153 * rem - returns first index after sequence, or 0, if none follow
2156 register int i = 1; /* walking index into the pixel array */
2157 register int count = 1; /* length of sequence discovered so far */
2160 if (npixels == ncolors) {
2165 while (count < ncolors && ncolors - count <= *rem)
2167 if (pixels[i-1] + delta == pixels[i])
2176 if (count != ncolors)
2182 /****************************************************************************/
2184 ROorRWcell(Display *dpy, Colormap cmap, unsigned long pixels[],
2185 int npixels, XColor *color, unsigned long p)
2187 unsigned long pixel;
2190 /* Free the read/write allocation of one cell in the colormap.
2191 * Request a read only allocation of one cell in the colormap.
2192 * If the read only allocation cannot be granted, give up, because
2193 * there must be no free cells in the colormap.
2194 * If the read only allocation is granted, but gives us a cell which
2195 * is not the one that we just freed, it is probably the case that
2196 * we are trying allocate White or Black or some other color which
2197 * already has a read-only allocation in the map. So we try to
2198 * allocate the previously freed cell with a read/write allocation,
2199 * because we want contiguous cells for image processing algorithms.
2202 pixel = color->pixel;
2203 request.red = color->red;
2204 request.green = color->green;
2205 request.blue = color->blue;
2207 XFreeColors(dpy, cmap, &pixel, 1, (unsigned long) 0);
2208 if (! XAllocColor(dpy, cmap, color)
2209 || (color->pixel != pixel &&
2210 (!RWcell(dpy, cmap, color, &request, &pixel))))
2212 free_cells(dpy, cmap, pixels, npixels, (int)p);
2219 /****************************************************************************/
2221 free_cells(Display *dpy, Colormap cmap, unsigned long pixels[],
2224 * pixels - to be freed
2225 * npixels - original number allocated
2228 /* One of the npixels allocated has already been freed.
2229 * p is the index of the freed pixel.
2230 * First free the pixels preceeding p, and there are p of them;
2231 * then free the pixels following p, there are npixels - p - 1 of them.
2233 XFreeColors(dpy, cmap, pixels, p, (unsigned long) 0);
2234 XFreeColors(dpy, cmap, &(pixels[p+1]), npixels - p - 1, (unsigned long) 0);
2235 free((char *) pixels);
2239 /****************************************************************************/
2241 RWcell(Display *dpy, Colormap cmap, XColor *color, XColor *request,
2242 unsigned long *pixel)
2244 unsigned long n = *pixel;
2246 XFreeColors(dpy, cmap, &(color->pixel), 1, (unsigned long)0);
2247 if (! XAllocColorCells(dpy, cmap, (Bool) 0, (unsigned long *) NULL,
2248 (unsigned) 0, pixel, (unsigned) 1))
2252 XFreeColors(dpy, cmap, pixel, 1, (unsigned long) 0);
2255 color->pixel = *pixel;
2256 color->flags = DoRed | DoGreen | DoBlue;
2257 color->red = request->red;
2258 color->green = request->green;
2259 color->blue = request->blue;
2260 XStoreColors(dpy, cmap, color, 1);
2265 /****************************************************************************/
2267 compare(_Xconst void *e1, _Xconst void *e2)
2269 return ((int)(*(long *)e1 - *(long *)e2));
2273 /****************************************************************************/
2275 readonly_map(Display *dpy, XVisualInfo *vinfo, XStandardColormap *colormap)
2280 last_pixel = (colormap->red_max + 1) * (colormap->green_max + 1) *
2281 (colormap->blue_max + 1) + colormap->base_pixel - 1;
2283 for(i=colormap->base_pixel; i <= last_pixel; i++) {
2285 color.pixel = (unsigned long) i;
2286 color.red = (unsigned short)
2287 (((i/colormap->red_mult) * 65535) / colormap->red_max);
2289 if (vinfo->c_class == StaticColor) {
2290 color.green = (unsigned short)
2291 ((((i/colormap->green_mult) % (colormap->green_max + 1)) *
2292 65535) / colormap->green_max);
2293 color.blue = (unsigned short)
2294 (((i%colormap->green_mult) * 65535) / colormap->blue_max);
2296 else /* vinfo->c_class == GrayScale, old style allocation XXX */
2297 color.green = color.blue = color.red;
2299 XAllocColor(dpy, colormap->colormap, &color);
2300 if (color.pixel != (unsigned long) i)
2307 /* $Xorg: DelCmap.c,v 1.4 2001/02/09 02:03:52 xorgcvs Exp $ */
2311 Copyright 1989, 1998 The Open Group
2313 Permission to use, copy, modify, distribute, and sell this software and its
2314 documentation for any purpose is hereby granted without fee, provided that
2315 the above copyright notice appear in all copies and that both that
2316 copyright notice and this permission notice appear in supporting
2319 The above copyright notice and this permission notice shall be included in
2320 all copies or substantial portions of the Software.
2322 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2323 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2324 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2325 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
2326 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
2327 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2329 Except as contained in this notice, the name of The Open Group shall not be
2330 used in advertising or otherwise to promote the sale, use or other dealings
2331 in this Software without prior written authorization from The Open Group.
2334 /* $XFree86: xc/lib/Xmu/DelCmap.c,v 1.7 2001/12/14 19:55:40 dawes Exp $ */
2337 * Author: Donna Converse, MIT X Consortium
2340 #include <X11/Xlib.h>
2341 #include <X11/Xutil.h>
2342 #include <X11/Xmu/StdCmap.h>
2344 int ignoreErrorHandler(Display* d, XErrorEvent* e) { }
2346 /* To remove any standard colormap property, use XmuDeleteStandardColormap().
2347 * XmuDeleteStandardColormap() will remove the specified property from the
2348 * specified screen, releasing any resources used by the colormap(s) of the
2349 * property if possible.
2353 XmuDeleteStandardColormap(Display *dpy, int screen, Atom property)
2354 /* dpy; - specifies the X server to connect to
2355 * screen - specifies the screen of the display
2356 * property - specifies the standard colormap property
2359 XStandardColormap *stdcmaps, *s;
2362 if (XGetRGBColormaps(dpy, RootWindow(dpy, screen), &stdcmaps, &count,
2365 for (s=stdcmaps; count > 0; count--, s++) {
2366 if ((s->killid == ReleaseByFreeingColormap) &&
2367 (s->colormap != None) &&
2368 (s->colormap != DefaultColormap(dpy, screen))) {
2370 // UGLY HACK written in by Adam Megacz -- sometimes s->colormap isn't valid, so we do some shuffling
2371 X11ErrorHandler* oldHandler = XSetErrorHandler(ignoreErrorHandler);
2373 XFreeColormap(dpy, s->colormap);
2375 XSetErrorHandler(oldHandler);
2378 } else if (s->killid != None) {
2379 XKillClient(dpy, s->killid);
2382 XDeleteProperty(dpy, RootWindow(dpy, screen), property);
2383 XFree((char *) stdcmaps);