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, 500, 300, 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::getBrowserEnvString() {
659 char* envstr = getenv("BROWSER");
660 return envstr == NULL ? NULL : JvNewStringLatin1(envstr);
663 void org::xwt::plat::POSIX::spawnChildProcess(JArray<jstring>* cmd) {
664 jstring* cmdstrings = elements(cmd);
665 char* cmd2[cmd->length + 1];
666 cmd2[cmd->length] = NULL;
667 for(int i=0; i<cmd->length; i++) {
668 cmd2[i] = (char*)malloc(JvGetStringUTFLength(cmdstrings[i]));
669 JvGetStringUTFRegion(cmdstrings[i], 0, JvGetStringUTFLength(cmdstrings[i]), cmd2[i]);
673 signal(SIGHUP, SIG_IGN);
674 signal(SIGQUIT, SIG_IGN);
675 signal(SIGINT, SIG_IGN);
676 signal(SIGTERM, SIG_IGN);
677 execvp(cmd2[0], cmd2);
681 void org::xwt::plat::POSIX::eventThread() {
684 XNextEvent(display, &e);
685 org::xwt::plat::POSIX$X11Surface* surface =
686 (org::xwt::plat::POSIX$X11Surface*)windowToSurfaceMap->get(new java::lang::Long(((XAnyEvent*)&e)->window));
687 if (surface != NULL) surface->dispatchEvent((gnu::gcj::RawData*)&e);
691 jstring org::xwt::plat::POSIX::_getClipBoard() {
692 XConvertSelection(display, XA_PRIMARY, XA_STRING, XInternAtom(display, "VT_SELECTION", False), selectionWindow, CurrentTime);
694 org::xwt::plat::POSIX::waiting_for_selection_event->block();
698 void org::xwt::plat::POSIX::_setClipBoard(jstring s) {
700 int len = JvGetStringUTFLength(clipboard);
702 JvGetStringUTFRegion(clipboard, 0, len, buf);
704 XSetSelectionOwner(display, XInternAtom(display, "PRIMARY", 0), selectionWindow, CurrentTime);
707 typedef int (X11ErrorHandler)(Display*, XErrorEvent*);
708 int errorHandler(Display* d, XErrorEvent* e) {
709 // this error handler is only installed during the initial
710 // test to see if shm is present
714 void org::xwt::plat::POSIX::natInit() {
717 org::xwt::Platform::criticalAbort(JvNewStringLatin1("Your X11 libraries do not support multithreaded programs"));
719 display = XOpenDisplay(NULL);
720 screen_num = XDefaultScreen(display);
721 colorDepth = (jint)(DefaultDepth(((Display*)display), 0));
722 shm_info.shmaddr = NULL;
724 shm_supported = (XShmQueryExtension(display) == True);
726 X11ErrorHandler* oldHandler = XSetErrorHandler(errorHandler);
727 XShmSegmentInfo sinfo;
728 sinfo.shmid = shmget(IPC_PRIVATE, 1, IPC_CREAT | 0777 | IPC_EXCL);
729 sinfo.readOnly = False;
730 // if the server is remote, this will trigger the error handler
731 XShmAttach(display, &sinfo);
732 XSync(display, False);
733 XSetErrorHandler(oldHandler);
737 shm_pixmaps_supported = (XShmPixmapFormat(display) == ZPixmap);
739 crosshair = JvNewStringLatin1("crosshair");
740 east = JvNewStringLatin1("east");
741 hand = JvNewStringLatin1("hand");
742 move = JvNewStringLatin1("move");
743 north = JvNewStringLatin1("north");
744 northeast = JvNewStringLatin1("northeast");
745 northwest = JvNewStringLatin1("northwest");
746 south = JvNewStringLatin1("south");
747 southeast = JvNewStringLatin1("southeast");
748 southwest = JvNewStringLatin1("southwest");
749 text = JvNewStringLatin1("text");
750 west = JvNewStringLatin1("west");
751 wait_string = JvNewStringLatin1("wait");
752 crosshair_cursor = XCreateFontCursor(display, XC_tcross);
753 east_cursor = XCreateFontCursor(display, XC_right_side);
754 hand_cursor = XCreateFontCursor(display, XC_hand2);
755 move_cursor = XCreateFontCursor(display, XC_fleur);
756 north_cursor = XCreateFontCursor(display, XC_top_side);
757 northeast_cursor = XCreateFontCursor(display, XC_top_right_corner);
758 northwest_cursor = XCreateFontCursor(display, XC_left_side);
759 south_cursor = XCreateFontCursor(display, XC_bottom_side);
760 southeast_cursor = XCreateFontCursor(display, XC_bottom_right_corner);
761 southwest_cursor = XCreateFontCursor(display, XC_bottom_left_corner);
762 text_cursor = XCreateFontCursor(display, XC_xterm);
763 west_cursor = XCreateFontCursor(display, XC_right_side);
764 wait_cursor = XCreateFontCursor(display, XC_watch);
765 default_cursor = XCreateFontCursor(display, XC_left_ptr);
767 selectionWindow = XCreateWindow(display, RootWindow(display, screen_num), 0, 0, 1, 1, 0, colorDepth, InputOutput, CopyFromParent, 0, NULL);
768 visual = DefaultVisual(display, screen_num);
770 sprintf(buf, "X11 DISPLAY: %s", JvNewStringLatin1(XDisplayString(display)));
771 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
772 sprintf(buf, "X11 SHM: %s", shm_supported ? "enabled" : "disabled");
773 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
774 sprintf(buf, "X11 Visual: %x %x %x bits: %i visualid: %i depth: %i",
775 visual->red_mask, visual->green_mask, visual->blue_mask, visual->bits_per_rgb, visual->visualid, colorDepth);
776 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
778 // FIXME: don't know why (True, False) is the best solution...
779 if(XmuLookupStandardColormap(display, screen_num, visual->visualid, colorDepth, XA_RGB_BEST_MAP, True, False) == 0)
780 org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: XmuLookupStandardColormap failed"));
782 XStandardColormap* best_map_info = NULL;
784 if (XGetRGBColormaps(display, RootWindow(display, screen_num), &best_map_info, &count, XA_RGB_BEST_MAP) == 0)
785 org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: couldn't allocate a standard colormap"));
786 if (!best_map_info->colormap)
787 org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: XmuLookupStandardColomap succeded, but no colormap was found on the root window"));
788 if (best_map_info->red_max == 0)
789 org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: standard colormap exists, but was improperly allocated"));
790 s_colormap = best_map_info->colormap;
791 colormap_info = best_map_info;
793 sprintf(buf, " red_max / red_mult: %x %x", colormap_info->red_max, colormap_info->red_mult);
794 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
795 sprintf(buf, " green_max / green_mult: %x %x", colormap_info->green_max, colormap_info->green_mult);
796 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
797 sprintf(buf, " blue_max / blue_mult: %x %x", colormap_info->blue_max, colormap_info->blue_mult);
798 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
799 sprintf(buf, " base_pixel: %x", colormap_info->base_pixel);
800 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
803 JArray<java::lang::String*>* org::xwt::plat::POSIX::listNativeFonts() {
805 char** xfonts = XListFonts(display, "-*-*-*-*-*-*-*-*-*-*-*-*-*-*", 0xFFFFFFFF, &numfonts);
806 JArray<java::lang::String*>* fonts = (JArray<java::lang::String*>*)JvNewObjectArray(numfonts, &(::java::lang::String::class$), NULL);
807 java::lang::String** jfonts = (java::lang::String**)(elements(fonts));
808 for(int i=0; i<numfonts; i++)
809 jfonts[i] = JvNewStringLatin1(xfonts[i], strlen(xfonts[i]));
813 gnu::gcj::RawData* org::xwt::plat::POSIX::fontStringToStruct(jstring s) {
814 int len = min(1024, JvGetStringUTFLength(s));
816 JvGetStringUTFRegion(s, 0, len, buf);
818 return (gnu::gcj::RawData*)XLoadQueryFont(display, buf);
821 jint org::xwt::plat::POSIX::_getMaxAscent(::java::lang::String* font) { return ((XFontStruct*)fontToXFont(font))->max_bounds.ascent; }
822 jint org::xwt::plat::POSIX::_getMaxDescent(::java::lang::String* font) { return ((XFontStruct*)fontToXFont(font))->max_bounds.descent; }
823 jint org::xwt::plat::POSIX::_stringWidth(::java::lang::String* font, ::java::lang::String* text) {
824 if (text == NULL) return 0;
825 int len = JvGetStringUTFLength(text);
827 JvGetStringUTFRegion(text, 0, len, buf);
829 return XTextWidth((XFontStruct*)fontToXFont(font), buf, len);
833 //////////////////////////////////////////////////////////////////////////////
834 //////////////////////////////////////////////////////////////////////////////
835 //////////////////////////////////////////////////////////////////////////////
836 //////////////////////////////////////////////////////////////////////////////
838 // Everything below this point was taken, cut-and-paste, from the //
839 // source for libXmu. It implements the official 'standard colormap //
840 // creation algorithm. I made some small changes to //
841 // XmuDeleteStandardColormap //
843 //////////////////////////////////////////////////////////////////////////////
844 //////////////////////////////////////////////////////////////////////////////
845 //////////////////////////////////////////////////////////////////////////////
846 //////////////////////////////////////////////////////////////////////////////
848 /* $Xorg: LookupCmap.c,v 1.4 2001/02/09 02:03:53 xorgcvs Exp $ */
852 Copyright 1989, 1998 The Open Group
854 Permission to use, copy, modify, distribute, and sell this software and its
855 documentation for any purpose is hereby granted without fee, provided that
856 the above copyright notice appear in all copies and that both that
857 copyright notice and this permission notice appear in supporting
860 The above copyright notice and this permission notice shall be included in
861 all copies or substantial portions of the Software.
863 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
864 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
865 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
866 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
867 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
868 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
870 Except as contained in this notice, the name of The Open Group shall not be
871 used in advertising or otherwise to promote the sale, use or other dealings
872 in this Software without prior written authorization from The Open Group.
875 /* $XFree86: xc/lib/Xmu/LookupCmap.c,v 1.8 2001/12/14 19:55:47 dawes Exp $ */
878 * Author: Donna Converse, MIT X Consortium
882 #include <X11/Xlib.h>
883 #include <X11/Xatom.h>
884 #include <X11/Xutil.h>
885 #include <X11/Xmu/StdCmap.h>
891 static Status lookup(Display*, int, VisualID, Atom, XStandardColormap*, Bool);
894 * To create a standard colormap if one does not currently exist, or
895 * replace the currently existing standard colormap, use
896 * XmuLookupStandardColormap().
898 * Given a screen, a visual, and a property, XmuLookupStandardColormap()
899 * will determine the best allocation for the property under the specified
900 * visual, and determine the whether to create a new colormap or to use
901 * the default colormap of the screen. It will call XmuStandardColormap()
902 * to create the standard colormap.
904 * If replace is true, any previous definition of the property will be
905 * replaced. If retain is true, the property and the colormap will be
906 * made permanent for the duration of the server session. However,
907 * pre-existing property definitions which are not replaced cannot be made
908 * permanent by a call to XmuLookupStandardColormap(); a request to retain
909 * resources pertains to newly created resources.
911 * Returns 0 on failure, non-zero on success. A request to create a
912 * standard colormap upon a visual which cannot support such a map is
913 * considered a failure. An example of this would be requesting any
914 * standard colormap property on a monochrome visual, or, requesting an
915 * RGB_BEST_MAP on a display whose colormap size is 16.
919 XmuLookupStandardColormap(Display *dpy, int screen, VisualID visualid,
920 unsigned int depth, Atom property,
921 Bool replace, Bool retain)
923 * dpy - specifies X server connection
924 * screen - specifies screen of display
925 * visualid - specifies the visual type
926 * depth - specifies the visual type
927 * property - a standard colormap property
928 * replace - specifies whether to replace
929 * retain - specifies whether to retain
932 Display *odpy; /* original display connection */
933 XStandardColormap *colormap;
934 XVisualInfo vinfo_template, *vinfo; /* visual */
936 unsigned long r_max, g_max, b_max; /* allocation */
938 Colormap cmap; /* colormap ID */
942 /* Match the requested visual */
944 vinfo_template.visualid = visualid;
945 vinfo_template.screen = screen;
946 vinfo_template.depth = depth;
947 vinfo_mask = VisualIDMask | VisualScreenMask | VisualDepthMask;
948 if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &count)) ==
952 /* Monochrome visuals have no standard maps */
954 if (vinfo->colormap_size <= 2) {
955 XFree((char *) vinfo);
959 /* If the requested property already exists on this screen, and,
960 * if the replace flag has not been set to true, return success.
961 * lookup() will remove a pre-existing map if replace is true.
964 if (lookup(dpy, screen, visualid, property, (XStandardColormap *) NULL,
965 replace) && !replace) {
966 XFree((char *) vinfo);
970 /* Determine the best allocation for this property under the requested
971 * visualid and depth, and determine whether or not to use the default
972 * colormap of the screen.
975 if (!XmuGetColormapAllocation(vinfo, property, &r_max, &g_max, &b_max)) {
976 XFree((char *) vinfo);
980 cmap = (property == XA_RGB_DEFAULT_MAP &&
981 visualid == XVisualIDFromVisual(DefaultVisual(dpy, screen)))
982 ? DefaultColormap(dpy, screen) : None;
984 /* If retaining resources, open a new connection to the same server */
988 if ((dpy = XOpenDisplay(XDisplayString(odpy))) == NULL) {
989 XFree((char *) vinfo);
994 /* Create the standard colormap */
996 colormap = XmuStandardColormap(dpy, screen, visualid, depth, property,
997 cmap, r_max, g_max, b_max);
999 /* Set the standard colormap property */
1004 if (lookup(dpy, screen, visualid, property, colormap, replace) &&
1006 /* Someone has defined the property since we last looked.
1007 * Since we will not replace it, release our own resources.
1008 * If this is the default map, our allocations will be freed
1009 * when this connection closes.
1011 if (colormap->killid == ReleaseByFreeingColormap)
1012 XFreeColormap(dpy, colormap->colormap);
1013 } else if (retain) {
1014 XSetCloseDownMode(dpy, RetainPermanent);
1017 XFree((char *) colormap);
1023 XFree((char *) vinfo);
1027 /***************************************************************************/
1029 /* Lookup a standard colormap property. If the property is RGB_DEFAULT_MAP,
1030 * the visualid is used to determine whether the indicated standard colormap
1031 * exists. If the map exists and replace is true, delete the resources used
1032 * by the map and remove the property. Return true if the map exists,
1033 * or did exist and was deleted; return false if the map was not found.
1035 * Note that this is not the way that a Status return is normally used.
1037 * If new is not NULL, new points to an XStandardColormap structure which
1038 * describes a standard colormap of the specified property. It will be made
1039 * a standard colormap of the screen if none already exists, or if replace
1044 lookup(Display *dpy, int screen, VisualID visualid, Atom property,
1045 XStandardColormap *cnew, Bool replace)
1047 * dpy - specifies display connection
1048 * screen - specifies screen number
1049 * visualid - specifies visualid for std map
1050 * property - specifies colormap property name
1051 * cnew - specifies a standard colormap
1052 * replace - specifies whether to replace
1057 XStandardColormap *stdcmaps, *s;
1058 Window win = RootWindow(dpy, screen);
1060 /* The property does not already exist */
1062 if (! XGetRGBColormaps(dpy, win, &stdcmaps, &count, property)) {
1064 XSetRGBColormaps(dpy, win, cnew, 1, property);
1068 /* The property exists and is not describing the RGB_DEFAULT_MAP */
1070 if (property != XA_RGB_DEFAULT_MAP) {
1072 XmuDeleteStandardColormap(dpy, screen, property);
1074 XSetRGBColormaps(dpy, win, cnew, 1, property);
1076 XFree((char *)stdcmaps);
1080 /* The property exists and is RGB_DEFAULT_MAP */
1082 for (i=0, s=stdcmaps; (i < count) && (s->visualid != visualid); i++, s++)
1085 /* No RGB_DEFAULT_MAP property matches the given visualid */
1089 XStandardColormap *m, *maps;
1091 s = (XStandardColormap *) malloc((unsigned) ((count+1) * sizeof
1092 (XStandardColormap)));
1094 for (i = 0, m = s, maps = stdcmaps; i < count; i++, m++, maps++) {
1095 m->colormap = maps->colormap;
1096 m->red_max = maps->red_max;
1097 m->red_mult = maps->red_mult;
1098 m->green_max = maps->green_max;
1099 m->green_mult = maps->green_mult;
1100 m->blue_max = maps->blue_max;
1101 m->blue_mult = maps->blue_mult;
1102 m->base_pixel = maps->base_pixel;
1103 m->visualid = maps->visualid;
1104 m->killid = maps->killid;
1106 m->colormap = cnew->colormap;
1107 m->red_max = cnew->red_max;
1108 m->red_mult = cnew->red_mult;
1109 m->green_max = cnew->green_max;
1110 m->green_mult = cnew->green_mult;
1111 m->blue_max = cnew->blue_max;
1112 m->blue_mult = cnew->blue_mult;
1113 m->base_pixel = cnew->base_pixel;
1114 m->visualid = cnew->visualid;
1115 m->killid = cnew->killid;
1117 XSetRGBColormaps(dpy, win, s, ++count, property);
1120 XFree((char *) stdcmaps);
1124 /* Found an RGB_DEFAULT_MAP property with a matching visualid */
1127 /* Free old resources first - we may need them, particularly in
1128 * the default colormap of the screen. However, because of this,
1129 * it is possible that we will destroy the old resource and fail
1130 * to create a new one if XmuStandardColormap() fails.
1134 XmuDeleteStandardColormap(dpy, screen, property);
1136 XSetRGBColormaps(dpy, win, cnew, 1, property);
1139 XStandardColormap *map;
1141 /* s still points to the matching standard colormap */
1143 if (s->killid == ReleaseByFreeingColormap) {
1144 if ((s->colormap != None) &&
1145 (s->colormap != DefaultColormap(dpy, screen)))
1146 XFreeColormap(dpy, s->colormap);
1148 else if (s->killid != None)
1149 XKillClient(dpy, s->killid);
1151 map = (cnew) ? cnew : stdcmaps + --count;
1153 s->colormap = map->colormap;
1154 s->red_max = map->red_max;
1155 s->red_mult = map->red_mult;
1156 s->green_max = map->green_max;
1157 s->green_mult = map->green_mult;
1158 s->blue_max = map->blue_max;
1159 s->blue_mult = map->blue_mult;
1160 s->visualid = map->visualid;
1161 s->killid = map->killid;
1163 XSetRGBColormaps(dpy, win, stdcmaps, count, property);
1166 XFree((char *) stdcmaps);
1170 /* $Xorg: CmapAlloc.c,v 1.4 2001/02/09 02:03:51 xorgcvs Exp $ */
1174 Copyright 1989, 1994, 1998 The Open Group
1176 Permission to use, copy, modify, distribute, and sell this software and its
1177 documentation for any purpose is hereby granted without fee, provided that
1178 the above copyright notice appear in all copies and that both that
1179 copyright notice and this permission notice appear in supporting
1182 The above copyright notice and this permission notice shall be included in
1183 all copies or substantial portions of the Software.
1185 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1186 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1187 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1188 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1189 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1190 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1192 Except as contained in this notice, the name of The Open Group shall not be
1193 used in advertising or otherwise to promote the sale, use or other dealings
1194 in this Software without prior written authorization from The Open Group.
1197 /* $XFree86: xc/lib/Xmu/CmapAlloc.c,v 1.7 2001/12/14 19:55:35 dawes Exp $ */
1200 * Author: Donna Converse, MIT X Consortium
1203 #include <X11/Xlib.h>
1204 #include <X11/Xatom.h>
1205 #include <X11/Xutil.h>
1206 #include <X11/Xmu/StdCmap.h>
1209 #define lowbit(x) ((x) & (~(x) + 1))
1214 static void best_allocation(XVisualInfo*, unsigned long*, unsigned long*,
1216 static int default_allocation(XVisualInfo*, unsigned long*,
1217 unsigned long*, unsigned long*);
1218 static void gray_allocation(int, unsigned long*, unsigned long*,
1220 static int icbrt(int);
1221 static int icbrt_with_bits(int, int);
1222 static int icbrt_with_guess(int, int);
1224 /* To determine the best allocation of reds, greens, and blues in a
1225 * standard colormap, use XmuGetColormapAllocation.
1226 * vinfo specifies visual information for a chosen visual
1227 * property specifies one of the standard colormap property names
1228 * red_max returns maximum red value
1229 * green_max returns maximum green value
1230 * blue_max returns maximum blue value
1232 * XmuGetColormapAllocation returns 0 on failure, non-zero on success.
1233 * It is assumed that the visual is appropriate for the colormap property.
1237 XmuGetColormapAllocation(XVisualInfo *vinfo, Atom property,
1238 unsigned long *red_max,
1239 unsigned long *green_max,
1240 unsigned long *blue_max)
1244 if (vinfo->colormap_size <= 2)
1249 case XA_RGB_DEFAULT_MAP:
1250 status = default_allocation(vinfo, red_max, green_max, blue_max);
1252 case XA_RGB_BEST_MAP:
1253 best_allocation(vinfo, red_max, green_max, blue_max);
1255 case XA_RGB_GRAY_MAP:
1256 gray_allocation(vinfo->colormap_size, red_max, green_max, blue_max);
1258 case XA_RGB_RED_MAP:
1259 *red_max = vinfo->colormap_size - 1;
1260 *green_max = *blue_max = 0;
1262 case XA_RGB_GREEN_MAP:
1263 *green_max = vinfo->colormap_size - 1;
1264 *red_max = *blue_max = 0;
1266 case XA_RGB_BLUE_MAP:
1267 *blue_max = vinfo->colormap_size - 1;
1268 *red_max = *green_max = 0;
1276 /****************************************************************************/
1277 /* Determine the appropriate color allocations of a gray scale.
1279 * Keith Packard, MIT X Consortium
1283 gray_allocation(int n, unsigned long *red_max, unsigned long *green_max,
1284 unsigned long *blue_max)
1286 *red_max = (n * 30) / 100;
1287 *green_max = (n * 59) / 100;
1288 *blue_max = (n * 11) / 100;
1289 *green_max += ((n - 1) - (*red_max + *green_max + *blue_max));
1292 /****************************************************************************/
1293 /* Determine an appropriate color allocation for the RGB_DEFAULT_MAP.
1294 * If a map has less than a minimum number of definable entries, we do not
1295 * produce an allocation for an RGB_DEFAULT_MAP.
1297 * For 16 planes, the default colormap will have 27 each RGB; for 12 planes,
1298 * 12 each. For 8 planes, let n = the number of colormap entries, which may
1299 * be 256 or 254. Then, maximum red value = floor(cube_root(n - 125)) - 1.
1300 * Maximum green and maximum blue values are identical to maximum red.
1301 * This leaves at least 125 cells which clients can allocate.
1303 * Return 0 if an allocation has been determined, non-zero otherwise.
1307 default_allocation(XVisualInfo *vinfo, unsigned long *red,
1308 unsigned long *green, unsigned long *blue)
1310 int ngrays; /* number of gray cells */
1312 switch (vinfo->c_class)
1316 if (vinfo->colormap_size > 65000)
1317 /* intended for displays with 16 planes */
1318 *red = *green = *blue = (unsigned long) 27;
1319 else if (vinfo->colormap_size > 4000)
1320 /* intended for displays with 12 planes */
1321 *red = *green = *blue = (unsigned long) 12;
1322 else if (vinfo->colormap_size < 250)
1325 /* intended for displays with 8 planes */
1326 *red = *green = *blue = (unsigned long)
1327 (icbrt(vinfo->colormap_size - 125) - 1);
1332 if (vinfo->colormap_size < 10)
1334 *red = *green = *blue = vinfo->colormap_size / 2 - 1;
1339 *red = vinfo->red_mask / lowbit(vinfo->red_mask);
1340 *green = vinfo->green_mask / lowbit(vinfo->green_mask);
1341 *blue = vinfo->blue_mask / lowbit(vinfo->blue_mask);
1346 if (vinfo->colormap_size > 65000)
1348 else if (vinfo->colormap_size > 4000)
1350 else if (vinfo->colormap_size < 250)
1354 gray_allocation(ngrays, red, green, blue);
1363 /****************************************************************************/
1364 /* Determine an appropriate color allocation for the RGB_BEST_MAP.
1366 * For a DirectColor or TrueColor visual, the allocation is determined
1367 * by the red_mask, green_mask, and blue_mask members of the visual info.
1369 * Otherwise, if the colormap size is an integral power of 2, determine
1370 * the allocation according to the number of bits given to each color,
1371 * with green getting more than red, and red more than blue, if there
1372 * are to be inequities in the distribution. If the colormap size is
1373 * not an integral power of 2, let n = the number of colormap entries.
1374 * Then maximum red value = floor(cube_root(n)) - 1;
1375 * maximum blue value = floor(cube_root(n)) - 1;
1376 * maximum green value = n / ((# red values) * (# blue values)) - 1;
1377 * Which, on a GPX, allows for 252 entries in the best map, out of 254
1378 * defineable colormap entries.
1382 best_allocation(XVisualInfo *vinfo, unsigned long *red, unsigned long *green,
1383 unsigned long *blue)
1386 if (vinfo->c_class == DirectColor || vinfo->c_class == TrueColor)
1388 *red = vinfo->red_mask;
1389 while ((*red & 01) == 0)
1391 *green = vinfo->green_mask;
1392 while ((*green & 01) == 0)
1394 *blue = vinfo->blue_mask;
1395 while ((*blue & 01) == 0)
1400 register int bits, n;
1402 /* Determine n such that n is the least integral power of 2 which is
1403 * greater than or equal to the number of entries in the colormap.
1407 while (vinfo->colormap_size > n)
1413 /* If the number of entries in the colormap is a power of 2, determine
1414 * the allocation by "dealing" the bits, first to green, then red, then
1415 * blue. If not, find the maximum integral red, green, and blue values
1416 * which, when multiplied together, do not exceed the number of
1420 if (n == vinfo->colormap_size)
1422 register int r, g, b;
1424 g = b + ((bits % 3) ? 1 : 0);
1425 r = b + (((bits % 3) == 2) ? 1 : 0);
1432 *red = icbrt_with_bits(vinfo->colormap_size, bits);
1434 *green = (vinfo->colormap_size / ((*red) * (*blue)));
1444 * integer cube roots by Newton's method
1446 * Stephen Gildea, MIT X Consortium, July 1991
1452 register int bits = 0;
1453 register unsigned n = a;
1460 return icbrt_with_bits(a, bits);
1465 icbrt_with_bits(int a, int bits)
1466 /* bits - log 2 of a */
1468 return icbrt_with_guess(a, a>>2*bits/3);
1471 #ifdef _X_ROOT_STATS
1472 int icbrt_loopcount;
1475 /* Newton's Method: x_n+1 = x_n - ( f(x_n) / f'(x_n) ) */
1477 /* for cube roots, x^3 - a = 0, x_new = x - 1/3 (x - a/x^2) */
1480 * Quick and dirty cube roots. Nothing fancy here, just Newton's method.
1481 * Only works for positive integers (since that's all we need).
1482 * We actually return floor(cbrt(a)) because that's what we need here, too.
1486 icbrt_with_guess(int a, int guess)
1490 #ifdef _X_ROOT_STATS
1491 icbrt_loopcount = 0;
1499 #ifdef _X_ROOT_STATS
1502 delta = (guess - a/(guess*guess))/3;
1504 printf("pass %d: guess=%d, delta=%d\n", icbrt_loopcount, guess, delta);
1507 } while (delta != 0);
1509 if (guess*guess*guess > a)
1516 /* $Xorg: StdCmap.c,v 1.4 2001/02/09 02:03:53 xorgcvs Exp $ */
1520 Copyright 1989, 1998 The Open Group
1522 Permission to use, copy, modify, distribute, and sell this software and its
1523 documentation for any purpose is hereby granted without fee, provided that
1524 the above copyright notice appear in all copies and that both that
1525 copyright notice and this permission notice appear in supporting
1528 The above copyright notice and this permission notice shall be included in
1529 all copies or substantial portions of the Software.
1531 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1532 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1533 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1534 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1535 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1536 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1538 Except as contained in this notice, the name of The Open Group shall not be
1539 used in advertising or otherwise to promote the sale, use or other dealings
1540 in this Software without prior written authorization from The Open Group.
1543 /* $XFree86: xc/lib/Xmu/StdCmap.c,v 1.6 2001/12/14 19:55:48 dawes Exp $ */
1546 * Author: Donna Converse, MIT X Consortium
1550 #include <X11/Xlib.h>
1551 #include <X11/Xatom.h>
1552 #include <X11/Xutil.h>
1553 #include <X11/Xmu/StdCmap.h>
1555 #define lowbit(x) ((x) & (~(x) + 1))
1560 /* argument restrictions */
1561 static Status valid_args(XVisualInfo*, unsigned long, unsigned long,
1562 unsigned long, Atom);
1565 * To create any one standard colormap, use XmuStandardColormap().
1567 * Create a standard colormap for the given screen, visualid, and visual
1568 * depth, with the given red, green, and blue maximum values, with the
1569 * given standard property name. Return a pointer to an XStandardColormap
1570 * structure which describes the newly created colormap, upon success.
1571 * Upon failure, return NULL.
1573 * XmuStandardColormap() calls XmuCreateColormap() to create the map.
1575 * Resources created by this function are not made permanent; that is the
1576 * caller's responsibility.
1580 XmuStandardColormap(Display *dpy, int screen, VisualID visualid,
1581 unsigned int depth, Atom property, Colormap cmap,
1582 unsigned long red_max, unsigned long green_max,
1583 unsigned long blue_max)
1585 * dpy - specifies X server connection
1586 * screen - specifies display screen
1587 * visualid - identifies the visual type
1588 * depth - identifies the visual type
1589 * property - a standard colormap property
1590 * cmap - specifies colormap ID or None
1591 * red_max, green_max, blue_max - allocations
1594 XStandardColormap *stdcmap;
1596 XVisualInfo vinfo_template, *vinfo;
1600 /* Match the required visual information to an actual visual */
1601 vinfo_template.visualid = visualid;
1602 vinfo_template.screen = screen;
1603 vinfo_template.depth = depth;
1604 vinfo_mask = VisualIDMask | VisualScreenMask | VisualDepthMask;
1605 if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &n)) == NULL)
1608 /* Check the validity of the combination of visual characteristics,
1609 * allocation, and colormap property. Create an XStandardColormap
1613 if (! valid_args(vinfo, red_max, green_max, blue_max, property)
1614 || ((stdcmap = XAllocStandardColormap()) == NULL)) {
1615 XFree((char *) vinfo);
1619 /* Fill in the XStandardColormap structure */
1621 if (cmap == DefaultColormap(dpy, screen)) {
1622 /* Allocating out of the default map, cannot use XFreeColormap() */
1623 Window win = XCreateWindow(dpy, RootWindow(dpy, screen), 1, 1, 1, 1,
1624 0, 0, InputOnly, vinfo->visual,
1626 (XSetWindowAttributes *)NULL);
1627 stdcmap->killid = (XID) XCreatePixmap(dpy, win, 1, 1, depth);
1628 XDestroyWindow(dpy, win);
1629 stdcmap->colormap = cmap;
1631 stdcmap->killid = ReleaseByFreeingColormap;
1632 stdcmap->colormap = XCreateColormap(dpy, RootWindow(dpy, screen),
1633 vinfo->visual, AllocNone);
1635 stdcmap->red_max = red_max;
1636 stdcmap->green_max = green_max;
1637 stdcmap->blue_max = blue_max;
1638 if (property == XA_RGB_GRAY_MAP)
1639 stdcmap->red_mult = stdcmap->green_mult = stdcmap->blue_mult = 1;
1640 else if (vinfo->c_class == TrueColor || vinfo->c_class == DirectColor) {
1641 stdcmap->red_mult = lowbit(vinfo->red_mask);
1642 stdcmap->green_mult = lowbit(vinfo->green_mask);
1643 stdcmap->blue_mult = lowbit(vinfo->blue_mask);
1645 stdcmap->red_mult = (red_max > 0)
1646 ? (green_max + 1) * (blue_max + 1) : 0;
1647 stdcmap->green_mult = (green_max > 0) ? blue_max + 1 : 0;
1648 stdcmap->blue_mult = (blue_max > 0) ? 1 : 0;
1650 stdcmap->base_pixel = 0; /* base pixel may change */
1651 stdcmap->visualid = vinfo->visualid;
1653 /* Make the colormap */
1655 status = XmuCreateColormap(dpy, stdcmap);
1659 XFree((char *) vinfo);
1662 /* Free the colormap or the pixmap, if we created one */
1663 if (stdcmap->killid == ReleaseByFreeingColormap)
1664 XFreeColormap(dpy, stdcmap->colormap);
1665 else if (stdcmap->killid != None)
1666 XFreePixmap(dpy, stdcmap->killid);
1668 XFree((char *) stdcmap);
1669 return (XStandardColormap *) NULL;
1674 /****************************************************************************/
1676 valid_args(XVisualInfo *vinfo, unsigned long red_max, unsigned long green_max,
1677 unsigned long blue_max, Atom property)
1679 * vinfo - specifies visual
1680 * red_max, green_max, blue_max - specifies alloc
1681 * property - specifies property name
1684 unsigned long ncolors; /* number of colors requested */
1686 /* Determine that the number of colors requested is <= map size */
1688 if ((vinfo->c_class == DirectColor) || (vinfo->c_class == TrueColor)) {
1691 mask = vinfo->red_mask;
1696 mask = vinfo->green_mask;
1699 if (green_max > mask)
1701 mask = vinfo->blue_mask;
1704 if (blue_max > mask)
1706 } else if (property == XA_RGB_GRAY_MAP) {
1707 ncolors = red_max + green_max + blue_max + 1;
1708 if (ncolors > vinfo->colormap_size)
1711 ncolors = (red_max + 1) * (green_max + 1) * (blue_max + 1);
1712 if (ncolors > vinfo->colormap_size)
1716 /* Determine that the allocation and visual make sense for the property */
1720 case XA_RGB_DEFAULT_MAP:
1721 if (red_max == 0 || green_max == 0 || blue_max == 0)
1724 case XA_RGB_RED_MAP:
1728 case XA_RGB_GREEN_MAP:
1732 case XA_RGB_BLUE_MAP:
1736 case XA_RGB_BEST_MAP:
1737 if (red_max == 0 || green_max == 0 || blue_max == 0)
1740 case XA_RGB_GRAY_MAP:
1741 if (red_max == 0 || blue_max == 0 || green_max == 0)
1751 /* $Xorg: CrCmap.c,v 1.4 2001/02/09 02:03:51 xorgcvs Exp $ */
1755 Copyright 1989, 1998 The Open Group
1757 Permission to use, copy, modify, distribute, and sell this software and its
1758 documentation for any purpose is hereby granted without fee, provided that
1759 the above copyright notice appear in all copies and that both that
1760 copyright notice and this permission notice appear in supporting
1763 The above copyright notice and this permission notice shall be included in
1764 all copies or substantial portions of the Software.
1766 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1767 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1768 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1769 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1770 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1771 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1773 Except as contained in this notice, the name of The Open Group shall not be
1774 used in advertising or otherwise to promote the sale, use or other dealings
1775 in this Software without prior written authorization from The Open Group.
1778 /* $XFree86: xc/lib/Xmu/CrCmap.c,v 3.7 2001/12/14 19:55:36 dawes Exp $ */
1781 * Author: Donna Converse, MIT X Consortium
1785 * CreateCmap.c - given a standard colormap description, make the map.
1790 #include <X11/Xlib.h>
1791 #include <X11/Xutil.h>
1792 #include <X11/Xmu/StdCmap.h>
1797 /* allocate entire map Read Only */
1798 static int ROmap(Display*, Colormap, unsigned long[], int, int);
1800 /* allocate a cell, prefer Read Only */
1801 static Status ROorRWcell(Display*, Colormap, unsigned long[], int,
1802 XColor*, unsigned long);
1804 /* allocate a cell Read Write */
1805 static Status RWcell(Display*, Colormap, XColor*, XColor*, unsigned long*);
1808 static int compare(_Xconst void*, _Xconst void*);
1810 /* find contiguous sequence of cells */
1811 static Status contiguous(unsigned long[], int, int, unsigned long, int*, int*);
1813 /* frees resources before quitting */
1814 static void free_cells(Display*, Colormap, unsigned long[], int, int);
1816 /* create a map in a RO visual type */
1817 static Status readonly_map(Display*, XVisualInfo*, XStandardColormap*);
1819 /* create a map in a RW visual type */
1820 static Status readwrite_map(Display*, XVisualInfo*, XStandardColormap*);
1822 #define lowbit(x) ((x) & (~(x) + 1))
1823 #define TRUEMATCH(mult,max,mask) \
1824 (colormap->max * colormap->mult <= vinfo->mask && \
1825 lowbit(vinfo->mask) == colormap->mult)
1828 * To create any one colormap which is described by an XStandardColormap
1829 * structure, use XmuCreateColormap().
1831 * Return 0 on failure, non-zero on success.
1832 * Resources created by this function are not made permanent.
1833 * No argument error checking is provided. Use at your own risk.
1835 * All colormaps are created with read only allocations, with the exception
1836 * of read only allocations of colors in the default map or otherwise
1837 * which fail to return the expected pixel value, and these are individually
1838 * defined as read/write allocations. This is done so that all the cells
1839 * defined in the default map are contiguous, for use in image processing.
1840 * This typically happens with White and Black in the default map.
1842 * Colormaps of static visuals are considered to be successfully created if
1843 * the map of the static visual matches the definition given in the
1844 * standard colormap structure.
1848 XmuCreateColormap(Display *dpy, XStandardColormap *colormap)
1849 /* dpy - specifies the connection under which the map is created
1850 * colormap - specifies the map to be created, and returns, particularly
1851 * if the map is created as a subset of the default colormap
1852 * of the screen, the base_pixel of the map.
1855 XVisualInfo vinfo_template; /* template visual information */
1856 XVisualInfo *vinfo; /* matching visual information */
1857 XVisualInfo *vpointer; /* for freeing the entire list */
1858 long vinfo_mask; /* specifies the visual mask value */
1859 int n; /* number of matching visuals */
1862 vinfo_template.visualid = colormap->visualid;
1863 vinfo_mask = VisualIDMask;
1864 if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &n)) == NULL)
1867 /* A visual id may be valid on multiple screens. Also, there may
1868 * be multiple visuals with identical visual ids at different depths.
1869 * If the colormap is the Default Colormap, use the Default Visual.
1870 * Otherwise, arbitrarily, use the deepest visual.
1876 register int screen_number;
1880 for (screen_number = ScreenCount(dpy); --screen_number >= 0; )
1881 if (colormap->colormap == DefaultColormap(dpy, screen_number)) {
1887 for (i=0; i < n; i++, vinfo++) {
1888 if (vinfo->visual == DefaultVisual(dpy, screen_number))
1893 XVisualInfo *v = NULL;
1895 for (i=0; i < n; i++, vinfo++)
1896 if (vinfo->depth > maxdepth) {
1897 maxdepth = vinfo->depth;
1904 if (vinfo->c_class == PseudoColor || vinfo->c_class == DirectColor ||
1905 vinfo->c_class == GrayScale)
1906 status = readwrite_map(dpy, vinfo, colormap);
1907 else if (vinfo->c_class == TrueColor)
1908 status = TRUEMATCH(red_mult, red_max, red_mask) &&
1909 TRUEMATCH(green_mult, green_max, green_mask) &&
1910 TRUEMATCH(blue_mult, blue_max, blue_mask);
1912 status = readonly_map(dpy, vinfo, colormap);
1914 XFree((char *) vpointer);
1918 /****************************************************************************/
1920 readwrite_map(Display *dpy, XVisualInfo *vinfo, XStandardColormap *colormap)
1922 register unsigned long i, n; /* index counters */
1923 unsigned long ncolors; /* number of colors to be defined */
1924 int npixels; /* number of pixels allocated R/W */
1925 int first_index; /* first index of pixels to use */
1926 int remainder; /* first index of remainder */
1927 XColor color; /* the definition of a color */
1928 unsigned long *pixels; /* array of colormap pixels */
1929 unsigned long delta;
1932 /* Determine ncolors, the number of colors to be defined.
1933 * Insure that 1 < ncolors <= the colormap size.
1935 if (vinfo->c_class == DirectColor) {
1936 ncolors = colormap->red_max;
1937 if (colormap->green_max > ncolors)
1938 ncolors = colormap->green_max;
1939 if (colormap->blue_max > ncolors)
1940 ncolors = colormap->blue_max;
1942 delta = lowbit(vinfo->red_mask) +
1943 lowbit(vinfo->green_mask) +
1944 lowbit(vinfo->blue_mask);
1946 ncolors = colormap->red_max * colormap->red_mult +
1947 colormap->green_max * colormap->green_mult +
1948 colormap->blue_max * colormap->blue_mult + 1;
1951 if (ncolors <= 1 || (int) ncolors > vinfo->colormap_size) return 0;
1953 /* Allocate Read/Write as much of the colormap as we can possibly get.
1954 * Then insure that the pixels we were allocated are given in
1955 * monotonically increasing order, using a quicksort. Next, insure
1956 * that our allocation includes a subset of contiguous pixels at least
1957 * as long as the number of colors to be defined. Now we know that
1958 * these conditions are met:
1959 * 1) There are no free cells in the colormap.
1960 * 2) We have a contiguous sequence of pixels, monotonically
1961 * increasing, of length >= the number of colors requested.
1963 * One cell at a time, we will free, compute the next color value,
1964 * then allocate read only. This takes a long time.
1965 * This is done to insure that cells are allocated read only in the
1966 * contiguous order which we prefer. If the server has a choice of
1967 * cells to grant to an allocation request, the server may give us any
1968 * cell, so that is why we do these slow gymnastics.
1971 if ((pixels = (unsigned long *) calloc((unsigned) vinfo->colormap_size,
1972 sizeof(unsigned long))) == NULL)
1975 if ((npixels = ROmap(dpy, colormap->colormap, pixels,
1976 vinfo->colormap_size, ncolors)) == 0) {
1977 free((char *) pixels);
1981 qsort((char *) pixels, npixels, sizeof(unsigned long), compare);
1983 if (!contiguous(pixels, npixels, ncolors, delta, &first_index, &remainder))
1985 /* can't find enough contiguous cells, give up */
1986 XFreeColors(dpy, colormap->colormap, pixels, npixels,
1988 free((char *) pixels);
1991 colormap->base_pixel = pixels[first_index];
1993 /* construct a gray map */
1994 if (colormap->red_mult == 1 && colormap->green_mult == 1 &&
1995 colormap->blue_mult == 1)
1996 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
1999 color.blue = color.green = color.red =
2000 (unsigned short) ((i * 65535) / (colormap->red_max +
2001 colormap->green_max +
2002 colormap->blue_max));
2004 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
2009 /* construct a red ramp map */
2010 else if (colormap->green_max == 0 && colormap->blue_max == 0)
2011 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
2014 color.red = (unsigned short) ((i * 65535) / colormap->red_max);
2015 color.green = color.blue = 0;
2017 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
2022 /* construct a green ramp map */
2023 else if (colormap->red_max == 0 && colormap->blue_max == 0)
2024 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
2027 color.green = (unsigned short) ((i * 65535) / colormap->green_max);
2028 color.red = color.blue = 0;
2030 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
2035 /* construct a blue ramp map */
2036 else if (colormap->red_max == 0 && colormap->green_max == 0)
2037 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
2040 color.blue = (unsigned short) ((i * 65535) / colormap->blue_max);
2041 color.red = color.green = 0;
2043 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
2048 /* construct a standard red green blue cube map */
2051 #define calc(max,mult) (((n / colormap->mult) % \
2052 (colormap->max + 1)) * 65535) / colormap->max
2054 for (n=0, i=0; i < ncolors; i++, n += delta)
2056 color.pixel = n + colormap->base_pixel;
2057 color.red = calc(red_max, red_mult);
2058 color.green = calc(green_max, green_mult);
2059 color.blue = calc(blue_max, blue_mult);
2060 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
2066 /* We have a read-only map defined. Now free unused cells,
2067 * first those occuring before the contiguous sequence begins,
2068 * then any following the contiguous sequence.
2072 XFreeColors(dpy, colormap->colormap, pixels, first_index,
2075 XFreeColors(dpy, colormap->colormap,
2076 &(pixels[first_index + ncolors]), remainder,
2079 free((char *) pixels);
2084 /****************************************************************************/
2086 ROmap(Display *dpy, Colormap cmap, unsigned long pixels[], int m, int n)
2088 * dpy - the X server connection
2089 * cmap - specifies colormap ID
2090 * pixels - returns pixel allocations
2091 * m - specifies colormap size
2092 * n - specifies number of colors
2097 /* first try to allocate the entire colormap */
2098 if (XAllocColorCells(dpy, cmap, 1, (unsigned long *) NULL,
2099 (unsigned) 0, pixels, (unsigned) m))
2102 /* Allocate all available cells in the colormap, using a binary
2103 * algorithm to discover how many cells we can allocate in the colormap.
2107 p = n + ((m - n + 1) / 2);
2108 if (XAllocColorCells(dpy, cmap, 1, (unsigned long *) NULL,
2109 (unsigned) 0, pixels, (unsigned) p)) {
2113 XFreeColors(dpy, cmap, pixels, p, (unsigned long) 0);
2124 /****************************************************************************/
2126 contiguous(unsigned long pixels[], int npixels, int ncolors,
2127 unsigned long delta, int *first, int *rem)
2128 /* pixels - specifies allocated pixels
2129 * npixels - specifies count of alloc'd pixels
2130 * ncolors - specifies needed sequence length
2131 * delta - between pixels
2132 * first - returns first index of sequence
2133 * rem - returns first index after sequence, or 0, if none follow
2136 register int i = 1; /* walking index into the pixel array */
2137 register int count = 1; /* length of sequence discovered so far */
2140 if (npixels == ncolors) {
2145 while (count < ncolors && ncolors - count <= *rem)
2147 if (pixels[i-1] + delta == pixels[i])
2156 if (count != ncolors)
2162 /****************************************************************************/
2164 ROorRWcell(Display *dpy, Colormap cmap, unsigned long pixels[],
2165 int npixels, XColor *color, unsigned long p)
2167 unsigned long pixel;
2170 /* Free the read/write allocation of one cell in the colormap.
2171 * Request a read only allocation of one cell in the colormap.
2172 * If the read only allocation cannot be granted, give up, because
2173 * there must be no free cells in the colormap.
2174 * If the read only allocation is granted, but gives us a cell which
2175 * is not the one that we just freed, it is probably the case that
2176 * we are trying allocate White or Black or some other color which
2177 * already has a read-only allocation in the map. So we try to
2178 * allocate the previously freed cell with a read/write allocation,
2179 * because we want contiguous cells for image processing algorithms.
2182 pixel = color->pixel;
2183 request.red = color->red;
2184 request.green = color->green;
2185 request.blue = color->blue;
2187 XFreeColors(dpy, cmap, &pixel, 1, (unsigned long) 0);
2188 if (! XAllocColor(dpy, cmap, color)
2189 || (color->pixel != pixel &&
2190 (!RWcell(dpy, cmap, color, &request, &pixel))))
2192 free_cells(dpy, cmap, pixels, npixels, (int)p);
2199 /****************************************************************************/
2201 free_cells(Display *dpy, Colormap cmap, unsigned long pixels[],
2204 * pixels - to be freed
2205 * npixels - original number allocated
2208 /* One of the npixels allocated has already been freed.
2209 * p is the index of the freed pixel.
2210 * First free the pixels preceeding p, and there are p of them;
2211 * then free the pixels following p, there are npixels - p - 1 of them.
2213 XFreeColors(dpy, cmap, pixels, p, (unsigned long) 0);
2214 XFreeColors(dpy, cmap, &(pixels[p+1]), npixels - p - 1, (unsigned long) 0);
2215 free((char *) pixels);
2219 /****************************************************************************/
2221 RWcell(Display *dpy, Colormap cmap, XColor *color, XColor *request,
2222 unsigned long *pixel)
2224 unsigned long n = *pixel;
2226 XFreeColors(dpy, cmap, &(color->pixel), 1, (unsigned long)0);
2227 if (! XAllocColorCells(dpy, cmap, (Bool) 0, (unsigned long *) NULL,
2228 (unsigned) 0, pixel, (unsigned) 1))
2232 XFreeColors(dpy, cmap, pixel, 1, (unsigned long) 0);
2235 color->pixel = *pixel;
2236 color->flags = DoRed | DoGreen | DoBlue;
2237 color->red = request->red;
2238 color->green = request->green;
2239 color->blue = request->blue;
2240 XStoreColors(dpy, cmap, color, 1);
2245 /****************************************************************************/
2247 compare(_Xconst void *e1, _Xconst void *e2)
2249 return ((int)(*(long *)e1 - *(long *)e2));
2253 /****************************************************************************/
2255 readonly_map(Display *dpy, XVisualInfo *vinfo, XStandardColormap *colormap)
2260 last_pixel = (colormap->red_max + 1) * (colormap->green_max + 1) *
2261 (colormap->blue_max + 1) + colormap->base_pixel - 1;
2263 for(i=colormap->base_pixel; i <= last_pixel; i++) {
2265 color.pixel = (unsigned long) i;
2266 color.red = (unsigned short)
2267 (((i/colormap->red_mult) * 65535) / colormap->red_max);
2269 if (vinfo->c_class == StaticColor) {
2270 color.green = (unsigned short)
2271 ((((i/colormap->green_mult) % (colormap->green_max + 1)) *
2272 65535) / colormap->green_max);
2273 color.blue = (unsigned short)
2274 (((i%colormap->green_mult) * 65535) / colormap->blue_max);
2276 else /* vinfo->c_class == GrayScale, old style allocation XXX */
2277 color.green = color.blue = color.red;
2279 XAllocColor(dpy, colormap->colormap, &color);
2280 if (color.pixel != (unsigned long) i)
2287 /* $Xorg: DelCmap.c,v 1.4 2001/02/09 02:03:52 xorgcvs Exp $ */
2291 Copyright 1989, 1998 The Open Group
2293 Permission to use, copy, modify, distribute, and sell this software and its
2294 documentation for any purpose is hereby granted without fee, provided that
2295 the above copyright notice appear in all copies and that both that
2296 copyright notice and this permission notice appear in supporting
2299 The above copyright notice and this permission notice shall be included in
2300 all copies or substantial portions of the Software.
2302 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2303 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2304 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2305 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
2306 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
2307 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2309 Except as contained in this notice, the name of The Open Group shall not be
2310 used in advertising or otherwise to promote the sale, use or other dealings
2311 in this Software without prior written authorization from The Open Group.
2314 /* $XFree86: xc/lib/Xmu/DelCmap.c,v 1.7 2001/12/14 19:55:40 dawes Exp $ */
2317 * Author: Donna Converse, MIT X Consortium
2320 #include <X11/Xlib.h>
2321 #include <X11/Xutil.h>
2322 #include <X11/Xmu/StdCmap.h>
2324 int ignoreErrorHandler(Display* d, XErrorEvent* e) { }
2326 /* To remove any standard colormap property, use XmuDeleteStandardColormap().
2327 * XmuDeleteStandardColormap() will remove the specified property from the
2328 * specified screen, releasing any resources used by the colormap(s) of the
2329 * property if possible.
2333 XmuDeleteStandardColormap(Display *dpy, int screen, Atom property)
2334 /* dpy; - specifies the X server to connect to
2335 * screen - specifies the screen of the display
2336 * property - specifies the standard colormap property
2339 XStandardColormap *stdcmaps, *s;
2342 if (XGetRGBColormaps(dpy, RootWindow(dpy, screen), &stdcmaps, &count,
2345 for (s=stdcmaps; count > 0; count--, s++) {
2346 if ((s->killid == ReleaseByFreeingColormap) &&
2347 (s->colormap != None) &&
2348 (s->colormap != DefaultColormap(dpy, screen))) {
2350 // UGLY HACK written in by Adam Megacz -- sometimes s->colormap isn't valid, so we do some shuffling
2351 X11ErrorHandler* oldHandler = XSetErrorHandler(ignoreErrorHandler);
2353 XFreeColormap(dpy, s->colormap);
2355 XSetErrorHandler(oldHandler);
2358 } else if (s->killid != None) {
2359 XKillClient(dpy, s->killid);
2362 XDeleteProperty(dpy, RootWindow(dpy, screen), property);
2363 XFree((char *) stdcmaps);