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 == SelectionNotify) {
471 XSelectionEvent* xsn = (XSelectionEvent*)(e);
472 if (xsn->property == None) org::xwt::plat::POSIX::clipboard = JvNewStringLatin1("", 0);
476 unsigned long numitems;
478 unsigned long bytes_after;
479 XGetWindowProperty(display, xsn->requestor, xsn->property, 0, 4096,
480 True, AnyPropertyType, &returntype, &returnformat,
481 &numitems, &bytes_after, &ret);
482 org::xwt::plat::POSIX::clipboard =
483 (returntype == None ? JvNewStringLatin1("", 0) : JvNewStringLatin1((char*)ret, strlen((char*)ret)));
485 org::xwt::plat::POSIX::waiting_for_selection_event->release();
487 } else if (e->type == SelectionRequest) {
488 XSelectionRequestEvent* xsr = (XSelectionRequestEvent*)(e);
490 xsn.type = SelectionNotify;
491 xsn.serial = xsr->serial;
492 xsn.send_event = True;
493 xsn.display = display;
494 xsn.requestor = xsr->requestor;
495 xsn.selection = xsr->selection;
496 xsn.target = xsr->target;
497 xsn.property = xsr->property;
498 xsn.time = xsr->time;
500 int len = min(1024, JvGetStringUTFLength(org::xwt::plat::POSIX::clipboard));
502 JvGetStringUTFRegion(org::xwt::plat::POSIX::clipboard, 0, len, buf);
505 XChangeProperty(display, xsr->requestor, xsr->property, xsr->target, 8, PropModeReplace, (unsigned char*)buf, len + 1);
506 XSendEvent(display, xsr->requestor, True, 0, (XEvent*)(&xsn));
508 } else if (e->type == KeyPress || e->type == KeyRelease) {
509 XKeyEvent *xbe = (XKeyEvent*)(e);
511 // drop faked KeyRelease events generated by the X server's autorepeat
512 if (e->type == KeyRelease) {
514 XQueryKeymap(display, depressed);
515 if ((depressed[(xbe->keycode & 0xff) / 8] & (0x1 << (xbe->keycode % 8))) >> (xbe->keycode % 8)) return;
521 unsigned int savestate = xbe->state;
522 xbe->state = xbe->state & ShiftMask; // ignore everything except shiftmask
523 XLookupString(xbe, s, 20, NULL, NULL);
524 xbe->state = savestate;
526 if (s != NULL && s[0] != '\0' && s[1] == '\0' && s[0] >= 0x20 && s[0] <= 0x7E) {
530 KeySym ks = XKeycodeToKeysym(display, xbe->keycode, 0);
532 case XK_BackSpace: s = "back_space"; break;
533 case XK_Tab: s = "tab"; break;
534 case XK_Linefeed: s = "enter"; break;
535 case XK_Return: s = "enter"; break;
536 case XK_Scroll_Lock: s = "scroll_lock"; break;
537 case XK_Escape: s = "escape"; break;
538 case XK_Insert: s = "insert"; break;
539 case XK_Delete: s = "delete"; break;
540 case XK_Home: s = "home"; break;
541 case XK_Left: s = "left"; break;
542 case XK_Up: s = "up"; break;
543 case XK_Right: s = "right"; break;
544 case XK_Down: s = "down"; break;
545 case XK_Page_Up: s = "page_up"; break;
546 case XK_Page_Down: s = "page_down"; break;
547 case XK_End: s = "end"; break;
548 case XK_Num_Lock: s = "num_lock"; break;
549 case XK_KP_Tab: s = "tab"; break;
550 case XK_KP_Enter: s = "enter"; break;
551 case XK_KP_F1: s = "f1"; break;
552 case XK_KP_F2: s = "f2"; break;
553 case XK_KP_F3: s = "f3"; break;
554 case XK_KP_F4: s = "f4"; break;
555 case XK_KP_Home: s = "home"; break;
556 case XK_KP_Left: s = "left"; break;
557 case XK_KP_Up: s = "up"; break;
558 case XK_KP_Right: s = "right"; break;
559 case XK_KP_Down: s = "down"; break;
560 case XK_KP_Page_Up: s = "page_up"; break;
561 case XK_KP_Page_Down: s = "page_down"; break;
562 case XK_KP_End: s = "end"; break;
563 case XK_KP_Insert: s = "insert"; break;
564 case XK_KP_Delete: s = "delete"; break;
565 case XK_F1: s = "f1"; break;
566 case XK_F2: s = "f2"; break;
567 case XK_F3: s = "f3"; break;
568 case XK_F4: s = "f4"; break;
569 case XK_F5: s = "f5"; break;
570 case XK_F6: s = "f6"; break;
571 case XK_F7: s = "f7"; break;
572 case XK_F8: s = "f8"; break;
573 case XK_F9: s = "f9"; break;
574 case XK_F10: s = "f10"; break;
575 case XK_F11: s = "f11"; break;
576 case XK_F12: s = "f12"; break;
577 case XK_Shift_L: s = "shift"; break;
578 case XK_Shift_R: s = "shift"; break;
579 case XK_Control_L: s = "control"; break;
580 case XK_Control_R: s = "control"; break;
581 case XK_Caps_Lock: s = "caps_lock"; break;
582 case XK_Meta_L: s = "alt"; break;
583 case XK_Meta_R: s = "alt"; break;
584 case XK_Alt_L: s = "alt"; break;
585 case XK_Alt_R: s = "alt"; break;
590 if (e->type == KeyPress) KeyPressed(JvNewStringLatin1(s));
591 if (e->type == KeyRelease) KeyReleased(JvNewStringLatin1(s));
593 } else if (e->type == ButtonPress) {
594 XButtonEvent* xbe = (XButtonEvent*)(e);
595 if (xbe->button == 2) xbe->button = 3;
596 else if (xbe->button == 3) xbe->button = 2;
599 } else if (e->type == ButtonRelease) {
600 XButtonEvent* xbe = (XButtonEvent*)(e);
601 if (xbe->button == 2) xbe->button = 3;
602 else if (xbe->button == 3) xbe->button = 2;
603 Release(xbe->button);
605 } else if (e->type == MotionNotify) {
606 XMotionEvent* xme = (XMotionEvent*)(e);
607 Move(xme->x, xme->y);
609 } else if (e->type == EnterNotify || e->type == LeaveNotify) {
610 XCrossingEvent* xce = (XCrossingEvent*)(e);
611 Move(xce->x, xce->y);
613 } else if (e->type == ConfigureNotify) {
616 XConfigureEvent* xce = (XConfigureEvent*)(e);
617 XTranslateCoordinates(display, (*((Window*)window)), RootWindow(display, screen_num), 0, 0, &x_out, &y_out, &child);
618 if (xce->width != width || xce->height != height) SizeChange(xce->width, xce->height);
619 if (x_out != root->abs(0) || y_out != root->abs(1)) PosChange(x_out, y_out);
624 static jstring crosshair, east, hand, move, north, northeast, northwest,
625 south, southeast, southwest, text, west, wait_string;
626 static Cursor crosshair_cursor, east_cursor, hand_cursor, move_cursor, north_cursor,
627 northeast_cursor, northwest_cursor, south_cursor, southeast_cursor,
628 southwest_cursor, text_cursor, west_cursor, wait_cursor, default_cursor;
630 void org::xwt::plat::POSIX$X11Surface::syncCursor() {
633 if (cursor->equals(crosshair)) curs = crosshair_cursor;
634 else if (cursor->equals(east)) curs = east_cursor;
635 else if (cursor->equals(hand)) curs = hand_cursor;
636 else if (cursor->equals(move)) curs = move_cursor;
637 else if (cursor->equals(north)) curs = north_cursor;
638 else if (cursor->equals(northeast)) curs = northeast_cursor;
639 else if (cursor->equals(northwest)) curs = northwest_cursor;
640 else if (cursor->equals(south)) curs = south_cursor;
641 else if (cursor->equals(southeast)) curs = southeast_cursor;
642 else if (cursor->equals(southwest)) curs = southwest_cursor;
643 else if (cursor->equals(text)) curs = text_cursor;
644 else if (cursor->equals(west)) curs = west_cursor;
645 else if (cursor->equals(wait_string)) curs = wait_cursor;
646 else curs = default_cursor;
648 XDefineCursor(display, (*((Window*)window)), curs);
653 // POSIX ///////////////////////////////////////////////////////////////////
655 jint org::xwt::plat::POSIX::_getScreenWidth() { return WidthOfScreen(DefaultScreenOfDisplay(display)); }
656 jint org::xwt::plat::POSIX::_getScreenHeight() { return HeightOfScreen(DefaultScreenOfDisplay(display)); }
658 jstring org::xwt::plat::POSIX::_getEnv(jstring key) {
659 int len = JvGetStringUTFLength(key);
661 JvGetStringUTFRegion(key, 0, len, buf);
663 char* envstr = getenv(buf);
664 return envstr == NULL ? NULL : JvNewStringLatin1(envstr);
667 void org::xwt::plat::POSIX::spawnChildProcess(JArray<jstring>* cmd) {
668 jstring* cmdstrings = elements(cmd);
669 char* cmd2[cmd->length + 1];
670 cmd2[cmd->length] = NULL;
671 for(int i=0; i<cmd->length; i++) {
672 cmd2[i] = (char*)malloc(JvGetStringUTFLength(cmdstrings[i]));
673 JvGetStringUTFRegion(cmdstrings[i], 0, JvGetStringUTFLength(cmdstrings[i]), cmd2[i]);
677 signal(SIGHUP, SIG_IGN);
678 signal(SIGQUIT, SIG_IGN);
679 signal(SIGINT, SIG_IGN);
680 signal(SIGTERM, SIG_IGN);
682 // ignore SIGPIPE in case we were launched from a browser and the browser closed
683 signal(SIGPIPE, SIG_IGN);
685 execvp(cmd2[0], cmd2);
689 void org::xwt::plat::POSIX::eventThread() {
692 XNextEvent(display, &e);
693 org::xwt::plat::POSIX$X11Surface* surface =
694 (org::xwt::plat::POSIX$X11Surface*)windowToSurfaceMap->get(new java::lang::Long(((XAnyEvent*)&e)->window));
695 if (surface != NULL) surface->dispatchEvent((gnu::gcj::RawData*)&e);
699 jstring org::xwt::plat::POSIX::_getClipBoard() {
700 XConvertSelection(display, XA_PRIMARY, XA_STRING, XInternAtom(display, "VT_SELECTION", False), selectionWindow, CurrentTime);
702 org::xwt::plat::POSIX::waiting_for_selection_event->block();
706 void org::xwt::plat::POSIX::_setClipBoard(jstring s) {
708 int len = JvGetStringUTFLength(clipboard);
710 JvGetStringUTFRegion(clipboard, 0, len, buf);
712 XSetSelectionOwner(display, XInternAtom(display, "PRIMARY", 0), selectionWindow, CurrentTime);
715 typedef int (X11ErrorHandler)(Display*, XErrorEvent*);
716 int errorHandler(Display* d, XErrorEvent* e) {
717 // this error handler is only installed during the initial
718 // test to see if shm is present
722 void org::xwt::plat::POSIX::natInit() {
725 org::xwt::Platform::criticalAbort(JvNewStringLatin1("Your X11 libraries do not support multithreaded programs"));
727 display = XOpenDisplay(NULL);
728 screen_num = XDefaultScreen(display);
729 colorDepth = (jint)(DefaultDepth(((Display*)display), 0));
730 shm_info.shmaddr = NULL;
732 shm_supported = (XShmQueryExtension(display) == True);
734 X11ErrorHandler* oldHandler = XSetErrorHandler(errorHandler);
735 XShmSegmentInfo sinfo;
736 sinfo.shmid = shmget(IPC_PRIVATE, 1, IPC_CREAT | 0777 | IPC_EXCL);
737 sinfo.readOnly = False;
738 // if the server is remote, this will trigger the error handler
739 XShmAttach(display, &sinfo);
740 XSync(display, False);
741 XSetErrorHandler(oldHandler);
745 shm_pixmaps_supported = (XShmPixmapFormat(display) == ZPixmap);
747 crosshair = JvNewStringLatin1("crosshair");
748 east = JvNewStringLatin1("east");
749 hand = JvNewStringLatin1("hand");
750 move = JvNewStringLatin1("move");
751 north = JvNewStringLatin1("north");
752 northeast = JvNewStringLatin1("northeast");
753 northwest = JvNewStringLatin1("northwest");
754 south = JvNewStringLatin1("south");
755 southeast = JvNewStringLatin1("southeast");
756 southwest = JvNewStringLatin1("southwest");
757 text = JvNewStringLatin1("text");
758 west = JvNewStringLatin1("west");
759 wait_string = JvNewStringLatin1("wait");
760 crosshair_cursor = XCreateFontCursor(display, XC_tcross);
761 east_cursor = XCreateFontCursor(display, XC_right_side);
762 hand_cursor = XCreateFontCursor(display, XC_hand2);
763 move_cursor = XCreateFontCursor(display, XC_fleur);
764 north_cursor = XCreateFontCursor(display, XC_top_side);
765 northeast_cursor = XCreateFontCursor(display, XC_top_right_corner);
766 northwest_cursor = XCreateFontCursor(display, XC_left_side);
767 south_cursor = XCreateFontCursor(display, XC_bottom_side);
768 southeast_cursor = XCreateFontCursor(display, XC_bottom_right_corner);
769 southwest_cursor = XCreateFontCursor(display, XC_bottom_left_corner);
770 text_cursor = XCreateFontCursor(display, XC_xterm);
771 west_cursor = XCreateFontCursor(display, XC_right_side);
772 wait_cursor = XCreateFontCursor(display, XC_watch);
773 default_cursor = XCreateFontCursor(display, XC_left_ptr);
775 selectionWindow = XCreateWindow(display, RootWindow(display, screen_num), 0, 0, 1, 1, 0, colorDepth, InputOutput, CopyFromParent, 0, NULL);
776 visual = DefaultVisual(display, screen_num);
778 sprintf(buf, "X11 DISPLAY: %s", XDisplayString(display));
779 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
780 sprintf(buf, "X11 SHM: %s", shm_supported ? "enabled" : "disabled");
781 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
782 sprintf(buf, "X11 Visual: %x %x %x bits: %i visualid: %i depth: %i",
783 visual->red_mask, visual->green_mask, visual->blue_mask, visual->bits_per_rgb, visual->visualid, colorDepth);
784 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
786 // FIXME: don't know why (True, False) is the best solution...
787 if(XmuLookupStandardColormap(display, screen_num, visual->visualid, colorDepth, XA_RGB_BEST_MAP, True, False) == 0)
788 org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: XmuLookupStandardColormap failed"));
790 XStandardColormap* best_map_info = NULL;
792 if (XGetRGBColormaps(display, RootWindow(display, screen_num), &best_map_info, &count, XA_RGB_BEST_MAP) == 0)
793 org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: couldn't allocate a standard colormap"));
794 if (!best_map_info->colormap)
795 org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: XmuLookupStandardColomap succeded, but no colormap was found on the root window"));
796 if (best_map_info->red_max == 0)
797 org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: standard colormap exists, but was improperly allocated"));
798 s_colormap = best_map_info->colormap;
799 colormap_info = best_map_info;
801 sprintf(buf, " red_max / red_mult: %x %x", colormap_info->red_max, colormap_info->red_mult);
802 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
803 sprintf(buf, " green_max / green_mult: %x %x", colormap_info->green_max, colormap_info->green_mult);
804 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
805 sprintf(buf, " blue_max / blue_mult: %x %x", colormap_info->blue_max, colormap_info->blue_mult);
806 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
807 sprintf(buf, " base_pixel: %x", colormap_info->base_pixel);
808 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
811 JArray<java::lang::String*>* org::xwt::plat::POSIX::listNativeFonts() {
813 char** xfonts = XListFonts(display, "-*-*-*-*-normal-*-*-*-*-*-*-*-*-*", 0xFFFFFFFF, &numfonts);
814 JArray<java::lang::String*>* fonts = (JArray<java::lang::String*>*)JvNewObjectArray(numfonts, &(::java::lang::String::class$), NULL);
815 java::lang::String** jfonts = (java::lang::String**)(elements(fonts));
816 for(int i=0; i<numfonts; i++)
817 jfonts[i] = JvNewStringLatin1(xfonts[i], strlen(xfonts[i]));
821 gnu::gcj::RawData* org::xwt::plat::POSIX::fontStringToStruct(jstring s) {
822 int len = min(1024, JvGetStringUTFLength(s));
824 JvGetStringUTFRegion(s, 0, len, buf);
826 return (gnu::gcj::RawData*)XLoadQueryFont(display, buf);
829 jint org::xwt::plat::POSIX::_getMaxAscent(::java::lang::String* font) { return ((XFontStruct*)fontToXFont(font))->max_bounds.ascent; }
830 jint org::xwt::plat::POSIX::_getMaxDescent(::java::lang::String* font) { return ((XFontStruct*)fontToXFont(font))->max_bounds.descent; }
831 jint org::xwt::plat::POSIX::_stringWidth(::java::lang::String* font, ::java::lang::String* text) {
832 if (text == NULL) return 0;
833 int len = JvGetStringUTFLength(text);
835 JvGetStringUTFRegion(text, 0, len, buf);
837 return XTextWidth((XFontStruct*)fontToXFont(font), buf, len);
841 //////////////////////////////////////////////////////////////////////////////
842 //////////////////////////////////////////////////////////////////////////////
843 //////////////////////////////////////////////////////////////////////////////
844 //////////////////////////////////////////////////////////////////////////////
846 // Everything below this point was taken, cut-and-paste, from the //
847 // source for libXmu. It implements the official 'standard colormap //
848 // creation algorithm. I made some small changes to //
849 // XmuDeleteStandardColormap //
851 //////////////////////////////////////////////////////////////////////////////
852 //////////////////////////////////////////////////////////////////////////////
853 //////////////////////////////////////////////////////////////////////////////
854 //////////////////////////////////////////////////////////////////////////////
856 /* $Xorg: LookupCmap.c,v 1.4 2001/02/09 02:03:53 xorgcvs Exp $ */
860 Copyright 1989, 1998 The Open Group
862 Permission to use, copy, modify, distribute, and sell this software and its
863 documentation for any purpose is hereby granted without fee, provided that
864 the above copyright notice appear in all copies and that both that
865 copyright notice and this permission notice appear in supporting
868 The above copyright notice and this permission notice shall be included in
869 all copies or substantial portions of the Software.
871 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
872 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
873 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
874 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
875 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
876 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
878 Except as contained in this notice, the name of The Open Group shall not be
879 used in advertising or otherwise to promote the sale, use or other dealings
880 in this Software without prior written authorization from The Open Group.
883 /* $XFree86: xc/lib/Xmu/LookupCmap.c,v 1.8 2001/12/14 19:55:47 dawes Exp $ */
886 * Author: Donna Converse, MIT X Consortium
890 #include <X11/Xlib.h>
891 #include <X11/Xatom.h>
892 #include <X11/Xutil.h>
893 #include <X11/Xmu/StdCmap.h>
899 static Status lookup(Display*, int, VisualID, Atom, XStandardColormap*, Bool);
902 * To create a standard colormap if one does not currently exist, or
903 * replace the currently existing standard colormap, use
904 * XmuLookupStandardColormap().
906 * Given a screen, a visual, and a property, XmuLookupStandardColormap()
907 * will determine the best allocation for the property under the specified
908 * visual, and determine the whether to create a new colormap or to use
909 * the default colormap of the screen. It will call XmuStandardColormap()
910 * to create the standard colormap.
912 * If replace is true, any previous definition of the property will be
913 * replaced. If retain is true, the property and the colormap will be
914 * made permanent for the duration of the server session. However,
915 * pre-existing property definitions which are not replaced cannot be made
916 * permanent by a call to XmuLookupStandardColormap(); a request to retain
917 * resources pertains to newly created resources.
919 * Returns 0 on failure, non-zero on success. A request to create a
920 * standard colormap upon a visual which cannot support such a map is
921 * considered a failure. An example of this would be requesting any
922 * standard colormap property on a monochrome visual, or, requesting an
923 * RGB_BEST_MAP on a display whose colormap size is 16.
927 XmuLookupStandardColormap(Display *dpy, int screen, VisualID visualid,
928 unsigned int depth, Atom property,
929 Bool replace, Bool retain)
931 * dpy - specifies X server connection
932 * screen - specifies screen of display
933 * visualid - specifies the visual type
934 * depth - specifies the visual type
935 * property - a standard colormap property
936 * replace - specifies whether to replace
937 * retain - specifies whether to retain
940 Display *odpy; /* original display connection */
941 XStandardColormap *colormap;
942 XVisualInfo vinfo_template, *vinfo; /* visual */
944 unsigned long r_max, g_max, b_max; /* allocation */
946 Colormap cmap; /* colormap ID */
950 /* Match the requested visual */
952 vinfo_template.visualid = visualid;
953 vinfo_template.screen = screen;
954 vinfo_template.depth = depth;
955 vinfo_mask = VisualIDMask | VisualScreenMask | VisualDepthMask;
956 if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &count)) ==
960 /* Monochrome visuals have no standard maps */
962 if (vinfo->colormap_size <= 2) {
963 XFree((char *) vinfo);
967 /* If the requested property already exists on this screen, and,
968 * if the replace flag has not been set to true, return success.
969 * lookup() will remove a pre-existing map if replace is true.
972 if (lookup(dpy, screen, visualid, property, (XStandardColormap *) NULL,
973 replace) && !replace) {
974 XFree((char *) vinfo);
978 /* Determine the best allocation for this property under the requested
979 * visualid and depth, and determine whether or not to use the default
980 * colormap of the screen.
983 if (!XmuGetColormapAllocation(vinfo, property, &r_max, &g_max, &b_max)) {
984 XFree((char *) vinfo);
988 cmap = (property == XA_RGB_DEFAULT_MAP &&
989 visualid == XVisualIDFromVisual(DefaultVisual(dpy, screen)))
990 ? DefaultColormap(dpy, screen) : None;
992 /* If retaining resources, open a new connection to the same server */
996 if ((dpy = XOpenDisplay(XDisplayString(odpy))) == NULL) {
997 XFree((char *) vinfo);
1002 /* Create the standard colormap */
1004 colormap = XmuStandardColormap(dpy, screen, visualid, depth, property,
1005 cmap, r_max, g_max, b_max);
1007 /* Set the standard colormap property */
1012 if (lookup(dpy, screen, visualid, property, colormap, replace) &&
1014 /* Someone has defined the property since we last looked.
1015 * Since we will not replace it, release our own resources.
1016 * If this is the default map, our allocations will be freed
1017 * when this connection closes.
1019 if (colormap->killid == ReleaseByFreeingColormap)
1020 XFreeColormap(dpy, colormap->colormap);
1021 } else if (retain) {
1022 XSetCloseDownMode(dpy, RetainPermanent);
1025 XFree((char *) colormap);
1031 XFree((char *) vinfo);
1035 /***************************************************************************/
1037 /* Lookup a standard colormap property. If the property is RGB_DEFAULT_MAP,
1038 * the visualid is used to determine whether the indicated standard colormap
1039 * exists. If the map exists and replace is true, delete the resources used
1040 * by the map and remove the property. Return true if the map exists,
1041 * or did exist and was deleted; return false if the map was not found.
1043 * Note that this is not the way that a Status return is normally used.
1045 * If new is not NULL, new points to an XStandardColormap structure which
1046 * describes a standard colormap of the specified property. It will be made
1047 * a standard colormap of the screen if none already exists, or if replace
1052 lookup(Display *dpy, int screen, VisualID visualid, Atom property,
1053 XStandardColormap *cnew, Bool replace)
1055 * dpy - specifies display connection
1056 * screen - specifies screen number
1057 * visualid - specifies visualid for std map
1058 * property - specifies colormap property name
1059 * cnew - specifies a standard colormap
1060 * replace - specifies whether to replace
1065 XStandardColormap *stdcmaps, *s;
1066 Window win = RootWindow(dpy, screen);
1068 /* The property does not already exist */
1070 if (! XGetRGBColormaps(dpy, win, &stdcmaps, &count, property)) {
1072 XSetRGBColormaps(dpy, win, cnew, 1, property);
1076 /* The property exists and is not describing the RGB_DEFAULT_MAP */
1078 if (property != XA_RGB_DEFAULT_MAP) {
1080 XmuDeleteStandardColormap(dpy, screen, property);
1082 XSetRGBColormaps(dpy, win, cnew, 1, property);
1084 XFree((char *)stdcmaps);
1088 /* The property exists and is RGB_DEFAULT_MAP */
1090 for (i=0, s=stdcmaps; (i < count) && (s->visualid != visualid); i++, s++)
1093 /* No RGB_DEFAULT_MAP property matches the given visualid */
1097 XStandardColormap *m, *maps;
1099 s = (XStandardColormap *) malloc((unsigned) ((count+1) * sizeof
1100 (XStandardColormap)));
1102 for (i = 0, m = s, maps = stdcmaps; i < count; i++, m++, maps++) {
1103 m->colormap = maps->colormap;
1104 m->red_max = maps->red_max;
1105 m->red_mult = maps->red_mult;
1106 m->green_max = maps->green_max;
1107 m->green_mult = maps->green_mult;
1108 m->blue_max = maps->blue_max;
1109 m->blue_mult = maps->blue_mult;
1110 m->base_pixel = maps->base_pixel;
1111 m->visualid = maps->visualid;
1112 m->killid = maps->killid;
1114 m->colormap = cnew->colormap;
1115 m->red_max = cnew->red_max;
1116 m->red_mult = cnew->red_mult;
1117 m->green_max = cnew->green_max;
1118 m->green_mult = cnew->green_mult;
1119 m->blue_max = cnew->blue_max;
1120 m->blue_mult = cnew->blue_mult;
1121 m->base_pixel = cnew->base_pixel;
1122 m->visualid = cnew->visualid;
1123 m->killid = cnew->killid;
1125 XSetRGBColormaps(dpy, win, s, ++count, property);
1128 XFree((char *) stdcmaps);
1132 /* Found an RGB_DEFAULT_MAP property with a matching visualid */
1135 /* Free old resources first - we may need them, particularly in
1136 * the default colormap of the screen. However, because of this,
1137 * it is possible that we will destroy the old resource and fail
1138 * to create a new one if XmuStandardColormap() fails.
1142 XmuDeleteStandardColormap(dpy, screen, property);
1144 XSetRGBColormaps(dpy, win, cnew, 1, property);
1147 XStandardColormap *map;
1149 /* s still points to the matching standard colormap */
1151 if (s->killid == ReleaseByFreeingColormap) {
1152 if ((s->colormap != None) &&
1153 (s->colormap != DefaultColormap(dpy, screen)))
1154 XFreeColormap(dpy, s->colormap);
1156 else if (s->killid != None)
1157 XKillClient(dpy, s->killid);
1159 map = (cnew) ? cnew : stdcmaps + --count;
1161 s->colormap = map->colormap;
1162 s->red_max = map->red_max;
1163 s->red_mult = map->red_mult;
1164 s->green_max = map->green_max;
1165 s->green_mult = map->green_mult;
1166 s->blue_max = map->blue_max;
1167 s->blue_mult = map->blue_mult;
1168 s->visualid = map->visualid;
1169 s->killid = map->killid;
1171 XSetRGBColormaps(dpy, win, stdcmaps, count, property);
1174 XFree((char *) stdcmaps);
1178 /* $Xorg: CmapAlloc.c,v 1.4 2001/02/09 02:03:51 xorgcvs Exp $ */
1182 Copyright 1989, 1994, 1998 The Open Group
1184 Permission to use, copy, modify, distribute, and sell this software and its
1185 documentation for any purpose is hereby granted without fee, provided that
1186 the above copyright notice appear in all copies and that both that
1187 copyright notice and this permission notice appear in supporting
1190 The above copyright notice and this permission notice shall be included in
1191 all copies or substantial portions of the Software.
1193 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1194 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1195 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1196 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1197 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1198 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1200 Except as contained in this notice, the name of The Open Group shall not be
1201 used in advertising or otherwise to promote the sale, use or other dealings
1202 in this Software without prior written authorization from The Open Group.
1205 /* $XFree86: xc/lib/Xmu/CmapAlloc.c,v 1.7 2001/12/14 19:55:35 dawes Exp $ */
1208 * Author: Donna Converse, MIT X Consortium
1211 #include <X11/Xlib.h>
1212 #include <X11/Xatom.h>
1213 #include <X11/Xutil.h>
1214 #include <X11/Xmu/StdCmap.h>
1217 #define lowbit(x) ((x) & (~(x) + 1))
1222 static void best_allocation(XVisualInfo*, unsigned long*, unsigned long*,
1224 static int default_allocation(XVisualInfo*, unsigned long*,
1225 unsigned long*, unsigned long*);
1226 static void gray_allocation(int, unsigned long*, unsigned long*,
1228 static int icbrt(int);
1229 static int icbrt_with_bits(int, int);
1230 static int icbrt_with_guess(int, int);
1232 /* To determine the best allocation of reds, greens, and blues in a
1233 * standard colormap, use XmuGetColormapAllocation.
1234 * vinfo specifies visual information for a chosen visual
1235 * property specifies one of the standard colormap property names
1236 * red_max returns maximum red value
1237 * green_max returns maximum green value
1238 * blue_max returns maximum blue value
1240 * XmuGetColormapAllocation returns 0 on failure, non-zero on success.
1241 * It is assumed that the visual is appropriate for the colormap property.
1245 XmuGetColormapAllocation(XVisualInfo *vinfo, Atom property,
1246 unsigned long *red_max,
1247 unsigned long *green_max,
1248 unsigned long *blue_max)
1252 if (vinfo->colormap_size <= 2)
1257 case XA_RGB_DEFAULT_MAP:
1258 status = default_allocation(vinfo, red_max, green_max, blue_max);
1260 case XA_RGB_BEST_MAP:
1261 best_allocation(vinfo, red_max, green_max, blue_max);
1263 case XA_RGB_GRAY_MAP:
1264 gray_allocation(vinfo->colormap_size, red_max, green_max, blue_max);
1266 case XA_RGB_RED_MAP:
1267 *red_max = vinfo->colormap_size - 1;
1268 *green_max = *blue_max = 0;
1270 case XA_RGB_GREEN_MAP:
1271 *green_max = vinfo->colormap_size - 1;
1272 *red_max = *blue_max = 0;
1274 case XA_RGB_BLUE_MAP:
1275 *blue_max = vinfo->colormap_size - 1;
1276 *red_max = *green_max = 0;
1284 /****************************************************************************/
1285 /* Determine the appropriate color allocations of a gray scale.
1287 * Keith Packard, MIT X Consortium
1291 gray_allocation(int n, unsigned long *red_max, unsigned long *green_max,
1292 unsigned long *blue_max)
1294 *red_max = (n * 30) / 100;
1295 *green_max = (n * 59) / 100;
1296 *blue_max = (n * 11) / 100;
1297 *green_max += ((n - 1) - (*red_max + *green_max + *blue_max));
1300 /****************************************************************************/
1301 /* Determine an appropriate color allocation for the RGB_DEFAULT_MAP.
1302 * If a map has less than a minimum number of definable entries, we do not
1303 * produce an allocation for an RGB_DEFAULT_MAP.
1305 * For 16 planes, the default colormap will have 27 each RGB; for 12 planes,
1306 * 12 each. For 8 planes, let n = the number of colormap entries, which may
1307 * be 256 or 254. Then, maximum red value = floor(cube_root(n - 125)) - 1.
1308 * Maximum green and maximum blue values are identical to maximum red.
1309 * This leaves at least 125 cells which clients can allocate.
1311 * Return 0 if an allocation has been determined, non-zero otherwise.
1315 default_allocation(XVisualInfo *vinfo, unsigned long *red,
1316 unsigned long *green, unsigned long *blue)
1318 int ngrays; /* number of gray cells */
1320 switch (vinfo->c_class)
1324 if (vinfo->colormap_size > 65000)
1325 /* intended for displays with 16 planes */
1326 *red = *green = *blue = (unsigned long) 27;
1327 else if (vinfo->colormap_size > 4000)
1328 /* intended for displays with 12 planes */
1329 *red = *green = *blue = (unsigned long) 12;
1330 else if (vinfo->colormap_size < 250)
1333 /* intended for displays with 8 planes */
1334 *red = *green = *blue = (unsigned long)
1335 (icbrt(vinfo->colormap_size - 125) - 1);
1340 if (vinfo->colormap_size < 10)
1342 *red = *green = *blue = vinfo->colormap_size / 2 - 1;
1347 *red = vinfo->red_mask / lowbit(vinfo->red_mask);
1348 *green = vinfo->green_mask / lowbit(vinfo->green_mask);
1349 *blue = vinfo->blue_mask / lowbit(vinfo->blue_mask);
1354 if (vinfo->colormap_size > 65000)
1356 else if (vinfo->colormap_size > 4000)
1358 else if (vinfo->colormap_size < 250)
1362 gray_allocation(ngrays, red, green, blue);
1371 /****************************************************************************/
1372 /* Determine an appropriate color allocation for the RGB_BEST_MAP.
1374 * For a DirectColor or TrueColor visual, the allocation is determined
1375 * by the red_mask, green_mask, and blue_mask members of the visual info.
1377 * Otherwise, if the colormap size is an integral power of 2, determine
1378 * the allocation according to the number of bits given to each color,
1379 * with green getting more than red, and red more than blue, if there
1380 * are to be inequities in the distribution. If the colormap size is
1381 * not an integral power of 2, let n = the number of colormap entries.
1382 * Then maximum red value = floor(cube_root(n)) - 1;
1383 * maximum blue value = floor(cube_root(n)) - 1;
1384 * maximum green value = n / ((# red values) * (# blue values)) - 1;
1385 * Which, on a GPX, allows for 252 entries in the best map, out of 254
1386 * defineable colormap entries.
1390 best_allocation(XVisualInfo *vinfo, unsigned long *red, unsigned long *green,
1391 unsigned long *blue)
1394 if (vinfo->c_class == DirectColor || vinfo->c_class == TrueColor)
1396 *red = vinfo->red_mask;
1397 while ((*red & 01) == 0)
1399 *green = vinfo->green_mask;
1400 while ((*green & 01) == 0)
1402 *blue = vinfo->blue_mask;
1403 while ((*blue & 01) == 0)
1408 register int bits, n;
1410 /* Determine n such that n is the least integral power of 2 which is
1411 * greater than or equal to the number of entries in the colormap.
1415 while (vinfo->colormap_size > n)
1421 /* If the number of entries in the colormap is a power of 2, determine
1422 * the allocation by "dealing" the bits, first to green, then red, then
1423 * blue. If not, find the maximum integral red, green, and blue values
1424 * which, when multiplied together, do not exceed the number of
1428 if (n == vinfo->colormap_size)
1430 register int r, g, b;
1432 g = b + ((bits % 3) ? 1 : 0);
1433 r = b + (((bits % 3) == 2) ? 1 : 0);
1440 *red = icbrt_with_bits(vinfo->colormap_size, bits);
1442 *green = (vinfo->colormap_size / ((*red) * (*blue)));
1452 * integer cube roots by Newton's method
1454 * Stephen Gildea, MIT X Consortium, July 1991
1460 register int bits = 0;
1461 register unsigned n = a;
1468 return icbrt_with_bits(a, bits);
1473 icbrt_with_bits(int a, int bits)
1474 /* bits - log 2 of a */
1476 return icbrt_with_guess(a, a>>2*bits/3);
1479 #ifdef _X_ROOT_STATS
1480 int icbrt_loopcount;
1483 /* Newton's Method: x_n+1 = x_n - ( f(x_n) / f'(x_n) ) */
1485 /* for cube roots, x^3 - a = 0, x_new = x - 1/3 (x - a/x^2) */
1488 * Quick and dirty cube roots. Nothing fancy here, just Newton's method.
1489 * Only works for positive integers (since that's all we need).
1490 * We actually return floor(cbrt(a)) because that's what we need here, too.
1494 icbrt_with_guess(int a, int guess)
1498 #ifdef _X_ROOT_STATS
1499 icbrt_loopcount = 0;
1507 #ifdef _X_ROOT_STATS
1510 delta = (guess - a/(guess*guess))/3;
1512 printf("pass %d: guess=%d, delta=%d\n", icbrt_loopcount, guess, delta);
1515 } while (delta != 0);
1517 if (guess*guess*guess > a)
1524 /* $Xorg: StdCmap.c,v 1.4 2001/02/09 02:03:53 xorgcvs Exp $ */
1528 Copyright 1989, 1998 The Open Group
1530 Permission to use, copy, modify, distribute, and sell this software and its
1531 documentation for any purpose is hereby granted without fee, provided that
1532 the above copyright notice appear in all copies and that both that
1533 copyright notice and this permission notice appear in supporting
1536 The above copyright notice and this permission notice shall be included in
1537 all copies or substantial portions of the Software.
1539 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1540 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1541 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1542 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1543 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1544 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1546 Except as contained in this notice, the name of The Open Group shall not be
1547 used in advertising or otherwise to promote the sale, use or other dealings
1548 in this Software without prior written authorization from The Open Group.
1551 /* $XFree86: xc/lib/Xmu/StdCmap.c,v 1.6 2001/12/14 19:55:48 dawes Exp $ */
1554 * Author: Donna Converse, MIT X Consortium
1558 #include <X11/Xlib.h>
1559 #include <X11/Xatom.h>
1560 #include <X11/Xutil.h>
1561 #include <X11/Xmu/StdCmap.h>
1563 #define lowbit(x) ((x) & (~(x) + 1))
1568 /* argument restrictions */
1569 static Status valid_args(XVisualInfo*, unsigned long, unsigned long,
1570 unsigned long, Atom);
1573 * To create any one standard colormap, use XmuStandardColormap().
1575 * Create a standard colormap for the given screen, visualid, and visual
1576 * depth, with the given red, green, and blue maximum values, with the
1577 * given standard property name. Return a pointer to an XStandardColormap
1578 * structure which describes the newly created colormap, upon success.
1579 * Upon failure, return NULL.
1581 * XmuStandardColormap() calls XmuCreateColormap() to create the map.
1583 * Resources created by this function are not made permanent; that is the
1584 * caller's responsibility.
1588 XmuStandardColormap(Display *dpy, int screen, VisualID visualid,
1589 unsigned int depth, Atom property, Colormap cmap,
1590 unsigned long red_max, unsigned long green_max,
1591 unsigned long blue_max)
1593 * dpy - specifies X server connection
1594 * screen - specifies display screen
1595 * visualid - identifies the visual type
1596 * depth - identifies the visual type
1597 * property - a standard colormap property
1598 * cmap - specifies colormap ID or None
1599 * red_max, green_max, blue_max - allocations
1602 XStandardColormap *stdcmap;
1604 XVisualInfo vinfo_template, *vinfo;
1608 /* Match the required visual information to an actual visual */
1609 vinfo_template.visualid = visualid;
1610 vinfo_template.screen = screen;
1611 vinfo_template.depth = depth;
1612 vinfo_mask = VisualIDMask | VisualScreenMask | VisualDepthMask;
1613 if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &n)) == NULL)
1616 /* Check the validity of the combination of visual characteristics,
1617 * allocation, and colormap property. Create an XStandardColormap
1621 if (! valid_args(vinfo, red_max, green_max, blue_max, property)
1622 || ((stdcmap = XAllocStandardColormap()) == NULL)) {
1623 XFree((char *) vinfo);
1627 /* Fill in the XStandardColormap structure */
1629 if (cmap == DefaultColormap(dpy, screen)) {
1630 /* Allocating out of the default map, cannot use XFreeColormap() */
1631 Window win = XCreateWindow(dpy, RootWindow(dpy, screen), 1, 1, 1, 1,
1632 0, 0, InputOnly, vinfo->visual,
1634 (XSetWindowAttributes *)NULL);
1635 stdcmap->killid = (XID) XCreatePixmap(dpy, win, 1, 1, depth);
1636 XDestroyWindow(dpy, win);
1637 stdcmap->colormap = cmap;
1639 stdcmap->killid = ReleaseByFreeingColormap;
1640 stdcmap->colormap = XCreateColormap(dpy, RootWindow(dpy, screen),
1641 vinfo->visual, AllocNone);
1643 stdcmap->red_max = red_max;
1644 stdcmap->green_max = green_max;
1645 stdcmap->blue_max = blue_max;
1646 if (property == XA_RGB_GRAY_MAP)
1647 stdcmap->red_mult = stdcmap->green_mult = stdcmap->blue_mult = 1;
1648 else if (vinfo->c_class == TrueColor || vinfo->c_class == DirectColor) {
1649 stdcmap->red_mult = lowbit(vinfo->red_mask);
1650 stdcmap->green_mult = lowbit(vinfo->green_mask);
1651 stdcmap->blue_mult = lowbit(vinfo->blue_mask);
1653 stdcmap->red_mult = (red_max > 0)
1654 ? (green_max + 1) * (blue_max + 1) : 0;
1655 stdcmap->green_mult = (green_max > 0) ? blue_max + 1 : 0;
1656 stdcmap->blue_mult = (blue_max > 0) ? 1 : 0;
1658 stdcmap->base_pixel = 0; /* base pixel may change */
1659 stdcmap->visualid = vinfo->visualid;
1661 /* Make the colormap */
1663 status = XmuCreateColormap(dpy, stdcmap);
1667 XFree((char *) vinfo);
1670 /* Free the colormap or the pixmap, if we created one */
1671 if (stdcmap->killid == ReleaseByFreeingColormap)
1672 XFreeColormap(dpy, stdcmap->colormap);
1673 else if (stdcmap->killid != None)
1674 XFreePixmap(dpy, stdcmap->killid);
1676 XFree((char *) stdcmap);
1677 return (XStandardColormap *) NULL;
1682 /****************************************************************************/
1684 valid_args(XVisualInfo *vinfo, unsigned long red_max, unsigned long green_max,
1685 unsigned long blue_max, Atom property)
1687 * vinfo - specifies visual
1688 * red_max, green_max, blue_max - specifies alloc
1689 * property - specifies property name
1692 unsigned long ncolors; /* number of colors requested */
1694 /* Determine that the number of colors requested is <= map size */
1696 if ((vinfo->c_class == DirectColor) || (vinfo->c_class == TrueColor)) {
1699 mask = vinfo->red_mask;
1704 mask = vinfo->green_mask;
1707 if (green_max > mask)
1709 mask = vinfo->blue_mask;
1712 if (blue_max > mask)
1714 } else if (property == XA_RGB_GRAY_MAP) {
1715 ncolors = red_max + green_max + blue_max + 1;
1716 if (ncolors > vinfo->colormap_size)
1719 ncolors = (red_max + 1) * (green_max + 1) * (blue_max + 1);
1720 if (ncolors > vinfo->colormap_size)
1724 /* Determine that the allocation and visual make sense for the property */
1728 case XA_RGB_DEFAULT_MAP:
1729 if (red_max == 0 || green_max == 0 || blue_max == 0)
1732 case XA_RGB_RED_MAP:
1736 case XA_RGB_GREEN_MAP:
1740 case XA_RGB_BLUE_MAP:
1744 case XA_RGB_BEST_MAP:
1745 if (red_max == 0 || green_max == 0 || blue_max == 0)
1748 case XA_RGB_GRAY_MAP:
1749 if (red_max == 0 || blue_max == 0 || green_max == 0)
1759 /* $Xorg: CrCmap.c,v 1.4 2001/02/09 02:03:51 xorgcvs Exp $ */
1763 Copyright 1989, 1998 The Open Group
1765 Permission to use, copy, modify, distribute, and sell this software and its
1766 documentation for any purpose is hereby granted without fee, provided that
1767 the above copyright notice appear in all copies and that both that
1768 copyright notice and this permission notice appear in supporting
1771 The above copyright notice and this permission notice shall be included in
1772 all copies or substantial portions of the Software.
1774 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1775 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1776 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1777 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1778 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1779 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1781 Except as contained in this notice, the name of The Open Group shall not be
1782 used in advertising or otherwise to promote the sale, use or other dealings
1783 in this Software without prior written authorization from The Open Group.
1786 /* $XFree86: xc/lib/Xmu/CrCmap.c,v 3.7 2001/12/14 19:55:36 dawes Exp $ */
1789 * Author: Donna Converse, MIT X Consortium
1793 * CreateCmap.c - given a standard colormap description, make the map.
1798 #include <X11/Xlib.h>
1799 #include <X11/Xutil.h>
1800 #include <X11/Xmu/StdCmap.h>
1805 /* allocate entire map Read Only */
1806 static int ROmap(Display*, Colormap, unsigned long[], int, int);
1808 /* allocate a cell, prefer Read Only */
1809 static Status ROorRWcell(Display*, Colormap, unsigned long[], int,
1810 XColor*, unsigned long);
1812 /* allocate a cell Read Write */
1813 static Status RWcell(Display*, Colormap, XColor*, XColor*, unsigned long*);
1816 static int compare(_Xconst void*, _Xconst void*);
1818 /* find contiguous sequence of cells */
1819 static Status contiguous(unsigned long[], int, int, unsigned long, int*, int*);
1821 /* frees resources before quitting */
1822 static void free_cells(Display*, Colormap, unsigned long[], int, int);
1824 /* create a map in a RO visual type */
1825 static Status readonly_map(Display*, XVisualInfo*, XStandardColormap*);
1827 /* create a map in a RW visual type */
1828 static Status readwrite_map(Display*, XVisualInfo*, XStandardColormap*);
1830 #define lowbit(x) ((x) & (~(x) + 1))
1831 #define TRUEMATCH(mult,max,mask) \
1832 (colormap->max * colormap->mult <= vinfo->mask && \
1833 lowbit(vinfo->mask) == colormap->mult)
1836 * To create any one colormap which is described by an XStandardColormap
1837 * structure, use XmuCreateColormap().
1839 * Return 0 on failure, non-zero on success.
1840 * Resources created by this function are not made permanent.
1841 * No argument error checking is provided. Use at your own risk.
1843 * All colormaps are created with read only allocations, with the exception
1844 * of read only allocations of colors in the default map or otherwise
1845 * which fail to return the expected pixel value, and these are individually
1846 * defined as read/write allocations. This is done so that all the cells
1847 * defined in the default map are contiguous, for use in image processing.
1848 * This typically happens with White and Black in the default map.
1850 * Colormaps of static visuals are considered to be successfully created if
1851 * the map of the static visual matches the definition given in the
1852 * standard colormap structure.
1856 XmuCreateColormap(Display *dpy, XStandardColormap *colormap)
1857 /* dpy - specifies the connection under which the map is created
1858 * colormap - specifies the map to be created, and returns, particularly
1859 * if the map is created as a subset of the default colormap
1860 * of the screen, the base_pixel of the map.
1863 XVisualInfo vinfo_template; /* template visual information */
1864 XVisualInfo *vinfo; /* matching visual information */
1865 XVisualInfo *vpointer; /* for freeing the entire list */
1866 long vinfo_mask; /* specifies the visual mask value */
1867 int n; /* number of matching visuals */
1870 vinfo_template.visualid = colormap->visualid;
1871 vinfo_mask = VisualIDMask;
1872 if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &n)) == NULL)
1875 /* A visual id may be valid on multiple screens. Also, there may
1876 * be multiple visuals with identical visual ids at different depths.
1877 * If the colormap is the Default Colormap, use the Default Visual.
1878 * Otherwise, arbitrarily, use the deepest visual.
1884 register int screen_number;
1888 for (screen_number = ScreenCount(dpy); --screen_number >= 0; )
1889 if (colormap->colormap == DefaultColormap(dpy, screen_number)) {
1895 for (i=0; i < n; i++, vinfo++) {
1896 if (vinfo->visual == DefaultVisual(dpy, screen_number))
1901 XVisualInfo *v = NULL;
1903 for (i=0; i < n; i++, vinfo++)
1904 if (vinfo->depth > maxdepth) {
1905 maxdepth = vinfo->depth;
1912 if (vinfo->c_class == PseudoColor || vinfo->c_class == DirectColor ||
1913 vinfo->c_class == GrayScale)
1914 status = readwrite_map(dpy, vinfo, colormap);
1915 else if (vinfo->c_class == TrueColor)
1916 status = TRUEMATCH(red_mult, red_max, red_mask) &&
1917 TRUEMATCH(green_mult, green_max, green_mask) &&
1918 TRUEMATCH(blue_mult, blue_max, blue_mask);
1920 status = readonly_map(dpy, vinfo, colormap);
1922 XFree((char *) vpointer);
1926 /****************************************************************************/
1928 readwrite_map(Display *dpy, XVisualInfo *vinfo, XStandardColormap *colormap)
1930 register unsigned long i, n; /* index counters */
1931 unsigned long ncolors; /* number of colors to be defined */
1932 int npixels; /* number of pixels allocated R/W */
1933 int first_index; /* first index of pixels to use */
1934 int remainder; /* first index of remainder */
1935 XColor color; /* the definition of a color */
1936 unsigned long *pixels; /* array of colormap pixels */
1937 unsigned long delta;
1940 /* Determine ncolors, the number of colors to be defined.
1941 * Insure that 1 < ncolors <= the colormap size.
1943 if (vinfo->c_class == DirectColor) {
1944 ncolors = colormap->red_max;
1945 if (colormap->green_max > ncolors)
1946 ncolors = colormap->green_max;
1947 if (colormap->blue_max > ncolors)
1948 ncolors = colormap->blue_max;
1950 delta = lowbit(vinfo->red_mask) +
1951 lowbit(vinfo->green_mask) +
1952 lowbit(vinfo->blue_mask);
1954 ncolors = colormap->red_max * colormap->red_mult +
1955 colormap->green_max * colormap->green_mult +
1956 colormap->blue_max * colormap->blue_mult + 1;
1959 if (ncolors <= 1 || (int) ncolors > vinfo->colormap_size) return 0;
1961 /* Allocate Read/Write as much of the colormap as we can possibly get.
1962 * Then insure that the pixels we were allocated are given in
1963 * monotonically increasing order, using a quicksort. Next, insure
1964 * that our allocation includes a subset of contiguous pixels at least
1965 * as long as the number of colors to be defined. Now we know that
1966 * these conditions are met:
1967 * 1) There are no free cells in the colormap.
1968 * 2) We have a contiguous sequence of pixels, monotonically
1969 * increasing, of length >= the number of colors requested.
1971 * One cell at a time, we will free, compute the next color value,
1972 * then allocate read only. This takes a long time.
1973 * This is done to insure that cells are allocated read only in the
1974 * contiguous order which we prefer. If the server has a choice of
1975 * cells to grant to an allocation request, the server may give us any
1976 * cell, so that is why we do these slow gymnastics.
1979 if ((pixels = (unsigned long *) calloc((unsigned) vinfo->colormap_size,
1980 sizeof(unsigned long))) == NULL)
1983 if ((npixels = ROmap(dpy, colormap->colormap, pixels,
1984 vinfo->colormap_size, ncolors)) == 0) {
1985 free((char *) pixels);
1989 qsort((char *) pixels, npixels, sizeof(unsigned long), compare);
1991 if (!contiguous(pixels, npixels, ncolors, delta, &first_index, &remainder))
1993 /* can't find enough contiguous cells, give up */
1994 XFreeColors(dpy, colormap->colormap, pixels, npixels,
1996 free((char *) pixels);
1999 colormap->base_pixel = pixels[first_index];
2001 /* construct a gray map */
2002 if (colormap->red_mult == 1 && colormap->green_mult == 1 &&
2003 colormap->blue_mult == 1)
2004 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
2007 color.blue = color.green = color.red =
2008 (unsigned short) ((i * 65535) / (colormap->red_max +
2009 colormap->green_max +
2010 colormap->blue_max));
2012 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
2017 /* construct a red ramp map */
2018 else if (colormap->green_max == 0 && colormap->blue_max == 0)
2019 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
2022 color.red = (unsigned short) ((i * 65535) / colormap->red_max);
2023 color.green = color.blue = 0;
2025 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
2030 /* construct a green ramp map */
2031 else if (colormap->red_max == 0 && colormap->blue_max == 0)
2032 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
2035 color.green = (unsigned short) ((i * 65535) / colormap->green_max);
2036 color.red = color.blue = 0;
2038 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
2043 /* construct a blue ramp map */
2044 else if (colormap->red_max == 0 && colormap->green_max == 0)
2045 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
2048 color.blue = (unsigned short) ((i * 65535) / colormap->blue_max);
2049 color.red = color.green = 0;
2051 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
2056 /* construct a standard red green blue cube map */
2059 #define calc(max,mult) (((n / colormap->mult) % \
2060 (colormap->max + 1)) * 65535) / colormap->max
2062 for (n=0, i=0; i < ncolors; i++, n += delta)
2064 color.pixel = n + colormap->base_pixel;
2065 color.red = calc(red_max, red_mult);
2066 color.green = calc(green_max, green_mult);
2067 color.blue = calc(blue_max, blue_mult);
2068 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
2074 /* We have a read-only map defined. Now free unused cells,
2075 * first those occuring before the contiguous sequence begins,
2076 * then any following the contiguous sequence.
2080 XFreeColors(dpy, colormap->colormap, pixels, first_index,
2083 XFreeColors(dpy, colormap->colormap,
2084 &(pixels[first_index + ncolors]), remainder,
2087 free((char *) pixels);
2092 /****************************************************************************/
2094 ROmap(Display *dpy, Colormap cmap, unsigned long pixels[], int m, int n)
2096 * dpy - the X server connection
2097 * cmap - specifies colormap ID
2098 * pixels - returns pixel allocations
2099 * m - specifies colormap size
2100 * n - specifies number of colors
2105 /* first try to allocate the entire colormap */
2106 if (XAllocColorCells(dpy, cmap, 1, (unsigned long *) NULL,
2107 (unsigned) 0, pixels, (unsigned) m))
2110 /* Allocate all available cells in the colormap, using a binary
2111 * algorithm to discover how many cells we can allocate in the colormap.
2115 p = n + ((m - n + 1) / 2);
2116 if (XAllocColorCells(dpy, cmap, 1, (unsigned long *) NULL,
2117 (unsigned) 0, pixels, (unsigned) p)) {
2121 XFreeColors(dpy, cmap, pixels, p, (unsigned long) 0);
2132 /****************************************************************************/
2134 contiguous(unsigned long pixels[], int npixels, int ncolors,
2135 unsigned long delta, int *first, int *rem)
2136 /* pixels - specifies allocated pixels
2137 * npixels - specifies count of alloc'd pixels
2138 * ncolors - specifies needed sequence length
2139 * delta - between pixels
2140 * first - returns first index of sequence
2141 * rem - returns first index after sequence, or 0, if none follow
2144 register int i = 1; /* walking index into the pixel array */
2145 register int count = 1; /* length of sequence discovered so far */
2148 if (npixels == ncolors) {
2153 while (count < ncolors && ncolors - count <= *rem)
2155 if (pixels[i-1] + delta == pixels[i])
2164 if (count != ncolors)
2170 /****************************************************************************/
2172 ROorRWcell(Display *dpy, Colormap cmap, unsigned long pixels[],
2173 int npixels, XColor *color, unsigned long p)
2175 unsigned long pixel;
2178 /* Free the read/write allocation of one cell in the colormap.
2179 * Request a read only allocation of one cell in the colormap.
2180 * If the read only allocation cannot be granted, give up, because
2181 * there must be no free cells in the colormap.
2182 * If the read only allocation is granted, but gives us a cell which
2183 * is not the one that we just freed, it is probably the case that
2184 * we are trying allocate White or Black or some other color which
2185 * already has a read-only allocation in the map. So we try to
2186 * allocate the previously freed cell with a read/write allocation,
2187 * because we want contiguous cells for image processing algorithms.
2190 pixel = color->pixel;
2191 request.red = color->red;
2192 request.green = color->green;
2193 request.blue = color->blue;
2195 XFreeColors(dpy, cmap, &pixel, 1, (unsigned long) 0);
2196 if (! XAllocColor(dpy, cmap, color)
2197 || (color->pixel != pixel &&
2198 (!RWcell(dpy, cmap, color, &request, &pixel))))
2200 free_cells(dpy, cmap, pixels, npixels, (int)p);
2207 /****************************************************************************/
2209 free_cells(Display *dpy, Colormap cmap, unsigned long pixels[],
2212 * pixels - to be freed
2213 * npixels - original number allocated
2216 /* One of the npixels allocated has already been freed.
2217 * p is the index of the freed pixel.
2218 * First free the pixels preceeding p, and there are p of them;
2219 * then free the pixels following p, there are npixels - p - 1 of them.
2221 XFreeColors(dpy, cmap, pixels, p, (unsigned long) 0);
2222 XFreeColors(dpy, cmap, &(pixels[p+1]), npixels - p - 1, (unsigned long) 0);
2223 free((char *) pixels);
2227 /****************************************************************************/
2229 RWcell(Display *dpy, Colormap cmap, XColor *color, XColor *request,
2230 unsigned long *pixel)
2232 unsigned long n = *pixel;
2234 XFreeColors(dpy, cmap, &(color->pixel), 1, (unsigned long)0);
2235 if (! XAllocColorCells(dpy, cmap, (Bool) 0, (unsigned long *) NULL,
2236 (unsigned) 0, pixel, (unsigned) 1))
2240 XFreeColors(dpy, cmap, pixel, 1, (unsigned long) 0);
2243 color->pixel = *pixel;
2244 color->flags = DoRed | DoGreen | DoBlue;
2245 color->red = request->red;
2246 color->green = request->green;
2247 color->blue = request->blue;
2248 XStoreColors(dpy, cmap, color, 1);
2253 /****************************************************************************/
2255 compare(_Xconst void *e1, _Xconst void *e2)
2257 return ((int)(*(long *)e1 - *(long *)e2));
2261 /****************************************************************************/
2263 readonly_map(Display *dpy, XVisualInfo *vinfo, XStandardColormap *colormap)
2268 last_pixel = (colormap->red_max + 1) * (colormap->green_max + 1) *
2269 (colormap->blue_max + 1) + colormap->base_pixel - 1;
2271 for(i=colormap->base_pixel; i <= last_pixel; i++) {
2273 color.pixel = (unsigned long) i;
2274 color.red = (unsigned short)
2275 (((i/colormap->red_mult) * 65535) / colormap->red_max);
2277 if (vinfo->c_class == StaticColor) {
2278 color.green = (unsigned short)
2279 ((((i/colormap->green_mult) % (colormap->green_max + 1)) *
2280 65535) / colormap->green_max);
2281 color.blue = (unsigned short)
2282 (((i%colormap->green_mult) * 65535) / colormap->blue_max);
2284 else /* vinfo->c_class == GrayScale, old style allocation XXX */
2285 color.green = color.blue = color.red;
2287 XAllocColor(dpy, colormap->colormap, &color);
2288 if (color.pixel != (unsigned long) i)
2295 /* $Xorg: DelCmap.c,v 1.4 2001/02/09 02:03:52 xorgcvs Exp $ */
2299 Copyright 1989, 1998 The Open Group
2301 Permission to use, copy, modify, distribute, and sell this software and its
2302 documentation for any purpose is hereby granted without fee, provided that
2303 the above copyright notice appear in all copies and that both that
2304 copyright notice and this permission notice appear in supporting
2307 The above copyright notice and this permission notice shall be included in
2308 all copies or substantial portions of the Software.
2310 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2311 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2312 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2313 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
2314 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
2315 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2317 Except as contained in this notice, the name of The Open Group shall not be
2318 used in advertising or otherwise to promote the sale, use or other dealings
2319 in this Software without prior written authorization from The Open Group.
2322 /* $XFree86: xc/lib/Xmu/DelCmap.c,v 1.7 2001/12/14 19:55:40 dawes Exp $ */
2325 * Author: Donna Converse, MIT X Consortium
2328 #include <X11/Xlib.h>
2329 #include <X11/Xutil.h>
2330 #include <X11/Xmu/StdCmap.h>
2332 int ignoreErrorHandler(Display* d, XErrorEvent* e) { }
2334 /* To remove any standard colormap property, use XmuDeleteStandardColormap().
2335 * XmuDeleteStandardColormap() will remove the specified property from the
2336 * specified screen, releasing any resources used by the colormap(s) of the
2337 * property if possible.
2341 XmuDeleteStandardColormap(Display *dpy, int screen, Atom property)
2342 /* dpy; - specifies the X server to connect to
2343 * screen - specifies the screen of the display
2344 * property - specifies the standard colormap property
2347 XStandardColormap *stdcmaps, *s;
2350 if (XGetRGBColormaps(dpy, RootWindow(dpy, screen), &stdcmaps, &count,
2353 for (s=stdcmaps; count > 0; count--, s++) {
2354 if ((s->killid == ReleaseByFreeingColormap) &&
2355 (s->colormap != None) &&
2356 (s->colormap != DefaultColormap(dpy, screen))) {
2358 // UGLY HACK written in by Adam Megacz -- sometimes s->colormap isn't valid, so we do some shuffling
2359 X11ErrorHandler* oldHandler = XSetErrorHandler(ignoreErrorHandler);
2361 XFreeColormap(dpy, s->colormap);
2363 XSetErrorHandler(oldHandler);
2366 } else if (s->killid != None) {
2367 XKillClient(dpy, s->killid);
2370 XDeleteProperty(dpy, RootWindow(dpy, screen), property);
2371 XFree((char *) stdcmaps);