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 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 = 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
711 java::lang::System::out->println(JvNewStringLatin1("here"));
715 void org::xwt::plat::POSIX::natInit() {
718 org::xwt::Platform::criticalAbort(JvNewStringLatin1("Your X11 libraries do not support multithreaded programs"));
720 display = XOpenDisplay(NULL);
721 screen_num = XDefaultScreen(display);
722 colorDepth = (jint)(DefaultDepth(((Display*)display), 0));
723 shm_info.shmaddr = NULL;
725 shm_supported = (XShmQueryExtension(display) == True);
727 X11ErrorHandler* oldHandler = XSetErrorHandler(errorHandler);
728 XShmSegmentInfo sinfo;
729 sinfo.shmid = shmget(IPC_PRIVATE, 1, IPC_CREAT | 0777 | IPC_EXCL);
730 sinfo.readOnly = False;
731 // if the server is remote, this will trigger the error handler
732 XShmAttach(display, &sinfo);
733 XSync(display, False);
734 XSetErrorHandler(oldHandler);
738 shm_pixmaps_supported = (XShmPixmapFormat(display) == ZPixmap);
740 crosshair = JvNewStringLatin1("crosshair");
741 east = JvNewStringLatin1("east");
742 hand = JvNewStringLatin1("hand");
743 move = JvNewStringLatin1("move");
744 north = JvNewStringLatin1("north");
745 northeast = JvNewStringLatin1("northeast");
746 northwest = JvNewStringLatin1("northwest");
747 south = JvNewStringLatin1("south");
748 southeast = JvNewStringLatin1("southeast");
749 southwest = JvNewStringLatin1("southwest");
750 text = JvNewStringLatin1("text");
751 west = JvNewStringLatin1("west");
752 wait_string = JvNewStringLatin1("wait");
753 crosshair_cursor = XCreateFontCursor(display, XC_tcross);
754 east_cursor = XCreateFontCursor(display, XC_right_side);
755 hand_cursor = XCreateFontCursor(display, XC_hand2);
756 move_cursor = XCreateFontCursor(display, XC_fleur);
757 north_cursor = XCreateFontCursor(display, XC_top_side);
758 northeast_cursor = XCreateFontCursor(display, XC_top_right_corner);
759 northwest_cursor = XCreateFontCursor(display, XC_left_side);
760 south_cursor = XCreateFontCursor(display, XC_bottom_side);
761 southeast_cursor = XCreateFontCursor(display, XC_bottom_right_corner);
762 southwest_cursor = XCreateFontCursor(display, XC_bottom_left_corner);
763 text_cursor = XCreateFontCursor(display, XC_xterm);
764 west_cursor = XCreateFontCursor(display, XC_right_side);
765 wait_cursor = XCreateFontCursor(display, XC_watch);
766 default_cursor = XCreateFontCursor(display, XC_left_ptr);
768 selectionWindow = XCreateWindow(display, RootWindow(display, screen_num), 0, 0, 1, 1, 0, colorDepth, InputOutput, CopyFromParent, 0, NULL);
769 visual = DefaultVisual(display, screen_num);
771 sprintf(buf, "X11 SHM: %s", shm_supported ? "enabled" : "disabled");
772 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
773 sprintf(buf, "X11 Visual: %x %x %x bits: %i visualid: %i depth: %i",
774 visual->red_mask, visual->green_mask, visual->blue_mask, visual->bits_per_rgb, visual->visualid, colorDepth);
775 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
777 if(XmuLookupStandardColormap(display, screen_num, visual->visualid, colorDepth, XA_RGB_BEST_MAP, False, True) == 0)
778 org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: XmuLookupStandardColormap failed"));
780 XStandardColormap* best_map_info = NULL;
782 if (XGetRGBColormaps(display, RootWindow(display, screen_num), &best_map_info, &count, XA_RGB_BEST_MAP) == 0)
783 org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: couldn't allocate a standard colormap"));
784 if (!best_map_info->colormap)
785 org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: XmuLookupStandardColomap succeded, but no colormap was found on the root window"));
786 if (best_map_info->red_max == 0)
787 org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: standard colormap exists, but was improperly allocated"));
788 colormap = best_map_info->colormap;
789 colormap_info = best_map_info;
791 sprintf(buf, " red_max / red_mult: %x %x", colormap_info->red_max, colormap_info->red_mult);
792 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
793 sprintf(buf, " green_max / green_mult: %x %x", colormap_info->green_max, colormap_info->green_mult);
794 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
795 sprintf(buf, " blue_max / blue_mult: %x %x", colormap_info->blue_max, colormap_info->blue_mult);
796 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
797 sprintf(buf, " base_pixel: %x", colormap_info->base_pixel);
798 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
801 JArray<java::lang::String*>* org::xwt::plat::POSIX::listNativeFonts() {
803 char** xfonts = XListFonts(display, "-*-*-*-*-*-*-*-*-*-*-*-*-*-*", 0xFFFFFFFF, &numfonts);
804 JArray<java::lang::String*>* fonts = (JArray<java::lang::String*>*)JvNewObjectArray(numfonts, &(::java::lang::String::class$), NULL);
805 java::lang::String** jfonts = (java::lang::String**)(elements(fonts));
806 for(int i=0; i<numfonts; i++)
807 jfonts[i] = JvNewStringLatin1(xfonts[i], strlen(xfonts[i]));
811 gnu::gcj::RawData* org::xwt::plat::POSIX::fontStringToStruct(jstring s) {
812 int len = min(1024, JvGetStringUTFLength(s));
814 JvGetStringUTFRegion(s, 0, len, buf);
816 return (gnu::gcj::RawData*)XLoadQueryFont(display, buf);
819 jint org::xwt::plat::POSIX::_getMaxAscent(::java::lang::String* font) { return ((XFontStruct*)fontToXFont(font))->max_bounds.ascent; }
820 jint org::xwt::plat::POSIX::_getMaxDescent(::java::lang::String* font) { return ((XFontStruct*)fontToXFont(font))->max_bounds.descent; }
821 jint org::xwt::plat::POSIX::_stringWidth(::java::lang::String* font, ::java::lang::String* text) {
822 if (text == NULL) return 0;
823 int len = JvGetStringUTFLength(text);
825 JvGetStringUTFRegion(text, 0, len, buf);
827 return XTextWidth((XFontStruct*)fontToXFont(font), buf, len);
831 //////////////////////////////////////////////////////////////////////////////
832 //////////////////////////////////////////////////////////////////////////////
833 //////////////////////////////////////////////////////////////////////////////
834 //////////////////////////////////////////////////////////////////////////////
836 // Everything below this point was taken, cut-and-paste, from the //
837 // source for libXmu. It implements the official 'standard colormap //
838 // creation algorithm. //
840 //////////////////////////////////////////////////////////////////////////////
841 //////////////////////////////////////////////////////////////////////////////
842 //////////////////////////////////////////////////////////////////////////////
843 //////////////////////////////////////////////////////////////////////////////
845 /* $Xorg: LookupCmap.c,v 1.4 2001/02/09 02:03:53 xorgcvs Exp $ */
849 Copyright 1989, 1998 The Open Group
851 Permission to use, copy, modify, distribute, and sell this software and its
852 documentation for any purpose is hereby granted without fee, provided that
853 the above copyright notice appear in all copies and that both that
854 copyright notice and this permission notice appear in supporting
857 The above copyright notice and this permission notice shall be included in
858 all copies or substantial portions of the Software.
860 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
861 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
862 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
863 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
864 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
865 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
867 Except as contained in this notice, the name of The Open Group shall not be
868 used in advertising or otherwise to promote the sale, use or other dealings
869 in this Software without prior written authorization from The Open Group.
872 /* $XFree86: xc/lib/Xmu/LookupCmap.c,v 1.8 2001/12/14 19:55:47 dawes Exp $ */
875 * Author: Donna Converse, MIT X Consortium
879 #include <X11/Xlib.h>
880 #include <X11/Xatom.h>
881 #include <X11/Xutil.h>
882 #include <X11/Xmu/StdCmap.h>
888 static Status lookup(Display*, int, VisualID, Atom, XStandardColormap*, Bool);
891 * To create a standard colormap if one does not currently exist, or
892 * replace the currently existing standard colormap, use
893 * XmuLookupStandardColormap().
895 * Given a screen, a visual, and a property, XmuLookupStandardColormap()
896 * will determine the best allocation for the property under the specified
897 * visual, and determine the whether to create a new colormap or to use
898 * the default colormap of the screen. It will call XmuStandardColormap()
899 * to create the standard colormap.
901 * If replace is true, any previous definition of the property will be
902 * replaced. If retain is true, the property and the colormap will be
903 * made permanent for the duration of the server session. However,
904 * pre-existing property definitions which are not replaced cannot be made
905 * permanent by a call to XmuLookupStandardColormap(); a request to retain
906 * resources pertains to newly created resources.
908 * Returns 0 on failure, non-zero on success. A request to create a
909 * standard colormap upon a visual which cannot support such a map is
910 * considered a failure. An example of this would be requesting any
911 * standard colormap property on a monochrome visual, or, requesting an
912 * RGB_BEST_MAP on a display whose colormap size is 16.
916 XmuLookupStandardColormap(Display *dpy, int screen, VisualID visualid,
917 unsigned int depth, Atom property,
918 Bool replace, Bool retain)
920 * dpy - specifies X server connection
921 * screen - specifies screen of display
922 * visualid - specifies the visual type
923 * depth - specifies the visual type
924 * property - a standard colormap property
925 * replace - specifies whether to replace
926 * retain - specifies whether to retain
929 Display *odpy; /* original display connection */
930 XStandardColormap *colormap;
931 XVisualInfo vinfo_template, *vinfo; /* visual */
933 unsigned long r_max, g_max, b_max; /* allocation */
935 Colormap cmap; /* colormap ID */
939 /* Match the requested visual */
941 vinfo_template.visualid = visualid;
942 vinfo_template.screen = screen;
943 vinfo_template.depth = depth;
944 vinfo_mask = VisualIDMask | VisualScreenMask | VisualDepthMask;
945 if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &count)) ==
949 /* Monochrome visuals have no standard maps */
951 if (vinfo->colormap_size <= 2) {
952 XFree((char *) vinfo);
956 /* If the requested property already exists on this screen, and,
957 * if the replace flag has not been set to true, return success.
958 * lookup() will remove a pre-existing map if replace is true.
961 if (lookup(dpy, screen, visualid, property, (XStandardColormap *) NULL,
962 replace) && !replace) {
963 XFree((char *) vinfo);
967 /* Determine the best allocation for this property under the requested
968 * visualid and depth, and determine whether or not to use the default
969 * colormap of the screen.
972 if (!XmuGetColormapAllocation(vinfo, property, &r_max, &g_max, &b_max)) {
973 XFree((char *) vinfo);
977 cmap = (property == XA_RGB_DEFAULT_MAP &&
978 visualid == XVisualIDFromVisual(DefaultVisual(dpy, screen)))
979 ? DefaultColormap(dpy, screen) : None;
981 /* If retaining resources, open a new connection to the same server */
985 if ((dpy = XOpenDisplay(XDisplayString(odpy))) == NULL) {
986 XFree((char *) vinfo);
991 /* Create the standard colormap */
993 colormap = XmuStandardColormap(dpy, screen, visualid, depth, property,
994 cmap, r_max, g_max, b_max);
996 /* Set the standard colormap property */
1001 if (lookup(dpy, screen, visualid, property, colormap, replace) &&
1003 /* Someone has defined the property since we last looked.
1004 * Since we will not replace it, release our own resources.
1005 * If this is the default map, our allocations will be freed
1006 * when this connection closes.
1008 if (colormap->killid == ReleaseByFreeingColormap)
1009 XFreeColormap(dpy, colormap->colormap);
1012 XSetCloseDownMode(dpy, RetainPermanent);
1015 XFree((char *) colormap);
1021 XFree((char *) vinfo);
1025 /***************************************************************************/
1027 /* Lookup a standard colormap property. If the property is RGB_DEFAULT_MAP,
1028 * the visualid is used to determine whether the indicated standard colormap
1029 * exists. If the map exists and replace is true, delete the resources used
1030 * by the map and remove the property. Return true if the map exists,
1031 * or did exist and was deleted; return false if the map was not found.
1033 * Note that this is not the way that a Status return is normally used.
1035 * If new is not NULL, new points to an XStandardColormap structure which
1036 * describes a standard colormap of the specified property. It will be made
1037 * a standard colormap of the screen if none already exists, or if replace
1042 lookup(Display *dpy, int screen, VisualID visualid, Atom property,
1043 XStandardColormap *cnew, Bool replace)
1045 * dpy - specifies display connection
1046 * screen - specifies screen number
1047 * visualid - specifies visualid for std map
1048 * property - specifies colormap property name
1049 * cnew - specifies a standard colormap
1050 * replace - specifies whether to replace
1055 XStandardColormap *stdcmaps, *s;
1056 Window win = RootWindow(dpy, screen);
1058 /* The property does not already exist */
1060 if (! XGetRGBColormaps(dpy, win, &stdcmaps, &count, property)) {
1062 XSetRGBColormaps(dpy, win, cnew, 1, property);
1066 /* The property exists and is not describing the RGB_DEFAULT_MAP */
1068 if (property != XA_RGB_DEFAULT_MAP) {
1070 XmuDeleteStandardColormap(dpy, screen, property);
1072 XSetRGBColormaps(dpy, win, cnew, 1, property);
1074 XFree((char *)stdcmaps);
1078 /* The property exists and is RGB_DEFAULT_MAP */
1080 for (i=0, s=stdcmaps; (i < count) && (s->visualid != visualid); i++, s++)
1083 /* No RGB_DEFAULT_MAP property matches the given visualid */
1087 XStandardColormap *m, *maps;
1089 s = (XStandardColormap *) malloc((unsigned) ((count+1) * sizeof
1090 (XStandardColormap)));
1092 for (i = 0, m = s, maps = stdcmaps; i < count; i++, m++, maps++) {
1093 m->colormap = maps->colormap;
1094 m->red_max = maps->red_max;
1095 m->red_mult = maps->red_mult;
1096 m->green_max = maps->green_max;
1097 m->green_mult = maps->green_mult;
1098 m->blue_max = maps->blue_max;
1099 m->blue_mult = maps->blue_mult;
1100 m->base_pixel = maps->base_pixel;
1101 m->visualid = maps->visualid;
1102 m->killid = maps->killid;
1104 m->colormap = cnew->colormap;
1105 m->red_max = cnew->red_max;
1106 m->red_mult = cnew->red_mult;
1107 m->green_max = cnew->green_max;
1108 m->green_mult = cnew->green_mult;
1109 m->blue_max = cnew->blue_max;
1110 m->blue_mult = cnew->blue_mult;
1111 m->base_pixel = cnew->base_pixel;
1112 m->visualid = cnew->visualid;
1113 m->killid = cnew->killid;
1115 XSetRGBColormaps(dpy, win, s, ++count, property);
1118 XFree((char *) stdcmaps);
1122 /* Found an RGB_DEFAULT_MAP property with a matching visualid */
1125 /* Free old resources first - we may need them, particularly in
1126 * the default colormap of the screen. However, because of this,
1127 * it is possible that we will destroy the old resource and fail
1128 * to create a new one if XmuStandardColormap() fails.
1132 XmuDeleteStandardColormap(dpy, screen, property);
1134 XSetRGBColormaps(dpy, win, cnew, 1, property);
1137 XStandardColormap *map;
1139 /* s still points to the matching standard colormap */
1141 if (s->killid == ReleaseByFreeingColormap) {
1142 if ((s->colormap != None) &&
1143 (s->colormap != DefaultColormap(dpy, screen)))
1144 XFreeColormap(dpy, s->colormap);
1146 else if (s->killid != None)
1147 XKillClient(dpy, s->killid);
1149 map = (cnew) ? cnew : stdcmaps + --count;
1151 s->colormap = map->colormap;
1152 s->red_max = map->red_max;
1153 s->red_mult = map->red_mult;
1154 s->green_max = map->green_max;
1155 s->green_mult = map->green_mult;
1156 s->blue_max = map->blue_max;
1157 s->blue_mult = map->blue_mult;
1158 s->visualid = map->visualid;
1159 s->killid = map->killid;
1161 XSetRGBColormaps(dpy, win, stdcmaps, count, property);
1164 XFree((char *) stdcmaps);
1168 /* $Xorg: CmapAlloc.c,v 1.4 2001/02/09 02:03:51 xorgcvs Exp $ */
1172 Copyright 1989, 1994, 1998 The Open Group
1174 Permission to use, copy, modify, distribute, and sell this software and its
1175 documentation for any purpose is hereby granted without fee, provided that
1176 the above copyright notice appear in all copies and that both that
1177 copyright notice and this permission notice appear in supporting
1180 The above copyright notice and this permission notice shall be included in
1181 all copies or substantial portions of the Software.
1183 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1184 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1185 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1186 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1187 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1188 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1190 Except as contained in this notice, the name of The Open Group shall not be
1191 used in advertising or otherwise to promote the sale, use or other dealings
1192 in this Software without prior written authorization from The Open Group.
1195 /* $XFree86: xc/lib/Xmu/CmapAlloc.c,v 1.7 2001/12/14 19:55:35 dawes Exp $ */
1198 * Author: Donna Converse, MIT X Consortium
1201 #include <X11/Xlib.h>
1202 #include <X11/Xatom.h>
1203 #include <X11/Xutil.h>
1204 #include <X11/Xmu/StdCmap.h>
1207 #define lowbit(x) ((x) & (~(x) + 1))
1212 static void best_allocation(XVisualInfo*, unsigned long*, unsigned long*,
1214 static int default_allocation(XVisualInfo*, unsigned long*,
1215 unsigned long*, unsigned long*);
1216 static void gray_allocation(int, unsigned long*, unsigned long*,
1218 static int icbrt(int);
1219 static int icbrt_with_bits(int, int);
1220 static int icbrt_with_guess(int, int);
1222 /* To determine the best allocation of reds, greens, and blues in a
1223 * standard colormap, use XmuGetColormapAllocation.
1224 * vinfo specifies visual information for a chosen visual
1225 * property specifies one of the standard colormap property names
1226 * red_max returns maximum red value
1227 * green_max returns maximum green value
1228 * blue_max returns maximum blue value
1230 * XmuGetColormapAllocation returns 0 on failure, non-zero on success.
1231 * It is assumed that the visual is appropriate for the colormap property.
1235 XmuGetColormapAllocation(XVisualInfo *vinfo, Atom property,
1236 unsigned long *red_max,
1237 unsigned long *green_max,
1238 unsigned long *blue_max)
1242 if (vinfo->colormap_size <= 2)
1247 case XA_RGB_DEFAULT_MAP:
1248 status = default_allocation(vinfo, red_max, green_max, blue_max);
1250 case XA_RGB_BEST_MAP:
1251 best_allocation(vinfo, red_max, green_max, blue_max);
1253 case XA_RGB_GRAY_MAP:
1254 gray_allocation(vinfo->colormap_size, red_max, green_max, blue_max);
1256 case XA_RGB_RED_MAP:
1257 *red_max = vinfo->colormap_size - 1;
1258 *green_max = *blue_max = 0;
1260 case XA_RGB_GREEN_MAP:
1261 *green_max = vinfo->colormap_size - 1;
1262 *red_max = *blue_max = 0;
1264 case XA_RGB_BLUE_MAP:
1265 *blue_max = vinfo->colormap_size - 1;
1266 *red_max = *green_max = 0;
1274 /****************************************************************************/
1275 /* Determine the appropriate color allocations of a gray scale.
1277 * Keith Packard, MIT X Consortium
1281 gray_allocation(int n, unsigned long *red_max, unsigned long *green_max,
1282 unsigned long *blue_max)
1284 *red_max = (n * 30) / 100;
1285 *green_max = (n * 59) / 100;
1286 *blue_max = (n * 11) / 100;
1287 *green_max += ((n - 1) - (*red_max + *green_max + *blue_max));
1290 /****************************************************************************/
1291 /* Determine an appropriate color allocation for the RGB_DEFAULT_MAP.
1292 * If a map has less than a minimum number of definable entries, we do not
1293 * produce an allocation for an RGB_DEFAULT_MAP.
1295 * For 16 planes, the default colormap will have 27 each RGB; for 12 planes,
1296 * 12 each. For 8 planes, let n = the number of colormap entries, which may
1297 * be 256 or 254. Then, maximum red value = floor(cube_root(n - 125)) - 1.
1298 * Maximum green and maximum blue values are identical to maximum red.
1299 * This leaves at least 125 cells which clients can allocate.
1301 * Return 0 if an allocation has been determined, non-zero otherwise.
1305 default_allocation(XVisualInfo *vinfo, unsigned long *red,
1306 unsigned long *green, unsigned long *blue)
1308 int ngrays; /* number of gray cells */
1310 switch (vinfo->c_class)
1314 if (vinfo->colormap_size > 65000)
1315 /* intended for displays with 16 planes */
1316 *red = *green = *blue = (unsigned long) 27;
1317 else if (vinfo->colormap_size > 4000)
1318 /* intended for displays with 12 planes */
1319 *red = *green = *blue = (unsigned long) 12;
1320 else if (vinfo->colormap_size < 250)
1323 /* intended for displays with 8 planes */
1324 *red = *green = *blue = (unsigned long)
1325 (icbrt(vinfo->colormap_size - 125) - 1);
1330 if (vinfo->colormap_size < 10)
1332 *red = *green = *blue = vinfo->colormap_size / 2 - 1;
1337 *red = vinfo->red_mask / lowbit(vinfo->red_mask);
1338 *green = vinfo->green_mask / lowbit(vinfo->green_mask);
1339 *blue = vinfo->blue_mask / lowbit(vinfo->blue_mask);
1344 if (vinfo->colormap_size > 65000)
1346 else if (vinfo->colormap_size > 4000)
1348 else if (vinfo->colormap_size < 250)
1352 gray_allocation(ngrays, red, green, blue);
1361 /****************************************************************************/
1362 /* Determine an appropriate color allocation for the RGB_BEST_MAP.
1364 * For a DirectColor or TrueColor visual, the allocation is determined
1365 * by the red_mask, green_mask, and blue_mask members of the visual info.
1367 * Otherwise, if the colormap size is an integral power of 2, determine
1368 * the allocation according to the number of bits given to each color,
1369 * with green getting more than red, and red more than blue, if there
1370 * are to be inequities in the distribution. If the colormap size is
1371 * not an integral power of 2, let n = the number of colormap entries.
1372 * Then maximum red value = floor(cube_root(n)) - 1;
1373 * maximum blue value = floor(cube_root(n)) - 1;
1374 * maximum green value = n / ((# red values) * (# blue values)) - 1;
1375 * Which, on a GPX, allows for 252 entries in the best map, out of 254
1376 * defineable colormap entries.
1380 best_allocation(XVisualInfo *vinfo, unsigned long *red, unsigned long *green,
1381 unsigned long *blue)
1384 if (vinfo->c_class == DirectColor || vinfo->c_class == TrueColor)
1386 *red = vinfo->red_mask;
1387 while ((*red & 01) == 0)
1389 *green = vinfo->green_mask;
1390 while ((*green & 01) == 0)
1392 *blue = vinfo->blue_mask;
1393 while ((*blue & 01) == 0)
1398 register int bits, n;
1400 /* Determine n such that n is the least integral power of 2 which is
1401 * greater than or equal to the number of entries in the colormap.
1405 while (vinfo->colormap_size > n)
1411 /* If the number of entries in the colormap is a power of 2, determine
1412 * the allocation by "dealing" the bits, first to green, then red, then
1413 * blue. If not, find the maximum integral red, green, and blue values
1414 * which, when multiplied together, do not exceed the number of
1418 if (n == vinfo->colormap_size)
1420 register int r, g, b;
1422 g = b + ((bits % 3) ? 1 : 0);
1423 r = b + (((bits % 3) == 2) ? 1 : 0);
1430 *red = icbrt_with_bits(vinfo->colormap_size, bits);
1432 *green = (vinfo->colormap_size / ((*red) * (*blue)));
1442 * integer cube roots by Newton's method
1444 * Stephen Gildea, MIT X Consortium, July 1991
1450 register int bits = 0;
1451 register unsigned n = a;
1458 return icbrt_with_bits(a, bits);
1463 icbrt_with_bits(int a, int bits)
1464 /* bits - log 2 of a */
1466 return icbrt_with_guess(a, a>>2*bits/3);
1469 #ifdef _X_ROOT_STATS
1470 int icbrt_loopcount;
1473 /* Newton's Method: x_n+1 = x_n - ( f(x_n) / f'(x_n) ) */
1475 /* for cube roots, x^3 - a = 0, x_new = x - 1/3 (x - a/x^2) */
1478 * Quick and dirty cube roots. Nothing fancy here, just Newton's method.
1479 * Only works for positive integers (since that's all we need).
1480 * We actually return floor(cbrt(a)) because that's what we need here, too.
1484 icbrt_with_guess(int a, int guess)
1488 #ifdef _X_ROOT_STATS
1489 icbrt_loopcount = 0;
1497 #ifdef _X_ROOT_STATS
1500 delta = (guess - a/(guess*guess))/3;
1502 printf("pass %d: guess=%d, delta=%d\n", icbrt_loopcount, guess, delta);
1505 } while (delta != 0);
1507 if (guess*guess*guess > a)
1514 /* $Xorg: StdCmap.c,v 1.4 2001/02/09 02:03:53 xorgcvs Exp $ */
1518 Copyright 1989, 1998 The Open Group
1520 Permission to use, copy, modify, distribute, and sell this software and its
1521 documentation for any purpose is hereby granted without fee, provided that
1522 the above copyright notice appear in all copies and that both that
1523 copyright notice and this permission notice appear in supporting
1526 The above copyright notice and this permission notice shall be included in
1527 all copies or substantial portions of the Software.
1529 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1530 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1531 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1532 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1533 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1534 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1536 Except as contained in this notice, the name of The Open Group shall not be
1537 used in advertising or otherwise to promote the sale, use or other dealings
1538 in this Software without prior written authorization from The Open Group.
1541 /* $XFree86: xc/lib/Xmu/StdCmap.c,v 1.6 2001/12/14 19:55:48 dawes Exp $ */
1544 * Author: Donna Converse, MIT X Consortium
1548 #include <X11/Xlib.h>
1549 #include <X11/Xatom.h>
1550 #include <X11/Xutil.h>
1551 #include <X11/Xmu/StdCmap.h>
1553 #define lowbit(x) ((x) & (~(x) + 1))
1558 /* argument restrictions */
1559 static Status valid_args(XVisualInfo*, unsigned long, unsigned long,
1560 unsigned long, Atom);
1563 * To create any one standard colormap, use XmuStandardColormap().
1565 * Create a standard colormap for the given screen, visualid, and visual
1566 * depth, with the given red, green, and blue maximum values, with the
1567 * given standard property name. Return a pointer to an XStandardColormap
1568 * structure which describes the newly created colormap, upon success.
1569 * Upon failure, return NULL.
1571 * XmuStandardColormap() calls XmuCreateColormap() to create the map.
1573 * Resources created by this function are not made permanent; that is the
1574 * caller's responsibility.
1578 XmuStandardColormap(Display *dpy, int screen, VisualID visualid,
1579 unsigned int depth, Atom property, Colormap cmap,
1580 unsigned long red_max, unsigned long green_max,
1581 unsigned long blue_max)
1583 * dpy - specifies X server connection
1584 * screen - specifies display screen
1585 * visualid - identifies the visual type
1586 * depth - identifies the visual type
1587 * property - a standard colormap property
1588 * cmap - specifies colormap ID or None
1589 * red_max, green_max, blue_max - allocations
1592 XStandardColormap *stdcmap;
1594 XVisualInfo vinfo_template, *vinfo;
1598 /* Match the required visual information to an actual visual */
1599 vinfo_template.visualid = visualid;
1600 vinfo_template.screen = screen;
1601 vinfo_template.depth = depth;
1602 vinfo_mask = VisualIDMask | VisualScreenMask | VisualDepthMask;
1603 if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &n)) == NULL)
1606 /* Check the validity of the combination of visual characteristics,
1607 * allocation, and colormap property. Create an XStandardColormap
1611 if (! valid_args(vinfo, red_max, green_max, blue_max, property)
1612 || ((stdcmap = XAllocStandardColormap()) == NULL)) {
1613 XFree((char *) vinfo);
1617 /* Fill in the XStandardColormap structure */
1619 if (cmap == DefaultColormap(dpy, screen)) {
1620 /* Allocating out of the default map, cannot use XFreeColormap() */
1621 Window win = XCreateWindow(dpy, RootWindow(dpy, screen), 1, 1, 1, 1,
1622 0, 0, InputOnly, vinfo->visual,
1624 (XSetWindowAttributes *)NULL);
1625 stdcmap->killid = (XID) XCreatePixmap(dpy, win, 1, 1, depth);
1626 XDestroyWindow(dpy, win);
1627 stdcmap->colormap = cmap;
1629 stdcmap->killid = ReleaseByFreeingColormap;
1630 stdcmap->colormap = XCreateColormap(dpy, RootWindow(dpy, screen),
1631 vinfo->visual, AllocNone);
1633 stdcmap->red_max = red_max;
1634 stdcmap->green_max = green_max;
1635 stdcmap->blue_max = blue_max;
1636 if (property == XA_RGB_GRAY_MAP)
1637 stdcmap->red_mult = stdcmap->green_mult = stdcmap->blue_mult = 1;
1638 else if (vinfo->c_class == TrueColor || vinfo->c_class == DirectColor) {
1639 stdcmap->red_mult = lowbit(vinfo->red_mask);
1640 stdcmap->green_mult = lowbit(vinfo->green_mask);
1641 stdcmap->blue_mult = lowbit(vinfo->blue_mask);
1643 stdcmap->red_mult = (red_max > 0)
1644 ? (green_max + 1) * (blue_max + 1) : 0;
1645 stdcmap->green_mult = (green_max > 0) ? blue_max + 1 : 0;
1646 stdcmap->blue_mult = (blue_max > 0) ? 1 : 0;
1648 stdcmap->base_pixel = 0; /* base pixel may change */
1649 stdcmap->visualid = vinfo->visualid;
1651 /* Make the colormap */
1653 status = XmuCreateColormap(dpy, stdcmap);
1657 XFree((char *) vinfo);
1660 /* Free the colormap or the pixmap, if we created one */
1661 if (stdcmap->killid == ReleaseByFreeingColormap)
1662 XFreeColormap(dpy, stdcmap->colormap);
1663 else if (stdcmap->killid != None)
1664 XFreePixmap(dpy, stdcmap->killid);
1666 XFree((char *) stdcmap);
1667 return (XStandardColormap *) NULL;
1672 /****************************************************************************/
1674 valid_args(XVisualInfo *vinfo, unsigned long red_max, unsigned long green_max,
1675 unsigned long blue_max, Atom property)
1677 * vinfo - specifies visual
1678 * red_max, green_max, blue_max - specifies alloc
1679 * property - specifies property name
1682 unsigned long ncolors; /* number of colors requested */
1684 /* Determine that the number of colors requested is <= map size */
1686 if ((vinfo->c_class == DirectColor) || (vinfo->c_class == TrueColor)) {
1689 mask = vinfo->red_mask;
1694 mask = vinfo->green_mask;
1697 if (green_max > mask)
1699 mask = vinfo->blue_mask;
1702 if (blue_max > mask)
1704 } else if (property == XA_RGB_GRAY_MAP) {
1705 ncolors = red_max + green_max + blue_max + 1;
1706 if (ncolors > vinfo->colormap_size)
1709 ncolors = (red_max + 1) * (green_max + 1) * (blue_max + 1);
1710 if (ncolors > vinfo->colormap_size)
1714 /* Determine that the allocation and visual make sense for the property */
1718 case XA_RGB_DEFAULT_MAP:
1719 if (red_max == 0 || green_max == 0 || blue_max == 0)
1722 case XA_RGB_RED_MAP:
1726 case XA_RGB_GREEN_MAP:
1730 case XA_RGB_BLUE_MAP:
1734 case XA_RGB_BEST_MAP:
1735 if (red_max == 0 || green_max == 0 || blue_max == 0)
1738 case XA_RGB_GRAY_MAP:
1739 if (red_max == 0 || blue_max == 0 || green_max == 0)
1749 /* $Xorg: CrCmap.c,v 1.4 2001/02/09 02:03:51 xorgcvs Exp $ */
1753 Copyright 1989, 1998 The Open Group
1755 Permission to use, copy, modify, distribute, and sell this software and its
1756 documentation for any purpose is hereby granted without fee, provided that
1757 the above copyright notice appear in all copies and that both that
1758 copyright notice and this permission notice appear in supporting
1761 The above copyright notice and this permission notice shall be included in
1762 all copies or substantial portions of the Software.
1764 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1765 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1766 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1767 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1768 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1769 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1771 Except as contained in this notice, the name of The Open Group shall not be
1772 used in advertising or otherwise to promote the sale, use or other dealings
1773 in this Software without prior written authorization from The Open Group.
1776 /* $XFree86: xc/lib/Xmu/CrCmap.c,v 3.7 2001/12/14 19:55:36 dawes Exp $ */
1779 * Author: Donna Converse, MIT X Consortium
1783 * CreateCmap.c - given a standard colormap description, make the map.
1788 #include <X11/Xlib.h>
1789 #include <X11/Xutil.h>
1790 #include <X11/Xmu/StdCmap.h>
1795 /* allocate entire map Read Only */
1796 static int ROmap(Display*, Colormap, unsigned long[], int, int);
1798 /* allocate a cell, prefer Read Only */
1799 static Status ROorRWcell(Display*, Colormap, unsigned long[], int,
1800 XColor*, unsigned long);
1802 /* allocate a cell Read Write */
1803 static Status RWcell(Display*, Colormap, XColor*, XColor*, unsigned long*);
1806 static int compare(_Xconst void*, _Xconst void*);
1808 /* find contiguous sequence of cells */
1809 static Status contiguous(unsigned long[], int, int, unsigned long, int*, int*);
1811 /* frees resources before quitting */
1812 static void free_cells(Display*, Colormap, unsigned long[], int, int);
1814 /* create a map in a RO visual type */
1815 static Status readonly_map(Display*, XVisualInfo*, XStandardColormap*);
1817 /* create a map in a RW visual type */
1818 static Status readwrite_map(Display*, XVisualInfo*, XStandardColormap*);
1820 #define lowbit(x) ((x) & (~(x) + 1))
1821 #define TRUEMATCH(mult,max,mask) \
1822 (colormap->max * colormap->mult <= vinfo->mask && \
1823 lowbit(vinfo->mask) == colormap->mult)
1826 * To create any one colormap which is described by an XStandardColormap
1827 * structure, use XmuCreateColormap().
1829 * Return 0 on failure, non-zero on success.
1830 * Resources created by this function are not made permanent.
1831 * No argument error checking is provided. Use at your own risk.
1833 * All colormaps are created with read only allocations, with the exception
1834 * of read only allocations of colors in the default map or otherwise
1835 * which fail to return the expected pixel value, and these are individually
1836 * defined as read/write allocations. This is done so that all the cells
1837 * defined in the default map are contiguous, for use in image processing.
1838 * This typically happens with White and Black in the default map.
1840 * Colormaps of static visuals are considered to be successfully created if
1841 * the map of the static visual matches the definition given in the
1842 * standard colormap structure.
1846 XmuCreateColormap(Display *dpy, XStandardColormap *colormap)
1847 /* dpy - specifies the connection under which the map is created
1848 * colormap - specifies the map to be created, and returns, particularly
1849 * if the map is created as a subset of the default colormap
1850 * of the screen, the base_pixel of the map.
1853 XVisualInfo vinfo_template; /* template visual information */
1854 XVisualInfo *vinfo; /* matching visual information */
1855 XVisualInfo *vpointer; /* for freeing the entire list */
1856 long vinfo_mask; /* specifies the visual mask value */
1857 int n; /* number of matching visuals */
1860 vinfo_template.visualid = colormap->visualid;
1861 vinfo_mask = VisualIDMask;
1862 if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &n)) == NULL)
1865 /* A visual id may be valid on multiple screens. Also, there may
1866 * be multiple visuals with identical visual ids at different depths.
1867 * If the colormap is the Default Colormap, use the Default Visual.
1868 * Otherwise, arbitrarily, use the deepest visual.
1874 register int screen_number;
1878 for (screen_number = ScreenCount(dpy); --screen_number >= 0; )
1879 if (colormap->colormap == DefaultColormap(dpy, screen_number)) {
1885 for (i=0; i < n; i++, vinfo++) {
1886 if (vinfo->visual == DefaultVisual(dpy, screen_number))
1891 XVisualInfo *v = NULL;
1893 for (i=0; i < n; i++, vinfo++)
1894 if (vinfo->depth > maxdepth) {
1895 maxdepth = vinfo->depth;
1902 if (vinfo->c_class == PseudoColor || vinfo->c_class == DirectColor ||
1903 vinfo->c_class == GrayScale)
1904 status = readwrite_map(dpy, vinfo, colormap);
1905 else if (vinfo->c_class == TrueColor)
1906 status = TRUEMATCH(red_mult, red_max, red_mask) &&
1907 TRUEMATCH(green_mult, green_max, green_mask) &&
1908 TRUEMATCH(blue_mult, blue_max, blue_mask);
1910 status = readonly_map(dpy, vinfo, colormap);
1912 XFree((char *) vpointer);
1916 /****************************************************************************/
1918 readwrite_map(Display *dpy, XVisualInfo *vinfo, XStandardColormap *colormap)
1920 register unsigned long i, n; /* index counters */
1921 unsigned long ncolors; /* number of colors to be defined */
1922 int npixels; /* number of pixels allocated R/W */
1923 int first_index; /* first index of pixels to use */
1924 int remainder; /* first index of remainder */
1925 XColor color; /* the definition of a color */
1926 unsigned long *pixels; /* array of colormap pixels */
1927 unsigned long delta;
1930 /* Determine ncolors, the number of colors to be defined.
1931 * Insure that 1 < ncolors <= the colormap size.
1933 if (vinfo->c_class == DirectColor) {
1934 ncolors = colormap->red_max;
1935 if (colormap->green_max > ncolors)
1936 ncolors = colormap->green_max;
1937 if (colormap->blue_max > ncolors)
1938 ncolors = colormap->blue_max;
1940 delta = lowbit(vinfo->red_mask) +
1941 lowbit(vinfo->green_mask) +
1942 lowbit(vinfo->blue_mask);
1944 ncolors = colormap->red_max * colormap->red_mult +
1945 colormap->green_max * colormap->green_mult +
1946 colormap->blue_max * colormap->blue_mult + 1;
1949 if (ncolors <= 1 || (int) ncolors > vinfo->colormap_size) return 0;
1951 /* Allocate Read/Write as much of the colormap as we can possibly get.
1952 * Then insure that the pixels we were allocated are given in
1953 * monotonically increasing order, using a quicksort. Next, insure
1954 * that our allocation includes a subset of contiguous pixels at least
1955 * as long as the number of colors to be defined. Now we know that
1956 * these conditions are met:
1957 * 1) There are no free cells in the colormap.
1958 * 2) We have a contiguous sequence of pixels, monotonically
1959 * increasing, of length >= the number of colors requested.
1961 * One cell at a time, we will free, compute the next color value,
1962 * then allocate read only. This takes a long time.
1963 * This is done to insure that cells are allocated read only in the
1964 * contiguous order which we prefer. If the server has a choice of
1965 * cells to grant to an allocation request, the server may give us any
1966 * cell, so that is why we do these slow gymnastics.
1969 if ((pixels = (unsigned long *) calloc((unsigned) vinfo->colormap_size,
1970 sizeof(unsigned long))) == NULL)
1973 if ((npixels = ROmap(dpy, colormap->colormap, pixels,
1974 vinfo->colormap_size, ncolors)) == 0) {
1975 free((char *) pixels);
1979 qsort((char *) pixels, npixels, sizeof(unsigned long), compare);
1981 if (!contiguous(pixels, npixels, ncolors, delta, &first_index, &remainder))
1983 /* can't find enough contiguous cells, give up */
1984 XFreeColors(dpy, colormap->colormap, pixels, npixels,
1986 free((char *) pixels);
1989 colormap->base_pixel = pixels[first_index];
1991 /* construct a gray map */
1992 if (colormap->red_mult == 1 && colormap->green_mult == 1 &&
1993 colormap->blue_mult == 1)
1994 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
1997 color.blue = color.green = color.red =
1998 (unsigned short) ((i * 65535) / (colormap->red_max +
1999 colormap->green_max +
2000 colormap->blue_max));
2002 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
2007 /* construct a red ramp map */
2008 else if (colormap->green_max == 0 && colormap->blue_max == 0)
2009 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
2012 color.red = (unsigned short) ((i * 65535) / colormap->red_max);
2013 color.green = color.blue = 0;
2015 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
2020 /* construct a green ramp map */
2021 else if (colormap->red_max == 0 && colormap->blue_max == 0)
2022 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
2025 color.green = (unsigned short) ((i * 65535) / colormap->green_max);
2026 color.red = color.blue = 0;
2028 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
2033 /* construct a blue ramp map */
2034 else if (colormap->red_max == 0 && colormap->green_max == 0)
2035 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
2038 color.blue = (unsigned short) ((i * 65535) / colormap->blue_max);
2039 color.red = color.green = 0;
2041 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
2046 /* construct a standard red green blue cube map */
2049 #define calc(max,mult) (((n / colormap->mult) % \
2050 (colormap->max + 1)) * 65535) / colormap->max
2052 for (n=0, i=0; i < ncolors; i++, n += delta)
2054 color.pixel = n + colormap->base_pixel;
2055 color.red = calc(red_max, red_mult);
2056 color.green = calc(green_max, green_mult);
2057 color.blue = calc(blue_max, blue_mult);
2058 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
2064 /* We have a read-only map defined. Now free unused cells,
2065 * first those occuring before the contiguous sequence begins,
2066 * then any following the contiguous sequence.
2070 XFreeColors(dpy, colormap->colormap, pixels, first_index,
2073 XFreeColors(dpy, colormap->colormap,
2074 &(pixels[first_index + ncolors]), remainder,
2077 free((char *) pixels);
2082 /****************************************************************************/
2084 ROmap(Display *dpy, Colormap cmap, unsigned long pixels[], int m, int n)
2086 * dpy - the X server connection
2087 * cmap - specifies colormap ID
2088 * pixels - returns pixel allocations
2089 * m - specifies colormap size
2090 * n - specifies number of colors
2095 /* first try to allocate the entire colormap */
2096 if (XAllocColorCells(dpy, cmap, 1, (unsigned long *) NULL,
2097 (unsigned) 0, pixels, (unsigned) m))
2100 /* Allocate all available cells in the colormap, using a binary
2101 * algorithm to discover how many cells we can allocate in the colormap.
2105 p = n + ((m - n + 1) / 2);
2106 if (XAllocColorCells(dpy, cmap, 1, (unsigned long *) NULL,
2107 (unsigned) 0, pixels, (unsigned) p)) {
2111 XFreeColors(dpy, cmap, pixels, p, (unsigned long) 0);
2122 /****************************************************************************/
2124 contiguous(unsigned long pixels[], int npixels, int ncolors,
2125 unsigned long delta, int *first, int *rem)
2126 /* pixels - specifies allocated pixels
2127 * npixels - specifies count of alloc'd pixels
2128 * ncolors - specifies needed sequence length
2129 * delta - between pixels
2130 * first - returns first index of sequence
2131 * rem - returns first index after sequence, or 0, if none follow
2134 register int i = 1; /* walking index into the pixel array */
2135 register int count = 1; /* length of sequence discovered so far */
2138 if (npixels == ncolors) {
2143 while (count < ncolors && ncolors - count <= *rem)
2145 if (pixels[i-1] + delta == pixels[i])
2154 if (count != ncolors)
2160 /****************************************************************************/
2162 ROorRWcell(Display *dpy, Colormap cmap, unsigned long pixels[],
2163 int npixels, XColor *color, unsigned long p)
2165 unsigned long pixel;
2168 /* Free the read/write allocation of one cell in the colormap.
2169 * Request a read only allocation of one cell in the colormap.
2170 * If the read only allocation cannot be granted, give up, because
2171 * there must be no free cells in the colormap.
2172 * If the read only allocation is granted, but gives us a cell which
2173 * is not the one that we just freed, it is probably the case that
2174 * we are trying allocate White or Black or some other color which
2175 * already has a read-only allocation in the map. So we try to
2176 * allocate the previously freed cell with a read/write allocation,
2177 * because we want contiguous cells for image processing algorithms.
2180 pixel = color->pixel;
2181 request.red = color->red;
2182 request.green = color->green;
2183 request.blue = color->blue;
2185 XFreeColors(dpy, cmap, &pixel, 1, (unsigned long) 0);
2186 if (! XAllocColor(dpy, cmap, color)
2187 || (color->pixel != pixel &&
2188 (!RWcell(dpy, cmap, color, &request, &pixel))))
2190 free_cells(dpy, cmap, pixels, npixels, (int)p);
2197 /****************************************************************************/
2199 free_cells(Display *dpy, Colormap cmap, unsigned long pixels[],
2202 * pixels - to be freed
2203 * npixels - original number allocated
2206 /* One of the npixels allocated has already been freed.
2207 * p is the index of the freed pixel.
2208 * First free the pixels preceeding p, and there are p of them;
2209 * then free the pixels following p, there are npixels - p - 1 of them.
2211 XFreeColors(dpy, cmap, pixels, p, (unsigned long) 0);
2212 XFreeColors(dpy, cmap, &(pixels[p+1]), npixels - p - 1, (unsigned long) 0);
2213 free((char *) pixels);
2217 /****************************************************************************/
2219 RWcell(Display *dpy, Colormap cmap, XColor *color, XColor *request,
2220 unsigned long *pixel)
2222 unsigned long n = *pixel;
2224 XFreeColors(dpy, cmap, &(color->pixel), 1, (unsigned long)0);
2225 if (! XAllocColorCells(dpy, cmap, (Bool) 0, (unsigned long *) NULL,
2226 (unsigned) 0, pixel, (unsigned) 1))
2230 XFreeColors(dpy, cmap, pixel, 1, (unsigned long) 0);
2233 color->pixel = *pixel;
2234 color->flags = DoRed | DoGreen | DoBlue;
2235 color->red = request->red;
2236 color->green = request->green;
2237 color->blue = request->blue;
2238 XStoreColors(dpy, cmap, color, 1);
2243 /****************************************************************************/
2245 compare(_Xconst void *e1, _Xconst void *e2)
2247 return ((int)(*(long *)e1 - *(long *)e2));
2251 /****************************************************************************/
2253 readonly_map(Display *dpy, XVisualInfo *vinfo, XStandardColormap *colormap)
2258 last_pixel = (colormap->red_max + 1) * (colormap->green_max + 1) *
2259 (colormap->blue_max + 1) + colormap->base_pixel - 1;
2261 for(i=colormap->base_pixel; i <= last_pixel; i++) {
2263 color.pixel = (unsigned long) i;
2264 color.red = (unsigned short)
2265 (((i/colormap->red_mult) * 65535) / colormap->red_max);
2267 if (vinfo->c_class == StaticColor) {
2268 color.green = (unsigned short)
2269 ((((i/colormap->green_mult) % (colormap->green_max + 1)) *
2270 65535) / colormap->green_max);
2271 color.blue = (unsigned short)
2272 (((i%colormap->green_mult) * 65535) / colormap->blue_max);
2274 else /* vinfo->c_class == GrayScale, old style allocation XXX */
2275 color.green = color.blue = color.red;
2277 XAllocColor(dpy, colormap->colormap, &color);
2278 if (color.pixel != (unsigned long) i)
2285 /* $Xorg: DelCmap.c,v 1.4 2001/02/09 02:03:52 xorgcvs Exp $ */
2289 Copyright 1989, 1998 The Open Group
2291 Permission to use, copy, modify, distribute, and sell this software and its
2292 documentation for any purpose is hereby granted without fee, provided that
2293 the above copyright notice appear in all copies and that both that
2294 copyright notice and this permission notice appear in supporting
2297 The above copyright notice and this permission notice shall be included in
2298 all copies or substantial portions of the Software.
2300 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2301 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2302 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2303 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
2304 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
2305 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2307 Except as contained in this notice, the name of The Open Group shall not be
2308 used in advertising or otherwise to promote the sale, use or other dealings
2309 in this Software without prior written authorization from The Open Group.
2312 /* $XFree86: xc/lib/Xmu/DelCmap.c,v 1.7 2001/12/14 19:55:40 dawes Exp $ */
2315 * Author: Donna Converse, MIT X Consortium
2318 #include <X11/Xlib.h>
2319 #include <X11/Xutil.h>
2320 #include <X11/Xmu/StdCmap.h>
2322 /* To remove any standard colormap property, use XmuDeleteStandardColormap().
2323 * XmuDeleteStandardColormap() will remove the specified property from the
2324 * specified screen, releasing any resources used by the colormap(s) of the
2325 * property if possible.
2329 XmuDeleteStandardColormap(Display *dpy, int screen, Atom property)
2330 /* dpy; - specifies the X server to connect to
2331 * screen - specifies the screen of the display
2332 * property - specifies the standard colormap property
2335 XStandardColormap *stdcmaps, *s;
2338 if (XGetRGBColormaps(dpy, RootWindow(dpy, screen), &stdcmaps, &count,
2341 for (s=stdcmaps; count > 0; count--, s++) {
2342 if ((s->killid == ReleaseByFreeingColormap) &&
2343 (s->colormap != None) &&
2344 (s->colormap != DefaultColormap(dpy, screen)))
2345 XFreeColormap(dpy, s->colormap);
2346 else if (s->killid != None)
2347 XKillClient(dpy, s->killid);
2349 XDeleteProperty(dpy, RootWindow(dpy, screen), property);
2350 XFree((char *) stdcmaps);