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::_dispose() { XDestroyWindow(display, (*((Window*)window))); }
386 void org::xwt::plat::POSIX$X11Surface::setLocation (jint x, jint y) { XMoveWindow(display, (*((Window*)window)), x, y); }
387 void org::xwt::plat::POSIX$X11Surface::toFront() { XRaiseWindow(display, (*((Window*)window))); }
388 void org::xwt::plat::POSIX$X11Surface::toBack() { XLowerWindow(display, (*((Window*)window))); }
390 void org::xwt::plat::POSIX$X11Surface::setInvisible(jboolean i) {
391 if (i) XUnmapWindow(display, (*((Window*)window)));
392 else XMapRaised(display, (*((Window*)window)));
396 void org::xwt::plat::POSIX$X11Surface::_setMinimized(jboolean b) {
397 if (b) XIconifyWindow(display, (*((Window*)window)), screen_num);
398 else XMapRaised(display, (*((Window*)window)));
402 void org::xwt::plat::POSIX$X11Surface::natInit() {
403 XSetWindowAttributes xswa;
404 window = (gnu::gcj::RawData*)malloc(sizeof(Window));
405 xswa.bit_gravity = NorthWestGravity;
406 xswa.colormap = s_colormap;
407 xswa.event_mask = ExposureMask | ButtonPressMask | StructureNotifyMask |
408 KeyPressMask | KeyReleaseMask | ButtonPressMask |
409 ButtonReleaseMask | EnterWindowMask | LeaveWindowMask |
410 PointerMotionMask | ButtonMotionMask | ConfigureNotify | FocusChangeMask;
411 *((Window*)window) = XCreateWindow(display, RootWindow(display, screen_num), 10, 10, 10, 10, 0,
412 colorDepth, InputOutput, CopyFromParent,
413 CWColormap | CWBitGravity | CWEventMask, &xswa);
416 // I don't know why this works....
417 int dat[5] = { 0x2, 0xbffff804, 0x0, 0x817f560, 0x8110694 };
418 XChangeProperty(display, (*((Window*)window)),
419 XInternAtom(display, "_MOTIF_WM_HINTS", False),
420 XInternAtom(display, "_MOTIF_WM_HINTS", False),
428 tp.value = (unsigned char*)"XWT";
430 tp.encoding = XA_STRING;
432 XSetTextProperty(display, (*((Window*)window)), &tp, XA_WM_CLASS);
434 Atom proto = XInternAtom(display, "WM_DELETE_WINDOW", False);
435 XSetWMProtocols(display, (*((Window*)window)), &proto, 1);
437 XSelectInput(display, (*((Window*)window)), StructureNotifyMask);
438 org::xwt::plat::POSIX::windowToSurfaceMap->put(new java::lang::Long(*((Window*)window)), this);
441 XMapRaised(display, (*((Window*)window)));
444 waitForCreation->block();
445 XSelectInput(display, (*((Window*)window)), xswa.event_mask);
448 gc = (gnu::gcj::RawData*)malloc(sizeof(GC));
449 *((GC*)gc) = XCreateGC(display, (*((Window*)window)), 0, 0);
452 vm.graphics_exposures = 0;
453 XChangeGC(display, *((GC*)gc), GCGraphicsExposures, &vm);
457 void org::xwt::plat::POSIX$X11Surface::dispatchEvent(gnu::gcj::RawData* ev) {
459 XEvent* e = (XEvent*)ev;
460 if (e->type == Expose) {
461 XExposeEvent *expose = (XExposeEvent*)(e);
462 Dirty(expose->x, expose->y, expose->width, expose->height);
464 } else if (e->type == ClientMessage) { if (((XClientMessageEvent*)(e))->data.l[0] == XInternAtom(display, "WM_DELETE_WINDOW", False)) Close();
465 } else if (e->type == MapNotify) { Minimized(0); waitForCreation->release();
466 } else if (e->type == UnmapNotify) { Minimized(1);
467 } else if (e->type == FocusIn) { Focused(1);
468 } else if (e->type == FocusOut) { Focused(0);
470 } else if (e->type == KeyPress || e->type == KeyRelease) {
471 XKeyEvent *xbe = (XKeyEvent*)(e);
473 // drop faked KeyRelease events generated by the X server's autorepeat
474 if (e->type == KeyRelease) {
476 XQueryKeymap(display, depressed);
477 if ((depressed[(xbe->keycode & 0xff) / 8] & (0x1 << (xbe->keycode % 8))) >> (xbe->keycode % 8)) return;
483 unsigned int savestate = xbe->state;
484 xbe->state = xbe->state & ShiftMask; // ignore everything except shiftmask
485 XLookupString(xbe, s, 20, NULL, NULL);
486 xbe->state = savestate;
488 if (s != NULL && s[0] != '\0' && s[1] == '\0' && s[0] >= 0x20 && s[0] <= 0x7E) {
492 KeySym ks = XKeycodeToKeysym(display, xbe->keycode, 0);
494 case XK_BackSpace: s = "back_space"; break;
495 case XK_Tab: s = "tab"; break;
496 case XK_Linefeed: s = "enter"; break;
497 case XK_Return: s = "enter"; break;
498 case XK_Scroll_Lock: s = "scroll_lock"; break;
499 case XK_Escape: s = "escape"; break;
500 case XK_Insert: s = "insert"; break;
501 case XK_Delete: s = "delete"; break;
502 case XK_Home: s = "home"; break;
503 case XK_Left: s = "left"; break;
504 case XK_Up: s = "up"; break;
505 case XK_Right: s = "right"; break;
506 case XK_Down: s = "down"; break;
507 case XK_Page_Up: s = "page_up"; break;
508 case XK_Page_Down: s = "page_down"; break;
509 case XK_End: s = "end"; break;
510 case XK_Num_Lock: s = "num_lock"; break;
511 case XK_KP_Tab: s = "tab"; break;
512 case XK_KP_Enter: s = "enter"; break;
513 case XK_KP_F1: s = "f1"; break;
514 case XK_KP_F2: s = "f2"; break;
515 case XK_KP_F3: s = "f3"; break;
516 case XK_KP_F4: s = "f4"; break;
517 case XK_KP_Home: s = "home"; break;
518 case XK_KP_Left: s = "left"; break;
519 case XK_KP_Up: s = "up"; break;
520 case XK_KP_Right: s = "right"; break;
521 case XK_KP_Down: s = "down"; break;
522 case XK_KP_Page_Up: s = "page_up"; break;
523 case XK_KP_Page_Down: s = "page_down"; break;
524 case XK_KP_End: s = "end"; break;
525 case XK_KP_Insert: s = "insert"; break;
526 case XK_KP_Delete: s = "delete"; break;
527 case XK_F1: s = "f1"; break;
528 case XK_F2: s = "f2"; break;
529 case XK_F3: s = "f3"; break;
530 case XK_F4: s = "f4"; break;
531 case XK_F5: s = "f5"; break;
532 case XK_F6: s = "f6"; break;
533 case XK_F7: s = "f7"; break;
534 case XK_F8: s = "f8"; break;
535 case XK_F9: s = "f9"; break;
536 case XK_F10: s = "f10"; break;
537 case XK_F11: s = "f11"; break;
538 case XK_F12: s = "f12"; break;
539 case XK_Shift_L: s = "shift"; break;
540 case XK_Shift_R: s = "shift"; break;
541 case XK_Control_L: s = "control"; break;
542 case XK_Control_R: s = "control"; break;
543 case XK_Meta_L: s = "alt"; break;
544 case XK_Meta_R: s = "alt"; break;
545 case XK_Alt_L: s = "alt"; break;
546 case XK_Alt_R: s = "alt"; break;
551 jstring s2 = JvNewStringLatin1(s);
552 if (e->type == KeyPress) KeyPressed((xbe->state & LockMask) ? s2->toUpperCase() : s2);
553 if (e->type == KeyRelease) KeyReleased(s2);
555 } else if (e->type == ButtonPress) {
556 XButtonEvent* xbe = (XButtonEvent*)(e);
557 if (xbe->button == 2) xbe->button = 3;
558 else if (xbe->button == 3) xbe->button = 2;
561 } else if (e->type == ButtonRelease) {
562 XButtonEvent* xbe = (XButtonEvent*)(e);
563 if (xbe->button == 2) xbe->button = 3;
564 else if (xbe->button == 3) xbe->button = 2;
565 Release(xbe->button);
567 } else if (e->type == MotionNotify) {
568 XMotionEvent* xme = (XMotionEvent*)(e);
569 Move(xme->x, xme->y);
571 } else if (e->type == EnterNotify || e->type == LeaveNotify) {
572 XCrossingEvent* xce = (XCrossingEvent*)(e);
573 Move(xce->x, xce->y);
575 } else if (e->type == ConfigureNotify) {
578 XConfigureEvent* xce = (XConfigureEvent*)(e);
579 XTranslateCoordinates(display, (*((Window*)window)), RootWindow(display, screen_num), 0, 0, &x_out, &y_out, &child);
580 if (xce->width != width || xce->height != height) SizeChange(xce->width, xce->height);
581 if (x_out != root->abs(0) || y_out != root->abs(1)) PosChange(x_out, y_out);
586 static jstring crosshair, east, hand, move, north, northeast, northwest,
587 south, southeast, southwest, text, west, wait_string;
588 static Cursor crosshair_cursor, east_cursor, hand_cursor, move_cursor, north_cursor,
589 northeast_cursor, northwest_cursor, south_cursor, southeast_cursor,
590 southwest_cursor, text_cursor, west_cursor, wait_cursor, default_cursor;
592 void org::xwt::plat::POSIX$X11Surface::syncCursor() {
595 if (cursor->equals(crosshair)) curs = crosshair_cursor;
596 else if (cursor->equals(east)) curs = east_cursor;
597 else if (cursor->equals(hand)) curs = hand_cursor;
598 else if (cursor->equals(move)) curs = move_cursor;
599 else if (cursor->equals(north)) curs = north_cursor;
600 else if (cursor->equals(northeast)) curs = northeast_cursor;
601 else if (cursor->equals(northwest)) curs = northwest_cursor;
602 else if (cursor->equals(south)) curs = south_cursor;
603 else if (cursor->equals(southeast)) curs = southeast_cursor;
604 else if (cursor->equals(southwest)) curs = southwest_cursor;
605 else if (cursor->equals(text)) curs = text_cursor;
606 else if (cursor->equals(west)) curs = west_cursor;
607 else if (cursor->equals(wait_string)) curs = wait_cursor;
608 else curs = default_cursor;
610 XDefineCursor(display, (*((Window*)window)), curs);
615 // POSIX ///////////////////////////////////////////////////////////////////
617 jint org::xwt::plat::POSIX::_getScreenWidth() { return WidthOfScreen(DefaultScreenOfDisplay(display)); }
618 jint org::xwt::plat::POSIX::_getScreenHeight() { return HeightOfScreen(DefaultScreenOfDisplay(display)); }
620 jstring org::xwt::plat::POSIX::_getEnv(jstring key) {
621 int len = JvGetStringUTFLength(key);
623 JvGetStringUTFRegion(key, 0, len, buf);
625 char* envstr = getenv(buf);
626 return envstr == NULL ? NULL : JvNewStringLatin1(envstr);
629 void org::xwt::plat::POSIX::spawnChildProcess(JArray<jstring>* cmd) {
630 jstring* cmdstrings = elements(cmd);
631 char* cmd2[cmd->length + 1];
632 cmd2[cmd->length] = NULL;
633 for(int i=0; i<cmd->length; i++) {
634 cmd2[i] = (char*)malloc(JvGetStringUTFLength(cmdstrings[i]));
635 JvGetStringUTFRegion(cmdstrings[i], 0, JvGetStringUTFLength(cmdstrings[i]), cmd2[i]);
639 signal(SIGHUP, SIG_IGN);
640 signal(SIGQUIT, SIG_IGN);
641 signal(SIGINT, SIG_IGN);
642 signal(SIGTERM, SIG_IGN);
644 // ignore SIGPIPE in case we were launched from a browser and the browser closed
645 signal(SIGPIPE, SIG_IGN);
647 execvp(cmd2[0], cmd2);
651 static void dispatchSelectionEvent(XEvent* e) {
652 if (e->type == SelectionNotify) {
653 XSelectionEvent* xsn = (XSelectionEvent*)(e);
654 if (xsn->property == None) org::xwt::plat::POSIX::clipboard = JvNewStringLatin1("", 0);
658 unsigned long numitems;
660 unsigned long bytes_after;
661 XGetWindowProperty(display, xsn->requestor, xsn->property, 0, 4096,
662 True, AnyPropertyType, &returntype, &returnformat,
663 &numitems, &bytes_after, &ret);
664 org::xwt::plat::POSIX::clipboard =
665 (returntype == None ? JvNewStringLatin1("", 0) : JvNewStringLatin1((char*)ret, strlen((char*)ret)));
667 org::xwt::plat::POSIX::waiting_for_selection_event->release();
669 } else if (e->type == SelectionRequest) {
670 XSelectionRequestEvent* xsr = (XSelectionRequestEvent*)(e);
672 xsn.type = SelectionNotify;
673 xsn.serial = xsr->serial;
674 xsn.send_event = True;
675 xsn.display = display;
676 xsn.requestor = xsr->requestor;
677 xsn.selection = xsr->selection;
678 xsn.target = xsr->target;
679 xsn.property = xsr->property;
680 xsn.time = xsr->time;
682 int len = min(1024, JvGetStringUTFLength(org::xwt::plat::POSIX::clipboard));
684 JvGetStringUTFRegion(org::xwt::plat::POSIX::clipboard, 0, len, buf);
687 XChangeProperty(display, xsr->requestor, xsr->property, xsr->target, 8, PropModeReplace, (unsigned char*)buf, len + 1);
688 XSendEvent(display, xsr->requestor, True, 0, (XEvent*)(&xsn));
692 void org::xwt::plat::POSIX::eventThread() {
695 XNextEvent(display, &e);
696 if (e.type == SelectionNotify || e.type == SelectionRequest) {
697 dispatchSelectionEvent(&e);
699 org::xwt::plat::POSIX$X11Surface* surface =
700 (org::xwt::plat::POSIX$X11Surface*)windowToSurfaceMap->get(new java::lang::Long(((XAnyEvent*)&e)->window));
701 if (surface != NULL) surface->dispatchEvent((gnu::gcj::RawData*)&e);
706 jstring org::xwt::plat::POSIX::_getClipBoard() {
707 XConvertSelection(display, XA_PRIMARY, XA_STRING, XInternAtom(display, "VT_SELECTION", False), selectionWindow, CurrentTime);
709 org::xwt::plat::POSIX::waiting_for_selection_event->block();
713 void org::xwt::plat::POSIX::_setClipBoard(jstring s) {
715 int len = JvGetStringUTFLength(clipboard);
717 JvGetStringUTFRegion(clipboard, 0, len, buf);
719 XSetSelectionOwner(display, XInternAtom(display, "PRIMARY", 0), selectionWindow, CurrentTime);
722 typedef int (X11ErrorHandler)(Display*, XErrorEvent*);
723 int errorHandler(Display* d, XErrorEvent* e) {
724 // this error handler is only installed during the initial
725 // test to see if shm is present
729 void org::xwt::plat::POSIX::natInit() {
732 org::xwt::Platform::criticalAbort(JvNewStringLatin1("Your X11 libraries do not support multithreaded programs"));
734 display = XOpenDisplay(NULL);
735 screen_num = XDefaultScreen(display);
736 colorDepth = (jint)(DefaultDepth(((Display*)display), 0));
737 shm_info.shmaddr = NULL;
739 shm_supported = (XShmQueryExtension(display) == True);
741 X11ErrorHandler* oldHandler = XSetErrorHandler(errorHandler);
742 XShmSegmentInfo sinfo;
743 sinfo.shmid = shmget(IPC_PRIVATE, 1, IPC_CREAT | 0777 | IPC_EXCL);
744 sinfo.readOnly = False;
745 // if the server is remote, this will trigger the error handler
746 XShmAttach(display, &sinfo);
747 XSync(display, False);
748 XSetErrorHandler(oldHandler);
752 shm_pixmaps_supported = (XShmPixmapFormat(display) == ZPixmap);
754 crosshair = JvNewStringLatin1("crosshair");
755 east = JvNewStringLatin1("east");
756 hand = JvNewStringLatin1("hand");
757 move = JvNewStringLatin1("move");
758 north = JvNewStringLatin1("north");
759 northeast = JvNewStringLatin1("northeast");
760 northwest = JvNewStringLatin1("northwest");
761 south = JvNewStringLatin1("south");
762 southeast = JvNewStringLatin1("southeast");
763 southwest = JvNewStringLatin1("southwest");
764 text = JvNewStringLatin1("text");
765 west = JvNewStringLatin1("west");
766 wait_string = JvNewStringLatin1("wait");
767 crosshair_cursor = XCreateFontCursor(display, XC_tcross);
768 east_cursor = XCreateFontCursor(display, XC_right_side);
769 hand_cursor = XCreateFontCursor(display, XC_hand2);
770 move_cursor = XCreateFontCursor(display, XC_fleur);
771 north_cursor = XCreateFontCursor(display, XC_top_side);
772 northeast_cursor = XCreateFontCursor(display, XC_top_right_corner);
773 northwest_cursor = XCreateFontCursor(display, XC_left_side);
774 south_cursor = XCreateFontCursor(display, XC_bottom_side);
775 southeast_cursor = XCreateFontCursor(display, XC_bottom_right_corner);
776 southwest_cursor = XCreateFontCursor(display, XC_bottom_left_corner);
777 text_cursor = XCreateFontCursor(display, XC_xterm);
778 west_cursor = XCreateFontCursor(display, XC_right_side);
779 wait_cursor = XCreateFontCursor(display, XC_watch);
780 default_cursor = XCreateFontCursor(display, XC_left_ptr);
782 selectionWindow = XCreateWindow(display, RootWindow(display, screen_num), 0, 0, 1, 1, 0, colorDepth, InputOutput, CopyFromParent, 0, NULL);
783 visual = DefaultVisual(display, screen_num);
785 sprintf(buf, "X11 DISPLAY: %s", XDisplayString(display));
786 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
787 sprintf(buf, "X11 SHM: %s", shm_supported ? "enabled" : "disabled");
788 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
789 sprintf(buf, "X11 Visual: %x %x %x bits: %i visualid: %i depth: %i",
790 visual->red_mask, visual->green_mask, visual->blue_mask, visual->bits_per_rgb, visual->visualid, colorDepth);
791 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
793 // FIXME: don't know why (True, False) is the best solution...
794 if(XmuLookupStandardColormap(display, screen_num, visual->visualid, colorDepth, XA_RGB_BEST_MAP, True, False) == 0)
795 org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: XmuLookupStandardColormap failed"));
797 XStandardColormap* best_map_info = NULL;
799 if (XGetRGBColormaps(display, RootWindow(display, screen_num), &best_map_info, &count, XA_RGB_BEST_MAP) == 0)
800 org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: couldn't allocate a standard colormap"));
801 if (!best_map_info->colormap)
802 org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: XmuLookupStandardColomap succeded, but no colormap was found on the root window"));
803 if (best_map_info->red_max == 0)
804 org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: standard colormap exists, but was improperly allocated"));
805 s_colormap = best_map_info->colormap;
806 colormap_info = best_map_info;
808 sprintf(buf, " red_max / red_mult: %x %x", colormap_info->red_max, colormap_info->red_mult);
809 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
810 sprintf(buf, " green_max / green_mult: %x %x", colormap_info->green_max, colormap_info->green_mult);
811 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
812 sprintf(buf, " blue_max / blue_mult: %x %x", colormap_info->blue_max, colormap_info->blue_mult);
813 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
814 sprintf(buf, " base_pixel: %x", colormap_info->base_pixel);
815 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
818 JArray<java::lang::String*>* org::xwt::plat::POSIX::listNativeFonts() {
820 char** xfonts = XListFonts(display, "-*-*-*-*-normal-*-*-*-*-*-*-*-*-*", 0xFFFFFFFF, &numfonts);
821 JArray<java::lang::String*>* fonts = (JArray<java::lang::String*>*)JvNewObjectArray(numfonts, &(::java::lang::String::class$), NULL);
822 java::lang::String** jfonts = (java::lang::String**)(elements(fonts));
823 for(int i=0; i<numfonts; i++)
824 jfonts[i] = JvNewStringLatin1(xfonts[i], strlen(xfonts[i]));
828 gnu::gcj::RawData* org::xwt::plat::POSIX::fontStringToStruct(jstring s) {
829 int len = min(1024, JvGetStringUTFLength(s));
831 JvGetStringUTFRegion(s, 0, len, buf);
833 return (gnu::gcj::RawData*)XLoadQueryFont(display, buf);
836 jint org::xwt::plat::POSIX::_getMaxAscent(::java::lang::String* font) { return ((XFontStruct*)fontToXFont(font))->max_bounds.ascent; }
837 jint org::xwt::plat::POSIX::_getMaxDescent(::java::lang::String* font) { return ((XFontStruct*)fontToXFont(font))->max_bounds.descent; }
838 jint org::xwt::plat::POSIX::_stringWidth(::java::lang::String* font, ::java::lang::String* text) {
839 if (text == NULL) return 0;
840 int len = JvGetStringUTFLength(text);
842 JvGetStringUTFRegion(text, 0, len, buf);
844 return XTextWidth((XFontStruct*)fontToXFont(font), buf, len);
848 //////////////////////////////////////////////////////////////////////////////
849 //////////////////////////////////////////////////////////////////////////////
850 //////////////////////////////////////////////////////////////////////////////
851 //////////////////////////////////////////////////////////////////////////////
853 // Everything below this point was taken, cut-and-paste, from the //
854 // source for libXmu. It implements the official 'standard colormap //
855 // creation algorithm. I made some small changes to //
856 // XmuDeleteStandardColormap //
858 //////////////////////////////////////////////////////////////////////////////
859 //////////////////////////////////////////////////////////////////////////////
860 //////////////////////////////////////////////////////////////////////////////
861 //////////////////////////////////////////////////////////////////////////////
863 /* $Xorg: LookupCmap.c,v 1.4 2001/02/09 02:03:53 xorgcvs Exp $ */
867 Copyright 1989, 1998 The Open Group
869 Permission to use, copy, modify, distribute, and sell this software and its
870 documentation for any purpose is hereby granted without fee, provided that
871 the above copyright notice appear in all copies and that both that
872 copyright notice and this permission notice appear in supporting
875 The above copyright notice and this permission notice shall be included in
876 all copies or substantial portions of the Software.
878 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
879 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
880 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
881 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
882 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
883 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
885 Except as contained in this notice, the name of The Open Group shall not be
886 used in advertising or otherwise to promote the sale, use or other dealings
887 in this Software without prior written authorization from The Open Group.
890 /* $XFree86: xc/lib/Xmu/LookupCmap.c,v 1.8 2001/12/14 19:55:47 dawes Exp $ */
893 * Author: Donna Converse, MIT X Consortium
897 #include <X11/Xlib.h>
898 #include <X11/Xatom.h>
899 #include <X11/Xutil.h>
900 #include <X11/Xmu/StdCmap.h>
906 static Status lookup(Display*, int, VisualID, Atom, XStandardColormap*, Bool);
909 * To create a standard colormap if one does not currently exist, or
910 * replace the currently existing standard colormap, use
911 * XmuLookupStandardColormap().
913 * Given a screen, a visual, and a property, XmuLookupStandardColormap()
914 * will determine the best allocation for the property under the specified
915 * visual, and determine the whether to create a new colormap or to use
916 * the default colormap of the screen. It will call XmuStandardColormap()
917 * to create the standard colormap.
919 * If replace is true, any previous definition of the property will be
920 * replaced. If retain is true, the property and the colormap will be
921 * made permanent for the duration of the server session. However,
922 * pre-existing property definitions which are not replaced cannot be made
923 * permanent by a call to XmuLookupStandardColormap(); a request to retain
924 * resources pertains to newly created resources.
926 * Returns 0 on failure, non-zero on success. A request to create a
927 * standard colormap upon a visual which cannot support such a map is
928 * considered a failure. An example of this would be requesting any
929 * standard colormap property on a monochrome visual, or, requesting an
930 * RGB_BEST_MAP on a display whose colormap size is 16.
934 XmuLookupStandardColormap(Display *dpy, int screen, VisualID visualid,
935 unsigned int depth, Atom property,
936 Bool replace, Bool retain)
938 * dpy - specifies X server connection
939 * screen - specifies screen of display
940 * visualid - specifies the visual type
941 * depth - specifies the visual type
942 * property - a standard colormap property
943 * replace - specifies whether to replace
944 * retain - specifies whether to retain
947 Display *odpy; /* original display connection */
948 XStandardColormap *colormap;
949 XVisualInfo vinfo_template, *vinfo; /* visual */
951 unsigned long r_max, g_max, b_max; /* allocation */
953 Colormap cmap; /* colormap ID */
957 /* Match the requested visual */
959 vinfo_template.visualid = visualid;
960 vinfo_template.screen = screen;
961 vinfo_template.depth = depth;
962 vinfo_mask = VisualIDMask | VisualScreenMask | VisualDepthMask;
963 if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &count)) ==
967 /* Monochrome visuals have no standard maps */
969 if (vinfo->colormap_size <= 2) {
970 XFree((char *) vinfo);
974 /* If the requested property already exists on this screen, and,
975 * if the replace flag has not been set to true, return success.
976 * lookup() will remove a pre-existing map if replace is true.
979 if (lookup(dpy, screen, visualid, property, (XStandardColormap *) NULL,
980 replace) && !replace) {
981 XFree((char *) vinfo);
985 /* Determine the best allocation for this property under the requested
986 * visualid and depth, and determine whether or not to use the default
987 * colormap of the screen.
990 if (!XmuGetColormapAllocation(vinfo, property, &r_max, &g_max, &b_max)) {
991 XFree((char *) vinfo);
995 cmap = (property == XA_RGB_DEFAULT_MAP &&
996 visualid == XVisualIDFromVisual(DefaultVisual(dpy, screen)))
997 ? DefaultColormap(dpy, screen) : None;
999 /* If retaining resources, open a new connection to the same server */
1003 if ((dpy = XOpenDisplay(XDisplayString(odpy))) == NULL) {
1004 XFree((char *) vinfo);
1009 /* Create the standard colormap */
1011 colormap = XmuStandardColormap(dpy, screen, visualid, depth, property,
1012 cmap, r_max, g_max, b_max);
1014 /* Set the standard colormap property */
1019 if (lookup(dpy, screen, visualid, property, colormap, replace) &&
1021 /* Someone has defined the property since we last looked.
1022 * Since we will not replace it, release our own resources.
1023 * If this is the default map, our allocations will be freed
1024 * when this connection closes.
1026 if (colormap->killid == ReleaseByFreeingColormap)
1027 XFreeColormap(dpy, colormap->colormap);
1028 } else if (retain) {
1029 XSetCloseDownMode(dpy, RetainPermanent);
1032 XFree((char *) colormap);
1038 XFree((char *) vinfo);
1042 /***************************************************************************/
1044 /* Lookup a standard colormap property. If the property is RGB_DEFAULT_MAP,
1045 * the visualid is used to determine whether the indicated standard colormap
1046 * exists. If the map exists and replace is true, delete the resources used
1047 * by the map and remove the property. Return true if the map exists,
1048 * or did exist and was deleted; return false if the map was not found.
1050 * Note that this is not the way that a Status return is normally used.
1052 * If new is not NULL, new points to an XStandardColormap structure which
1053 * describes a standard colormap of the specified property. It will be made
1054 * a standard colormap of the screen if none already exists, or if replace
1059 lookup(Display *dpy, int screen, VisualID visualid, Atom property,
1060 XStandardColormap *cnew, Bool replace)
1062 * dpy - specifies display connection
1063 * screen - specifies screen number
1064 * visualid - specifies visualid for std map
1065 * property - specifies colormap property name
1066 * cnew - specifies a standard colormap
1067 * replace - specifies whether to replace
1072 XStandardColormap *stdcmaps, *s;
1073 Window win = RootWindow(dpy, screen);
1075 /* The property does not already exist */
1077 if (! XGetRGBColormaps(dpy, win, &stdcmaps, &count, property)) {
1079 XSetRGBColormaps(dpy, win, cnew, 1, property);
1083 /* The property exists and is not describing the RGB_DEFAULT_MAP */
1085 if (property != XA_RGB_DEFAULT_MAP) {
1087 XmuDeleteStandardColormap(dpy, screen, property);
1089 XSetRGBColormaps(dpy, win, cnew, 1, property);
1091 XFree((char *)stdcmaps);
1095 /* The property exists and is RGB_DEFAULT_MAP */
1097 for (i=0, s=stdcmaps; (i < count) && (s->visualid != visualid); i++, s++)
1100 /* No RGB_DEFAULT_MAP property matches the given visualid */
1104 XStandardColormap *m, *maps;
1106 s = (XStandardColormap *) malloc((unsigned) ((count+1) * sizeof
1107 (XStandardColormap)));
1109 for (i = 0, m = s, maps = stdcmaps; i < count; i++, m++, maps++) {
1110 m->colormap = maps->colormap;
1111 m->red_max = maps->red_max;
1112 m->red_mult = maps->red_mult;
1113 m->green_max = maps->green_max;
1114 m->green_mult = maps->green_mult;
1115 m->blue_max = maps->blue_max;
1116 m->blue_mult = maps->blue_mult;
1117 m->base_pixel = maps->base_pixel;
1118 m->visualid = maps->visualid;
1119 m->killid = maps->killid;
1121 m->colormap = cnew->colormap;
1122 m->red_max = cnew->red_max;
1123 m->red_mult = cnew->red_mult;
1124 m->green_max = cnew->green_max;
1125 m->green_mult = cnew->green_mult;
1126 m->blue_max = cnew->blue_max;
1127 m->blue_mult = cnew->blue_mult;
1128 m->base_pixel = cnew->base_pixel;
1129 m->visualid = cnew->visualid;
1130 m->killid = cnew->killid;
1132 XSetRGBColormaps(dpy, win, s, ++count, property);
1135 XFree((char *) stdcmaps);
1139 /* Found an RGB_DEFAULT_MAP property with a matching visualid */
1142 /* Free old resources first - we may need them, particularly in
1143 * the default colormap of the screen. However, because of this,
1144 * it is possible that we will destroy the old resource and fail
1145 * to create a new one if XmuStandardColormap() fails.
1149 XmuDeleteStandardColormap(dpy, screen, property);
1151 XSetRGBColormaps(dpy, win, cnew, 1, property);
1154 XStandardColormap *map;
1156 /* s still points to the matching standard colormap */
1158 if (s->killid == ReleaseByFreeingColormap) {
1159 if ((s->colormap != None) &&
1160 (s->colormap != DefaultColormap(dpy, screen)))
1161 XFreeColormap(dpy, s->colormap);
1163 else if (s->killid != None)
1164 XKillClient(dpy, s->killid);
1166 map = (cnew) ? cnew : stdcmaps + --count;
1168 s->colormap = map->colormap;
1169 s->red_max = map->red_max;
1170 s->red_mult = map->red_mult;
1171 s->green_max = map->green_max;
1172 s->green_mult = map->green_mult;
1173 s->blue_max = map->blue_max;
1174 s->blue_mult = map->blue_mult;
1175 s->visualid = map->visualid;
1176 s->killid = map->killid;
1178 XSetRGBColormaps(dpy, win, stdcmaps, count, property);
1181 XFree((char *) stdcmaps);
1185 /* $Xorg: CmapAlloc.c,v 1.4 2001/02/09 02:03:51 xorgcvs Exp $ */
1189 Copyright 1989, 1994, 1998 The Open Group
1191 Permission to use, copy, modify, distribute, and sell this software and its
1192 documentation for any purpose is hereby granted without fee, provided that
1193 the above copyright notice appear in all copies and that both that
1194 copyright notice and this permission notice appear in supporting
1197 The above copyright notice and this permission notice shall be included in
1198 all copies or substantial portions of the Software.
1200 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1201 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1202 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1203 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1204 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1205 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1207 Except as contained in this notice, the name of The Open Group shall not be
1208 used in advertising or otherwise to promote the sale, use or other dealings
1209 in this Software without prior written authorization from The Open Group.
1212 /* $XFree86: xc/lib/Xmu/CmapAlloc.c,v 1.7 2001/12/14 19:55:35 dawes Exp $ */
1215 * Author: Donna Converse, MIT X Consortium
1218 #include <X11/Xlib.h>
1219 #include <X11/Xatom.h>
1220 #include <X11/Xutil.h>
1221 #include <X11/Xmu/StdCmap.h>
1224 #define lowbit(x) ((x) & (~(x) + 1))
1229 static void best_allocation(XVisualInfo*, unsigned long*, unsigned long*,
1231 static int default_allocation(XVisualInfo*, unsigned long*,
1232 unsigned long*, unsigned long*);
1233 static void gray_allocation(int, unsigned long*, unsigned long*,
1235 static int icbrt(int);
1236 static int icbrt_with_bits(int, int);
1237 static int icbrt_with_guess(int, int);
1239 /* To determine the best allocation of reds, greens, and blues in a
1240 * standard colormap, use XmuGetColormapAllocation.
1241 * vinfo specifies visual information for a chosen visual
1242 * property specifies one of the standard colormap property names
1243 * red_max returns maximum red value
1244 * green_max returns maximum green value
1245 * blue_max returns maximum blue value
1247 * XmuGetColormapAllocation returns 0 on failure, non-zero on success.
1248 * It is assumed that the visual is appropriate for the colormap property.
1252 XmuGetColormapAllocation(XVisualInfo *vinfo, Atom property,
1253 unsigned long *red_max,
1254 unsigned long *green_max,
1255 unsigned long *blue_max)
1259 if (vinfo->colormap_size <= 2)
1264 case XA_RGB_DEFAULT_MAP:
1265 status = default_allocation(vinfo, red_max, green_max, blue_max);
1267 case XA_RGB_BEST_MAP:
1268 best_allocation(vinfo, red_max, green_max, blue_max);
1270 case XA_RGB_GRAY_MAP:
1271 gray_allocation(vinfo->colormap_size, red_max, green_max, blue_max);
1273 case XA_RGB_RED_MAP:
1274 *red_max = vinfo->colormap_size - 1;
1275 *green_max = *blue_max = 0;
1277 case XA_RGB_GREEN_MAP:
1278 *green_max = vinfo->colormap_size - 1;
1279 *red_max = *blue_max = 0;
1281 case XA_RGB_BLUE_MAP:
1282 *blue_max = vinfo->colormap_size - 1;
1283 *red_max = *green_max = 0;
1291 /****************************************************************************/
1292 /* Determine the appropriate color allocations of a gray scale.
1294 * Keith Packard, MIT X Consortium
1298 gray_allocation(int n, unsigned long *red_max, unsigned long *green_max,
1299 unsigned long *blue_max)
1301 *red_max = (n * 30) / 100;
1302 *green_max = (n * 59) / 100;
1303 *blue_max = (n * 11) / 100;
1304 *green_max += ((n - 1) - (*red_max + *green_max + *blue_max));
1307 /****************************************************************************/
1308 /* Determine an appropriate color allocation for the RGB_DEFAULT_MAP.
1309 * If a map has less than a minimum number of definable entries, we do not
1310 * produce an allocation for an RGB_DEFAULT_MAP.
1312 * For 16 planes, the default colormap will have 27 each RGB; for 12 planes,
1313 * 12 each. For 8 planes, let n = the number of colormap entries, which may
1314 * be 256 or 254. Then, maximum red value = floor(cube_root(n - 125)) - 1.
1315 * Maximum green and maximum blue values are identical to maximum red.
1316 * This leaves at least 125 cells which clients can allocate.
1318 * Return 0 if an allocation has been determined, non-zero otherwise.
1322 default_allocation(XVisualInfo *vinfo, unsigned long *red,
1323 unsigned long *green, unsigned long *blue)
1325 int ngrays; /* number of gray cells */
1327 switch (vinfo->c_class)
1331 if (vinfo->colormap_size > 65000)
1332 /* intended for displays with 16 planes */
1333 *red = *green = *blue = (unsigned long) 27;
1334 else if (vinfo->colormap_size > 4000)
1335 /* intended for displays with 12 planes */
1336 *red = *green = *blue = (unsigned long) 12;
1337 else if (vinfo->colormap_size < 250)
1340 /* intended for displays with 8 planes */
1341 *red = *green = *blue = (unsigned long)
1342 (icbrt(vinfo->colormap_size - 125) - 1);
1347 if (vinfo->colormap_size < 10)
1349 *red = *green = *blue = vinfo->colormap_size / 2 - 1;
1354 *red = vinfo->red_mask / lowbit(vinfo->red_mask);
1355 *green = vinfo->green_mask / lowbit(vinfo->green_mask);
1356 *blue = vinfo->blue_mask / lowbit(vinfo->blue_mask);
1361 if (vinfo->colormap_size > 65000)
1363 else if (vinfo->colormap_size > 4000)
1365 else if (vinfo->colormap_size < 250)
1369 gray_allocation(ngrays, red, green, blue);
1378 /****************************************************************************/
1379 /* Determine an appropriate color allocation for the RGB_BEST_MAP.
1381 * For a DirectColor or TrueColor visual, the allocation is determined
1382 * by the red_mask, green_mask, and blue_mask members of the visual info.
1384 * Otherwise, if the colormap size is an integral power of 2, determine
1385 * the allocation according to the number of bits given to each color,
1386 * with green getting more than red, and red more than blue, if there
1387 * are to be inequities in the distribution. If the colormap size is
1388 * not an integral power of 2, let n = the number of colormap entries.
1389 * Then maximum red value = floor(cube_root(n)) - 1;
1390 * maximum blue value = floor(cube_root(n)) - 1;
1391 * maximum green value = n / ((# red values) * (# blue values)) - 1;
1392 * Which, on a GPX, allows for 252 entries in the best map, out of 254
1393 * defineable colormap entries.
1397 best_allocation(XVisualInfo *vinfo, unsigned long *red, unsigned long *green,
1398 unsigned long *blue)
1401 if (vinfo->c_class == DirectColor || vinfo->c_class == TrueColor)
1403 *red = vinfo->red_mask;
1404 while ((*red & 01) == 0)
1406 *green = vinfo->green_mask;
1407 while ((*green & 01) == 0)
1409 *blue = vinfo->blue_mask;
1410 while ((*blue & 01) == 0)
1415 register int bits, n;
1417 /* Determine n such that n is the least integral power of 2 which is
1418 * greater than or equal to the number of entries in the colormap.
1422 while (vinfo->colormap_size > n)
1428 /* If the number of entries in the colormap is a power of 2, determine
1429 * the allocation by "dealing" the bits, first to green, then red, then
1430 * blue. If not, find the maximum integral red, green, and blue values
1431 * which, when multiplied together, do not exceed the number of
1435 if (n == vinfo->colormap_size)
1437 register int r, g, b;
1439 g = b + ((bits % 3) ? 1 : 0);
1440 r = b + (((bits % 3) == 2) ? 1 : 0);
1447 *red = icbrt_with_bits(vinfo->colormap_size, bits);
1449 *green = (vinfo->colormap_size / ((*red) * (*blue)));
1459 * integer cube roots by Newton's method
1461 * Stephen Gildea, MIT X Consortium, July 1991
1467 register int bits = 0;
1468 register unsigned n = a;
1475 return icbrt_with_bits(a, bits);
1480 icbrt_with_bits(int a, int bits)
1481 /* bits - log 2 of a */
1483 return icbrt_with_guess(a, a>>2*bits/3);
1486 #ifdef _X_ROOT_STATS
1487 int icbrt_loopcount;
1490 /* Newton's Method: x_n+1 = x_n - ( f(x_n) / f'(x_n) ) */
1492 /* for cube roots, x^3 - a = 0, x_new = x - 1/3 (x - a/x^2) */
1495 * Quick and dirty cube roots. Nothing fancy here, just Newton's method.
1496 * Only works for positive integers (since that's all we need).
1497 * We actually return floor(cbrt(a)) because that's what we need here, too.
1501 icbrt_with_guess(int a, int guess)
1505 #ifdef _X_ROOT_STATS
1506 icbrt_loopcount = 0;
1514 #ifdef _X_ROOT_STATS
1517 delta = (guess - a/(guess*guess))/3;
1519 printf("pass %d: guess=%d, delta=%d\n", icbrt_loopcount, guess, delta);
1522 } while (delta != 0);
1524 if (guess*guess*guess > a)
1531 /* $Xorg: StdCmap.c,v 1.4 2001/02/09 02:03:53 xorgcvs Exp $ */
1535 Copyright 1989, 1998 The Open Group
1537 Permission to use, copy, modify, distribute, and sell this software and its
1538 documentation for any purpose is hereby granted without fee, provided that
1539 the above copyright notice appear in all copies and that both that
1540 copyright notice and this permission notice appear in supporting
1543 The above copyright notice and this permission notice shall be included in
1544 all copies or substantial portions of the Software.
1546 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1547 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1548 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1549 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1550 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1551 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1553 Except as contained in this notice, the name of The Open Group shall not be
1554 used in advertising or otherwise to promote the sale, use or other dealings
1555 in this Software without prior written authorization from The Open Group.
1558 /* $XFree86: xc/lib/Xmu/StdCmap.c,v 1.6 2001/12/14 19:55:48 dawes Exp $ */
1561 * Author: Donna Converse, MIT X Consortium
1565 #include <X11/Xlib.h>
1566 #include <X11/Xatom.h>
1567 #include <X11/Xutil.h>
1568 #include <X11/Xmu/StdCmap.h>
1570 #define lowbit(x) ((x) & (~(x) + 1))
1575 /* argument restrictions */
1576 static Status valid_args(XVisualInfo*, unsigned long, unsigned long,
1577 unsigned long, Atom);
1580 * To create any one standard colormap, use XmuStandardColormap().
1582 * Create a standard colormap for the given screen, visualid, and visual
1583 * depth, with the given red, green, and blue maximum values, with the
1584 * given standard property name. Return a pointer to an XStandardColormap
1585 * structure which describes the newly created colormap, upon success.
1586 * Upon failure, return NULL.
1588 * XmuStandardColormap() calls XmuCreateColormap() to create the map.
1590 * Resources created by this function are not made permanent; that is the
1591 * caller's responsibility.
1595 XmuStandardColormap(Display *dpy, int screen, VisualID visualid,
1596 unsigned int depth, Atom property, Colormap cmap,
1597 unsigned long red_max, unsigned long green_max,
1598 unsigned long blue_max)
1600 * dpy - specifies X server connection
1601 * screen - specifies display screen
1602 * visualid - identifies the visual type
1603 * depth - identifies the visual type
1604 * property - a standard colormap property
1605 * cmap - specifies colormap ID or None
1606 * red_max, green_max, blue_max - allocations
1609 XStandardColormap *stdcmap;
1611 XVisualInfo vinfo_template, *vinfo;
1615 /* Match the required visual information to an actual visual */
1616 vinfo_template.visualid = visualid;
1617 vinfo_template.screen = screen;
1618 vinfo_template.depth = depth;
1619 vinfo_mask = VisualIDMask | VisualScreenMask | VisualDepthMask;
1620 if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &n)) == NULL)
1623 /* Check the validity of the combination of visual characteristics,
1624 * allocation, and colormap property. Create an XStandardColormap
1628 if (! valid_args(vinfo, red_max, green_max, blue_max, property)
1629 || ((stdcmap = XAllocStandardColormap()) == NULL)) {
1630 XFree((char *) vinfo);
1634 /* Fill in the XStandardColormap structure */
1636 if (cmap == DefaultColormap(dpy, screen)) {
1637 /* Allocating out of the default map, cannot use XFreeColormap() */
1638 Window win = XCreateWindow(dpy, RootWindow(dpy, screen), 1, 1, 1, 1,
1639 0, 0, InputOnly, vinfo->visual,
1641 (XSetWindowAttributes *)NULL);
1642 stdcmap->killid = (XID) XCreatePixmap(dpy, win, 1, 1, depth);
1643 XDestroyWindow(dpy, win);
1644 stdcmap->colormap = cmap;
1646 stdcmap->killid = ReleaseByFreeingColormap;
1647 stdcmap->colormap = XCreateColormap(dpy, RootWindow(dpy, screen),
1648 vinfo->visual, AllocNone);
1650 stdcmap->red_max = red_max;
1651 stdcmap->green_max = green_max;
1652 stdcmap->blue_max = blue_max;
1653 if (property == XA_RGB_GRAY_MAP)
1654 stdcmap->red_mult = stdcmap->green_mult = stdcmap->blue_mult = 1;
1655 else if (vinfo->c_class == TrueColor || vinfo->c_class == DirectColor) {
1656 stdcmap->red_mult = lowbit(vinfo->red_mask);
1657 stdcmap->green_mult = lowbit(vinfo->green_mask);
1658 stdcmap->blue_mult = lowbit(vinfo->blue_mask);
1660 stdcmap->red_mult = (red_max > 0)
1661 ? (green_max + 1) * (blue_max + 1) : 0;
1662 stdcmap->green_mult = (green_max > 0) ? blue_max + 1 : 0;
1663 stdcmap->blue_mult = (blue_max > 0) ? 1 : 0;
1665 stdcmap->base_pixel = 0; /* base pixel may change */
1666 stdcmap->visualid = vinfo->visualid;
1668 /* Make the colormap */
1670 status = XmuCreateColormap(dpy, stdcmap);
1674 XFree((char *) vinfo);
1677 /* Free the colormap or the pixmap, if we created one */
1678 if (stdcmap->killid == ReleaseByFreeingColormap)
1679 XFreeColormap(dpy, stdcmap->colormap);
1680 else if (stdcmap->killid != None)
1681 XFreePixmap(dpy, stdcmap->killid);
1683 XFree((char *) stdcmap);
1684 return (XStandardColormap *) NULL;
1689 /****************************************************************************/
1691 valid_args(XVisualInfo *vinfo, unsigned long red_max, unsigned long green_max,
1692 unsigned long blue_max, Atom property)
1694 * vinfo - specifies visual
1695 * red_max, green_max, blue_max - specifies alloc
1696 * property - specifies property name
1699 unsigned long ncolors; /* number of colors requested */
1701 /* Determine that the number of colors requested is <= map size */
1703 if ((vinfo->c_class == DirectColor) || (vinfo->c_class == TrueColor)) {
1706 mask = vinfo->red_mask;
1711 mask = vinfo->green_mask;
1714 if (green_max > mask)
1716 mask = vinfo->blue_mask;
1719 if (blue_max > mask)
1721 } else if (property == XA_RGB_GRAY_MAP) {
1722 ncolors = red_max + green_max + blue_max + 1;
1723 if (ncolors > vinfo->colormap_size)
1726 ncolors = (red_max + 1) * (green_max + 1) * (blue_max + 1);
1727 if (ncolors > vinfo->colormap_size)
1731 /* Determine that the allocation and visual make sense for the property */
1735 case XA_RGB_DEFAULT_MAP:
1736 if (red_max == 0 || green_max == 0 || blue_max == 0)
1739 case XA_RGB_RED_MAP:
1743 case XA_RGB_GREEN_MAP:
1747 case XA_RGB_BLUE_MAP:
1751 case XA_RGB_BEST_MAP:
1752 if (red_max == 0 || green_max == 0 || blue_max == 0)
1755 case XA_RGB_GRAY_MAP:
1756 if (red_max == 0 || blue_max == 0 || green_max == 0)
1766 /* $Xorg: CrCmap.c,v 1.4 2001/02/09 02:03:51 xorgcvs Exp $ */
1770 Copyright 1989, 1998 The Open Group
1772 Permission to use, copy, modify, distribute, and sell this software and its
1773 documentation for any purpose is hereby granted without fee, provided that
1774 the above copyright notice appear in all copies and that both that
1775 copyright notice and this permission notice appear in supporting
1778 The above copyright notice and this permission notice shall be included in
1779 all copies or substantial portions of the Software.
1781 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1782 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1783 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1784 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1785 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1786 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1788 Except as contained in this notice, the name of The Open Group shall not be
1789 used in advertising or otherwise to promote the sale, use or other dealings
1790 in this Software without prior written authorization from The Open Group.
1793 /* $XFree86: xc/lib/Xmu/CrCmap.c,v 3.7 2001/12/14 19:55:36 dawes Exp $ */
1796 * Author: Donna Converse, MIT X Consortium
1800 * CreateCmap.c - given a standard colormap description, make the map.
1805 #include <X11/Xlib.h>
1806 #include <X11/Xutil.h>
1807 #include <X11/Xmu/StdCmap.h>
1812 /* allocate entire map Read Only */
1813 static int ROmap(Display*, Colormap, unsigned long[], int, int);
1815 /* allocate a cell, prefer Read Only */
1816 static Status ROorRWcell(Display*, Colormap, unsigned long[], int,
1817 XColor*, unsigned long);
1819 /* allocate a cell Read Write */
1820 static Status RWcell(Display*, Colormap, XColor*, XColor*, unsigned long*);
1823 static int compare(_Xconst void*, _Xconst void*);
1825 /* find contiguous sequence of cells */
1826 static Status contiguous(unsigned long[], int, int, unsigned long, int*, int*);
1828 /* frees resources before quitting */
1829 static void free_cells(Display*, Colormap, unsigned long[], int, int);
1831 /* create a map in a RO visual type */
1832 static Status readonly_map(Display*, XVisualInfo*, XStandardColormap*);
1834 /* create a map in a RW visual type */
1835 static Status readwrite_map(Display*, XVisualInfo*, XStandardColormap*);
1837 #define lowbit(x) ((x) & (~(x) + 1))
1838 #define TRUEMATCH(mult,max,mask) \
1839 (colormap->max * colormap->mult <= vinfo->mask && \
1840 lowbit(vinfo->mask) == colormap->mult)
1843 * To create any one colormap which is described by an XStandardColormap
1844 * structure, use XmuCreateColormap().
1846 * Return 0 on failure, non-zero on success.
1847 * Resources created by this function are not made permanent.
1848 * No argument error checking is provided. Use at your own risk.
1850 * All colormaps are created with read only allocations, with the exception
1851 * of read only allocations of colors in the default map or otherwise
1852 * which fail to return the expected pixel value, and these are individually
1853 * defined as read/write allocations. This is done so that all the cells
1854 * defined in the default map are contiguous, for use in image processing.
1855 * This typically happens with White and Black in the default map.
1857 * Colormaps of static visuals are considered to be successfully created if
1858 * the map of the static visual matches the definition given in the
1859 * standard colormap structure.
1863 XmuCreateColormap(Display *dpy, XStandardColormap *colormap)
1864 /* dpy - specifies the connection under which the map is created
1865 * colormap - specifies the map to be created, and returns, particularly
1866 * if the map is created as a subset of the default colormap
1867 * of the screen, the base_pixel of the map.
1870 XVisualInfo vinfo_template; /* template visual information */
1871 XVisualInfo *vinfo; /* matching visual information */
1872 XVisualInfo *vpointer; /* for freeing the entire list */
1873 long vinfo_mask; /* specifies the visual mask value */
1874 int n; /* number of matching visuals */
1877 vinfo_template.visualid = colormap->visualid;
1878 vinfo_mask = VisualIDMask;
1879 if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &n)) == NULL)
1882 /* A visual id may be valid on multiple screens. Also, there may
1883 * be multiple visuals with identical visual ids at different depths.
1884 * If the colormap is the Default Colormap, use the Default Visual.
1885 * Otherwise, arbitrarily, use the deepest visual.
1891 register int screen_number;
1895 for (screen_number = ScreenCount(dpy); --screen_number >= 0; )
1896 if (colormap->colormap == DefaultColormap(dpy, screen_number)) {
1902 for (i=0; i < n; i++, vinfo++) {
1903 if (vinfo->visual == DefaultVisual(dpy, screen_number))
1908 XVisualInfo *v = NULL;
1910 for (i=0; i < n; i++, vinfo++)
1911 if (vinfo->depth > maxdepth) {
1912 maxdepth = vinfo->depth;
1919 if (vinfo->c_class == PseudoColor || vinfo->c_class == DirectColor ||
1920 vinfo->c_class == GrayScale)
1921 status = readwrite_map(dpy, vinfo, colormap);
1922 else if (vinfo->c_class == TrueColor)
1923 status = TRUEMATCH(red_mult, red_max, red_mask) &&
1924 TRUEMATCH(green_mult, green_max, green_mask) &&
1925 TRUEMATCH(blue_mult, blue_max, blue_mask);
1927 status = readonly_map(dpy, vinfo, colormap);
1929 XFree((char *) vpointer);
1933 /****************************************************************************/
1935 readwrite_map(Display *dpy, XVisualInfo *vinfo, XStandardColormap *colormap)
1937 register unsigned long i, n; /* index counters */
1938 unsigned long ncolors; /* number of colors to be defined */
1939 int npixels; /* number of pixels allocated R/W */
1940 int first_index; /* first index of pixels to use */
1941 int remainder; /* first index of remainder */
1942 XColor color; /* the definition of a color */
1943 unsigned long *pixels; /* array of colormap pixels */
1944 unsigned long delta;
1947 /* Determine ncolors, the number of colors to be defined.
1948 * Insure that 1 < ncolors <= the colormap size.
1950 if (vinfo->c_class == DirectColor) {
1951 ncolors = colormap->red_max;
1952 if (colormap->green_max > ncolors)
1953 ncolors = colormap->green_max;
1954 if (colormap->blue_max > ncolors)
1955 ncolors = colormap->blue_max;
1957 delta = lowbit(vinfo->red_mask) +
1958 lowbit(vinfo->green_mask) +
1959 lowbit(vinfo->blue_mask);
1961 ncolors = colormap->red_max * colormap->red_mult +
1962 colormap->green_max * colormap->green_mult +
1963 colormap->blue_max * colormap->blue_mult + 1;
1966 if (ncolors <= 1 || (int) ncolors > vinfo->colormap_size) return 0;
1968 /* Allocate Read/Write as much of the colormap as we can possibly get.
1969 * Then insure that the pixels we were allocated are given in
1970 * monotonically increasing order, using a quicksort. Next, insure
1971 * that our allocation includes a subset of contiguous pixels at least
1972 * as long as the number of colors to be defined. Now we know that
1973 * these conditions are met:
1974 * 1) There are no free cells in the colormap.
1975 * 2) We have a contiguous sequence of pixels, monotonically
1976 * increasing, of length >= the number of colors requested.
1978 * One cell at a time, we will free, compute the next color value,
1979 * then allocate read only. This takes a long time.
1980 * This is done to insure that cells are allocated read only in the
1981 * contiguous order which we prefer. If the server has a choice of
1982 * cells to grant to an allocation request, the server may give us any
1983 * cell, so that is why we do these slow gymnastics.
1986 if ((pixels = (unsigned long *) calloc((unsigned) vinfo->colormap_size,
1987 sizeof(unsigned long))) == NULL)
1990 if ((npixels = ROmap(dpy, colormap->colormap, pixels,
1991 vinfo->colormap_size, ncolors)) == 0) {
1992 free((char *) pixels);
1996 qsort((char *) pixels, npixels, sizeof(unsigned long), compare);
1998 if (!contiguous(pixels, npixels, ncolors, delta, &first_index, &remainder))
2000 /* can't find enough contiguous cells, give up */
2001 XFreeColors(dpy, colormap->colormap, pixels, npixels,
2003 free((char *) pixels);
2006 colormap->base_pixel = pixels[first_index];
2008 /* construct a gray map */
2009 if (colormap->red_mult == 1 && colormap->green_mult == 1 &&
2010 colormap->blue_mult == 1)
2011 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
2014 color.blue = color.green = color.red =
2015 (unsigned short) ((i * 65535) / (colormap->red_max +
2016 colormap->green_max +
2017 colormap->blue_max));
2019 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
2024 /* construct a red ramp map */
2025 else if (colormap->green_max == 0 && colormap->blue_max == 0)
2026 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
2029 color.red = (unsigned short) ((i * 65535) / colormap->red_max);
2030 color.green = color.blue = 0;
2032 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
2037 /* construct a green ramp map */
2038 else if (colormap->red_max == 0 && colormap->blue_max == 0)
2039 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
2042 color.green = (unsigned short) ((i * 65535) / colormap->green_max);
2043 color.red = color.blue = 0;
2045 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
2050 /* construct a blue ramp map */
2051 else if (colormap->red_max == 0 && colormap->green_max == 0)
2052 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
2055 color.blue = (unsigned short) ((i * 65535) / colormap->blue_max);
2056 color.red = color.green = 0;
2058 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
2063 /* construct a standard red green blue cube map */
2066 #define calc(max,mult) (((n / colormap->mult) % \
2067 (colormap->max + 1)) * 65535) / colormap->max
2069 for (n=0, i=0; i < ncolors; i++, n += delta)
2071 color.pixel = n + colormap->base_pixel;
2072 color.red = calc(red_max, red_mult);
2073 color.green = calc(green_max, green_mult);
2074 color.blue = calc(blue_max, blue_mult);
2075 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
2081 /* We have a read-only map defined. Now free unused cells,
2082 * first those occuring before the contiguous sequence begins,
2083 * then any following the contiguous sequence.
2087 XFreeColors(dpy, colormap->colormap, pixels, first_index,
2090 XFreeColors(dpy, colormap->colormap,
2091 &(pixels[first_index + ncolors]), remainder,
2094 free((char *) pixels);
2099 /****************************************************************************/
2101 ROmap(Display *dpy, Colormap cmap, unsigned long pixels[], int m, int n)
2103 * dpy - the X server connection
2104 * cmap - specifies colormap ID
2105 * pixels - returns pixel allocations
2106 * m - specifies colormap size
2107 * n - specifies number of colors
2112 /* first try to allocate the entire colormap */
2113 if (XAllocColorCells(dpy, cmap, 1, (unsigned long *) NULL,
2114 (unsigned) 0, pixels, (unsigned) m))
2117 /* Allocate all available cells in the colormap, using a binary
2118 * algorithm to discover how many cells we can allocate in the colormap.
2122 p = n + ((m - n + 1) / 2);
2123 if (XAllocColorCells(dpy, cmap, 1, (unsigned long *) NULL,
2124 (unsigned) 0, pixels, (unsigned) p)) {
2128 XFreeColors(dpy, cmap, pixels, p, (unsigned long) 0);
2139 /****************************************************************************/
2141 contiguous(unsigned long pixels[], int npixels, int ncolors,
2142 unsigned long delta, int *first, int *rem)
2143 /* pixels - specifies allocated pixels
2144 * npixels - specifies count of alloc'd pixels
2145 * ncolors - specifies needed sequence length
2146 * delta - between pixels
2147 * first - returns first index of sequence
2148 * rem - returns first index after sequence, or 0, if none follow
2151 register int i = 1; /* walking index into the pixel array */
2152 register int count = 1; /* length of sequence discovered so far */
2155 if (npixels == ncolors) {
2160 while (count < ncolors && ncolors - count <= *rem)
2162 if (pixels[i-1] + delta == pixels[i])
2171 if (count != ncolors)
2177 /****************************************************************************/
2179 ROorRWcell(Display *dpy, Colormap cmap, unsigned long pixels[],
2180 int npixels, XColor *color, unsigned long p)
2182 unsigned long pixel;
2185 /* Free the read/write allocation of one cell in the colormap.
2186 * Request a read only allocation of one cell in the colormap.
2187 * If the read only allocation cannot be granted, give up, because
2188 * there must be no free cells in the colormap.
2189 * If the read only allocation is granted, but gives us a cell which
2190 * is not the one that we just freed, it is probably the case that
2191 * we are trying allocate White or Black or some other color which
2192 * already has a read-only allocation in the map. So we try to
2193 * allocate the previously freed cell with a read/write allocation,
2194 * because we want contiguous cells for image processing algorithms.
2197 pixel = color->pixel;
2198 request.red = color->red;
2199 request.green = color->green;
2200 request.blue = color->blue;
2202 XFreeColors(dpy, cmap, &pixel, 1, (unsigned long) 0);
2203 if (! XAllocColor(dpy, cmap, color)
2204 || (color->pixel != pixel &&
2205 (!RWcell(dpy, cmap, color, &request, &pixel))))
2207 free_cells(dpy, cmap, pixels, npixels, (int)p);
2214 /****************************************************************************/
2216 free_cells(Display *dpy, Colormap cmap, unsigned long pixels[],
2219 * pixels - to be freed
2220 * npixels - original number allocated
2223 /* One of the npixels allocated has already been freed.
2224 * p is the index of the freed pixel.
2225 * First free the pixels preceeding p, and there are p of them;
2226 * then free the pixels following p, there are npixels - p - 1 of them.
2228 XFreeColors(dpy, cmap, pixels, p, (unsigned long) 0);
2229 XFreeColors(dpy, cmap, &(pixels[p+1]), npixels - p - 1, (unsigned long) 0);
2230 free((char *) pixels);
2234 /****************************************************************************/
2236 RWcell(Display *dpy, Colormap cmap, XColor *color, XColor *request,
2237 unsigned long *pixel)
2239 unsigned long n = *pixel;
2241 XFreeColors(dpy, cmap, &(color->pixel), 1, (unsigned long)0);
2242 if (! XAllocColorCells(dpy, cmap, (Bool) 0, (unsigned long *) NULL,
2243 (unsigned) 0, pixel, (unsigned) 1))
2247 XFreeColors(dpy, cmap, pixel, 1, (unsigned long) 0);
2250 color->pixel = *pixel;
2251 color->flags = DoRed | DoGreen | DoBlue;
2252 color->red = request->red;
2253 color->green = request->green;
2254 color->blue = request->blue;
2255 XStoreColors(dpy, cmap, color, 1);
2260 /****************************************************************************/
2262 compare(_Xconst void *e1, _Xconst void *e2)
2264 return ((int)(*(long *)e1 - *(long *)e2));
2268 /****************************************************************************/
2270 readonly_map(Display *dpy, XVisualInfo *vinfo, XStandardColormap *colormap)
2275 last_pixel = (colormap->red_max + 1) * (colormap->green_max + 1) *
2276 (colormap->blue_max + 1) + colormap->base_pixel - 1;
2278 for(i=colormap->base_pixel; i <= last_pixel; i++) {
2280 color.pixel = (unsigned long) i;
2281 color.red = (unsigned short)
2282 (((i/colormap->red_mult) * 65535) / colormap->red_max);
2284 if (vinfo->c_class == StaticColor) {
2285 color.green = (unsigned short)
2286 ((((i/colormap->green_mult) % (colormap->green_max + 1)) *
2287 65535) / colormap->green_max);
2288 color.blue = (unsigned short)
2289 (((i%colormap->green_mult) * 65535) / colormap->blue_max);
2291 else /* vinfo->c_class == GrayScale, old style allocation XXX */
2292 color.green = color.blue = color.red;
2294 XAllocColor(dpy, colormap->colormap, &color);
2295 if (color.pixel != (unsigned long) i)
2302 /* $Xorg: DelCmap.c,v 1.4 2001/02/09 02:03:52 xorgcvs Exp $ */
2306 Copyright 1989, 1998 The Open Group
2308 Permission to use, copy, modify, distribute, and sell this software and its
2309 documentation for any purpose is hereby granted without fee, provided that
2310 the above copyright notice appear in all copies and that both that
2311 copyright notice and this permission notice appear in supporting
2314 The above copyright notice and this permission notice shall be included in
2315 all copies or substantial portions of the Software.
2317 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2318 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2319 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2320 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
2321 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
2322 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2324 Except as contained in this notice, the name of The Open Group shall not be
2325 used in advertising or otherwise to promote the sale, use or other dealings
2326 in this Software without prior written authorization from The Open Group.
2329 /* $XFree86: xc/lib/Xmu/DelCmap.c,v 1.7 2001/12/14 19:55:40 dawes Exp $ */
2332 * Author: Donna Converse, MIT X Consortium
2335 #include <X11/Xlib.h>
2336 #include <X11/Xutil.h>
2337 #include <X11/Xmu/StdCmap.h>
2339 int ignoreErrorHandler(Display* d, XErrorEvent* e) { }
2341 /* To remove any standard colormap property, use XmuDeleteStandardColormap().
2342 * XmuDeleteStandardColormap() will remove the specified property from the
2343 * specified screen, releasing any resources used by the colormap(s) of the
2344 * property if possible.
2348 XmuDeleteStandardColormap(Display *dpy, int screen, Atom property)
2349 /* dpy; - specifies the X server to connect to
2350 * screen - specifies the screen of the display
2351 * property - specifies the standard colormap property
2354 XStandardColormap *stdcmaps, *s;
2357 if (XGetRGBColormaps(dpy, RootWindow(dpy, screen), &stdcmaps, &count,
2360 for (s=stdcmaps; count > 0; count--, s++) {
2361 if ((s->killid == ReleaseByFreeingColormap) &&
2362 (s->colormap != None) &&
2363 (s->colormap != DefaultColormap(dpy, screen))) {
2365 // UGLY HACK written in by Adam Megacz -- sometimes s->colormap isn't valid, so we do some shuffling
2366 X11ErrorHandler* oldHandler = XSetErrorHandler(ignoreErrorHandler);
2368 XFreeColormap(dpy, s->colormap);
2370 XSetErrorHandler(oldHandler);
2373 } else if (s->killid != None) {
2374 XKillClient(dpy, s->killid);
2377 XDeleteProperty(dpy, RootWindow(dpy, screen), property);
2378 XFree((char *) stdcmaps);