4 #include <X11/extensions/XShm.h>
5 #include <X11/keysymdef.h>
6 #include <X11/keysym.h>
7 #include <X11/cursorfont.h>
10 #include <X11/Xmu/StdCmap.h>
14 #include <sys/types.h>
17 #include <java/lang/String.h>
18 #include <org/xwt/Surface.h>
19 #include <org/xwt/Picture.h>
20 #include <org/xwt/Box.h>
21 #include <org/xwt/plat/POSIX.h>
22 #include <org/xwt/plat/POSIX$X11Surface.h>
23 #include <org/xwt/plat/POSIX$X11Picture.h>
24 #include <org/xwt/plat/POSIX$X11DoubleBuffer.h>
25 #include <org/xwt/util/Semaphore.h>
26 #include <org/xwt/Platform.h>
27 #include <java/lang/Long.h>
28 #include <java/util/Hashtable.h>
29 #include <org/xwt/util/Log.h>
31 #include <java/lang/System.h>
32 #include <java/io/PrintStream.h>
34 // static (per-xserver) data
35 static Visual* visual;
36 static Colormap colormap;
37 static XStandardColormap* colormap_info;
38 static XShmSegmentInfo shm_info;
39 static Window selectionWindow;
40 static int shm_supported;
41 static int screen_num;
42 static int colorDepth = 0;
43 static Display* display;
45 #define min(a, b) (a < b ? a : b)
47 // X11DoubleBuffer //////////////////////////////////////////////////////////////////////
49 void org::xwt::plat::POSIX$X11DoubleBuffer::drawPicture(org::xwt::Picture* s,
50 jint dx1, jint dy1, jint dx2, jint dy2, jint sx1, jint sy1, jint sx2, jint sy2) {
52 if (pm == NULL) return;
53 org::xwt::plat::POSIX$X11Picture* source = (org::xwt::plat::POSIX$X11Picture*)s;
55 int scaling = dx2 - dx1 != sx2 - sx1 || dy2 - dy1 != sy2 - sy1;
57 // FIXME: this needs to be moved into the fastpath-only to prevent image wriggling
58 if (dx1 < clipx) { sx1 += ((clipx - dx1) * (sx2 - sx1)) / (dx2 - dx1); dx1 = clipx; }
59 if (dy1 < clipy) { sy1 += ((clipy - dy1) * (sy2 - sy1)) / (dy2 - dy1); dy1 = clipy; }
60 if (dx2 > clipx + clipw) { sx2 -= ((dx2 - clipx - clipw) * (sx2 - sx1)) / (dx2 - dx1); dx2 = clipx + clipw; }
61 if (dy2 > clipy + cliph) { sy2 -= ((dy2 - clipy - cliph) * (sy2 - sy1)) / (dy2 - dy1); dy2 = clipy + cliph; }
62 if (dx1 > clipx + clipw) return;
63 if (dy1 > clipy + cliph) return;
65 if (dx2 - dx1 <= 0 || dy2 - dy1 <= 0) return;
67 // fastpath: if the X11Picture has a pixmap, and no scaling, and all-or-nothing alpha
68 if (!scaling && source->doublebuf != NULL) {
69 if (source->doublebuf->stipple != NULL) {
70 XSetClipMask(display, (*((GC*)clipped_gc)), *((Pixmap*)source->doublebuf->stipple));
71 XSetClipOrigin(display, (*((GC*)clipped_gc)), dx1 - sx1, dy1 - sy1);
73 XSetClipMask(display, (*((GC*)clipped_gc)), None);
75 XCopyArea(display, *((Pixmap*)source->doublebuf->pm), (*((Pixmap*)pm)), (*((GC*)clipped_gc)), sx1, sy1, sx2 - sx1, sy2 - sy1, dx1, dy1);
79 // slowpath: true alpha or scaling
81 // the following optimizations were abandoned because they don't
82 // improve performance in the presence of XSHM extensions, and
83 // therefore aren't worth the code-bloat:
84 // - scaling clipmask bitmaps (and caching them)
85 // - caching pre-scaled XImages
87 // ximage from our destination -- if true_alpha is false, we can use malloc() instead of XGetImage
90 if (force_slowpath && shm_supported) {
92 // if the shared memory area is unsuitable, destroy it
94 if (((XImage*)shm_ximage) != NULL && (dx2 - dx1 != ((XImage*)shm_ximage)->width || dy2 - dy1 != ((XImage*)shm_ximage)->height)) {
95 XShmDetach(display, &shm_info);
96 XDestroyImage(((XImage*)shm_ximage));
99 // FIXME: replace 4 with something sensible
100 if (((XImage*)shm_ximage) != NULL && (dx2 - dx1) * (dy2 - dy1) * 4 < old_shmsize) {
101 shmdt(shm_info.shmaddr);
102 shmctl(shm_info.shmid, IPC_RMID, 0);
103 memset(&shm_info, 0, sizeof(XShmSegmentInfo));
104 shm_info.shmaddr = NULL;
107 // if we need to recreate the shared memory area
108 if (shm_info.shmaddr == NULL) {
109 old_shmsize = xi->bytes_per_line * xi->height;
110 memset(&shm_info, 0, sizeof(XShmSegmentInfo));
111 shm_info.shmid = shmget(IPC_PRIVATE, xi->bytes_per_line * xi->height, IPC_CREAT | 0777 | IPC_EXCL);
112 shm_info.shmaddr = xi->data = (char*)shmat(shm_info.shmid, 0, 0);
113 shm_info.readOnly = False;
115 XSync(display, False);
116 shmctl(shm_info.shmid, IPC_RMID, 0);
117 XShmAttach(display, &shm_info);
118 XSync(display, False);
121 xi = ((XImage*)shm_ximage) = XShmCreateImage(display, visual, colorDepth, ZPixmap, shm_info.shmaddr, &shm_info, dx2 - dx1, dy2 - dy1);
123 } else if (shared_pixmap && shm_supported) {
127 xi = XGetImage(display, (*((Pixmap*)pm)), dx1, dy1, dx2 - dx1, dy2 - dy1, AllPlanes, ZPixmap);
132 // FIXME: optimize pixels that have 0xFF or 0x00 alpha
136 // further assumption: the only time source->data will be null is
137 // if we're drawing from a bordercache -- but those don't get
139 if (source->data == NULL || elements(source->data) == NULL) {
140 printf("AIEEEEE %i %i %i %i\n", dx2 - dx1, dy2 - dy1, sx2 - sx1, sy2 - sy1);
143 int* sourcedata = (int*)elements(source->data);
145 for(int y=dy1; y<dy2; y++) {
147 if (y < clipy || y >= clipy + cliph) continue;
150 if (shared_pixmap && shm_supported) {
151 // FIXME: not sure if bitmap_unit is the right thing
152 bitstart = xi->data + y * xi->bytes_per_line + dx1 * (xi->bits_per_pixel / 8);
154 bitstart = xi->data + (y - dy1) * xi->bytes_per_line;
157 for(int x=dx1; x<dx2; x++, bitstart += xi->bits_per_pixel / 8) {
159 if (x < clipx || x >= clipx + clipw) continue;
161 int source_x = ((x - dx1) * (sx2 - sx1)) / (dx2 - dx1) + sx1;
162 int source_y = ((y - dy1) * (sy2 - sy1)) / (dy2 - dy1) + sy1;
164 // note that we can assume that source->data exists here, since writeable PixelGrids (ie
165 // doublebuffers) never have true_alpha, and are never scaled.
166 int sourcepixel = sourcedata[source_x + source_y * source->getWidth()];
167 int alpha = (sourcepixel & 0xFF000000) >> 24;
168 int source_red = (sourcepixel & 0x00FF0000) >> 16;
169 int source_green = (sourcepixel & 0x0000FF00) >> 8;
170 int source_blue = (sourcepixel & 0x000000FF);
171 int red = 0, blue = 0, green = 0;
175 switch (xi->bits_per_pixel) {
176 case 8: targetpixel = (int)(*bitstart); break;
177 case 16: targetpixel = (int)(*((u_int16_t*)bitstart)); break;
178 case 24: targetpixel = (((int)*bitstart) << 16) | (((int)*(bitstart + 1)) << 8) | (((int)*(bitstart + 2))); break;
179 case 32: targetpixel = *((int*)bitstart); break;
180 default: org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: bpp not a multiple of 8!"));
183 targetpixel -= colormap_info->base_pixel;
185 // if you're on some wierd display that isn't either RGB or BGR, that's your problem, not mine
186 if (colormap_info->red_mult > colormap_info->green_mult && colormap_info->green_mult > colormap_info->blue_mult) {
187 red = targetpixel / colormap_info->red_mult;
188 green = (targetpixel - red * colormap_info->red_mult) / colormap_info->green_mult;
189 blue = (targetpixel - red * colormap_info->red_mult - green * colormap_info->green_mult) / colormap_info->blue_mult;
191 blue = targetpixel / colormap_info->blue_mult;
192 green = (targetpixel - blue * colormap_info->blue_mult) / colormap_info->green_mult;
193 red = (targetpixel - blue * colormap_info->blue_mult - green * colormap_info->green_mult) / colormap_info->red_mult;
197 red = ((source_red * colormap_info->red_max * alpha) + (red * 0xFF * (0xFF - alpha))) / (0xFF * 0xFF);
198 green = ((source_green * colormap_info->green_max * alpha) + (green * 0xFF * (0xFF - alpha))) / (0xFF * 0xFF);
199 blue = ((source_blue * colormap_info->blue_max * alpha) + (blue * 0xFF * (0xFF - alpha))) / (0xFF * 0xFF);
201 int destpixel = red * colormap_info->red_mult + green * colormap_info->green_mult +
202 blue * colormap_info->blue_mult + colormap_info->base_pixel;
204 switch (xi->bits_per_pixel) {
205 case 8: *bitstart = (char)(destpixel & 0xFF); break;
206 case 16: *((u_int16_t*)bitstart) = (u_int16_t)destpixel; break;
207 case 24: break; // FIXME, unimplemented
208 case 32: *((int*)bitstart) = destpixel; break;
209 default: org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: bpp not a multiple of 8!"));
215 if (force_slowpath && shm_supported) {
216 // watch for concurrency issues if we're going to keep the shm region around
217 XShmPutImage(display, (*((Pixmap*)pm)), (*((GC*)gc)), xi, 0, 0, dx1, dy1, dx2 - dx1, dy2 - dy1, False);
219 } if (shared_pixmap && shm_supported) {
220 // do nothing, it's all taken care of
223 XPutImage(display, (*((Pixmap*)pm)), (*((GC*)gc)), xi, 0, 0, dx1, dy1, dx2 - dx1, dy2 - dy1);
228 void org::xwt::plat::POSIX$X11DoubleBuffer::natInit() {
230 if (width == 0 || height == 0) return;
232 pm = (gnu::gcj::RawData*)malloc(sizeof(Pixmap));
234 if (shared_pixmap && shm_supported) {
236 // FIXME: check if server pixmaps are XYPixmaps
237 printf("CREATING SHARED (*((Pixmap*)pm)) %i %i\n", width, height);
239 XShmSegmentInfo *sinfo = (XShmSegmentInfo*)malloc(sizeof(XShmSegmentInfo));
240 ((XImage*)mxi) = XShmCreateImage(display, visual, colorDepth, ZPixmap, NULL, sinfo, width, height);
242 memset(sinfo, 0, sizeof(XShmSegmentInfo));
244 sinfo->shmid = shmget(IPC_PRIVATE, ((XImage*)mxi)->bytes_per_line * height, IPC_CREAT | 0777 | IPC_EXCL);
245 ((XImage*)mxi)->data = sinfo->shmaddr = (char*)shmat(sinfo->shmid, 0, 0);
246 sinfo->readOnly = False;
247 XShmAttach(display, sinfo);
249 XSync(display, False);
250 shmctl(sinfo->shmid, IPC_RMID, 0);
252 (*((Pixmap*)pm)) = XShmCreatePixmap(display, RootWindow(display, 0), sinfo->shmaddr, sinfo, width, height, colorDepth);
253 XSync(display, False);
256 (*((Pixmap*)pm)) = XCreatePixmap(display, RootWindow(display, 0), width, height, colorDepth);
259 gc = (gnu::gcj::RawData*)malloc(sizeof(GC));
260 clipped_gc = (gnu::gcj::RawData*)malloc(sizeof(GC));
261 (*((GC*)gc)) = XCreateGC(display, (*((Pixmap*)pm)), 0, 0);
262 (*((GC*)clipped_gc)) = XCreateGC(display, (*((Pixmap*)pm)), 0, 0);
265 vm.graphics_exposures = 0;
266 XChangeGC(display, (*((GC*)gc)), GCGraphicsExposures, &vm);
267 XChangeGC(display, (*((GC*)clipped_gc)), GCGraphicsExposures, &vm);
270 void org::xwt::plat::POSIX$X11DoubleBuffer::createStipple(org::xwt::plat::POSIX$X11Picture* xpi) {
272 stipple = (gnu::gcj::RawData*)malloc(sizeof(Pixmap));
273 (*((Pixmap*)stipple)) = XCreatePixmap(display, RootWindow(display, 0), width, height, 1);
276 xi.data = (char*)malloc((width + 1) * height);
283 xi.byte_order = LSBFirst;
285 xi.bytes_per_line = (width / 8) + 1;
286 xi.bits_per_pixel = 1;
288 jint* d = (jint*)elements(xpi->data);
289 memset(xi.data, 0xFF, (width + 1) * height);
290 for(int x=0; x<width; x++)
291 for (int y=0; y<height; y++)
292 xi.data[y * xi.bytes_per_line + (x/8)] &= ~(((d[x + y * width] & 0xFF000000) != 0 ? 0 : 1) << (x % 8));
294 GC stipple_gc = XCreateGC(display, (*((Pixmap*)stipple)), 0, 0);
297 vm.graphics_exposures = 0;
298 XChangeGC(display, (*((GC*)stipple_gc)), GCGraphicsExposures, &vm);
300 XPutImage(display, (*((Pixmap*)stipple)), stipple_gc, &xi, 0, 0, 0, 0, width, height);
303 void org::xwt::plat::POSIX$X11Surface::blit(org::xwt::DoubleBuffer* db, jint sx, jint sy, jint dx, jint dy, jint dx2, jint dy2) {
304 org::xwt::plat::POSIX$X11DoubleBuffer *xdb = (org::xwt::plat::POSIX$X11DoubleBuffer*)db;
305 XCopyArea(display, *((Pixmap*)xdb->pm), *((Window*)window), *((GC*)gc), sx, sy, dx2 - dx, dy2 - dy, dx, dy);
309 void org::xwt::plat::POSIX$X11DoubleBuffer::fillRect (jint x, jint y, jint x2, jint y2, jint argb) {
314 if (x < clipx) { w -= (clipx - x); x = clipx; }
315 if (y < clipy) { h -= (clipy - y); y = clipy; }
316 if (x + w > clipx + clipw) w = (clipx + clipw - x);
317 if (y + h > clipy + cliph) h = (cliph + clipy - y);
319 XSetForeground(display, (*((GC*)gc)),
320 ((((argb & 0x00FF0000) >> 16) * colormap_info->red_max) / 0xFF) * colormap_info->red_mult +
321 ((((argb & 0x0000FF00) >> 8) * colormap_info->green_max) / 0xFF) * colormap_info->green_mult +
322 ((((argb & 0x000000FF)) * colormap_info->blue_max) / 0xFF) * colormap_info->blue_mult +
323 colormap_info->base_pixel
326 XFillRectangle(display, (*((Pixmap*)pm)), (*((GC*)gc)), x, y, w, h);
330 void org::xwt::plat::POSIX$X11DoubleBuffer::drawString(::java::lang::String* font, ::java::lang::String* text, jint x, jint y, jint argb) {
333 rect.x = clipx, rect.y = clipy; rect.width = clipw; rect.height = cliph;
334 XSetClipMask(display, (*((GC*)clipped_gc)), None);
335 XSetClipRectangles(display, (*((GC*)clipped_gc)), 0, 0, &rect, 1, YSorted);
336 XSetForeground(display, (*((GC*)clipped_gc)),
337 ((((argb & 0x00FF0000) >> 16) * colormap_info->red_max) / 0xFF) * colormap_info->red_mult +
338 ((((argb & 0x0000FF00) >> 8) * colormap_info->green_max) / 0xFF) * colormap_info->green_mult +
339 ((((argb & 0x000000FF)) * colormap_info->blue_max) / 0xFF) * colormap_info->blue_mult +
340 colormap_info->base_pixel
344 char buf[text->length() + 1];
345 JvGetStringUTFRegion(text, 0, text->length(), buf);
346 buf[text->length()] = '\0';
348 // Build the XTextItem structure
350 textitem.chars = buf;
351 textitem.nchars = text->length();
353 textitem.font = ((XFontStruct*)org::xwt::plat::POSIX::fontToXFont(font))->fid;
356 XDrawText(display, (*((Pixmap*)pm)), (*((GC*)clipped_gc)), x, y, &textitem, 1);
360 // X11Surface //////////////////////////////////////////////////////////////////////
362 void org::xwt::plat::POSIX$X11Surface::setTitleBarText(java::lang::String* s) {
363 int len = min(JvGetStringUTFLength(s), 1024);
365 JvGetStringUTFRegion(s, 0, len, buf);
369 tp.value = (unsigned char*)buf;
371 tp.encoding = XA_STRING;
373 XSetTextProperty(display, (*((Window*)window)), &tp, XA_WM_NAME);
374 XSetTextProperty(display, (*((Window*)window)), &tp, XA_WM_ICON_NAME);
377 void org::xwt::plat::POSIX$X11Surface::setLimits(jint minw, jint minh, jint maxw, jint maxh) {
379 hints.min_width = minw;
380 hints.min_height = minh;
381 hints.max_width = maxw;
382 hints.max_height = maxh;
383 hints.flags = PMinSize | PMaxSize;
384 XSetWMNormalHints(display, (*((Window*)window)), &hints);
387 void org::xwt::plat::POSIX$X11Surface::setSize (jint width, jint height) {
388 if (width <= 0 || height <= 0) return;
389 XResizeWindow(display, (*((Window*)window)), width, height);
393 void org::xwt::plat::POSIX$X11Surface::_dispose() { XDestroyWindow(display, (*((Window*)window))); }
394 void org::xwt::plat::POSIX$X11Surface::setLocation (jint x, jint y) { XMoveWindow(display, (*((Window*)window)), x, y); }
395 void org::xwt::plat::POSIX$X11Surface::toFront() { XRaiseWindow(display, (*((Window*)window))); }
396 void org::xwt::plat::POSIX$X11Surface::toBack() { XLowerWindow(display, (*((Window*)window))); }
398 void org::xwt::plat::POSIX$X11Surface::_setMinimized(jboolean b) {
399 if (b) XIconifyWindow(display, (*((Window*)window)), screen_num);
400 else XMapRaised(display, (*((Window*)window)));
403 void org::xwt::plat::POSIX$X11Surface::natInit() {
404 XSetWindowAttributes xswa;
405 window = (gnu::gcj::RawData*)malloc(sizeof(Window));
406 xswa.bit_gravity = NorthWestGravity;
407 xswa.colormap = colormap;
408 xswa.event_mask = ExposureMask | ButtonPressMask | StructureNotifyMask |
409 KeyPressMask | KeyReleaseMask | ButtonPressMask |
410 ButtonReleaseMask | EnterWindowMask | LeaveWindowMask |
411 PointerMotionMask | ButtonMotionMask | ConfigureNotify | FocusChangeMask;
412 *((Window*)window) = XCreateWindow(display, DefaultRootWindow(display), 10, 10, 500, 300, 0,
413 colorDepth, InputOutput, CopyFromParent,
414 CWColormap | CWBitGravity | CWEventMask, &xswa);
417 // FIXME: figure out why this works and make it elegant
418 int dat[5] = { 0x2, 0xbffff804, 0x0, 0x817f560, 0x8110694 };
419 XChangeProperty(display, (*((Window*)window)),
420 XInternAtom(display, "_MOTIF_WM_HINTS", False),
421 XInternAtom(display, "_MOTIF_WM_HINTS", False),
429 tp.value = (unsigned char*)"XWT";
431 tp.encoding = XA_STRING;
433 XSetTextProperty(display, (*((Window*)window)), &tp, XA_WM_CLASS);
435 Atom proto = XInternAtom(display, "WM_DELETE_WINDOW", False);
436 XSetWMProtocols(display, (*((Window*)window)), &proto, 1);
438 XSelectInput(display, (*((Window*)window)), StructureNotifyMask);
439 org::xwt::plat::POSIX::windowToSurfaceMap->put(new java::lang::Long(*((Window*)window)), this);
442 XMapRaised(display, (*((Window*)window)));
445 waitForCreation->block();
446 XSelectInput(display, (*((Window*)window)), xswa.event_mask);
449 gc = (gnu::gcj::RawData*)malloc(sizeof(GC));
450 *((GC*)gc) = XCreateGC(display, (*((Window*)window)), 0, 0);
453 vm.graphics_exposures = 0;
454 XChangeGC(display, *((GC*)gc), GCGraphicsExposures, &vm);
458 void org::xwt::plat::POSIX$X11Surface::dispatchEvent(gnu::gcj::RawData* ev) {
460 XEvent* e = (XEvent*)ev;
461 if (e->type == Expose) {
462 XExposeEvent *expose = (XExposeEvent*)(e);
463 Dirty(expose->x, expose->y, expose->width, expose->height);
465 } else if (e->type == ClientMessage) { if (((XClientMessageEvent*)(e))->data.l[0] == XInternAtom(display, "WM_DELETE_WINDOW", False)) Close();
466 } else if (e->type == MapNotify) { Minimized(0); waitForCreation->release();
467 } else if (e->type == UnmapNotify) { Minimized(1);
468 } else if (e->type == FocusIn) { Focused(1);
469 } else if (e->type == FocusOut) { Focused(0);
471 } else if (e->type == SelectionNotify) {
472 XSelectionEvent* xsn = (XSelectionEvent*)(e);
473 if (xsn->property == None) org::xwt::plat::POSIX::clipboard = JvNewStringLatin1("", 0);
477 unsigned long numitems;
479 unsigned long bytes_after;
480 XGetWindowProperty(display, xsn->requestor, xsn->property, 0, 4096,
481 True, AnyPropertyType, &returntype, &returnformat,
482 &numitems, &bytes_after, &ret);
483 org::xwt::plat::POSIX::clipboard =
484 (returntype == None ? JvNewStringLatin1("", 0) : JvNewStringLatin1((char*)ret, strlen((char*)ret)));
486 org::xwt::plat::POSIX::waiting_for_selection_event->release();
488 } else if (e->type == SelectionRequest) {
489 XSelectionRequestEvent* xsr = (XSelectionRequestEvent*)(e);
491 xsn.type = SelectionNotify;
492 xsn.serial = xsr->serial;
493 xsn.send_event = True;
494 xsn.display = display;
495 xsn.requestor = xsr->requestor;
496 xsn.selection = xsr->selection;
497 xsn.target = xsr->target;
498 xsn.property = xsr->property;
499 xsn.time = xsr->time;
501 int len = min(1024, JvGetStringUTFLength(org::xwt::plat::POSIX::clipboard));
503 JvGetStringUTFRegion(org::xwt::plat::POSIX::clipboard, 0, len, buf);
506 XChangeProperty(display, xsr->requestor, xsr->property, xsr->target, 8, PropModeReplace, (unsigned char*)buf, len + 1);
507 XSendEvent(display, xsr->requestor, True, 0, (XEvent*)(&xsn));
509 } else if (e->type == KeyPress || e->type == KeyRelease) {
510 XKeyEvent *xbe = (XKeyEvent*)(e);
512 // drop faked KeyRelease events generated by the X server's autorepeat
513 if (e->type == KeyRelease) {
515 XQueryKeymap(display, depressed);
516 if ((depressed[(xbe->keycode & 0xff) / 8] & (0x1 << (xbe->keycode % 8))) >> (xbe->keycode % 8)) return;
522 unsigned int savestate = xbe->state;
523 xbe->state = xbe->state & ShiftMask; // ignore everything except shiftmask
524 XLookupString(xbe, s, 20, NULL, NULL);
525 xbe->state = savestate;
527 if (s != NULL && s[0] != '\0' && s[1] == '\0' && s[0] >= 0x20 && s[0] <= 0x7E) {
531 KeySym ks = XKeycodeToKeysym(display, xbe->keycode, 0);
533 case XK_BackSpace: s = "back_space"; break;
534 case XK_Tab: s = "tab"; break;
535 case XK_Linefeed: s = "enter"; break;
536 case XK_Return: s = "enter"; break;
537 case XK_Scroll_Lock: s = "scroll_lock"; break;
538 case XK_Escape: s = "escape"; break;
539 case XK_Insert: s = "insert"; break;
540 case XK_Delete: s = "delete"; break;
541 case XK_Home: s = "home"; break;
542 case XK_Left: s = "left"; break;
543 case XK_Up: s = "up"; break;
544 case XK_Right: s = "right"; break;
545 case XK_Down: s = "down"; break;
546 case XK_Page_Up: s = "page_up"; break;
547 case XK_Page_Down: s = "page_down"; break;
548 case XK_End: s = "end"; break;
549 case XK_Num_Lock: s = "num_lock"; break;
550 case XK_KP_Tab: s = "tab"; break;
551 case XK_KP_Enter: s = "enter"; break;
552 case XK_KP_F1: s = "f1"; break;
553 case XK_KP_F2: s = "f2"; break;
554 case XK_KP_F3: s = "f3"; break;
555 case XK_KP_F4: s = "f4"; break;
556 case XK_KP_Home: s = "home"; break;
557 case XK_KP_Left: s = "left"; break;
558 case XK_KP_Up: s = "up"; break;
559 case XK_KP_Right: s = "right"; break;
560 case XK_KP_Down: s = "down"; break;
561 case XK_KP_Page_Up: s = "page_up"; break;
562 case XK_KP_Page_Down: s = "page_down"; break;
563 case XK_KP_End: s = "end"; break;
564 case XK_KP_Insert: s = "insert"; break;
565 case XK_KP_Delete: s = "delete"; break;
566 case XK_F1: s = "f1"; break;
567 case XK_F2: s = "f2"; break;
568 case XK_F3: s = "f3"; break;
569 case XK_F4: s = "f4"; break;
570 case XK_F5: s = "f5"; break;
571 case XK_F6: s = "f6"; break;
572 case XK_F7: s = "f7"; break;
573 case XK_F8: s = "f8"; break;
574 case XK_F9: s = "f9"; break;
575 case XK_F10: s = "f10"; break;
576 case XK_F11: s = "f11"; break;
577 case XK_F12: s = "f12"; break;
578 case XK_Shift_L: s = "shift"; break;
579 case XK_Shift_R: s = "shift"; break;
580 case XK_Control_L: s = "control"; break;
581 case XK_Control_R: s = "control"; break;
582 case XK_Caps_Lock: s = "caps_lock"; break;
583 case XK_Meta_L: s = "alt"; break;
584 case XK_Meta_R: s = "alt"; break;
585 case XK_Alt_L: s = "alt"; break;
586 case XK_Alt_R: s = "alt"; break;
591 if (e->type == KeyPress) KeyPressed(JvNewStringLatin1(s));
592 if (e->type == KeyRelease) KeyReleased(JvNewStringLatin1(s));
594 } else if (e->type == ButtonPress) {
595 XButtonEvent* xbe = (XButtonEvent*)(e);
596 if (xbe->button == 2) xbe->button = 3;
597 else if (xbe->button == 3) xbe->button = 2;
600 } else if (e->type == ButtonRelease) {
601 XButtonEvent* xbe = (XButtonEvent*)(e);
602 if (xbe->button == 2) xbe->button = 3;
603 else if (xbe->button == 3) xbe->button = 2;
604 Release(xbe->button);
606 } else if (e->type == MotionNotify) {
607 XMotionEvent* xme = (XMotionEvent*)(e);
608 Move(xme->x, xme->y);
610 } else if (e->type == EnterNotify || e->type == LeaveNotify) {
611 XCrossingEvent* xce = (XCrossingEvent*)(e);
612 Move(xce->x, xce->y);
614 } else if (e->type == ConfigureNotify) {
617 XConfigureEvent* xce = (XConfigureEvent*)(e);
618 XTranslateCoordinates(display, (*((Window*)window)), DefaultRootWindow(display), 0, 0, &x_out, &y_out, &child);
619 if (xce->width != width || xce->height != height) SizeChange(xce->width, xce->height);
620 if (x_out != root->abs(0) || y_out != root->abs(1)) PosChange(x_out, y_out);
625 static jstring crosshair, east, hand, move, north, northeast, northwest,
626 south, southeast, southwest, text, west, wait_string;
627 static Cursor crosshair_cursor, east_cursor, hand_cursor, move_cursor, north_cursor,
628 northeast_cursor, northwest_cursor, south_cursor, southeast_cursor,
629 southwest_cursor, text_cursor, west_cursor, wait_cursor, default_cursor;
631 void org::xwt::plat::POSIX$X11Surface::syncCursor() {
634 if (cursor->equals(crosshair)) curs = crosshair_cursor;
635 else if (cursor->equals(east)) curs = east_cursor;
636 else if (cursor->equals(hand)) curs = hand_cursor;
637 else if (cursor->equals(move)) curs = move_cursor;
638 else if (cursor->equals(north)) curs = north_cursor;
639 else if (cursor->equals(northeast)) curs = northeast_cursor;
640 else if (cursor->equals(northwest)) curs = northwest_cursor;
641 else if (cursor->equals(south)) curs = south_cursor;
642 else if (cursor->equals(southeast)) curs = southeast_cursor;
643 else if (cursor->equals(southwest)) curs = southwest_cursor;
644 else if (cursor->equals(text)) curs = text_cursor;
645 else if (cursor->equals(west)) curs = west_cursor;
646 else if (cursor->equals(wait_string)) curs = wait_cursor;
647 else curs = default_cursor;
649 XDefineCursor(display, (*((Window*)window)), curs);
654 // POSIX ///////////////////////////////////////////////////////////////////
656 jint org::xwt::plat::POSIX::_getScreenWidth() { return WidthOfScreen(DefaultScreenOfDisplay(display)); }
657 jint org::xwt::plat::POSIX::_getScreenHeight() { return HeightOfScreen(DefaultScreenOfDisplay(display)); }
659 void org::xwt::plat::POSIX::eventThread() {
662 XNextEvent(display, &e);
663 org::xwt::plat::POSIX$X11Surface* surface =
664 (org::xwt::plat::POSIX$X11Surface*)windowToSurfaceMap->get(new java::lang::Long(((XAnyEvent*)&e)->window));
665 if (surface != NULL) surface->dispatchEvent((gnu::gcj::RawData*)&e);
669 jstring org::xwt::plat::POSIX::_getClipBoard() {
670 XConvertSelection(display, XA_PRIMARY, XA_STRING, XInternAtom(display, "VT_SELECTION", False), selectionWindow, CurrentTime);
672 org::xwt::plat::POSIX::waiting_for_selection_event->block();
676 void org::xwt::plat::POSIX::_setClipBoard(jstring s) {
678 int len = JvGetStringUTFLength(clipboard);
680 JvGetStringUTFRegion(clipboard, 0, len, buf);
682 XSetSelectionOwner(display, XInternAtom(display, "PRIMARY", 0), selectionWindow, CurrentTime);
685 void org::xwt::plat::POSIX::natInit() {
688 org::xwt::Platform::criticalAbort(JvNewStringLatin1("Your X11 libraries do not support multithreaded programs"));
690 display = XOpenDisplay(NULL);
691 screen_num = XDefaultScreen(display);
692 colorDepth = (jint)(DefaultDepth(((Display*)display), 0));
693 shm_info.shmaddr = NULL;
694 shm_supported = (XShmQueryExtension(display) == True);
697 crosshair = JvNewStringLatin1("crosshair");
698 east = JvNewStringLatin1("east");
699 hand = JvNewStringLatin1("hand");
700 move = JvNewStringLatin1("move");
701 north = JvNewStringLatin1("north");
702 northeast = JvNewStringLatin1("northeast");
703 northwest = JvNewStringLatin1("northwest");
704 south = JvNewStringLatin1("south");
705 southeast = JvNewStringLatin1("southeast");
706 southwest = JvNewStringLatin1("southwest");
707 text = JvNewStringLatin1("text");
708 west = JvNewStringLatin1("west");
709 wait_string = JvNewStringLatin1("wait");
710 crosshair_cursor = XCreateFontCursor(display, XC_tcross);
711 east_cursor = XCreateFontCursor(display, XC_right_side);
712 hand_cursor = XCreateFontCursor(display, XC_hand2);
713 move_cursor = XCreateFontCursor(display, XC_fleur);
714 north_cursor = XCreateFontCursor(display, XC_top_side);
715 northeast_cursor = XCreateFontCursor(display, XC_top_right_corner);
716 northwest_cursor = XCreateFontCursor(display, XC_left_side);
717 south_cursor = XCreateFontCursor(display, XC_bottom_side);
718 southeast_cursor = XCreateFontCursor(display, XC_bottom_right_corner);
719 southwest_cursor = XCreateFontCursor(display, XC_bottom_left_corner);
720 text_cursor = XCreateFontCursor(display, XC_xterm);
721 west_cursor = XCreateFontCursor(display, XC_right_side);
722 wait_cursor = XCreateFontCursor(display, XC_watch);
723 default_cursor = XCreateFontCursor(display, XC_left_ptr);
725 selectionWindow = XCreateWindow(display, DefaultRootWindow(display), 0, 0, 1, 1, 0, colorDepth, InputOutput, CopyFromParent, 0, NULL);
726 visual = DefaultVisual(display, screen_num);
728 sprintf(buf, "X11 SHM: %s", shm_supported ? "enabled" : "disabled");
729 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
730 sprintf(buf, "X11 Visual: %x %x %x bits: %i visualid: %i depth: %i",
731 visual->red_mask, visual->green_mask, visual->blue_mask, visual->bits_per_rgb, visual->visualid, colorDepth);
732 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
734 if(XmuLookupStandardColormap(display, screen_num, visual->visualid, colorDepth, XA_RGB_BEST_MAP, False, True) == 0)
735 org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: XmuLookupStandardColormap failed"));
737 XStandardColormap* best_map_info = NULL;
739 if (XGetRGBColormaps(display, RootWindow(display, screen_num), &best_map_info, &count, XA_RGB_BEST_MAP) == 0)
740 org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: couldn't allocate a standard colormap"));
741 if (!best_map_info->colormap)
742 org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: XmuLookupStandardColomap succeded, but no colormap was found on the root window"));
743 if (best_map_info->red_max == 0)
744 org::xwt::Platform::criticalAbort(JvNewStringLatin1("ERROR: standard colormap exists, but was improperly allocated"));
745 colormap = best_map_info->colormap;
746 colormap_info = best_map_info;
748 sprintf(buf, " red_max / red_mult: %x %x", colormap_info->red_max, colormap_info->red_mult);
749 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
750 sprintf(buf, " green_max / green_mult: %x %x", colormap_info->green_max, colormap_info->green_mult);
751 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
752 sprintf(buf, " blue_max / blue_mult: %x %x", colormap_info->blue_max, colormap_info->blue_mult);
753 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
754 sprintf(buf, " base_pixel: %x", colormap_info->base_pixel);
755 org::xwt::util::Log::log(this->getClass(), JvNewStringLatin1(buf));
758 JArray<java::lang::String*>* org::xwt::plat::POSIX::listNativeFonts() {
760 char** xfonts = XListFonts(display, "-*-*-*-*-*-*-*-*-*-*-*-*-*-*", 0xFFFFFFFF, &numfonts);
761 JArray<java::lang::String*>* fonts = (JArray<java::lang::String*>*)JvNewObjectArray(numfonts, &(::java::lang::String::class$), NULL);
762 java::lang::String** jfonts = (java::lang::String**)(elements(fonts));
763 for(int i=0; i<numfonts; i++)
764 jfonts[i] = JvNewStringLatin1(xfonts[i], strlen(xfonts[i]));
768 gnu::gcj::RawData* org::xwt::plat::POSIX::fontStringToStruct(jstring s) {
769 int len = min(1024, JvGetStringUTFLength(s));
771 JvGetStringUTFRegion(s, 0, len, buf);
773 return (gnu::gcj::RawData*)XLoadQueryFont(display, buf);
776 jint org::xwt::plat::POSIX::_getMaxAscent(::java::lang::String* font) { return ((XFontStruct*)fontToXFont(font))->max_bounds.ascent; }
777 jint org::xwt::plat::POSIX::_getMaxDescent(::java::lang::String* font) { return ((XFontStruct*)fontToXFont(font))->max_bounds.descent; }
778 jint org::xwt::plat::POSIX::_stringWidth(::java::lang::String* font, ::java::lang::String* text) {
779 if (text == NULL) return 0;
780 int len = JvGetStringUTFLength(text);
782 JvGetStringUTFRegion(text, 0, len, buf);
784 return XTextWidth((XFontStruct*)fontToXFont(font), buf, len);
788 //////////////////////////////////////////////////////////////////////////////
790 /* $Xorg: LookupCmap.c,v 1.4 2001/02/09 02:03:53 xorgcvs Exp $ */
794 Copyright 1989, 1998 The Open Group
796 Permission to use, copy, modify, distribute, and sell this software and its
797 documentation for any purpose is hereby granted without fee, provided that
798 the above copyright notice appear in all copies and that both that
799 copyright notice and this permission notice appear in supporting
802 The above copyright notice and this permission notice shall be included in
803 all copies or substantial portions of the Software.
805 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
806 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
807 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
808 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
809 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
810 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
812 Except as contained in this notice, the name of The Open Group shall not be
813 used in advertising or otherwise to promote the sale, use or other dealings
814 in this Software without prior written authorization from The Open Group.
817 /* $XFree86: xc/lib/Xmu/LookupCmap.c,v 1.8 2001/12/14 19:55:47 dawes Exp $ */
820 * Author: Donna Converse, MIT X Consortium
824 #include <X11/Xlib.h>
825 #include <X11/Xatom.h>
826 #include <X11/Xutil.h>
827 #include <X11/Xmu/StdCmap.h>
833 static Status lookup(Display*, int, VisualID, Atom, XStandardColormap*, Bool);
836 * To create a standard colormap if one does not currently exist, or
837 * replace the currently existing standard colormap, use
838 * XmuLookupStandardColormap().
840 * Given a screen, a visual, and a property, XmuLookupStandardColormap()
841 * will determine the best allocation for the property under the specified
842 * visual, and determine the whether to create a new colormap or to use
843 * the default colormap of the screen. It will call XmuStandardColormap()
844 * to create the standard colormap.
846 * If replace is true, any previous definition of the property will be
847 * replaced. If retain is true, the property and the colormap will be
848 * made permanent for the duration of the server session. However,
849 * pre-existing property definitions which are not replaced cannot be made
850 * permanent by a call to XmuLookupStandardColormap(); a request to retain
851 * resources pertains to newly created resources.
853 * Returns 0 on failure, non-zero on success. A request to create a
854 * standard colormap upon a visual which cannot support such a map is
855 * considered a failure. An example of this would be requesting any
856 * standard colormap property on a monochrome visual, or, requesting an
857 * RGB_BEST_MAP on a display whose colormap size is 16.
861 XmuLookupStandardColormap(Display *dpy, int screen, VisualID visualid,
862 unsigned int depth, Atom property,
863 Bool replace, Bool retain)
865 * dpy - specifies X server connection
866 * screen - specifies screen of display
867 * visualid - specifies the visual type
868 * depth - specifies the visual type
869 * property - a standard colormap property
870 * replace - specifies whether to replace
871 * retain - specifies whether to retain
874 Display *odpy; /* original display connection */
875 XStandardColormap *colormap;
876 XVisualInfo vinfo_template, *vinfo; /* visual */
878 unsigned long r_max, g_max, b_max; /* allocation */
880 Colormap cmap; /* colormap ID */
884 /* Match the requested visual */
886 vinfo_template.visualid = visualid;
887 vinfo_template.screen = screen;
888 vinfo_template.depth = depth;
889 vinfo_mask = VisualIDMask | VisualScreenMask | VisualDepthMask;
890 if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &count)) ==
894 /* Monochrome visuals have no standard maps */
896 if (vinfo->colormap_size <= 2) {
897 XFree((char *) vinfo);
901 /* If the requested property already exists on this screen, and,
902 * if the replace flag has not been set to true, return success.
903 * lookup() will remove a pre-existing map if replace is true.
906 if (lookup(dpy, screen, visualid, property, (XStandardColormap *) NULL,
907 replace) && !replace) {
908 XFree((char *) vinfo);
912 /* Determine the best allocation for this property under the requested
913 * visualid and depth, and determine whether or not to use the default
914 * colormap of the screen.
917 if (!XmuGetColormapAllocation(vinfo, property, &r_max, &g_max, &b_max)) {
918 XFree((char *) vinfo);
922 cmap = (property == XA_RGB_DEFAULT_MAP &&
923 visualid == XVisualIDFromVisual(DefaultVisual(dpy, screen)))
924 ? DefaultColormap(dpy, screen) : None;
926 /* If retaining resources, open a new connection to the same server */
930 if ((dpy = XOpenDisplay(XDisplayString(odpy))) == NULL) {
931 XFree((char *) vinfo);
936 /* Create the standard colormap */
938 colormap = XmuStandardColormap(dpy, screen, visualid, depth, property,
939 cmap, r_max, g_max, b_max);
941 /* Set the standard colormap property */
946 if (lookup(dpy, screen, visualid, property, colormap, replace) &&
948 /* Someone has defined the property since we last looked.
949 * Since we will not replace it, release our own resources.
950 * If this is the default map, our allocations will be freed
951 * when this connection closes.
953 if (colormap->killid == ReleaseByFreeingColormap)
954 XFreeColormap(dpy, colormap->colormap);
957 XSetCloseDownMode(dpy, RetainPermanent);
960 XFree((char *) colormap);
966 XFree((char *) vinfo);
970 /***************************************************************************/
972 /* Lookup a standard colormap property. If the property is RGB_DEFAULT_MAP,
973 * the visualid is used to determine whether the indicated standard colormap
974 * exists. If the map exists and replace is true, delete the resources used
975 * by the map and remove the property. Return true if the map exists,
976 * or did exist and was deleted; return false if the map was not found.
978 * Note that this is not the way that a Status return is normally used.
980 * If new is not NULL, new points to an XStandardColormap structure which
981 * describes a standard colormap of the specified property. It will be made
982 * a standard colormap of the screen if none already exists, or if replace
987 lookup(Display *dpy, int screen, VisualID visualid, Atom property,
988 XStandardColormap *cnew, Bool replace)
990 * dpy - specifies display connection
991 * screen - specifies screen number
992 * visualid - specifies visualid for std map
993 * property - specifies colormap property name
994 * cnew - specifies a standard colormap
995 * replace - specifies whether to replace
1000 XStandardColormap *stdcmaps, *s;
1001 Window win = RootWindow(dpy, screen);
1003 /* The property does not already exist */
1005 if (! XGetRGBColormaps(dpy, win, &stdcmaps, &count, property)) {
1007 XSetRGBColormaps(dpy, win, cnew, 1, property);
1011 /* The property exists and is not describing the RGB_DEFAULT_MAP */
1013 if (property != XA_RGB_DEFAULT_MAP) {
1015 XmuDeleteStandardColormap(dpy, screen, property);
1017 XSetRGBColormaps(dpy, win, cnew, 1, property);
1019 XFree((char *)stdcmaps);
1023 /* The property exists and is RGB_DEFAULT_MAP */
1025 for (i=0, s=stdcmaps; (i < count) && (s->visualid != visualid); i++, s++)
1028 /* No RGB_DEFAULT_MAP property matches the given visualid */
1032 XStandardColormap *m, *maps;
1034 s = (XStandardColormap *) malloc((unsigned) ((count+1) * sizeof
1035 (XStandardColormap)));
1037 for (i = 0, m = s, maps = stdcmaps; i < count; i++, m++, maps++) {
1038 m->colormap = maps->colormap;
1039 m->red_max = maps->red_max;
1040 m->red_mult = maps->red_mult;
1041 m->green_max = maps->green_max;
1042 m->green_mult = maps->green_mult;
1043 m->blue_max = maps->blue_max;
1044 m->blue_mult = maps->blue_mult;
1045 m->base_pixel = maps->base_pixel;
1046 m->visualid = maps->visualid;
1047 m->killid = maps->killid;
1049 m->colormap = cnew->colormap;
1050 m->red_max = cnew->red_max;
1051 m->red_mult = cnew->red_mult;
1052 m->green_max = cnew->green_max;
1053 m->green_mult = cnew->green_mult;
1054 m->blue_max = cnew->blue_max;
1055 m->blue_mult = cnew->blue_mult;
1056 m->base_pixel = cnew->base_pixel;
1057 m->visualid = cnew->visualid;
1058 m->killid = cnew->killid;
1060 XSetRGBColormaps(dpy, win, s, ++count, property);
1063 XFree((char *) stdcmaps);
1067 /* Found an RGB_DEFAULT_MAP property with a matching visualid */
1070 /* Free old resources first - we may need them, particularly in
1071 * the default colormap of the screen. However, because of this,
1072 * it is possible that we will destroy the old resource and fail
1073 * to create a new one if XmuStandardColormap() fails.
1077 XmuDeleteStandardColormap(dpy, screen, property);
1079 XSetRGBColormaps(dpy, win, cnew, 1, property);
1082 XStandardColormap *map;
1084 /* s still points to the matching standard colormap */
1086 if (s->killid == ReleaseByFreeingColormap) {
1087 if ((s->colormap != None) &&
1088 (s->colormap != DefaultColormap(dpy, screen)))
1089 XFreeColormap(dpy, s->colormap);
1091 else if (s->killid != None)
1092 XKillClient(dpy, s->killid);
1094 map = (cnew) ? cnew : stdcmaps + --count;
1096 s->colormap = map->colormap;
1097 s->red_max = map->red_max;
1098 s->red_mult = map->red_mult;
1099 s->green_max = map->green_max;
1100 s->green_mult = map->green_mult;
1101 s->blue_max = map->blue_max;
1102 s->blue_mult = map->blue_mult;
1103 s->visualid = map->visualid;
1104 s->killid = map->killid;
1106 XSetRGBColormaps(dpy, win, stdcmaps, count, property);
1109 XFree((char *) stdcmaps);
1113 /* $Xorg: CmapAlloc.c,v 1.4 2001/02/09 02:03:51 xorgcvs Exp $ */
1117 Copyright 1989, 1994, 1998 The Open Group
1119 Permission to use, copy, modify, distribute, and sell this software and its
1120 documentation for any purpose is hereby granted without fee, provided that
1121 the above copyright notice appear in all copies and that both that
1122 copyright notice and this permission notice appear in supporting
1125 The above copyright notice and this permission notice shall be included in
1126 all copies or substantial portions of the Software.
1128 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1129 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1130 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1131 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1132 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1133 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1135 Except as contained in this notice, the name of The Open Group shall not be
1136 used in advertising or otherwise to promote the sale, use or other dealings
1137 in this Software without prior written authorization from The Open Group.
1140 /* $XFree86: xc/lib/Xmu/CmapAlloc.c,v 1.7 2001/12/14 19:55:35 dawes Exp $ */
1143 * Author: Donna Converse, MIT X Consortium
1146 #include <X11/Xlib.h>
1147 #include <X11/Xatom.h>
1148 #include <X11/Xutil.h>
1149 #include <X11/Xmu/StdCmap.h>
1152 #define lowbit(x) ((x) & (~(x) + 1))
1157 static void best_allocation(XVisualInfo*, unsigned long*, unsigned long*,
1159 static int default_allocation(XVisualInfo*, unsigned long*,
1160 unsigned long*, unsigned long*);
1161 static void gray_allocation(int, unsigned long*, unsigned long*,
1163 static int icbrt(int);
1164 static int icbrt_with_bits(int, int);
1165 static int icbrt_with_guess(int, int);
1167 /* To determine the best allocation of reds, greens, and blues in a
1168 * standard colormap, use XmuGetColormapAllocation.
1169 * vinfo specifies visual information for a chosen visual
1170 * property specifies one of the standard colormap property names
1171 * red_max returns maximum red value
1172 * green_max returns maximum green value
1173 * blue_max returns maximum blue value
1175 * XmuGetColormapAllocation returns 0 on failure, non-zero on success.
1176 * It is assumed that the visual is appropriate for the colormap property.
1180 XmuGetColormapAllocation(XVisualInfo *vinfo, Atom property,
1181 unsigned long *red_max,
1182 unsigned long *green_max,
1183 unsigned long *blue_max)
1187 if (vinfo->colormap_size <= 2)
1192 case XA_RGB_DEFAULT_MAP:
1193 status = default_allocation(vinfo, red_max, green_max, blue_max);
1195 case XA_RGB_BEST_MAP:
1196 best_allocation(vinfo, red_max, green_max, blue_max);
1198 case XA_RGB_GRAY_MAP:
1199 gray_allocation(vinfo->colormap_size, red_max, green_max, blue_max);
1201 case XA_RGB_RED_MAP:
1202 *red_max = vinfo->colormap_size - 1;
1203 *green_max = *blue_max = 0;
1205 case XA_RGB_GREEN_MAP:
1206 *green_max = vinfo->colormap_size - 1;
1207 *red_max = *blue_max = 0;
1209 case XA_RGB_BLUE_MAP:
1210 *blue_max = vinfo->colormap_size - 1;
1211 *red_max = *green_max = 0;
1219 /****************************************************************************/
1220 /* Determine the appropriate color allocations of a gray scale.
1222 * Keith Packard, MIT X Consortium
1226 gray_allocation(int n, unsigned long *red_max, unsigned long *green_max,
1227 unsigned long *blue_max)
1229 *red_max = (n * 30) / 100;
1230 *green_max = (n * 59) / 100;
1231 *blue_max = (n * 11) / 100;
1232 *green_max += ((n - 1) - (*red_max + *green_max + *blue_max));
1235 /****************************************************************************/
1236 /* Determine an appropriate color allocation for the RGB_DEFAULT_MAP.
1237 * If a map has less than a minimum number of definable entries, we do not
1238 * produce an allocation for an RGB_DEFAULT_MAP.
1240 * For 16 planes, the default colormap will have 27 each RGB; for 12 planes,
1241 * 12 each. For 8 planes, let n = the number of colormap entries, which may
1242 * be 256 or 254. Then, maximum red value = floor(cube_root(n - 125)) - 1.
1243 * Maximum green and maximum blue values are identical to maximum red.
1244 * This leaves at least 125 cells which clients can allocate.
1246 * Return 0 if an allocation has been determined, non-zero otherwise.
1250 default_allocation(XVisualInfo *vinfo, unsigned long *red,
1251 unsigned long *green, unsigned long *blue)
1253 int ngrays; /* number of gray cells */
1255 switch (vinfo->c_class)
1259 if (vinfo->colormap_size > 65000)
1260 /* intended for displays with 16 planes */
1261 *red = *green = *blue = (unsigned long) 27;
1262 else if (vinfo->colormap_size > 4000)
1263 /* intended for displays with 12 planes */
1264 *red = *green = *blue = (unsigned long) 12;
1265 else if (vinfo->colormap_size < 250)
1268 /* intended for displays with 8 planes */
1269 *red = *green = *blue = (unsigned long)
1270 (icbrt(vinfo->colormap_size - 125) - 1);
1275 if (vinfo->colormap_size < 10)
1277 *red = *green = *blue = vinfo->colormap_size / 2 - 1;
1282 *red = vinfo->red_mask / lowbit(vinfo->red_mask);
1283 *green = vinfo->green_mask / lowbit(vinfo->green_mask);
1284 *blue = vinfo->blue_mask / lowbit(vinfo->blue_mask);
1289 if (vinfo->colormap_size > 65000)
1291 else if (vinfo->colormap_size > 4000)
1293 else if (vinfo->colormap_size < 250)
1297 gray_allocation(ngrays, red, green, blue);
1306 /****************************************************************************/
1307 /* Determine an appropriate color allocation for the RGB_BEST_MAP.
1309 * For a DirectColor or TrueColor visual, the allocation is determined
1310 * by the red_mask, green_mask, and blue_mask members of the visual info.
1312 * Otherwise, if the colormap size is an integral power of 2, determine
1313 * the allocation according to the number of bits given to each color,
1314 * with green getting more than red, and red more than blue, if there
1315 * are to be inequities in the distribution. If the colormap size is
1316 * not an integral power of 2, let n = the number of colormap entries.
1317 * Then maximum red value = floor(cube_root(n)) - 1;
1318 * maximum blue value = floor(cube_root(n)) - 1;
1319 * maximum green value = n / ((# red values) * (# blue values)) - 1;
1320 * Which, on a GPX, allows for 252 entries in the best map, out of 254
1321 * defineable colormap entries.
1325 best_allocation(XVisualInfo *vinfo, unsigned long *red, unsigned long *green,
1326 unsigned long *blue)
1329 if (vinfo->c_class == DirectColor || vinfo->c_class == TrueColor)
1331 *red = vinfo->red_mask;
1332 while ((*red & 01) == 0)
1334 *green = vinfo->green_mask;
1335 while ((*green & 01) == 0)
1337 *blue = vinfo->blue_mask;
1338 while ((*blue & 01) == 0)
1343 register int bits, n;
1345 /* Determine n such that n is the least integral power of 2 which is
1346 * greater than or equal to the number of entries in the colormap.
1350 while (vinfo->colormap_size > n)
1356 /* If the number of entries in the colormap is a power of 2, determine
1357 * the allocation by "dealing" the bits, first to green, then red, then
1358 * blue. If not, find the maximum integral red, green, and blue values
1359 * which, when multiplied together, do not exceed the number of
1363 if (n == vinfo->colormap_size)
1365 register int r, g, b;
1367 g = b + ((bits % 3) ? 1 : 0);
1368 r = b + (((bits % 3) == 2) ? 1 : 0);
1375 *red = icbrt_with_bits(vinfo->colormap_size, bits);
1377 *green = (vinfo->colormap_size / ((*red) * (*blue)));
1387 * integer cube roots by Newton's method
1389 * Stephen Gildea, MIT X Consortium, July 1991
1395 register int bits = 0;
1396 register unsigned n = a;
1403 return icbrt_with_bits(a, bits);
1408 icbrt_with_bits(int a, int bits)
1409 /* bits - log 2 of a */
1411 return icbrt_with_guess(a, a>>2*bits/3);
1414 #ifdef _X_ROOT_STATS
1415 int icbrt_loopcount;
1418 /* Newton's Method: x_n+1 = x_n - ( f(x_n) / f'(x_n) ) */
1420 /* for cube roots, x^3 - a = 0, x_new = x - 1/3 (x - a/x^2) */
1423 * Quick and dirty cube roots. Nothing fancy here, just Newton's method.
1424 * Only works for positive integers (since that's all we need).
1425 * We actually return floor(cbrt(a)) because that's what we need here, too.
1429 icbrt_with_guess(int a, int guess)
1433 #ifdef _X_ROOT_STATS
1434 icbrt_loopcount = 0;
1442 #ifdef _X_ROOT_STATS
1445 delta = (guess - a/(guess*guess))/3;
1447 printf("pass %d: guess=%d, delta=%d\n", icbrt_loopcount, guess, delta);
1450 } while (delta != 0);
1452 if (guess*guess*guess > a)
1459 /* $Xorg: StdCmap.c,v 1.4 2001/02/09 02:03:53 xorgcvs Exp $ */
1463 Copyright 1989, 1998 The Open Group
1465 Permission to use, copy, modify, distribute, and sell this software and its
1466 documentation for any purpose is hereby granted without fee, provided that
1467 the above copyright notice appear in all copies and that both that
1468 copyright notice and this permission notice appear in supporting
1471 The above copyright notice and this permission notice shall be included in
1472 all copies or substantial portions of the Software.
1474 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1475 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1476 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1477 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1478 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1479 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1481 Except as contained in this notice, the name of The Open Group shall not be
1482 used in advertising or otherwise to promote the sale, use or other dealings
1483 in this Software without prior written authorization from The Open Group.
1486 /* $XFree86: xc/lib/Xmu/StdCmap.c,v 1.6 2001/12/14 19:55:48 dawes Exp $ */
1489 * Author: Donna Converse, MIT X Consortium
1493 #include <X11/Xlib.h>
1494 #include <X11/Xatom.h>
1495 #include <X11/Xutil.h>
1496 #include <X11/Xmu/StdCmap.h>
1498 #define lowbit(x) ((x) & (~(x) + 1))
1503 /* argument restrictions */
1504 static Status valid_args(XVisualInfo*, unsigned long, unsigned long,
1505 unsigned long, Atom);
1508 * To create any one standard colormap, use XmuStandardColormap().
1510 * Create a standard colormap for the given screen, visualid, and visual
1511 * depth, with the given red, green, and blue maximum values, with the
1512 * given standard property name. Return a pointer to an XStandardColormap
1513 * structure which describes the newly created colormap, upon success.
1514 * Upon failure, return NULL.
1516 * XmuStandardColormap() calls XmuCreateColormap() to create the map.
1518 * Resources created by this function are not made permanent; that is the
1519 * caller's responsibility.
1523 XmuStandardColormap(Display *dpy, int screen, VisualID visualid,
1524 unsigned int depth, Atom property, Colormap cmap,
1525 unsigned long red_max, unsigned long green_max,
1526 unsigned long blue_max)
1528 * dpy - specifies X server connection
1529 * screen - specifies display screen
1530 * visualid - identifies the visual type
1531 * depth - identifies the visual type
1532 * property - a standard colormap property
1533 * cmap - specifies colormap ID or None
1534 * red_max, green_max, blue_max - allocations
1537 XStandardColormap *stdcmap;
1539 XVisualInfo vinfo_template, *vinfo;
1543 /* Match the required visual information to an actual visual */
1544 vinfo_template.visualid = visualid;
1545 vinfo_template.screen = screen;
1546 vinfo_template.depth = depth;
1547 vinfo_mask = VisualIDMask | VisualScreenMask | VisualDepthMask;
1548 if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &n)) == NULL)
1551 /* Check the validity of the combination of visual characteristics,
1552 * allocation, and colormap property. Create an XStandardColormap
1556 if (! valid_args(vinfo, red_max, green_max, blue_max, property)
1557 || ((stdcmap = XAllocStandardColormap()) == NULL)) {
1558 XFree((char *) vinfo);
1562 /* Fill in the XStandardColormap structure */
1564 if (cmap == DefaultColormap(dpy, screen)) {
1565 /* Allocating out of the default map, cannot use XFreeColormap() */
1566 Window win = XCreateWindow(dpy, RootWindow(dpy, screen), 1, 1, 1, 1,
1567 0, 0, InputOnly, vinfo->visual,
1569 (XSetWindowAttributes *)NULL);
1570 stdcmap->killid = (XID) XCreatePixmap(dpy, win, 1, 1, depth);
1571 XDestroyWindow(dpy, win);
1572 stdcmap->colormap = cmap;
1574 stdcmap->killid = ReleaseByFreeingColormap;
1575 stdcmap->colormap = XCreateColormap(dpy, RootWindow(dpy, screen),
1576 vinfo->visual, AllocNone);
1578 stdcmap->red_max = red_max;
1579 stdcmap->green_max = green_max;
1580 stdcmap->blue_max = blue_max;
1581 if (property == XA_RGB_GRAY_MAP)
1582 stdcmap->red_mult = stdcmap->green_mult = stdcmap->blue_mult = 1;
1583 else if (vinfo->c_class == TrueColor || vinfo->c_class == DirectColor) {
1584 stdcmap->red_mult = lowbit(vinfo->red_mask);
1585 stdcmap->green_mult = lowbit(vinfo->green_mask);
1586 stdcmap->blue_mult = lowbit(vinfo->blue_mask);
1588 stdcmap->red_mult = (red_max > 0)
1589 ? (green_max + 1) * (blue_max + 1) : 0;
1590 stdcmap->green_mult = (green_max > 0) ? blue_max + 1 : 0;
1591 stdcmap->blue_mult = (blue_max > 0) ? 1 : 0;
1593 stdcmap->base_pixel = 0; /* base pixel may change */
1594 stdcmap->visualid = vinfo->visualid;
1596 /* Make the colormap */
1598 status = XmuCreateColormap(dpy, stdcmap);
1602 XFree((char *) vinfo);
1605 /* Free the colormap or the pixmap, if we created one */
1606 if (stdcmap->killid == ReleaseByFreeingColormap)
1607 XFreeColormap(dpy, stdcmap->colormap);
1608 else if (stdcmap->killid != None)
1609 XFreePixmap(dpy, stdcmap->killid);
1611 XFree((char *) stdcmap);
1612 return (XStandardColormap *) NULL;
1617 /****************************************************************************/
1619 valid_args(XVisualInfo *vinfo, unsigned long red_max, unsigned long green_max,
1620 unsigned long blue_max, Atom property)
1622 * vinfo - specifies visual
1623 * red_max, green_max, blue_max - specifies alloc
1624 * property - specifies property name
1627 unsigned long ncolors; /* number of colors requested */
1629 /* Determine that the number of colors requested is <= map size */
1631 if ((vinfo->c_class == DirectColor) || (vinfo->c_class == TrueColor)) {
1634 mask = vinfo->red_mask;
1639 mask = vinfo->green_mask;
1642 if (green_max > mask)
1644 mask = vinfo->blue_mask;
1647 if (blue_max > mask)
1649 } else if (property == XA_RGB_GRAY_MAP) {
1650 ncolors = red_max + green_max + blue_max + 1;
1651 if (ncolors > vinfo->colormap_size)
1654 ncolors = (red_max + 1) * (green_max + 1) * (blue_max + 1);
1655 if (ncolors > vinfo->colormap_size)
1659 /* Determine that the allocation and visual make sense for the property */
1663 case XA_RGB_DEFAULT_MAP:
1664 if (red_max == 0 || green_max == 0 || blue_max == 0)
1667 case XA_RGB_RED_MAP:
1671 case XA_RGB_GREEN_MAP:
1675 case XA_RGB_BLUE_MAP:
1679 case XA_RGB_BEST_MAP:
1680 if (red_max == 0 || green_max == 0 || blue_max == 0)
1683 case XA_RGB_GRAY_MAP:
1684 if (red_max == 0 || blue_max == 0 || green_max == 0)
1694 /* $Xorg: CrCmap.c,v 1.4 2001/02/09 02:03:51 xorgcvs Exp $ */
1698 Copyright 1989, 1998 The Open Group
1700 Permission to use, copy, modify, distribute, and sell this software and its
1701 documentation for any purpose is hereby granted without fee, provided that
1702 the above copyright notice appear in all copies and that both that
1703 copyright notice and this permission notice appear in supporting
1706 The above copyright notice and this permission notice shall be included in
1707 all copies or substantial portions of the Software.
1709 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1710 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1711 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1712 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1713 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1714 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1716 Except as contained in this notice, the name of The Open Group shall not be
1717 used in advertising or otherwise to promote the sale, use or other dealings
1718 in this Software without prior written authorization from The Open Group.
1721 /* $XFree86: xc/lib/Xmu/CrCmap.c,v 3.7 2001/12/14 19:55:36 dawes Exp $ */
1724 * Author: Donna Converse, MIT X Consortium
1728 * CreateCmap.c - given a standard colormap description, make the map.
1733 #include <X11/Xlib.h>
1734 #include <X11/Xutil.h>
1735 #include <X11/Xmu/StdCmap.h>
1740 /* allocate entire map Read Only */
1741 static int ROmap(Display*, Colormap, unsigned long[], int, int);
1743 /* allocate a cell, prefer Read Only */
1744 static Status ROorRWcell(Display*, Colormap, unsigned long[], int,
1745 XColor*, unsigned long);
1747 /* allocate a cell Read Write */
1748 static Status RWcell(Display*, Colormap, XColor*, XColor*, unsigned long*);
1751 static int compare(_Xconst void*, _Xconst void*);
1753 /* find contiguous sequence of cells */
1754 static Status contiguous(unsigned long[], int, int, unsigned long, int*, int*);
1756 /* frees resources before quitting */
1757 static void free_cells(Display*, Colormap, unsigned long[], int, int);
1759 /* create a map in a RO visual type */
1760 static Status readonly_map(Display*, XVisualInfo*, XStandardColormap*);
1762 /* create a map in a RW visual type */
1763 static Status readwrite_map(Display*, XVisualInfo*, XStandardColormap*);
1765 #define lowbit(x) ((x) & (~(x) + 1))
1766 #define TRUEMATCH(mult,max,mask) \
1767 (colormap->max * colormap->mult <= vinfo->mask && \
1768 lowbit(vinfo->mask) == colormap->mult)
1771 * To create any one colormap which is described by an XStandardColormap
1772 * structure, use XmuCreateColormap().
1774 * Return 0 on failure, non-zero on success.
1775 * Resources created by this function are not made permanent.
1776 * No argument error checking is provided. Use at your own risk.
1778 * All colormaps are created with read only allocations, with the exception
1779 * of read only allocations of colors in the default map or otherwise
1780 * which fail to return the expected pixel value, and these are individually
1781 * defined as read/write allocations. This is done so that all the cells
1782 * defined in the default map are contiguous, for use in image processing.
1783 * This typically happens with White and Black in the default map.
1785 * Colormaps of static visuals are considered to be successfully created if
1786 * the map of the static visual matches the definition given in the
1787 * standard colormap structure.
1791 XmuCreateColormap(Display *dpy, XStandardColormap *colormap)
1792 /* dpy - specifies the connection under which the map is created
1793 * colormap - specifies the map to be created, and returns, particularly
1794 * if the map is created as a subset of the default colormap
1795 * of the screen, the base_pixel of the map.
1798 XVisualInfo vinfo_template; /* template visual information */
1799 XVisualInfo *vinfo; /* matching visual information */
1800 XVisualInfo *vpointer; /* for freeing the entire list */
1801 long vinfo_mask; /* specifies the visual mask value */
1802 int n; /* number of matching visuals */
1805 vinfo_template.visualid = colormap->visualid;
1806 vinfo_mask = VisualIDMask;
1807 if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &n)) == NULL)
1810 /* A visual id may be valid on multiple screens. Also, there may
1811 * be multiple visuals with identical visual ids at different depths.
1812 * If the colormap is the Default Colormap, use the Default Visual.
1813 * Otherwise, arbitrarily, use the deepest visual.
1819 register int screen_number;
1823 for (screen_number = ScreenCount(dpy); --screen_number >= 0; )
1824 if (colormap->colormap == DefaultColormap(dpy, screen_number)) {
1830 for (i=0; i < n; i++, vinfo++) {
1831 if (vinfo->visual == DefaultVisual(dpy, screen_number))
1836 XVisualInfo *v = NULL;
1838 for (i=0; i < n; i++, vinfo++)
1839 if (vinfo->depth > maxdepth) {
1840 maxdepth = vinfo->depth;
1847 if (vinfo->c_class == PseudoColor || vinfo->c_class == DirectColor ||
1848 vinfo->c_class == GrayScale)
1849 status = readwrite_map(dpy, vinfo, colormap);
1850 else if (vinfo->c_class == TrueColor)
1851 status = TRUEMATCH(red_mult, red_max, red_mask) &&
1852 TRUEMATCH(green_mult, green_max, green_mask) &&
1853 TRUEMATCH(blue_mult, blue_max, blue_mask);
1855 status = readonly_map(dpy, vinfo, colormap);
1857 XFree((char *) vpointer);
1861 /****************************************************************************/
1863 readwrite_map(Display *dpy, XVisualInfo *vinfo, XStandardColormap *colormap)
1865 register unsigned long i, n; /* index counters */
1866 unsigned long ncolors; /* number of colors to be defined */
1867 int npixels; /* number of pixels allocated R/W */
1868 int first_index; /* first index of pixels to use */
1869 int remainder; /* first index of remainder */
1870 XColor color; /* the definition of a color */
1871 unsigned long *pixels; /* array of colormap pixels */
1872 unsigned long delta;
1875 /* Determine ncolors, the number of colors to be defined.
1876 * Insure that 1 < ncolors <= the colormap size.
1878 if (vinfo->c_class == DirectColor) {
1879 ncolors = colormap->red_max;
1880 if (colormap->green_max > ncolors)
1881 ncolors = colormap->green_max;
1882 if (colormap->blue_max > ncolors)
1883 ncolors = colormap->blue_max;
1885 delta = lowbit(vinfo->red_mask) +
1886 lowbit(vinfo->green_mask) +
1887 lowbit(vinfo->blue_mask);
1889 ncolors = colormap->red_max * colormap->red_mult +
1890 colormap->green_max * colormap->green_mult +
1891 colormap->blue_max * colormap->blue_mult + 1;
1894 if (ncolors <= 1 || (int) ncolors > vinfo->colormap_size) return 0;
1896 /* Allocate Read/Write as much of the colormap as we can possibly get.
1897 * Then insure that the pixels we were allocated are given in
1898 * monotonically increasing order, using a quicksort. Next, insure
1899 * that our allocation includes a subset of contiguous pixels at least
1900 * as long as the number of colors to be defined. Now we know that
1901 * these conditions are met:
1902 * 1) There are no free cells in the colormap.
1903 * 2) We have a contiguous sequence of pixels, monotonically
1904 * increasing, of length >= the number of colors requested.
1906 * One cell at a time, we will free, compute the next color value,
1907 * then allocate read only. This takes a long time.
1908 * This is done to insure that cells are allocated read only in the
1909 * contiguous order which we prefer. If the server has a choice of
1910 * cells to grant to an allocation request, the server may give us any
1911 * cell, so that is why we do these slow gymnastics.
1914 if ((pixels = (unsigned long *) calloc((unsigned) vinfo->colormap_size,
1915 sizeof(unsigned long))) == NULL)
1918 if ((npixels = ROmap(dpy, colormap->colormap, pixels,
1919 vinfo->colormap_size, ncolors)) == 0) {
1920 free((char *) pixels);
1924 qsort((char *) pixels, npixels, sizeof(unsigned long), compare);
1926 if (!contiguous(pixels, npixels, ncolors, delta, &first_index, &remainder))
1928 /* can't find enough contiguous cells, give up */
1929 XFreeColors(dpy, colormap->colormap, pixels, npixels,
1931 free((char *) pixels);
1934 colormap->base_pixel = pixels[first_index];
1936 /* construct a gray map */
1937 if (colormap->red_mult == 1 && colormap->green_mult == 1 &&
1938 colormap->blue_mult == 1)
1939 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
1942 color.blue = color.green = color.red =
1943 (unsigned short) ((i * 65535) / (colormap->red_max +
1944 colormap->green_max +
1945 colormap->blue_max));
1947 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
1952 /* construct a red ramp map */
1953 else if (colormap->green_max == 0 && colormap->blue_max == 0)
1954 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
1957 color.red = (unsigned short) ((i * 65535) / colormap->red_max);
1958 color.green = color.blue = 0;
1960 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
1965 /* construct a green ramp map */
1966 else if (colormap->red_max == 0 && colormap->blue_max == 0)
1967 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
1970 color.green = (unsigned short) ((i * 65535) / colormap->green_max);
1971 color.red = color.blue = 0;
1973 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
1978 /* construct a blue ramp map */
1979 else if (colormap->red_max == 0 && colormap->green_max == 0)
1980 for (n=colormap->base_pixel, i=0; i < ncolors; i++, n += delta)
1983 color.blue = (unsigned short) ((i * 65535) / colormap->blue_max);
1984 color.red = color.green = 0;
1986 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
1991 /* construct a standard red green blue cube map */
1994 #define calc(max,mult) (((n / colormap->mult) % \
1995 (colormap->max + 1)) * 65535) / colormap->max
1997 for (n=0, i=0; i < ncolors; i++, n += delta)
1999 color.pixel = n + colormap->base_pixel;
2000 color.red = calc(red_max, red_mult);
2001 color.green = calc(green_max, green_mult);
2002 color.blue = calc(blue_max, blue_mult);
2003 if (! ROorRWcell(dpy, colormap->colormap, pixels, npixels, &color,
2009 /* We have a read-only map defined. Now free unused cells,
2010 * first those occuring before the contiguous sequence begins,
2011 * then any following the contiguous sequence.
2015 XFreeColors(dpy, colormap->colormap, pixels, first_index,
2018 XFreeColors(dpy, colormap->colormap,
2019 &(pixels[first_index + ncolors]), remainder,
2022 free((char *) pixels);
2027 /****************************************************************************/
2029 ROmap(Display *dpy, Colormap cmap, unsigned long pixels[], int m, int n)
2031 * dpy - the X server connection
2032 * cmap - specifies colormap ID
2033 * pixels - returns pixel allocations
2034 * m - specifies colormap size
2035 * n - specifies number of colors
2040 /* first try to allocate the entire colormap */
2041 if (XAllocColorCells(dpy, cmap, 1, (unsigned long *) NULL,
2042 (unsigned) 0, pixels, (unsigned) m))
2045 /* Allocate all available cells in the colormap, using a binary
2046 * algorithm to discover how many cells we can allocate in the colormap.
2050 p = n + ((m - n + 1) / 2);
2051 if (XAllocColorCells(dpy, cmap, 1, (unsigned long *) NULL,
2052 (unsigned) 0, pixels, (unsigned) p)) {
2056 XFreeColors(dpy, cmap, pixels, p, (unsigned long) 0);
2067 /****************************************************************************/
2069 contiguous(unsigned long pixels[], int npixels, int ncolors,
2070 unsigned long delta, int *first, int *rem)
2071 /* pixels - specifies allocated pixels
2072 * npixels - specifies count of alloc'd pixels
2073 * ncolors - specifies needed sequence length
2074 * delta - between pixels
2075 * first - returns first index of sequence
2076 * rem - returns first index after sequence, or 0, if none follow
2079 register int i = 1; /* walking index into the pixel array */
2080 register int count = 1; /* length of sequence discovered so far */
2083 if (npixels == ncolors) {
2088 while (count < ncolors && ncolors - count <= *rem)
2090 if (pixels[i-1] + delta == pixels[i])
2099 if (count != ncolors)
2105 /****************************************************************************/
2107 ROorRWcell(Display *dpy, Colormap cmap, unsigned long pixels[],
2108 int npixels, XColor *color, unsigned long p)
2110 unsigned long pixel;
2113 /* Free the read/write allocation of one cell in the colormap.
2114 * Request a read only allocation of one cell in the colormap.
2115 * If the read only allocation cannot be granted, give up, because
2116 * there must be no free cells in the colormap.
2117 * If the read only allocation is granted, but gives us a cell which
2118 * is not the one that we just freed, it is probably the case that
2119 * we are trying allocate White or Black or some other color which
2120 * already has a read-only allocation in the map. So we try to
2121 * allocate the previously freed cell with a read/write allocation,
2122 * because we want contiguous cells for image processing algorithms.
2125 pixel = color->pixel;
2126 request.red = color->red;
2127 request.green = color->green;
2128 request.blue = color->blue;
2130 XFreeColors(dpy, cmap, &pixel, 1, (unsigned long) 0);
2131 if (! XAllocColor(dpy, cmap, color)
2132 || (color->pixel != pixel &&
2133 (!RWcell(dpy, cmap, color, &request, &pixel))))
2135 free_cells(dpy, cmap, pixels, npixels, (int)p);
2142 /****************************************************************************/
2144 free_cells(Display *dpy, Colormap cmap, unsigned long pixels[],
2147 * pixels - to be freed
2148 * npixels - original number allocated
2151 /* One of the npixels allocated has already been freed.
2152 * p is the index of the freed pixel.
2153 * First free the pixels preceeding p, and there are p of them;
2154 * then free the pixels following p, there are npixels - p - 1 of them.
2156 XFreeColors(dpy, cmap, pixels, p, (unsigned long) 0);
2157 XFreeColors(dpy, cmap, &(pixels[p+1]), npixels - p - 1, (unsigned long) 0);
2158 free((char *) pixels);
2162 /****************************************************************************/
2164 RWcell(Display *dpy, Colormap cmap, XColor *color, XColor *request,
2165 unsigned long *pixel)
2167 unsigned long n = *pixel;
2169 XFreeColors(dpy, cmap, &(color->pixel), 1, (unsigned long)0);
2170 if (! XAllocColorCells(dpy, cmap, (Bool) 0, (unsigned long *) NULL,
2171 (unsigned) 0, pixel, (unsigned) 1))
2175 XFreeColors(dpy, cmap, pixel, 1, (unsigned long) 0);
2178 color->pixel = *pixel;
2179 color->flags = DoRed | DoGreen | DoBlue;
2180 color->red = request->red;
2181 color->green = request->green;
2182 color->blue = request->blue;
2183 XStoreColors(dpy, cmap, color, 1);
2188 /****************************************************************************/
2190 compare(_Xconst void *e1, _Xconst void *e2)
2192 return ((int)(*(long *)e1 - *(long *)e2));
2196 /****************************************************************************/
2198 readonly_map(Display *dpy, XVisualInfo *vinfo, XStandardColormap *colormap)
2203 last_pixel = (colormap->red_max + 1) * (colormap->green_max + 1) *
2204 (colormap->blue_max + 1) + colormap->base_pixel - 1;
2206 for(i=colormap->base_pixel; i <= last_pixel; i++) {
2208 color.pixel = (unsigned long) i;
2209 color.red = (unsigned short)
2210 (((i/colormap->red_mult) * 65535) / colormap->red_max);
2212 if (vinfo->c_class == StaticColor) {
2213 color.green = (unsigned short)
2214 ((((i/colormap->green_mult) % (colormap->green_max + 1)) *
2215 65535) / colormap->green_max);
2216 color.blue = (unsigned short)
2217 (((i%colormap->green_mult) * 65535) / colormap->blue_max);
2219 else /* vinfo->c_class == GrayScale, old style allocation XXX */
2220 color.green = color.blue = color.red;
2222 XAllocColor(dpy, colormap->colormap, &color);
2223 if (color.pixel != (unsigned long) i)
2230 /* $Xorg: DelCmap.c,v 1.4 2001/02/09 02:03:52 xorgcvs Exp $ */
2234 Copyright 1989, 1998 The Open Group
2236 Permission to use, copy, modify, distribute, and sell this software and its
2237 documentation for any purpose is hereby granted without fee, provided that
2238 the above copyright notice appear in all copies and that both that
2239 copyright notice and this permission notice appear in supporting
2242 The above copyright notice and this permission notice shall be included in
2243 all copies or substantial portions of the Software.
2245 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2246 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2247 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2248 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
2249 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
2250 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2252 Except as contained in this notice, the name of The Open Group shall not be
2253 used in advertising or otherwise to promote the sale, use or other dealings
2254 in this Software without prior written authorization from The Open Group.
2257 /* $XFree86: xc/lib/Xmu/DelCmap.c,v 1.7 2001/12/14 19:55:40 dawes Exp $ */
2260 * Author: Donna Converse, MIT X Consortium
2263 #include <X11/Xlib.h>
2264 #include <X11/Xutil.h>
2265 #include <X11/Xmu/StdCmap.h>
2267 /* To remove any standard colormap property, use XmuDeleteStandardColormap().
2268 * XmuDeleteStandardColormap() will remove the specified property from the
2269 * specified screen, releasing any resources used by the colormap(s) of the
2270 * property if possible.
2274 XmuDeleteStandardColormap(Display *dpy, int screen, Atom property)
2275 /* dpy; - specifies the X server to connect to
2276 * screen - specifies the screen of the display
2277 * property - specifies the standard colormap property
2280 XStandardColormap *stdcmaps, *s;
2283 if (XGetRGBColormaps(dpy, RootWindow(dpy, screen), &stdcmaps, &count,
2286 for (s=stdcmaps; count > 0; count--, s++) {
2287 if ((s->killid == ReleaseByFreeingColormap) &&
2288 (s->colormap != None) &&
2289 (s->colormap != DefaultColormap(dpy, screen)))
2290 XFreeColormap(dpy, s->colormap);
2291 else if (s->killid != None)
2292 XKillClient(dpy, s->killid);
2294 XDeleteProperty(dpy, RootWindow(dpy, screen), property);
2295 XFree((char *) stdcmaps);