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);
681 execvp(cmd2[0], cmd2);
685 void org::xwt::plat::POSIX::eventThread() {
688 XNextEvent(display, &e);
689 org::xwt::plat::POSIX$X11Surface* surface =
690 (org::xwt::plat::POSIX$X11Surface*)windowToSurfaceMap->get(new java::lang::Long(((XAnyEvent*)&e)->window));
691 if (surface != NULL) surface->dispatchEvent((gnu::gcj::RawData*)&e);
695 jstring org::xwt::plat::POSIX::_getClipBoard() {
696 XConvertSelection(display, XA_PRIMARY, XA_STRING, XInternAtom(display, "VT_SELECTION", False), selectionWindow, CurrentTime);
698 org::xwt::plat::POSIX::waiting_for_selection_event->block();
702 void org::xwt::plat::POSIX::_setClipBoard(jstring s) {
704 int len = JvGetStringUTFLength(clipboard);
706 JvGetStringUTFRegion(clipboard, 0, len, buf);
708 XSetSelectionOwner(display, XInternAtom(display, "PRIMARY", 0), selectionWindow, CurrentTime);
711 typedef int (X11ErrorHandler)(Display*, XErrorEvent*);
712 int errorHandler(Display* d, XErrorEvent* e) {
713 // this error handler is only installed during the initial
714 // test to see if shm is present
718 void org::xwt::plat::POSIX::natInit() {
721 org::xwt::Platform::criticalAbort(JvNewStringLatin1("Your X11 libraries do not support multithreaded programs"));
723 display = XOpenDisplay(NULL);
724 screen_num = XDefaultScreen(display);
725 colorDepth = (jint)(DefaultDepth(((Display*)display), 0));
726 shm_info.shmaddr = NULL;
728 shm_supported = (XShmQueryExtension(display) == True);
730 X11ErrorHandler* oldHandler = XSetErrorHandler(errorHandler);
731 XShmSegmentInfo sinfo;
732 sinfo.shmid = shmget(IPC_PRIVATE, 1, IPC_CREAT | 0777 | IPC_EXCL);
733 sinfo.readOnly = False;
734 // if the server is remote, this will trigger the error handler
735 XShmAttach(display, &sinfo);
736 XSync(display, False);
737 XSetErrorHandler(oldHandler);
741 shm_pixmaps_supported = (XShmPixmapFormat(display) == ZPixmap);
743 crosshair = JvNewStringLatin1("crosshair");
744 east = JvNewStringLatin1("east");
745 hand = JvNewStringLatin1("hand");
746 move = JvNewStringLatin1("move");
747 north = JvNewStringLatin1("north");
748 northeast = JvNewStringLatin1("northeast");
749 northwest = JvNewStringLatin1("northwest");
750 south = JvNewStringLatin1("south");
751 southeast = JvNewStringLatin1("southeast");
752 southwest = JvNewStringLatin1("southwest");
753 text = JvNewStringLatin1("text");
754 west = JvNewStringLatin1("west");
755 wait_string = JvNewStringLatin1("wait");
756 crosshair_cursor = XCreateFontCursor(display, XC_tcross);
757 east_cursor = XCreateFontCursor(display, XC_right_side);
758 hand_cursor = XCreateFontCursor(display, XC_hand2);
759 move_cursor = XCreateFontCursor(display, XC_fleur);
760 north_cursor = XCreateFontCursor(display, XC_top_side);
761 northeast_cursor = XCreateFontCursor(display, XC_top_right_corner);
762 northwest_cursor = XCreateFontCursor(display, XC_left_side);
763 south_cursor = XCreateFontCursor(display, XC_bottom_side);
764 southeast_cursor = XCreateFontCursor(display, XC_bottom_right_corner);
765 southwest_cursor = XCreateFontCursor(display, XC_bottom_left_corner);
766 text_cursor = XCreateFontCursor(display, XC_xterm);
767 west_cursor = XCreateFontCursor(display, XC_right_side);
768 wait_cursor = XCreateFontCursor(display, XC_watch);
769 default_cursor = XCreateFontCursor(display, XC_left_ptr);
771 selectionWindow = XCreateWindow(display, RootWindow(display, screen_num), 0, 0, 1, 1, 0, colorDepth, InputOutput, CopyFromParent, 0, NULL);
772 visual = DefaultVisual(display, screen_num);
774 sprintf(buf, "X11 DISPLAY: %s", XDisplayString(display));
775 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
776 sprintf(buf, "X11 SHM: %s", shm_supported ? "enabled" : "disabled");
777 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
778 sprintf(buf, "X11 Visual: %x %x %x bits: %i visualid: %i depth: %i",
779 visual->red_mask, visual->green_mask, visual->blue_mask, visual->bits_per_rgb, visual->visualid, colorDepth);
780 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
782 // FIXME: don't know why (True, False) is the best solution...
783 if(XmuLookupStandardColormap(display, screen_num, visual->visualid, colorDepth, XA_RGB_BEST_MAP, True, False) == 0)
784 org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: XmuLookupStandardColormap failed"));
786 XStandardColormap* best_map_info = NULL;
788 if (XGetRGBColormaps(display, RootWindow(display, screen_num), &best_map_info, &count, XA_RGB_BEST_MAP) == 0)
789 org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: couldn't allocate a standard colormap"));
790 if (!best_map_info->colormap)
791 org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: XmuLookupStandardColomap succeded, but no colormap was found on the root window"));
792 if (best_map_info->red_max == 0)
793 org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: standard colormap exists, but was improperly allocated"));
794 s_colormap = best_map_info->colormap;
795 colormap_info = best_map_info;
797 sprintf(buf, " red_max / red_mult: %x %x", colormap_info->red_max, colormap_info->red_mult);
798 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
799 sprintf(buf, " green_max / green_mult: %x %x", colormap_info->green_max, colormap_info->green_mult);
800 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
801 sprintf(buf, " blue_max / blue_mult: %x %x", colormap_info->blue_max, colormap_info->blue_mult);
802 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
803 sprintf(buf, " base_pixel: %x", colormap_info->base_pixel);
804 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
807 JArray<java::lang::String*>* org::xwt::plat::POSIX::listNativeFonts() {
809 char** xfonts = XListFonts(display, "-*-*-*-*-normal-*-*-*-*-*-*-*-*-*", 0xFFFFFFFF, &numfonts);
810 JArray<java::lang::String*>* fonts = (JArray<java::lang::String*>*)JvNewObjectArray(numfonts, &(::java::lang::String::class$), NULL);
811 java::lang::String** jfonts = (java::lang::String**)(elements(fonts));
812 for(int i=0; i<numfonts; i++)
813 jfonts[i] = JvNewStringLatin1(xfonts[i], strlen(xfonts[i]));
817 gnu::gcj::RawData* org::xwt::plat::POSIX::fontStringToStruct(jstring s) {
818 int len = min(1024, JvGetStringUTFLength(s));
820 JvGetStringUTFRegion(s, 0, len, buf);
822 return (gnu::gcj::RawData*)XLoadQueryFont(display, buf);
825 jint org::xwt::plat::POSIX::_getMaxAscent(::java::lang::String* font) { return ((XFontStruct*)fontToXFont(font))->max_bounds.ascent; }
826 jint org::xwt::plat::POSIX::_getMaxDescent(::java::lang::String* font) { return ((XFontStruct*)fontToXFont(font))->max_bounds.descent; }
827 jint org::xwt::plat::POSIX::_stringWidth(::java::lang::String* font, ::java::lang::String* text) {
828 if (text == NULL) return 0;
829 int len = JvGetStringUTFLength(text);
831 JvGetStringUTFRegion(text, 0, len, buf);
833 return XTextWidth((XFontStruct*)fontToXFont(font), buf, len);
837 //////////////////////////////////////////////////////////////////////////////
838 //////////////////////////////////////////////////////////////////////////////
839 //////////////////////////////////////////////////////////////////////////////
840 //////////////////////////////////////////////////////////////////////////////
842 // Everything below this point was taken, cut-and-paste, from the //
843 // source for libXmu. It implements the official 'standard colormap //
844 // creation algorithm. I made some small changes to //
845 // XmuDeleteStandardColormap //
847 //////////////////////////////////////////////////////////////////////////////
848 //////////////////////////////////////////////////////////////////////////////
849 //////////////////////////////////////////////////////////////////////////////
850 //////////////////////////////////////////////////////////////////////////////
852 /* $Xorg: LookupCmap.c,v 1.4 2001/02/09 02:03:53 xorgcvs Exp $ */
856 Copyright 1989, 1998 The Open Group
858 Permission to use, copy, modify, distribute, and sell this software and its
859 documentation for any purpose is hereby granted without fee, provided that
860 the above copyright notice appear in all copies and that both that
861 copyright notice and this permission notice appear in supporting
864 The above copyright notice and this permission notice shall be included in
865 all copies or substantial portions of the Software.
867 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
868 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
869 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
870 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
871 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
872 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
874 Except as contained in this notice, the name of The Open Group shall not be
875 used in advertising or otherwise to promote the sale, use or other dealings
876 in this Software without prior written authorization from The Open Group.
879 /* $XFree86: xc/lib/Xmu/LookupCmap.c,v 1.8 2001/12/14 19:55:47 dawes Exp $ */
882 * Author: Donna Converse, MIT X Consortium
886 #include <X11/Xlib.h>
887 #include <X11/Xatom.h>
888 #include <X11/Xutil.h>
889 #include <X11/Xmu/StdCmap.h>
895 static Status lookup(Display*, int, VisualID, Atom, XStandardColormap*, Bool);
898 * To create a standard colormap if one does not currently exist, or
899 * replace the currently existing standard colormap, use
900 * XmuLookupStandardColormap().
902 * Given a screen, a visual, and a property, XmuLookupStandardColormap()
903 * will determine the best allocation for the property under the specified
904 * visual, and determine the whether to create a new colormap or to use
905 * the default colormap of the screen. It will call XmuStandardColormap()
906 * to create the standard colormap.
908 * If replace is true, any previous definition of the property will be
909 * replaced. If retain is true, the property and the colormap will be
910 * made permanent for the duration of the server session. However,
911 * pre-existing property definitions which are not replaced cannot be made
912 * permanent by a call to XmuLookupStandardColormap(); a request to retain
913 * resources pertains to newly created resources.
915 * Returns 0 on failure, non-zero on success. A request to create a
916 * standard colormap upon a visual which cannot support such a map is
917 * considered a failure. An example of this would be requesting any
918 * standard colormap property on a monochrome visual, or, requesting an
919 * RGB_BEST_MAP on a display whose colormap size is 16.
923 XmuLookupStandardColormap(Display *dpy, int screen, VisualID visualid,
924 unsigned int depth, Atom property,
925 Bool replace, Bool retain)
927 * dpy - specifies X server connection
928 * screen - specifies screen of display
929 * visualid - specifies the visual type
930 * depth - specifies the visual type
931 * property - a standard colormap property
932 * replace - specifies whether to replace
933 * retain - specifies whether to retain
936 Display *odpy; /* original display connection */
937 XStandardColormap *colormap;
938 XVisualInfo vinfo_template, *vinfo; /* visual */
940 unsigned long r_max, g_max, b_max; /* allocation */
942 Colormap cmap; /* colormap ID */
946 /* Match the requested visual */
948 vinfo_template.visualid = visualid;
949 vinfo_template.screen = screen;
950 vinfo_template.depth = depth;
951 vinfo_mask = VisualIDMask | VisualScreenMask | VisualDepthMask;
952 if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &count)) ==
956 /* Monochrome visuals have no standard maps */
958 if (vinfo->colormap_size <= 2) {
959 XFree((char *) vinfo);
963 /* If the requested property already exists on this screen, and,
964 * if the replace flag has not been set to true, return success.
965 * lookup() will remove a pre-existing map if replace is true.
968 if (lookup(dpy, screen, visualid, property, (XStandardColormap *) NULL,
969 replace) && !replace) {
970 XFree((char *) vinfo);
974 /* Determine the best allocation for this property under the requested
975 * visualid and depth, and determine whether or not to use the default
976 * colormap of the screen.
979 if (!XmuGetColormapAllocation(vinfo, property, &r_max, &g_max, &b_max)) {
980 XFree((char *) vinfo);
984 cmap = (property == XA_RGB_DEFAULT_MAP &&
985 visualid == XVisualIDFromVisual(DefaultVisual(dpy, screen)))
986 ? DefaultColormap(dpy, screen) : None;
988 /* If retaining resources, open a new connection to the same server */
992 if ((dpy = XOpenDisplay(XDisplayString(odpy))) == NULL) {
993 XFree((char *) vinfo);
998 /* Create the standard colormap */
1000 colormap = XmuStandardColormap(dpy, screen, visualid, depth, property,
1001 cmap, r_max, g_max, b_max);
1003 /* Set the standard colormap property */
1008 if (lookup(dpy, screen, visualid, property, colormap, replace) &&
1010 /* Someone has defined the property since we last looked.
1011 * Since we will not replace it, release our own resources.
1012 * If this is the default map, our allocations will be freed
1013 * when this connection closes.
1015 if (colormap->killid == ReleaseByFreeingColormap)
1016 XFreeColormap(dpy, colormap->colormap);
1017 } else if (retain) {
1018 XSetCloseDownMode(dpy, RetainPermanent);
1021 XFree((char *) colormap);
1027 XFree((char *) vinfo);
1031 /***************************************************************************/
1033 /* Lookup a standard colormap property. If the property is RGB_DEFAULT_MAP,
1034 * the visualid is used to determine whether the indicated standard colormap
1035 * exists. If the map exists and replace is true, delete the resources used
1036 * by the map and remove the property. Return true if the map exists,
1037 * or did exist and was deleted; return false if the map was not found.
1039 * Note that this is not the way that a Status return is normally used.
1041 * If new is not NULL, new points to an XStandardColormap structure which
1042 * describes a standard colormap of the specified property. It will be made
1043 * a standard colormap of the screen if none already exists, or if replace
1048 lookup(Display *dpy, int screen, VisualID visualid, Atom property,
1049 XStandardColormap *cnew, Bool replace)
1051 * dpy - specifies display connection
1052 * screen - specifies screen number
1053 * visualid - specifies visualid for std map
1054 * property - specifies colormap property name
1055 * cnew - specifies a standard colormap
1056 * replace - specifies whether to replace
1061 XStandardColormap *stdcmaps, *s;
1062 Window win = RootWindow(dpy, screen);
1064 /* The property does not already exist */
1066 if (! XGetRGBColormaps(dpy, win, &stdcmaps, &count, property)) {
1068 XSetRGBColormaps(dpy, win, cnew, 1, property);
1072 /* The property exists and is not describing the RGB_DEFAULT_MAP */
1074 if (property != XA_RGB_DEFAULT_MAP) {
1076 XmuDeleteStandardColormap(dpy, screen, property);
1078 XSetRGBColormaps(dpy, win, cnew, 1, property);
1080 XFree((char *)stdcmaps);
1084 /* The property exists and is RGB_DEFAULT_MAP */
1086 for (i=0, s=stdcmaps; (i < count) && (s->visualid != visualid); i++, s++)
1089 /* No RGB_DEFAULT_MAP property matches the given visualid */
1093 XStandardColormap *m, *maps;
1095 s = (XStandardColormap *) malloc((unsigned) ((count+1) * sizeof
1096 (XStandardColormap)));
1098 for (i = 0, m = s, maps = stdcmaps; i < count; i++, m++, maps++) {
1099 m->colormap = maps->colormap;
1100 m->red_max = maps->red_max;
1101 m->red_mult = maps->red_mult;
1102 m->green_max = maps->green_max;
1103 m->green_mult = maps->green_mult;
1104 m->blue_max = maps->blue_max;
1105 m->blue_mult = maps->blue_mult;
1106 m->base_pixel = maps->base_pixel;
1107 m->visualid = maps->visualid;
1108 m->killid = maps->killid;
1110 m->colormap = cnew->colormap;
1111 m->red_max = cnew->red_max;
1112 m->red_mult = cnew->red_mult;
1113 m->green_max = cnew->green_max;
1114 m->green_mult = cnew->green_mult;
1115 m->blue_max = cnew->blue_max;
1116 m->blue_mult = cnew->blue_mult;
1117 m->base_pixel = cnew->base_pixel;
1118 m->visualid = cnew->visualid;
1119 m->killid = cnew->killid;
1121 XSetRGBColormaps(dpy, win, s, ++count, property);
1124 XFree((char *) stdcmaps);
1128 /* Found an RGB_DEFAULT_MAP property with a matching visualid */
1131 /* Free old resources first - we may need them, particularly in
1132 * the default colormap of the screen. However, because of this,
1133 * it is possible that we will destroy the old resource and fail
1134 * to create a new one if XmuStandardColormap() fails.
1138 XmuDeleteStandardColormap(dpy, screen, property);
1140 XSetRGBColormaps(dpy, win, cnew, 1, property);
1143 XStandardColormap *map;
1145 /* s still points to the matching standard colormap */
1147 if (s->killid == ReleaseByFreeingColormap) {
1148 if ((s->colormap != None) &&
1149 (s->colormap != DefaultColormap(dpy, screen)))
1150 XFreeColormap(dpy, s->colormap);
1152 else if (s->killid != None)
1153 XKillClient(dpy, s->killid);
1155 map = (cnew) ? cnew : stdcmaps + --count;
1157 s->colormap = map->colormap;
1158 s->red_max = map->red_max;
1159 s->red_mult = map->red_mult;
1160 s->green_max = map->green_max;
1161 s->green_mult = map->green_mult;
1162 s->blue_max = map->blue_max;
1163 s->blue_mult = map->blue_mult;
1164 s->visualid = map->visualid;
1165 s->killid = map->killid;
1167 XSetRGBColormaps(dpy, win, stdcmaps, count, property);
1170 XFree((char *) stdcmaps);
1174 /* $Xorg: CmapAlloc.c,v 1.4 2001/02/09 02:03:51 xorgcvs Exp $ */
1178 Copyright 1989, 1994, 1998 The Open Group
1180 Permission to use, copy, modify, distribute, and sell this software and its
1181 documentation for any purpose is hereby granted without fee, provided that
1182 the above copyright notice appear in all copies and that both that
1183 copyright notice and this permission notice appear in supporting
1186 The above copyright notice and this permission notice shall be included in
1187 all copies or substantial portions of the Software.
1189 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1190 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1191 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1192 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1193 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1194 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1196 Except as contained in this notice, the name of The Open Group shall not be
1197 used in advertising or otherwise to promote the sale, use or other dealings
1198 in this Software without prior written authorization from The Open Group.
1201 /* $XFree86: xc/lib/Xmu/CmapAlloc.c,v 1.7 2001/12/14 19:55:35 dawes Exp $ */
1204 * Author: Donna Converse, MIT X Consortium
1207 #include <X11/Xlib.h>
1208 #include <X11/Xatom.h>
1209 #include <X11/Xutil.h>
1210 #include <X11/Xmu/StdCmap.h>
1213 #define lowbit(x) ((x) & (~(x) + 1))
1218 static void best_allocation(XVisualInfo*, unsigned long*, unsigned long*,
1220 static int default_allocation(XVisualInfo*, unsigned long*,
1221 unsigned long*, unsigned long*);
1222 static void gray_allocation(int, unsigned long*, unsigned long*,
1224 static int icbrt(int);
1225 static int icbrt_with_bits(int, int);
1226 static int icbrt_with_guess(int, int);
1228 /* To determine the best allocation of reds, greens, and blues in a
1229 * standard colormap, use XmuGetColormapAllocation.
1230 * vinfo specifies visual information for a chosen visual
1231 * property specifies one of the standard colormap property names
1232 * red_max returns maximum red value
1233 * green_max returns maximum green value
1234 * blue_max returns maximum blue value
1236 * XmuGetColormapAllocation returns 0 on failure, non-zero on success.
1237 * It is assumed that the visual is appropriate for the colormap property.
1241 XmuGetColormapAllocation(XVisualInfo *vinfo, Atom property,
1242 unsigned long *red_max,
1243 unsigned long *green_max,
1244 unsigned long *blue_max)
1248 if (vinfo->colormap_size <= 2)
1253 case XA_RGB_DEFAULT_MAP:
1254 status = default_allocation(vinfo, red_max, green_max, blue_max);
1256 case XA_RGB_BEST_MAP:
1257 best_allocation(vinfo, red_max, green_max, blue_max);
1259 case XA_RGB_GRAY_MAP:
1260 gray_allocation(vinfo->colormap_size, red_max, green_max, blue_max);
1262 case XA_RGB_RED_MAP:
1263 *red_max = vinfo->colormap_size - 1;
1264 *green_max = *blue_max = 0;
1266 case XA_RGB_GREEN_MAP:
1267 *green_max = vinfo->colormap_size - 1;
1268 *red_max = *blue_max = 0;
1270 case XA_RGB_BLUE_MAP:
1271 *blue_max = vinfo->colormap_size - 1;
1272 *red_max = *green_max = 0;
1280 /****************************************************************************/
1281 /* Determine the appropriate color allocations of a gray scale.
1283 * Keith Packard, MIT X Consortium
1287 gray_allocation(int n, unsigned long *red_max, unsigned long *green_max,
1288 unsigned long *blue_max)
1290 *red_max = (n * 30) / 100;
1291 *green_max = (n * 59) / 100;
1292 *blue_max = (n * 11) / 100;
1293 *green_max += ((n - 1) - (*red_max + *green_max + *blue_max));
1296 /****************************************************************************/
1297 /* Determine an appropriate color allocation for the RGB_DEFAULT_MAP.
1298 * If a map has less than a minimum number of definable entries, we do not
1299 * produce an allocation for an RGB_DEFAULT_MAP.
1301 * For 16 planes, the default colormap will have 27 each RGB; for 12 planes,
1302 * 12 each. For 8 planes, let n = the number of colormap entries, which may
1303 * be 256 or 254. Then, maximum red value = floor(cube_root(n - 125)) - 1.
1304 * Maximum green and maximum blue values are identical to maximum red.
1305 * This leaves at least 125 cells which clients can allocate.
1307 * Return 0 if an allocation has been determined, non-zero otherwise.
1311 default_allocation(XVisualInfo *vinfo, unsigned long *red,
1312 unsigned long *green, unsigned long *blue)
1314 int ngrays; /* number of gray cells */
1316 switch (vinfo->c_class)
1320 if (vinfo->colormap_size > 65000)
1321 /* intended for displays with 16 planes */
1322 *red = *green = *blue = (unsigned long) 27;
1323 else if (vinfo->colormap_size > 4000)
1324 /* intended for displays with 12 planes */
1325 *red = *green = *blue = (unsigned long) 12;
1326 else if (vinfo->colormap_size < 250)
1329 /* intended for displays with 8 planes */
1330 *red = *green = *blue = (unsigned long)
1331 (icbrt(vinfo->colormap_size - 125) - 1);
1336 if (vinfo->colormap_size < 10)
1338 *red = *green = *blue = vinfo->colormap_size / 2 - 1;
1343 *red = vinfo->red_mask / lowbit(vinfo->red_mask);
1344 *green = vinfo->green_mask / lowbit(vinfo->green_mask);
1345 *blue = vinfo->blue_mask / lowbit(vinfo->blue_mask);
1350 if (vinfo->colormap_size > 65000)
1352 else if (vinfo->colormap_size > 4000)
1354 else if (vinfo->colormap_size < 250)
1358 gray_allocation(ngrays, red, green, blue);
1367 /****************************************************************************/
1368 /* Determine an appropriate color allocation for the RGB_BEST_MAP.
1370 * For a DirectColor or TrueColor visual, the allocation is determined
1371 * by the red_mask, green_mask, and blue_mask members of the visual info.
1373 * Otherwise, if the colormap size is an integral power of 2, determine
1374 * the allocation according to the number of bits given to each color,
1375 * with green getting more than red, and red more than blue, if there
1376 * are to be inequities in the distribution. If the colormap size is
1377 * not an integral power of 2, let n = the number of colormap entries.
1378 * Then maximum red value = floor(cube_root(n)) - 1;
1379 * maximum blue value = floor(cube_root(n)) - 1;
1380 * maximum green value = n / ((# red values) * (# blue values)) - 1;
1381 * Which, on a GPX, allows for 252 entries in the best map, out of 254
1382 * defineable colormap entries.
1386 best_allocation(XVisualInfo *vinfo, unsigned long *red, unsigned long *green,
1387 unsigned long *blue)
1390 if (vinfo->c_class == DirectColor || vinfo->c_class == TrueColor)
1392 *red = vinfo->red_mask;
1393 while ((*red & 01) == 0)
1395 *green = vinfo->green_mask;
1396 while ((*green & 01) == 0)
1398 *blue = vinfo->blue_mask;
1399 while ((*blue & 01) == 0)
1404 register int bits, n;
1406 /* Determine n such that n is the least integral power of 2 which is
1407 * greater than or equal to the number of entries in the colormap.
1411 while (vinfo->colormap_size > n)
1417 /* If the number of entries in the colormap is a power of 2, determine
1418 * the allocation by "dealing" the bits, first to green, then red, then
1419 * blue. If not, find the maximum integral red, green, and blue values
1420 * which, when multiplied together, do not exceed the number of
1424 if (n == vinfo->colormap_size)
1426 register int r, g, b;
1428 g = b + ((bits % 3) ? 1 : 0);
1429 r = b + (((bits % 3) == 2) ? 1 : 0);
1436 *red = icbrt_with_bits(vinfo->colormap_size, bits);
1438 *green = (vinfo->colormap_size / ((*red) * (*blue)));
1448 * integer cube roots by Newton's method
1450 * Stephen Gildea, MIT X Consortium, July 1991
1456 register int bits = 0;
1457 register unsigned n = a;
1464 return icbrt_with_bits(a, bits);
1469 icbrt_with_bits(int a, int bits)
1470 /* bits - log 2 of a */
1472 return icbrt_with_guess(a, a>>2*bits/3);
1475 #ifdef _X_ROOT_STATS
1476 int icbrt_loopcount;
1479 /* Newton's Method: x_n+1 = x_n - ( f(x_n) / f'(x_n) ) */
1481 /* for cube roots, x^3 - a = 0, x_new = x - 1/3 (x - a/x^2) */
1484 * Quick and dirty cube roots. Nothing fancy here, just Newton's method.
1485 * Only works for positive integers (since that's all we need).
1486 * We actually return floor(cbrt(a)) because that's what we need here, too.
1490 icbrt_with_guess(int a, int guess)
1494 #ifdef _X_ROOT_STATS
1495 icbrt_loopcount = 0;
1503 #ifdef _X_ROOT_STATS
1506 delta = (guess - a/(guess*guess))/3;
1508 printf("pass %d: guess=%d, delta=%d\n", icbrt_loopcount, guess, delta);
1511 } while (delta != 0);
1513 if (guess*guess*guess > a)
1520 /* $Xorg: StdCmap.c,v 1.4 2001/02/09 02:03:53 xorgcvs Exp $ */
1524 Copyright 1989, 1998 The Open Group
1526 Permission to use, copy, modify, distribute, and sell this software and its
1527 documentation for any purpose is hereby granted without fee, provided that
1528 the above copyright notice appear in all copies and that both that
1529 copyright notice and this permission notice appear in supporting
1532 The above copyright notice and this permission notice shall be included in
1533 all copies or substantial portions of the Software.
1535 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1536 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1537 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1538 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1539 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1540 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1542 Except as contained in this notice, the name of The Open Group shall not be
1543 used in advertising or otherwise to promote the sale, use or other dealings
1544 in this Software without prior written authorization from The Open Group.
1547 /* $XFree86: xc/lib/Xmu/StdCmap.c,v 1.6 2001/12/14 19:55:48 dawes Exp $ */
1550 * Author: Donna Converse, MIT X Consortium
1554 #include <X11/Xlib.h>
1555 #include <X11/Xatom.h>
1556 #include <X11/Xutil.h>
1557 #include <X11/Xmu/StdCmap.h>
1559 #define lowbit(x) ((x) & (~(x) + 1))
1564 /* argument restrictions */
1565 static Status valid_args(XVisualInfo*, unsigned long, unsigned long,
1566 unsigned long, Atom);
1569 * To create any one standard colormap, use XmuStandardColormap().
1571 * Create a standard colormap for the given screen, visualid, and visual
1572 * depth, with the given red, green, and blue maximum values, with the
1573 * given standard property name. Return a pointer to an XStandardColormap
1574 * structure which describes the newly created colormap, upon success.
1575 * Upon failure, return NULL.
1577 * XmuStandardColormap() calls XmuCreateColormap() to create the map.
1579 * Resources created by this function are not made permanent; that is the
1580 * caller's responsibility.
1584 XmuStandardColormap(Display *dpy, int screen, VisualID visualid,
1585 unsigned int depth, Atom property, Colormap cmap,
1586 unsigned long red_max, unsigned long green_max,
1587 unsigned long blue_max)
1589 * dpy - specifies X server connection
1590 * screen - specifies display screen
1591 * visualid - identifies the visual type
1592 * depth - identifies the visual type
1593 * property - a standard colormap property
1594 * cmap - specifies colormap ID or None
1595 * red_max, green_max, blue_max - allocations
1598 XStandardColormap *stdcmap;
1600 XVisualInfo vinfo_template, *vinfo;
1604 /* Match the required visual information to an actual visual */
1605 vinfo_template.visualid = visualid;
1606 vinfo_template.screen = screen;
1607 vinfo_template.depth = depth;
1608 vinfo_mask = VisualIDMask | VisualScreenMask | VisualDepthMask;
1609 if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &n)) == NULL)
1612 /* Check the validity of the combination of visual characteristics,
1613 * allocation, and colormap property. Create an XStandardColormap
1617 if (! valid_args(vinfo, red_max, green_max, blue_max, property)
1618 || ((stdcmap = XAllocStandardColormap()) == NULL)) {
1619 XFree((char *) vinfo);
1623 /* Fill in the XStandardColormap structure */
1625 if (cmap == DefaultColormap(dpy, screen)) {
1626 /* Allocating out of the default map, cannot use XFreeColormap() */
1627 Window win = XCreateWindow(dpy, RootWindow(dpy, screen), 1, 1, 1, 1,
1628 0, 0, InputOnly, vinfo->visual,
1630 (XSetWindowAttributes *)NULL);
1631 stdcmap->killid = (XID) XCreatePixmap(dpy, win, 1, 1, depth);
1632 XDestroyWindow(dpy, win);
1633 stdcmap->colormap = cmap;
1635 stdcmap->killid = ReleaseByFreeingColormap;
1636 stdcmap->colormap = XCreateColormap(dpy, RootWindow(dpy, screen),
1637 vinfo->visual, AllocNone);
1639 stdcmap->red_max = red_max;
1640 stdcmap->green_max = green_max;
1641 stdcmap->blue_max = blue_max;
1642 if (property == XA_RGB_GRAY_MAP)
1643 stdcmap->red_mult = stdcmap->green_mult = stdcmap->blue_mult = 1;
1644 else if (vinfo->c_class == TrueColor || vinfo->c_class == DirectColor) {
1645 stdcmap->red_mult = lowbit(vinfo->red_mask);
1646 stdcmap->green_mult = lowbit(vinfo->green_mask);
1647 stdcmap->blue_mult = lowbit(vinfo->blue_mask);
1649 stdcmap->red_mult = (red_max > 0)
1650 ? (green_max + 1) * (blue_max + 1) : 0;
1651 stdcmap->green_mult = (green_max > 0) ? blue_max + 1 : 0;
1652 stdcmap->blue_mult = (blue_max > 0) ? 1 : 0;
1654 stdcmap->base_pixel = 0; /* base pixel may change */
1655 stdcmap->visualid = vinfo->visualid;
1657 /* Make the colormap */
1659 status = XmuCreateColormap(dpy, stdcmap);
1663 XFree((char *) vinfo);
1666 /* Free the colormap or the pixmap, if we created one */
1667 if (stdcmap->killid == ReleaseByFreeingColormap)
1668 XFreeColormap(dpy, stdcmap->colormap);
1669 else if (stdcmap->killid != None)
1670 XFreePixmap(dpy, stdcmap->killid);
1672 XFree((char *) stdcmap);
1673 return (XStandardColormap *) NULL;
1678 /****************************************************************************/
1680 valid_args(XVisualInfo *vinfo, unsigned long red_max, unsigned long green_max,
1681 unsigned long blue_max, Atom property)
1683 * vinfo - specifies visual
1684 * red_max, green_max, blue_max - specifies alloc
1685 * property - specifies property name
1688 unsigned long ncolors; /* number of colors requested */
1690 /* Determine that the number of colors requested is <= map size */
1692 if ((vinfo->c_class == DirectColor) || (vinfo->c_class == TrueColor)) {
1695 mask = vinfo->red_mask;
1700 mask = vinfo->green_mask;
1703 if (green_max > mask)
1705 mask = vinfo->blue_mask;
1708 if (blue_max > mask)
1710 } else if (property == XA_RGB_GRAY_MAP) {
1711 ncolors = red_max + green_max + blue_max + 1;
1712 if (ncolors > vinfo->colormap_size)
1715 ncolors = (red_max + 1) * (green_max + 1) * (blue_max + 1);
1716 if (ncolors > vinfo->colormap_size)
1720 /* Determine that the allocation and visual make sense for the property */
1724 case XA_RGB_DEFAULT_MAP:
1725 if (red_max == 0 || green_max == 0 || blue_max == 0)
1728 case XA_RGB_RED_MAP:
1732 case XA_RGB_GREEN_MAP:
1736 case XA_RGB_BLUE_MAP:
1740 case XA_RGB_BEST_MAP:
1741 if (red_max == 0 || green_max == 0 || blue_max == 0)
1744 case XA_RGB_GRAY_MAP:
1745 if (red_max == 0 || blue_max == 0 || green_max == 0)
1755 /* $Xorg: CrCmap.c,v 1.4 2001/02/09 02:03:51 xorgcvs Exp $ */
1759 Copyright 1989, 1998 The Open Group
1761 Permission to use, copy, modify, distribute, and sell this software and its
1762 documentation for any purpose is hereby granted without fee, provided that
1763 the above copyright notice appear in all copies and that both that
1764 copyright notice and this permission notice appear in supporting
1767 The above copyright notice and this permission notice shall be included in
1768 all copies or substantial portions of the Software.
1770 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1771 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1772 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1773 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1774 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1775 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1777 Except as contained in this notice, the name of The Open Group shall not be
1778 used in advertising or otherwise to promote the sale, use or other dealings
1779 in this Software without prior written authorization from The Open Group.
1782 /* $XFree86: xc/lib/Xmu/CrCmap.c,v 3.7 2001/12/14 19:55:36 dawes Exp $ */
1785 * Author: Donna Converse, MIT X Consortium
1789 * CreateCmap.c - given a standard colormap description, make the map.
1794 #include <X11/Xlib.h>
1795 #include <X11/Xutil.h>
1796 #include <X11/Xmu/StdCmap.h>
1801 /* allocate entire map Read Only */
1802 static int ROmap(Display*, Colormap, unsigned long[], int, int);
1804 /* allocate a cell, prefer Read Only */
1805 static Status ROorRWcell(Display*, Colormap, unsigned long[], int,
1806 XColor*, unsigned long);
1808 /* allocate a cell Read Write */
1809 static Status RWcell(Display*, Colormap, XColor*, XColor*, unsigned long*);
1812 static int compare(_Xconst void*, _Xconst void*);
1814 /* find contiguous sequence of cells */
1815 static Status contiguous(unsigned long[], int, int, unsigned long, int*, int*);
1817 /* frees resources before quitting */
1818 static void free_cells(Display*, Colormap, unsigned long[], int, int);
1820 /* create a map in a RO visual type */
1821 static Status readonly_map(Display*, XVisualInfo*, XStandardColormap*);
1823 /* create a map in a RW visual type */
1824 static Status readwrite_map(Display*, XVisualInfo*, XStandardColormap*);
1826 #define lowbit(x) ((x) & (~(x) + 1))
1827 #define TRUEMATCH(mult,max,mask) \
1828 (colormap->max * colormap->mult <= vinfo->mask && \
1829 lowbit(vinfo->mask) == colormap->mult)
1832 * To create any one colormap which is described by an XStandardColormap
1833 * structure, use XmuCreateColormap().
1835 * Return 0 on failure, non-zero on success.
1836 * Resources created by this function are not made permanent.
1837 * No argument error checking is provided. Use at your own risk.
1839 * All colormaps are created with read only allocations, with the exception
1840 * of read only allocations of colors in the default map or otherwise
1841 * which fail to return the expected pixel value, and these are individually
1842 * defined as read/write allocations. This is done so that all the cells
1843 * defined in the default map are contiguous, for use in image processing.
1844 * This typically happens with White and Black in the default map.
1846 * Colormaps of static visuals are considered to be successfully created if
1847 * the map of the static visual matches the definition given in the
1848 * standard colormap structure.
1852 XmuCreateColormap(Display *dpy, XStandardColormap *colormap)
1853 /* dpy - specifies the connection under which the map is created
1854 * colormap - specifies the map to be created, and returns, particularly
1855 * if the map is created as a subset of the default colormap
1856 * of the screen, the base_pixel of the map.
1859 XVisualInfo vinfo_template; /* template visual information */
1860 XVisualInfo *vinfo; /* matching visual information */
1861 XVisualInfo *vpointer; /* for freeing the entire list */
1862 long vinfo_mask; /* specifies the visual mask value */
1863 int n; /* number of matching visuals */
1866 vinfo_template.visualid = colormap->visualid;
1867 vinfo_mask = VisualIDMask;
1868 if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &n)) == NULL)
1871 /* A visual id may be valid on multiple screens. Also, there may
1872 * be multiple visuals with identical visual ids at different depths.
1873 * If the colormap is the Default Colormap, use the Default Visual.
1874 * Otherwise, arbitrarily, use the deepest visual.
1880 register int screen_number;
1884 for (screen_number = ScreenCount(dpy); --screen_number >= 0; )
1885 if (colormap->colormap == DefaultColormap(dpy, screen_number)) {
1891 for (i=0; i < n; i++, vinfo++) {
1892 if (vinfo->visual == DefaultVisual(dpy, screen_number))
1897 XVisualInfo *v = NULL;
1899 for (i=0; i < n; i++, vinfo++)
1900 if (vinfo->depth > maxdepth) {
1901 maxdepth = vinfo->depth;
1908 if (vinfo->c_class == PseudoColor || vinfo->c_class == DirectColor ||
1909 vinfo->c_class == GrayScale)
1910 status = readwrite_map(dpy, vinfo, colormap);
1911 else if (vinfo->c_class == TrueColor)
1912 status = TRUEMATCH(red_mult, red_max, red_mask) &&
1913 TRUEMATCH(green_mult, green_max, green_mask) &&
1914 TRUEMATCH(blue_mult, blue_max, blue_mask);
1916 status = readonly_map(dpy, vinfo, colormap);
1918 XFree((char *) vpointer);
1922 /****************************************************************************/
1924 readwrite_map(Display *dpy, XVisualInfo *vinfo, XStandardColormap *colormap)
1926 register unsigned long i, n; /* index counters */
1927 unsigned long ncolors; /* number of colors to be defined */
1928 int npixels; /* number of pixels allocated R/W */
1929 int first_index; /* first index of pixels to use */
1930 int remainder; /* first index of remainder */
1931 XColor color; /* the definition of a color */
1932 unsigned long *pixels; /* array of colormap pixels */
1933 unsigned long delta;
1936 /* Determine ncolors, the number of colors to be defined.
1937 * Insure that 1 < ncolors <= the colormap size.
1939 if (vinfo->c_class == DirectColor) {
1940 ncolors = colormap->red_max;
1941 if (colormap->green_max > ncolors)
1942 ncolors = colormap->green_max;
1943 if (colormap->blue_max > ncolors)
1944 ncolors = colormap->blue_max;
1946 delta = lowbit(vinfo->red_mask) +
1947 lowbit(vinfo->green_mask) +
1948 lowbit(vinfo->blue_mask);
1950 ncolors = colormap->red_max * colormap->red_mult +
1951 colormap->green_max * colormap->green_mult +
1952 colormap->blue_max * colormap->blue_mult + 1;
1955 if (ncolors <= 1 || (int) ncolors > vinfo->colormap_size) return 0;
1957 /* Allocate Read/Write as much of the colormap as we can possibly get.
1958 * Then insure that the pixels we were allocated are given in
1959 * monotonically increasing order, using a quicksort. Next, insure
1960 * that our allocation includes a subset of contiguous pixels at least
1961 * as long as the number of colors to be defined. Now we know that
1962 * these conditions are met:
1963 * 1) There are no free cells in the colormap.
1964 * 2) We have a contiguous sequence of pixels, monotonically
1965 * increasing, of length >= the number of colors requested.
1967 * One cell at a time, we will free, compute the next color value,
1968 * then allocate read only. This takes a long time.
1969 * This is done to insure that cells are allocated read only in the
1970 * contiguous order which we prefer. If the server has a choice of
1971 * cells to grant to an allocation request, the server may give us any
1972 * cell, so that is why we do these slow gymnastics.
1975 if ((pixels = (unsigned long *) calloc((unsigned) vinfo->colormap_size,
1976 sizeof(unsigned long))) == NULL)
1979 if ((npixels = ROmap(dpy, colormap->colormap, pixels,
1980 vinfo->colormap_size, ncolors)) == 0) {
1981 free((char *) pixels);
1985 qsort((char *) pixels, npixels, sizeof(unsigned long), compare);
1987 if (!contiguous(pixels, npixels, ncolors, delta, &first_index, &remainder))
1989 /* can't find enough contiguous cells, give up */
1990 XFreeColors(dpy, colormap->colormap, pixels, npixels,
1992 free((char *) pixels);
1995 colormap->base_pixel = pixels[first_index];
1997 /* construct a gray map */
1998 if (colormap->red_mult == 1 && colormap->green_mult == 1 &&
1999 colormap->blue_mult == 1)
2000 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
2003 color.blue = color.green = color.red =
2004 (unsigned short) ((i * 65535) / (colormap->red_max +
2005 colormap->green_max +
2006 colormap->blue_max));
2008 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
2013 /* construct a red ramp map */
2014 else if (colormap->green_max == 0 && colormap->blue_max == 0)
2015 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
2018 color.red = (unsigned short) ((i * 65535) / colormap->red_max);
2019 color.green = color.blue = 0;
2021 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
2026 /* construct a green ramp map */
2027 else if (colormap->red_max == 0 && colormap->blue_max == 0)
2028 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
2031 color.green = (unsigned short) ((i * 65535) / colormap->green_max);
2032 color.red = color.blue = 0;
2034 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
2039 /* construct a blue ramp map */
2040 else if (colormap->red_max == 0 && colormap->green_max == 0)
2041 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
2044 color.blue = (unsigned short) ((i * 65535) / colormap->blue_max);
2045 color.red = color.green = 0;
2047 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
2052 /* construct a standard red green blue cube map */
2055 #define calc(max,mult) (((n / colormap->mult) % \
2056 (colormap->max + 1)) * 65535) / colormap->max
2058 for (n=0, i=0; i < ncolors; i++, n += delta)
2060 color.pixel = n + colormap->base_pixel;
2061 color.red = calc(red_max, red_mult);
2062 color.green = calc(green_max, green_mult);
2063 color.blue = calc(blue_max, blue_mult);
2064 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
2070 /* We have a read-only map defined. Now free unused cells,
2071 * first those occuring before the contiguous sequence begins,
2072 * then any following the contiguous sequence.
2076 XFreeColors(dpy, colormap->colormap, pixels, first_index,
2079 XFreeColors(dpy, colormap->colormap,
2080 &(pixels[first_index + ncolors]), remainder,
2083 free((char *) pixels);
2088 /****************************************************************************/
2090 ROmap(Display *dpy, Colormap cmap, unsigned long pixels[], int m, int n)
2092 * dpy - the X server connection
2093 * cmap - specifies colormap ID
2094 * pixels - returns pixel allocations
2095 * m - specifies colormap size
2096 * n - specifies number of colors
2101 /* first try to allocate the entire colormap */
2102 if (XAllocColorCells(dpy, cmap, 1, (unsigned long *) NULL,
2103 (unsigned) 0, pixels, (unsigned) m))
2106 /* Allocate all available cells in the colormap, using a binary
2107 * algorithm to discover how many cells we can allocate in the colormap.
2111 p = n + ((m - n + 1) / 2);
2112 if (XAllocColorCells(dpy, cmap, 1, (unsigned long *) NULL,
2113 (unsigned) 0, pixels, (unsigned) p)) {
2117 XFreeColors(dpy, cmap, pixels, p, (unsigned long) 0);
2128 /****************************************************************************/
2130 contiguous(unsigned long pixels[], int npixels, int ncolors,
2131 unsigned long delta, int *first, int *rem)
2132 /* pixels - specifies allocated pixels
2133 * npixels - specifies count of alloc'd pixels
2134 * ncolors - specifies needed sequence length
2135 * delta - between pixels
2136 * first - returns first index of sequence
2137 * rem - returns first index after sequence, or 0, if none follow
2140 register int i = 1; /* walking index into the pixel array */
2141 register int count = 1; /* length of sequence discovered so far */
2144 if (npixels == ncolors) {
2149 while (count < ncolors && ncolors - count <= *rem)
2151 if (pixels[i-1] + delta == pixels[i])
2160 if (count != ncolors)
2166 /****************************************************************************/
2168 ROorRWcell(Display *dpy, Colormap cmap, unsigned long pixels[],
2169 int npixels, XColor *color, unsigned long p)
2171 unsigned long pixel;
2174 /* Free the read/write allocation of one cell in the colormap.
2175 * Request a read only allocation of one cell in the colormap.
2176 * If the read only allocation cannot be granted, give up, because
2177 * there must be no free cells in the colormap.
2178 * If the read only allocation is granted, but gives us a cell which
2179 * is not the one that we just freed, it is probably the case that
2180 * we are trying allocate White or Black or some other color which
2181 * already has a read-only allocation in the map. So we try to
2182 * allocate the previously freed cell with a read/write allocation,
2183 * because we want contiguous cells for image processing algorithms.
2186 pixel = color->pixel;
2187 request.red = color->red;
2188 request.green = color->green;
2189 request.blue = color->blue;
2191 XFreeColors(dpy, cmap, &pixel, 1, (unsigned long) 0);
2192 if (! XAllocColor(dpy, cmap, color)
2193 || (color->pixel != pixel &&
2194 (!RWcell(dpy, cmap, color, &request, &pixel))))
2196 free_cells(dpy, cmap, pixels, npixels, (int)p);
2203 /****************************************************************************/
2205 free_cells(Display *dpy, Colormap cmap, unsigned long pixels[],
2208 * pixels - to be freed
2209 * npixels - original number allocated
2212 /* One of the npixels allocated has already been freed.
2213 * p is the index of the freed pixel.
2214 * First free the pixels preceeding p, and there are p of them;
2215 * then free the pixels following p, there are npixels - p - 1 of them.
2217 XFreeColors(dpy, cmap, pixels, p, (unsigned long) 0);
2218 XFreeColors(dpy, cmap, &(pixels[p+1]), npixels - p - 1, (unsigned long) 0);
2219 free((char *) pixels);
2223 /****************************************************************************/
2225 RWcell(Display *dpy, Colormap cmap, XColor *color, XColor *request,
2226 unsigned long *pixel)
2228 unsigned long n = *pixel;
2230 XFreeColors(dpy, cmap, &(color->pixel), 1, (unsigned long)0);
2231 if (! XAllocColorCells(dpy, cmap, (Bool) 0, (unsigned long *) NULL,
2232 (unsigned) 0, pixel, (unsigned) 1))
2236 XFreeColors(dpy, cmap, pixel, 1, (unsigned long) 0);
2239 color->pixel = *pixel;
2240 color->flags = DoRed | DoGreen | DoBlue;
2241 color->red = request->red;
2242 color->green = request->green;
2243 color->blue = request->blue;
2244 XStoreColors(dpy, cmap, color, 1);
2249 /****************************************************************************/
2251 compare(_Xconst void *e1, _Xconst void *e2)
2253 return ((int)(*(long *)e1 - *(long *)e2));
2257 /****************************************************************************/
2259 readonly_map(Display *dpy, XVisualInfo *vinfo, XStandardColormap *colormap)
2264 last_pixel = (colormap->red_max + 1) * (colormap->green_max + 1) *
2265 (colormap->blue_max + 1) + colormap->base_pixel - 1;
2267 for(i=colormap->base_pixel; i <= last_pixel; i++) {
2269 color.pixel = (unsigned long) i;
2270 color.red = (unsigned short)
2271 (((i/colormap->red_mult) * 65535) / colormap->red_max);
2273 if (vinfo->c_class == StaticColor) {
2274 color.green = (unsigned short)
2275 ((((i/colormap->green_mult) % (colormap->green_max + 1)) *
2276 65535) / colormap->green_max);
2277 color.blue = (unsigned short)
2278 (((i%colormap->green_mult) * 65535) / colormap->blue_max);
2280 else /* vinfo->c_class == GrayScale, old style allocation XXX */
2281 color.green = color.blue = color.red;
2283 XAllocColor(dpy, colormap->colormap, &color);
2284 if (color.pixel != (unsigned long) i)
2291 /* $Xorg: DelCmap.c,v 1.4 2001/02/09 02:03:52 xorgcvs Exp $ */
2295 Copyright 1989, 1998 The Open Group
2297 Permission to use, copy, modify, distribute, and sell this software and its
2298 documentation for any purpose is hereby granted without fee, provided that
2299 the above copyright notice appear in all copies and that both that
2300 copyright notice and this permission notice appear in supporting
2303 The above copyright notice and this permission notice shall be included in
2304 all copies or substantial portions of the Software.
2306 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2307 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2308 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2309 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
2310 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
2311 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2313 Except as contained in this notice, the name of The Open Group shall not be
2314 used in advertising or otherwise to promote the sale, use or other dealings
2315 in this Software without prior written authorization from The Open Group.
2318 /* $XFree86: xc/lib/Xmu/DelCmap.c,v 1.7 2001/12/14 19:55:40 dawes Exp $ */
2321 * Author: Donna Converse, MIT X Consortium
2324 #include <X11/Xlib.h>
2325 #include <X11/Xutil.h>
2326 #include <X11/Xmu/StdCmap.h>
2328 int ignoreErrorHandler(Display* d, XErrorEvent* e) { }
2330 /* To remove any standard colormap property, use XmuDeleteStandardColormap().
2331 * XmuDeleteStandardColormap() will remove the specified property from the
2332 * specified screen, releasing any resources used by the colormap(s) of the
2333 * property if possible.
2337 XmuDeleteStandardColormap(Display *dpy, int screen, Atom property)
2338 /* dpy; - specifies the X server to connect to
2339 * screen - specifies the screen of the display
2340 * property - specifies the standard colormap property
2343 XStandardColormap *stdcmaps, *s;
2346 if (XGetRGBColormaps(dpy, RootWindow(dpy, screen), &stdcmaps, &count,
2349 for (s=stdcmaps; count > 0; count--, s++) {
2350 if ((s->killid == ReleaseByFreeingColormap) &&
2351 (s->colormap != None) &&
2352 (s->colormap != DefaultColormap(dpy, screen))) {
2354 // UGLY HACK written in by Adam Megacz -- sometimes s->colormap isn't valid, so we do some shuffling
2355 X11ErrorHandler* oldHandler = XSetErrorHandler(ignoreErrorHandler);
2357 XFreeColormap(dpy, s->colormap);
2359 XSetErrorHandler(oldHandler);
2362 } else if (s->killid != None) {
2363 XKillClient(dpy, s->killid);
2366 XDeleteProperty(dpy, RootWindow(dpy, screen), property);
2367 XFree((char *) stdcmaps);