1 /* X-specific Lisp objects.
2 Copyright (C) 1993, 1994 Free Software Foundation, Inc.
3 Copyright (C) 1995 Board of Trustees, University of Illinois.
4 Copyright (C) 1995 Tinker Systems
5 Copyright (C) 1995, 1996 Ben Wing
6 Copyright (C) 1995 Sun Microsystems
7 Copyright (C) 1999, 2000, 2002 Andy Piper
9 This file is part of SXEmacs
11 SXEmacs is free software: you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation, either version 3 of the License, or
14 (at your option) any later version.
16 SXEmacs is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program. If not, see <http://www.gnu.org/licenses/>. */
25 /* Synched up with: Not in FSF. */
27 /* 7-8-00 This file is more or less Mule-ized in my Mule workspace. */
29 /* Original author: Jamie Zawinski for 19.8
30 font-truename stuff added by Jamie Zawinski for 19.10
31 subwindow support added by Chuck Thompson
32 additional XPM support added by Chuck Thompson
33 initial X-Face support added by Stig
34 rewritten/restructured by Ben Wing for 19.12/19.13
35 GIF/JPEG support added by Ben Wing for 19.14
36 PNG support added by Bill Perry for 19.14
37 Improved GIF/JPEG support added by Bill Perry for 19.14
38 Cleanup/simplification of error handling by Ben Wing for 19.14
39 Pointer/icon overhaul, more restructuring by Ben Wing for 19.14
40 GIF support changed to external GIFlib 3.1 by Jareth Hein for 21.0
41 Many changes for color work and optimizations by Jareth Hein for 21.0
42 Switch of GIF/JPEG/PNG to new EImage intermediate code by Jareth Hein for 21.0
43 TIFF code by Jareth Hein for 21.0
44 GIF/JPEG/PNG/TIFF code moved to new glyph-eimage.c by Andy Piper for 21.0
45 Subwindow and Widget support by Andy Piper for 21.2
48 Support the GrayScale, StaticColor and StaticGray visual classes.
49 Convert images.el to C and stick it in here?
55 #include "console-x.h"
57 #include "objects-x.h"
64 #include "ui/window.h"
66 #include "ui/insdel.h"
71 #include "ui/imgproc.h"
78 #include "mule/file-coding.h"
81 #ifdef LWLIB_WIDGETS_MOTIF
84 #include <X11/IntrinsicP.h>
86 /* what's this? what's wrong with uint32_t? */
89 # define FOUR_BYTE_TYPE unsigned int
90 #elif SXE_LONGBITS == 32
91 # define FOUR_BYTE_TYPE unsigned long
92 #elif SXE_SHORTBITS == 32
93 # define FOUR_BYTE_TYPE unsigned short
95 #error What kind of strange-ass system are we running on?
99 #define LISP_DEVICE_TO_X_SCREEN(dev) XDefaultScreenOfDisplay (DEVICE_X_DISPLAY (XDEVICE (dev)))
101 DECLARE_IMAGE_INSTANTIATOR_FORMAT(nothing);
102 DECLARE_IMAGE_INSTANTIATOR_FORMAT(string);
103 DECLARE_IMAGE_INSTANTIATOR_FORMAT(formatted_string);
104 DECLARE_IMAGE_INSTANTIATOR_FORMAT(inherit);
106 DECLARE_IMAGE_INSTANTIATOR_FORMAT(jpeg);
109 DECLARE_IMAGE_INSTANTIATOR_FORMAT(tiff);
111 #if defined WITH_PNG && defined HAVE_PNG
112 DECLARE_IMAGE_INSTANTIATOR_FORMAT(png);
115 DECLARE_IMAGE_INSTANTIATOR_FORMAT(gif);
118 DEFINE_DEVICE_IIFORMAT(x, xpm);
120 DEFINE_DEVICE_IIFORMAT(x, xbm);
121 DEFINE_DEVICE_IIFORMAT(x, subwindow);
123 DEFINE_DEVICE_IIFORMAT(x, xface);
126 DECLARE_IMAGE_INSTANTIATOR_FORMAT(rawrgb);
127 DECLARE_IMAGE_INSTANTIATOR_FORMAT(rawrgba);
130 DEFINE_IMAGE_INSTANTIATOR_FORMAT(cursor_font);
131 Lisp_Object Qcursor_font;
133 DEFINE_IMAGE_INSTANTIATOR_FORMAT(font);
135 DEFINE_IMAGE_INSTANTIATOR_FORMAT(autodetect);
138 DECLARE_IMAGE_INSTANTIATOR_FORMAT(layout);
139 DEFINE_DEVICE_IIFORMAT(x, widget);
140 DEFINE_DEVICE_IIFORMAT(x, native_layout);
141 DEFINE_DEVICE_IIFORMAT(x, button);
142 DEFINE_DEVICE_IIFORMAT(x, progress_gauge);
143 DEFINE_DEVICE_IIFORMAT(x, edit_field);
144 #if defined (LWLIB_WIDGETS_MOTIF) && XmVERSION > 1
145 DEFINE_DEVICE_IIFORMAT(x, combo_box);
147 DEFINE_DEVICE_IIFORMAT(x, tab_control);
148 DEFINE_DEVICE_IIFORMAT(x, label);
151 static void cursor_font_instantiate(Lisp_Object image_instance,
152 Lisp_Object instantiator,
153 Lisp_Object pointer_fg,
154 Lisp_Object pointer_bg,
155 int dest_mask, Lisp_Object domain);
159 update_widget_face(widget_value * wv,
160 Lisp_Image_Instance * ii, Lisp_Object domain);
162 update_tab_widget_face(widget_value * wv,
163 Lisp_Image_Instance * ii, Lisp_Object domain);
165 void emacs_Xt_handle_widget_losing_focus(struct frame *f, Widget losing_widget);
166 void enqueue_focus_event(Widget wants_it, Lisp_Object frame, int in_p);
168 #include "ui/bitmaps.h"
170 /************************************************************************/
171 /* image instance methods */
172 /************************************************************************/
174 /************************************************************************/
175 /* convert from a series of RGB triples to an XImage formated for the */
177 /************************************************************************/
178 static XImage *convert_EImage_to_XImage(Lisp_Object device, int width,
179 int height, unsigned char *pic,
180 unsigned long **pixtbl, int *npixels)
186 int depth, bitmap_pad, bits_per_pixel, byte_cnt, i, j;
188 unsigned char *data, *ip, *dp;
189 quant_table *qtable = 0;
192 /* kicked in favour of C99's uint32_t */
199 dpy = DEVICE_X_DISPLAY(XDEVICE(device));
200 cmap = DEVICE_X_COLORMAP(XDEVICE(device));
201 vis = DEVICE_X_VISUAL(XDEVICE(device));
202 depth = DEVICE_X_DEPTH(XDEVICE(device));
204 if (vis->class == GrayScale || vis->class == StaticColor ||
205 vis->class == StaticGray) {
206 /* #### Implement me!!! */
210 if (vis->class == PseudoColor) {
211 /* Quantize the image and get a histogram while we're at it.
212 Do this first to save memory */
213 qtable = build_EImage_quantable(pic, width, height, 256);
218 bitmap_pad = ((depth > 16) ? 32 : (depth > 8) ? 16 : 8);
220 outimg = XCreateImage(dpy, vis,
221 depth, ZPixmap, 0, 0, width, height,
226 bits_per_pixel = outimg->bits_per_pixel;
227 byte_cnt = bits_per_pixel >> 3;
229 data = xmalloc_atomic(outimg->bytes_per_line * height);
231 XDestroyImage(outimg);
234 outimg->data = (char *)data;
236 if (vis->class == PseudoColor) {
237 unsigned long pixarray[256];
240 /* use our quantize table to allocate the colors */
242 *pixtbl = xnew_atomic_array(unsigned long, pixcount);
245 /* #### should implement a sort by popularity to
246 * assure proper allocation */
248 for (i = 0; i < qtable->num_active_colors; i++) {
252 color.red = qtable->rm[i] ? qtable->rm[i] << 8 : 0;
253 color.green = qtable->gm[i] ? qtable->gm[i] << 8 : 0;
254 color.blue = qtable->bm[i] ? qtable->bm[i] << 8 : 0;
255 color.flags = DoRed | DoGreen | DoBlue;
256 res = allocate_nearest_color(dpy, cmap, vis, &color);
257 if (res > 0 && res < 3) {
258 DO_REALLOC_ATOMIC(*pixtbl, pixcount, n + 1,
260 (*pixtbl)[n] = color.pixel;
263 pixarray[i] = color.pixel;
267 for (i = 0; i < height; i++) {
268 dp = data + (i * outimg->bytes_per_line);
269 for (j = 0; j < width; j++) {
274 pixarray[QUANT_GET_COLOR
275 (qtable, rd, gr, bl)];
276 #ifdef WORDS_BIGENDIAN
277 if (outimg->byte_order == MSBFirst)
278 for (q = 4 - byte_cnt; q < 4; q++)
281 for (q = 3; q >= 4 - byte_cnt; q--)
284 if (outimg->byte_order == MSBFirst)
285 for (q = byte_cnt - 1; q >= 0; q--)
288 for (q = 0; q < byte_cnt; q++)
295 unsigned long rshift, gshift, bshift, rbits, gbits, bbits, junk;
296 junk = vis->red_mask;
298 while ((junk & 0x1) == 0) {
307 junk = vis->green_mask;
309 while ((junk & 0x1) == 0) {
318 junk = vis->blue_mask;
320 while ((junk & 0x1) == 0) {
330 for (i = 0; i < height; i++) {
331 dp = data + (i * outimg->bytes_per_line);
332 for (j = 0; j < width; j++) {
334 rd = *ip++ << (rbits - 8);
336 rd = *ip++ >> (8 - rbits);
338 gr = *ip++ << (gbits - 8);
340 gr = *ip++ >> (8 - gbits);
342 bl = *ip++ << (bbits - 8);
344 bl = *ip++ >> (8 - bbits);
347 (rd << rshift) | (gr << gshift) | (bl <<
349 #ifdef WORDS_BIGENDIAN
350 if (outimg->byte_order == MSBFirst)
351 for (q = 4 - byte_cnt; q < 4; q++)
354 for (q = 3; q >= 4 - byte_cnt; q--)
357 if (outimg->byte_order == MSBFirst)
358 for (q = byte_cnt - 1; q >= 0; q--)
361 for (q = 0; q < byte_cnt; q++)
371 x_print_image_instance(Lisp_Image_Instance * p,
372 Lisp_Object printcharfun, int escapeflag)
374 switch (IMAGE_INSTANCE_TYPE(p)) {
375 case IMAGE_MONO_PIXMAP:
376 case IMAGE_COLOR_PIXMAP:
378 write_fmt_str(printcharfun, " (0x%lx",
379 (unsigned long)IMAGE_INSTANCE_X_PIXMAP(p));
380 if (IMAGE_INSTANCE_X_MASK(p))
381 write_fmt_str(printcharfun, "/0x%lx",
382 (unsigned long)IMAGE_INSTANCE_X_MASK(p));
383 write_c_string(")", printcharfun);
389 case IMAGE_SUBWINDOW:
397 extern int debug_widget_instances;
400 static void x_finalize_image_instance(Lisp_Image_Instance * p)
405 if (DEVICE_LIVE_P(XDEVICE(IMAGE_INSTANCE_DEVICE(p)))) {
406 Display *dpy = DEVICE_X_DISPLAY
407 (XDEVICE(IMAGE_INSTANCE_DEVICE(p)));
410 else if (IMAGE_INSTANCE_TYPE(p) == IMAGE_WIDGET) {
411 if (IMAGE_INSTANCE_SUBWINDOW_ID(p)) {
413 debug_widget_instances--;
414 stderr_out("widget destroyed, %d left\n",
415 debug_widget_instances);
417 lw_destroy_widget(IMAGE_INSTANCE_X_WIDGET_ID
419 lw_destroy_widget(IMAGE_INSTANCE_X_CLIPWIDGET
422 /* We can release the callbacks again. */
423 ungcpro_popup_callbacks
424 (IMAGE_INSTANCE_X_WIDGET_LWID(p));
426 IMAGE_INSTANCE_X_WIDGET_ID(p) = 0;
427 IMAGE_INSTANCE_X_CLIPWIDGET(p) = 0;
431 else if (IMAGE_INSTANCE_TYPE(p) == IMAGE_SUBWINDOW) {
432 if (IMAGE_INSTANCE_SUBWINDOW_ID(p))
434 IMAGE_INSTANCE_X_SUBWINDOW_ID
436 IMAGE_INSTANCE_SUBWINDOW_ID(p) = 0;
439 if (IMAGE_INSTANCE_PIXMAP_TIMEOUT(p))
440 disable_glyph_animated_timeout
441 (IMAGE_INSTANCE_PIXMAP_TIMEOUT(p));
443 if (IMAGE_INSTANCE_X_MASK(p) &&
444 IMAGE_INSTANCE_X_MASK(p) !=
445 IMAGE_INSTANCE_X_PIXMAP(p))
446 XFreePixmap(dpy, IMAGE_INSTANCE_X_MASK(p));
447 IMAGE_INSTANCE_PIXMAP_MASK(p) = 0;
449 if (IMAGE_INSTANCE_X_PIXMAP_SLICES(p)) {
451 i < IMAGE_INSTANCE_PIXMAP_MAXSLICE(p); i++)
452 if (IMAGE_INSTANCE_X_PIXMAP_SLICE(p, i)) {
454 IMAGE_INSTANCE_X_PIXMAP_SLICE
456 IMAGE_INSTANCE_X_PIXMAP_SLICE(p,
460 xfree(IMAGE_INSTANCE_X_PIXMAP_SLICES(p));
461 IMAGE_INSTANCE_X_PIXMAP_SLICES(p) = 0;
464 if (IMAGE_INSTANCE_X_CURSOR(p)) {
465 XFreeCursor(dpy, IMAGE_INSTANCE_X_CURSOR(p));
466 IMAGE_INSTANCE_X_CURSOR(p) = 0;
469 if (IMAGE_INSTANCE_X_NPIXELS(p) != 0) {
471 IMAGE_INSTANCE_X_COLORMAP(p),
472 IMAGE_INSTANCE_X_PIXELS(p),
473 IMAGE_INSTANCE_X_NPIXELS(p), 0);
474 IMAGE_INSTANCE_X_NPIXELS(p) = 0;
478 /* You can sometimes have pixels without a live device. I forget
479 why, but that's why we free them here if we have a pixmap type
480 image instance. It probably means that we might also get a memory
481 leak with widgets. */
482 if (IMAGE_INSTANCE_TYPE(p) != IMAGE_WIDGET
483 && IMAGE_INSTANCE_TYPE(p) != IMAGE_SUBWINDOW
484 && IMAGE_INSTANCE_X_PIXELS(p)) {
485 xfree(IMAGE_INSTANCE_X_PIXELS(p));
486 IMAGE_INSTANCE_X_PIXELS(p) = 0;
494 x_image_instance_equal(Lisp_Image_Instance * p1,
495 Lisp_Image_Instance * p2, int depth)
497 switch (IMAGE_INSTANCE_TYPE(p1)) {
498 case IMAGE_MONO_PIXMAP:
499 case IMAGE_COLOR_PIXMAP:
501 if (IMAGE_INSTANCE_X_COLORMAP(p1) !=
502 IMAGE_INSTANCE_X_COLORMAP(p2)
503 || IMAGE_INSTANCE_X_NPIXELS(p1) !=
504 IMAGE_INSTANCE_X_NPIXELS(p2))
511 case IMAGE_SUBWINDOW:
520 static unsigned long x_image_instance_hash(Lisp_Image_Instance * p, int depth)
522 switch (IMAGE_INSTANCE_TYPE(p)) {
523 case IMAGE_MONO_PIXMAP:
524 case IMAGE_COLOR_PIXMAP:
526 return IMAGE_INSTANCE_X_NPIXELS(p);
531 case IMAGE_SUBWINDOW:
538 /* Set all the slots in an image instance structure to reasonable
539 default values. This is used somewhere within an instantiate
540 method. It is assumed that the device slot within the image
541 instance is already set -- this is the case when instantiate
542 methods are called. */
545 x_initialize_pixmap_image_instance(Lisp_Image_Instance * ii,
546 int slices, enum image_instance_type type)
548 ii->data = xnew_and_zero(struct x_image_instance_data);
549 IMAGE_INSTANCE_PIXMAP_MAXSLICE(ii) = slices;
550 IMAGE_INSTANCE_X_PIXMAP_SLICES(ii) =
551 xnew_array_and_zero(Pixmap, slices);
552 IMAGE_INSTANCE_TYPE(ii) = type;
553 IMAGE_INSTANCE_PIXMAP_FILENAME(ii) = Qnil;
554 IMAGE_INSTANCE_PIXMAP_MASK_FILENAME(ii) = Qnil;
555 IMAGE_INSTANCE_PIXMAP_HOTSPOT_X(ii) = Qnil;
556 IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y(ii) = Qnil;
557 IMAGE_INSTANCE_PIXMAP_FG(ii) = Qnil;
558 IMAGE_INSTANCE_PIXMAP_BG(ii) = Qnil;
561 /************************************************************************/
562 /* pixmap file functions */
563 /************************************************************************/
565 /* Where bitmaps are; initialized from resource database */
566 Lisp_Object Vx_bitmap_file_path;
569 #define BITMAPDIR "/usr/include/X11/bitmaps"
572 #define USE_XBMLANGPATH
574 /* Given a pixmap filename, look through all of the "standard" places
575 where the file might be located. Return a full pathname if found;
576 otherwise, return Qnil. */
578 static Lisp_Object x_locate_pixmap_file(Lisp_Object name)
580 /* This function can GC if IN_REDISPLAY is false */
583 /* Check non-absolute pathnames with a directory component relative to
584 the search path; that's the way Xt does it. */
585 /* #### Unix-specific */
586 if (XSTRING_BYTE(name, 0) == '/' ||
587 (XSTRING_BYTE(name, 0) == '.' &&
588 (XSTRING_BYTE(name, 1) == '/' ||
589 (XSTRING_BYTE(name, 1) == '.' &&
590 (XSTRING_BYTE(name, 2) == '/'))))) {
591 if (!NILP(Ffile_readable_p(name)))
592 return Fexpand_file_name(name, Qnil);
597 if (NILP(Vdefault_x_device))
598 /* This may occur during initialization. */
601 /* We only check the bitmapFilePath resource on the original X device. */
602 display = DEVICE_X_DISPLAY(XDEVICE(Vdefault_x_device));
604 #ifdef USE_XBMLANGPATH
606 char *path = egetenv("XBMLANGPATH");
607 SubstitutionRec subs[1];
609 subs[0].substitution = (char *)XSTRING_DATA(name);
610 /* #### Motif uses a big hairy default if $XBMLANGPATH isn't set.
611 We don't. If you want it used, set it. */
613 (path = XtResolvePathname(display, "bitmaps", 0, 0, path,
614 subs, XtNumber(subs), 0))) {
615 name = build_string(path);
622 if (NILP(Vx_bitmap_file_path)) {
625 if (XrmGetResource(XtDatabase(display),
626 "bitmapFilePath", "BitmapFilePath", &type,
628 && !strcmp(type, "String"))
629 Vx_bitmap_file_path =
630 decode_env_path(0, (char *)value.addr);
631 Vx_bitmap_file_path =
632 nconc2(Vx_bitmap_file_path, (decode_path(BITMAPDIR)));
637 if (locate_file(Vx_bitmap_file_path, name, Qnil, &found, R_OK) <
639 Lisp_Object temp = list1(Vdata_directory);
643 locate_file(temp, name, Qnil, &found, R_OK);
651 static Lisp_Object locate_pixmap_file(Lisp_Object name)
653 return x_locate_pixmap_file(name);
657 /************************************************************************/
658 /* cursor functions */
659 /************************************************************************/
661 /* Check that this server supports cursors of size WIDTH * HEIGHT. If
662 not, signal an error. INSTANTIATOR is only used in the error
666 check_pointer_sizes(Screen * xs, unsigned int width, unsigned int height,
667 Lisp_Object instantiator)
669 unsigned int best_width, best_height;
670 if (!XQueryBestCursor(DisplayOfScreen(xs), RootWindowOfScreen(xs),
671 width, height, &best_width, &best_height))
672 /* this means that an X error of some sort occurred (we trap
673 these so they're not fatal). */
674 signal_simple_error("XQueryBestCursor() failed?", instantiator);
676 if (width > best_width || height > best_height)
677 error_with_frob(instantiator,
678 "pointer too large (%dx%d): "
679 "server requires %dx%d or smaller",
680 width, height, best_width, best_height);
684 generate_cursor_fg_bg(Lisp_Object device, Lisp_Object * foreground,
685 Lisp_Object * background, XColor * xfg, XColor * xbg)
687 if (!NILP(*foreground) && !COLOR_INSTANCEP(*foreground))
689 Fmake_color_instance(*foreground, device,
690 encode_error_behavior_flag(ERROR_ME));
691 if (COLOR_INSTANCEP(*foreground))
692 *xfg = COLOR_INSTANCE_X_COLOR(XCOLOR_INSTANCE(*foreground));
695 xfg->red = xfg->green = xfg->blue = 0;
698 if (!NILP(*background) && !COLOR_INSTANCEP(*background))
700 Fmake_color_instance(*background, device,
701 encode_error_behavior_flag(ERROR_ME));
702 if (COLOR_INSTANCEP(*background))
703 *xbg = COLOR_INSTANCE_X_COLOR(XCOLOR_INSTANCE(*background));
706 xbg->red = xbg->green = xbg->blue = USHRT_MAX;
711 maybe_recolor_cursor(Lisp_Object image_instance, Lisp_Object foreground,
712 Lisp_Object background)
714 Lisp_Object device = XIMAGE_INSTANCE_DEVICE(image_instance);
717 generate_cursor_fg_bg(device, &foreground, &background, &xfg, &xbg);
718 if (!NILP(foreground) || !NILP(background)) {
719 XRecolorCursor(DEVICE_X_DISPLAY(XDEVICE(device)),
720 XIMAGE_INSTANCE_X_CURSOR(image_instance),
722 XIMAGE_INSTANCE_PIXMAP_FG(image_instance) = foreground;
723 XIMAGE_INSTANCE_PIXMAP_BG(image_instance) = background;
727 /************************************************************************/
728 /* color pixmap functions */
729 /************************************************************************/
731 /* Initialize an image instance from an XImage.
733 DEST_MASK specifies the mask of allowed image types.
735 PIXELS and NPIXELS specify an array of pixels that are used in
736 the image. These need to be kept around for the duration of the
737 image. When the image instance is freed, XFreeColors() will
738 automatically be called on all the pixels specified here; thus,
739 you should have allocated the pixels yourself using XAllocColor()
740 or the like. The array passed in is used directly without
741 being copied, so it should be heap data created with xmalloc().
742 It will be freed using xfree() when the image instance is
745 If this fails, signal an error. INSTANTIATOR is only used
746 in the error message.
748 #### This should be able to handle conversion into `pointer'.
749 Use the same code as for `xpm'. */
752 init_image_instance_from_x_image(Lisp_Image_Instance * ii,
756 unsigned long *pixels,
758 int slices, Lisp_Object instantiator)
760 Lisp_Object device = IMAGE_INSTANCE_DEVICE(ii);
766 if (!DEVICE_X_P(XDEVICE(device)))
767 signal_simple_error("Not an X device", device);
769 dpy = DEVICE_X_DISPLAY(XDEVICE(device));
770 d = XtWindow(DEVICE_XT_APP_SHELL(XDEVICE(device)));
772 if (!(dest_mask & IMAGE_COLOR_PIXMAP_MASK))
773 incompatible_image_types(instantiator, dest_mask,
774 IMAGE_COLOR_PIXMAP_MASK);
776 pixmap = XCreatePixmap(dpy, d, ximage->width,
777 ximage->height, ximage->depth);
779 signal_simple_error("Unable to create pixmap", instantiator);
781 gc = XCreateGC(dpy, pixmap, 0, NULL);
783 XFreePixmap(dpy, pixmap);
784 signal_simple_error("Unable to create GC", instantiator);
787 XPutImage(dpy, pixmap, gc, ximage, 0, 0, 0, 0,
788 ximage->width, ximage->height);
792 x_initialize_pixmap_image_instance(ii, slices, IMAGE_COLOR_PIXMAP);
794 IMAGE_INSTANCE_PIXMAP_FILENAME(ii) =
795 find_keyword_in_vector(instantiator, Q_file);
797 /* Fixup a set of pixmaps. */
798 IMAGE_INSTANCE_X_PIXMAP(ii) = pixmap;
800 IMAGE_INSTANCE_PIXMAP_MASK(ii) = 0;
801 IMAGE_INSTANCE_PIXMAP_WIDTH(ii) = ximage->width;
802 IMAGE_INSTANCE_PIXMAP_HEIGHT(ii) = ximage->height;
803 IMAGE_INSTANCE_PIXMAP_DEPTH(ii) = ximage->depth;
804 IMAGE_INSTANCE_X_COLORMAP(ii) = cmap;
805 IMAGE_INSTANCE_X_PIXELS(ii) = pixels;
806 IMAGE_INSTANCE_X_NPIXELS(ii) = npixels;
810 image_instance_add_x_image(Lisp_Image_Instance * ii,
811 XImage * ximage, int slice, Lisp_Object instantiator)
813 Lisp_Object device = IMAGE_INSTANCE_DEVICE(ii);
819 dpy = DEVICE_X_DISPLAY(XDEVICE(device));
820 d = XtWindow(DEVICE_XT_APP_SHELL(XDEVICE(device)));
822 pixmap = XCreatePixmap(dpy, d, ximage->width,
823 ximage->height, ximage->depth);
825 signal_simple_error("Unable to create pixmap", instantiator);
827 gc = XCreateGC(dpy, pixmap, 0, NULL);
829 XFreePixmap(dpy, pixmap);
830 signal_simple_error("Unable to create GC", instantiator);
833 XPutImage(dpy, pixmap, gc, ximage, 0, 0, 0, 0,
834 ximage->width, ximage->height);
838 IMAGE_INSTANCE_X_PIXMAP_SLICE(ii, slice) = pixmap;
842 x_init_image_instance_from_eimage(Lisp_Image_Instance * ii,
843 int width, int height,
845 unsigned char *eimage,
847 Lisp_Object instantiator, Lisp_Object domain)
849 Lisp_Object device = IMAGE_INSTANCE_DEVICE(ii);
850 Colormap cmap = DEVICE_X_COLORMAP(XDEVICE(device));
851 unsigned long *pixtbl = NULL;
854 XImage *volatile ximage;
856 for (slice = 0; slice < slices; slice++) {
857 ximage = convert_EImage_to_XImage(device, width, height,
859 (width * height * 3 * slice),
864 signal_image_error("EImage to XImage conversion failed",
868 /* Now create the pixmap and set up the image instance */
870 init_image_instance_from_x_image(ii, ximage, dest_mask,
871 cmap, pixtbl, npixels,
872 slices, instantiator);
876 image_instance_add_x_image(ii, ximage, slice,
885 XDestroyImage(ximage);
891 int read_bitmap_data_from_file(const char *filename, unsigned int *width,
892 unsigned int *height, unsigned char **datap,
893 int *x_hot, int *y_hot)
895 return XmuReadBitmapDataFromFile(filename, width, height,
896 datap, x_hot, y_hot);
899 /* Given inline data for a mono pixmap, create and return the
900 corresponding X object. */
903 pixmap_from_xbm_inline(Lisp_Object device, int width, int height,
904 /* Note that data is in ext-format! */
907 return XCreatePixmapFromBitmapData
908 (DEVICE_X_DISPLAY(XDEVICE(device)),
909 XtWindow(DEVICE_XT_APP_SHELL(XDEVICE(device))),
910 bits, width, height, 1, 0, 1);
913 /* Given inline data for a mono pixmap, initialize the given
914 image instance accordingly. */
917 init_image_instance_from_xbm_inline(Lisp_Image_Instance * ii,
918 int width, int height,
919 /* Note that data is in ext-format! */
921 Lisp_Object instantiator,
922 Lisp_Object pointer_fg,
923 Lisp_Object pointer_bg,
925 Pixmap mask, Lisp_Object mask_filename)
927 Lisp_Object device = IMAGE_INSTANCE_DEVICE(ii);
928 Lisp_Object foreground =
929 find_keyword_in_vector(instantiator, Q_foreground);
930 Lisp_Object background =
931 find_keyword_in_vector(instantiator, Q_background);
935 enum image_instance_type type;
937 if (!DEVICE_X_P(XDEVICE(device)))
938 signal_simple_error("Not an X device", device);
940 dpy = DEVICE_X_DISPLAY(XDEVICE(device));
941 draw = XtWindow(DEVICE_XT_APP_SHELL(XDEVICE(device)));
942 scr = DefaultScreenOfDisplay(dpy);
944 if ((dest_mask & IMAGE_MONO_PIXMAP_MASK) &&
945 (dest_mask & IMAGE_COLOR_PIXMAP_MASK)) {
946 if (!NILP(foreground) || !NILP(background))
947 type = IMAGE_COLOR_PIXMAP;
949 type = IMAGE_MONO_PIXMAP;
950 } else if (dest_mask & IMAGE_MONO_PIXMAP_MASK)
951 type = IMAGE_MONO_PIXMAP;
952 else if (dest_mask & IMAGE_COLOR_PIXMAP_MASK)
953 type = IMAGE_COLOR_PIXMAP;
954 else if (dest_mask & IMAGE_POINTER_MASK)
955 type = IMAGE_POINTER;
957 incompatible_image_types(instantiator, dest_mask,
958 IMAGE_MONO_PIXMAP_MASK |
959 IMAGE_COLOR_PIXMAP_MASK |
962 x_initialize_pixmap_image_instance(ii, 1, type);
963 IMAGE_INSTANCE_PIXMAP_WIDTH(ii) = width;
964 IMAGE_INSTANCE_PIXMAP_HEIGHT(ii) = height;
965 IMAGE_INSTANCE_PIXMAP_FILENAME(ii) =
966 find_keyword_in_vector(instantiator, Q_file);
969 case IMAGE_MONO_PIXMAP: {
970 IMAGE_INSTANCE_X_PIXMAP(ii) =
971 pixmap_from_xbm_inline(device, width, height,
976 case IMAGE_COLOR_PIXMAP: {
977 Dimension d = DEVICE_X_DEPTH(XDEVICE(device));
978 unsigned long fg = BlackPixelOfScreen(scr);
979 unsigned long bg = WhitePixelOfScreen(scr);
981 if (!NILP(foreground) && !COLOR_INSTANCEP(foreground))
983 Fmake_color_instance(foreground, device,
984 encode_error_behavior_flag
987 if (COLOR_INSTANCEP(foreground))
988 fg = COLOR_INSTANCE_X_COLOR(XCOLOR_INSTANCE
991 if (!NILP(background) && !COLOR_INSTANCEP(background))
993 Fmake_color_instance(background, device,
994 encode_error_behavior_flag
997 if (COLOR_INSTANCEP(background))
998 bg = COLOR_INSTANCE_X_COLOR(XCOLOR_INSTANCE
1001 /* We used to duplicate the pixels using XAllocColor(), to protect
1002 against their getting freed. Just as easy to just store the
1003 color instances here and GC-protect them, so this doesn't
1005 IMAGE_INSTANCE_PIXMAP_FG(ii) = foreground;
1006 IMAGE_INSTANCE_PIXMAP_BG(ii) = background;
1007 IMAGE_INSTANCE_X_PIXMAP(ii) =
1008 XCreatePixmapFromBitmapData(dpy, draw,
1009 (char *)bits, width,
1011 IMAGE_INSTANCE_PIXMAP_DEPTH(ii) = d;
1015 case IMAGE_POINTER: {
1016 XColor fg_color, bg_color;
1019 check_pointer_sizes(scr, width, height, instantiator);
1022 XCreatePixmapFromBitmapData(dpy, draw,
1023 (char *)bits, width,
1026 if (NILP(foreground))
1027 foreground = pointer_fg;
1028 if (NILP(background))
1029 background = pointer_bg;
1030 generate_cursor_fg_bg(device, &foreground, &background,
1031 &fg_color, &bg_color);
1033 IMAGE_INSTANCE_PIXMAP_FG(ii) = foreground;
1034 IMAGE_INSTANCE_PIXMAP_BG(ii) = background;
1035 IMAGE_INSTANCE_PIXMAP_HOTSPOT_X(ii) =
1036 find_keyword_in_vector(instantiator, Q_hotspot_x);
1037 IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y(ii) =
1038 find_keyword_in_vector(instantiator, Q_hotspot_y);
1039 IMAGE_INSTANCE_X_CURSOR(ii) =
1041 (dpy, source, mask, &fg_color, &bg_color,
1042 !NILP(IMAGE_INSTANCE_PIXMAP_HOTSPOT_X(ii)) ?
1043 XINT(IMAGE_INSTANCE_PIXMAP_HOTSPOT_X(ii)) : 0,
1044 !NILP(IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y(ii)) ?
1045 XINT(IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y(ii)) : 0);
1052 case IMAGE_SUBWINDOW:
1060 xbm_instantiate_1(Lisp_Object image_instance, Lisp_Object instantiator,
1061 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1062 int dest_mask, int width, int height,
1063 /* Note that data is in ext-format! */
1066 Lisp_Object mask_data =
1067 find_keyword_in_vector(instantiator, Q_mask_data);
1068 Lisp_Object mask_file =
1069 find_keyword_in_vector(instantiator, Q_mask_file);
1070 Lisp_Image_Instance *ii = XIMAGE_INSTANCE(image_instance);
1073 if (!NILP(mask_data)) {
1076 LISP_STRING_TO_EXTERNAL(XCAR(XCDR(XCDR(mask_data))), ext_data,
1078 mask = pixmap_from_xbm_inline(
1079 IMAGE_INSTANCE_DEVICE(ii),
1080 XINT(XCAR(mask_data)),
1081 XINT(XCAR(XCDR(mask_data))),
1085 init_image_instance_from_xbm_inline(ii, width, height, bits,
1086 instantiator, pointer_fg,
1087 pointer_bg, dest_mask, mask,
1091 /* Instantiate method for XBM's. */
1094 x_xbm_instantiate(Lisp_Object image_instance, Lisp_Object instantiator,
1095 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1096 int dest_mask, Lisp_Object domain)
1098 Lisp_Object data = find_keyword_in_vector(instantiator, Q_data);
1101 assert(!NILP(data));
1103 LISP_STRING_TO_EXTERNAL(XCAR(XCDR(XCDR(data))), ext_data, Qbinary);
1105 xbm_instantiate_1(image_instance, instantiator, pointer_fg,
1106 pointer_bg, dest_mask, XINT(XCAR(data)),
1107 XINT(XCAR(XCDR(data))), ext_data);
1112 /**********************************************************************
1114 **********************************************************************/
1115 /* xpm 3.2g and better has XpmCreatePixmapFromBuffer()...
1116 There was no version number in xpm.h before 3.3, but this should do.
1118 #if (XpmVersion >= 3) || defined(XpmExactColors)
1119 # define XPM_DOES_BUFFERS
1122 #ifndef XPM_DOES_BUFFERS
1123 Your version of XPM is too old.You cannot compile with it.
1124 Upgrade to version 3.2 g or better or compile with-- with - xpm = no.
1125 #endif /* !XPM_DOES_BUFFERS */
1126 static XpmColorSymbol *
1127 extract_xpm_color_names(XpmAttributes * xpmattrs, Lisp_Object device,
1129 Lisp_Object color_symbol_alist) {
1130 /* This function can GC */
1131 Display * dpy = DEVICE_X_DISPLAY(XDEVICE(device));
1132 Colormap cmap = DEVICE_X_COLORMAP(XDEVICE(device));
1135 Lisp_Object results = Qnil;
1137 XpmColorSymbol *symbols;
1138 struct gcpro gcpro1, gcpro2;
1140 GCPRO2(results, device);
1142 /* We built up results to be (("name" . #<color>) ...) so that if an
1143 error happens we don't lose any malloc()ed data, or more importantly,
1144 leave any pixels allocated in the server. */
1146 LIST_LOOP(rest, color_symbol_alist) {
1147 Lisp_Object cons = XCAR(rest);
1148 Lisp_Object name = XCAR(cons);
1149 Lisp_Object value = XCDR(cons);
1154 Fmake_color_instance
1156 encode_error_behavior_flag(ERROR_ME_NOT));
1158 assert(COLOR_SPECIFIERP(value));
1159 value = Fspecifier_instance(value, domain, Qnil, Qnil);
1163 results = noseeum_cons(noseeum_cons(name, value), results);
1166 UNGCPRO; /* no more evaluation */
1171 symbols = xnew_atomic_array(XpmColorSymbol, i);
1172 xpmattrs->valuemask |= XpmColorSymbols;
1173 xpmattrs->colorsymbols = symbols;
1174 xpmattrs->numsymbols = i;
1177 Lisp_Object cons = XCAR(results);
1178 color = COLOR_INSTANCE_X_COLOR(XCOLOR_INSTANCE(XCDR(cons)));
1179 /* Duplicate the pixel value so that we still have
1180 * a lock on it if the pixel we were passed is later freed. */
1181 if (!XAllocColor(dpy, cmap, &color)) {
1182 /* it must be allocable since we're
1183 * just duplicating it */
1187 symbols[i].name = (char *)XSTRING_DATA(XCAR(cons));
1188 symbols[i].pixel = color.pixel;
1189 symbols[i].value = 0;
1190 free_cons(XCONS(cons));
1192 results = XCDR(results);
1193 free_cons(XCONS(cons));
1198 static void xpm_free(XpmAttributes * xpmattrs)
1200 /* Could conceivably lose if XpmXXX returned an error without first
1201 initializing this structure, if we didn't know that initializing it
1202 to all zeros was ok (and also that it's ok to call XpmFreeAttributes()
1203 multiple times, since it zeros slots as it frees them...) */
1204 XpmFreeAttributes(xpmattrs);
1208 x_xpm_instantiate(Lisp_Object image_instance, Lisp_Object instantiator,
1209 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1210 int dest_mask, Lisp_Object domain)
1212 /* This function can GC */
1213 Lisp_Image_Instance *ii = XIMAGE_INSTANCE(image_instance);
1214 Lisp_Object device = IMAGE_INSTANCE_DEVICE(ii);
1215 Lisp_Object data = find_keyword_in_vector(instantiator, Q_data);
1223 XpmAttributes xpmattrs;
1225 XpmColorSymbol *color_symbols;
1226 Lisp_Object color_symbol_alist = find_keyword_in_vector(instantiator,
1228 enum image_instance_type type;
1232 if (!DEVICE_X_P(XDEVICE(device)))
1233 signal_simple_error("Not an X device", device);
1235 dpy = DEVICE_X_DISPLAY(XDEVICE(device));
1236 xs = DefaultScreenOfDisplay(dpy);
1238 if (dest_mask & IMAGE_COLOR_PIXMAP_MASK)
1239 type = IMAGE_COLOR_PIXMAP;
1240 else if (dest_mask & IMAGE_MONO_PIXMAP_MASK)
1241 type = IMAGE_MONO_PIXMAP;
1242 else if (dest_mask & IMAGE_POINTER_MASK)
1243 type = IMAGE_POINTER;
1245 incompatible_image_types(instantiator, dest_mask,
1246 IMAGE_MONO_PIXMAP_MASK |
1247 IMAGE_COLOR_PIXMAP_MASK |
1248 IMAGE_POINTER_MASK);
1249 force_mono = (type != IMAGE_COLOR_PIXMAP);
1252 /* Although I haven't found it documented yet, it appears that pointers are
1253 always colored via the default window colormap... Sigh. */
1254 if (type == IMAGE_POINTER) {
1255 cmap = DefaultColormap(dpy, DefaultScreen(dpy));
1256 depth = DefaultDepthOfScreen(xs);
1257 visual = DefaultVisualOfScreen(xs);
1259 cmap = DEVICE_X_COLORMAP(XDEVICE(device));
1260 depth = DEVICE_X_DEPTH(XDEVICE(device));
1261 visual = DEVICE_X_VISUAL(XDEVICE(device));
1264 cmap = DEVICE_X_COLORMAP(XDEVICE(device));
1265 depth = DEVICE_X_DEPTH(XDEVICE(device));
1266 visual = DEVICE_X_VISUAL(XDEVICE(device));
1269 x_initialize_pixmap_image_instance(ii, 1, type);
1271 assert(!NILP(data));
1275 xzero(xpmattrs); /* want XpmInitAttributes() */
1276 xpmattrs.valuemask = XpmReturnPixels;
1278 /* Without this, we get a 1-bit version of the color image, which
1279 isn't quite right. With this, we get the mono image, which might
1280 be very different looking. */
1281 xpmattrs.valuemask |= XpmColorKey;
1282 xpmattrs.color_key = XPM_MONO;
1284 xpmattrs.valuemask |= XpmDepth;
1286 xpmattrs.closeness = 65535;
1287 xpmattrs.valuemask |= XpmCloseness;
1288 xpmattrs.depth = depth;
1289 xpmattrs.valuemask |= XpmDepth;
1290 xpmattrs.visual = visual;
1291 xpmattrs.valuemask |= XpmVisual;
1292 xpmattrs.colormap = cmap;
1293 xpmattrs.valuemask |= XpmColormap;
1296 color_symbols = extract_xpm_color_names(&xpmattrs, device, domain,
1297 color_symbol_alist);
1299 result = XpmCreatePixmapFromBuffer(dpy,
1300 XtWindow(DEVICE_XT_APP_SHELL
1302 (char *)XSTRING_DATA(data), &pixmap,
1305 if (color_symbols) {
1306 xfree(color_symbols);
1307 xpmattrs.colorsymbols = 0; /* in case XpmFreeAttr is too smart... */
1308 xpmattrs.numsymbols = 0;
1314 case XpmFileInvalid:
1316 xpm_free(&xpmattrs);
1317 signal_image_error("invalid XPM data", data);
1319 case XpmColorFailed:
1322 xpm_free(&xpmattrs);
1324 /* second time; blow out. */
1325 signal_double_file_error("Reading pixmap data",
1326 "color allocation failed",
1329 if (!(dest_mask & IMAGE_MONO_PIXMAP_MASK)) {
1330 /* second time; blow out. */
1331 signal_double_file_error
1332 ("Reading pixmap data",
1333 "color allocation failed", data);
1336 IMAGE_INSTANCE_TYPE(ii) = IMAGE_MONO_PIXMAP;
1342 xpm_free(&xpmattrs);
1343 signal_double_file_error("Parsing pixmap data",
1344 "out of memory", data);
1348 xpm_free(&xpmattrs);
1349 signal_double_file_error_2("Parsing pixmap data",
1350 "unknown error code",
1351 make_int(result), data);
1356 h = xpmattrs.height;
1359 int npixels = xpmattrs.npixels;
1363 pixels = xnew_atomic_array(Pixel, npixels);
1364 memcpy(pixels, xpmattrs.pixels,
1365 npixels * sizeof(Pixel));
1370 IMAGE_INSTANCE_X_PIXMAP(ii) = pixmap;
1371 IMAGE_INSTANCE_PIXMAP_MASK(ii) = (void *)mask;
1372 IMAGE_INSTANCE_X_COLORMAP(ii) = cmap;
1373 IMAGE_INSTANCE_X_PIXELS(ii) = pixels;
1374 IMAGE_INSTANCE_X_NPIXELS(ii) = npixels;
1375 IMAGE_INSTANCE_PIXMAP_WIDTH(ii) = w;
1376 IMAGE_INSTANCE_PIXMAP_HEIGHT(ii) = h;
1377 IMAGE_INSTANCE_PIXMAP_FILENAME(ii) =
1378 find_keyword_in_vector(instantiator, Q_file);
1382 case IMAGE_MONO_PIXMAP:
1385 case IMAGE_COLOR_PIXMAP: {
1386 IMAGE_INSTANCE_PIXMAP_DEPTH(ii) = depth;
1390 case IMAGE_POINTER: {
1391 int npixels = xpmattrs.npixels;
1392 Pixel *pixels = xpmattrs.pixels;
1395 int xhot = 0, yhot = 0;
1397 if (xpmattrs.valuemask & XpmHotspot) {
1398 xhot = xpmattrs.x_hotspot;
1399 XSETINT(IMAGE_INSTANCE_PIXMAP_HOTSPOT_X(ii),
1400 xpmattrs.x_hotspot);
1402 if (xpmattrs.valuemask & XpmHotspot) {
1403 yhot = xpmattrs.y_hotspot;
1404 XSETINT(IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y(ii),
1405 xpmattrs.y_hotspot);
1407 check_pointer_sizes(xs, w, h, instantiator);
1409 /* If the loaded pixmap has colors allocated (meaning it came
1410 from an XPM file), then use those as the default colors for
1411 the cursor we create. Otherwise, default to pointer_fg and
1415 /* With an XBM file, it's obvious which bit is
1416 foreground and which is background, or rather, it's
1417 implicit: in an XBM file, a 1 bit is foreground, and
1418 a 0 bit is background.
1420 XCreatePixmapCursor() assumes this property of the
1421 pixmap it is called with as well; the `foreground'
1422 color argument is used for the 1 bits.
1424 With an XPM file, it's tricker, since the elements of
1425 the pixmap don't represent FG and BG, but are actual
1426 pixel values. So we need to figure out which of
1427 those pixels is the foreground color and which is the
1428 background. We do it by comparing RGB and assuming
1429 that the darker color is the foreground. This works
1430 with the result of xbmtopbm|ppmtoxpm, at least.
1432 It might be nice if there was some way to tag the
1433 colors in the XPM file with whether they are the
1434 foreground - perhaps with logical color names
1437 Once we have decided which color is the foreground,
1438 we need to ensure that that color corresponds to a
1439 `1' bit in the Pixmap. The XPM library wrote into
1440 the (1-bit) pixmap with XPutPixel, which will ignore
1441 all but the least significant bit.
1443 This means that a 1 bit in the image corresponds to
1444 `fg' only if `fg.pixel' is odd.
1446 (This also means that the image will be all the same
1447 color if both `fg' and `bg' are odd or even, but we
1448 can safely assume that that won't happen if the XPM
1449 file is sensible I think.)
1451 The desired result is that the image use `1' to
1452 represent the foreground color, and `0' to represent
1453 the background color. So, we may need to invert the
1454 image to accomplish this; we invert if fg is
1455 odd. (Remember that WhitePixel and BlackPixel are not
1456 necessarily 1 and 0 respectively, though I think it
1457 might be safe to assume that one of them is always 1
1458 and the other is always 0. We also pretty much need
1459 to assume that one is even and the other is odd.)
1462 fg.pixel = pixels[0]; /* pick a pixel at random. */
1463 bg.pixel = fg.pixel;
1464 for (i = 1; i < npixels; i++) {
1465 /* Look for an "other" pixel value. */
1466 bg.pixel = pixels[i];
1467 if (fg.pixel != bg.pixel)
1471 /* If (fg.pixel == bg.pixel) then probably something has
1472 gone wrong, but I don't think signalling an error
1473 would be appropriate. */
1475 XQueryColor(dpy, cmap, &fg);
1476 XQueryColor(dpy, cmap, &bg);
1478 /* If the foreground is lighter than the background,
1479 swap them. (This occurs semi-randomly, depending on
1480 the ordering of the color list in the XPM file.)
1483 unsigned short fg_total =
1484 ((fg.red / 3) + (fg.green / 3)
1486 unsigned short bg_total =
1487 ((bg.red / 3) + (bg.green / 3)
1489 if (fg_total > bg_total) {
1497 /* If the fg pixel corresponds to a `0' in the bitmap,
1498 invert it. (This occurs (only?) on servers with
1501 if ((fg.pixel & 1) == 0) {
1504 gcv.function = GXxor;
1506 gc = XCreateGC(dpy, pixmap,
1508 GCForeground), &gcv);
1509 XFillRectangle(dpy, pixmap, gc, 0, 0, w,
1514 generate_cursor_fg_bg(device, &pointer_fg,
1515 &pointer_bg, &fg, &bg);
1516 IMAGE_INSTANCE_PIXMAP_FG(ii) = pointer_fg;
1517 IMAGE_INSTANCE_PIXMAP_BG(ii) = pointer_bg;
1520 IMAGE_INSTANCE_X_CURSOR(ii) =
1522 (dpy, pixmap, mask, &fg, &bg, xhot, yhot);
1530 case IMAGE_SUBWINDOW:
1536 xpm_free(&xpmattrs); /* after we've read pixels and hotspot */
1539 #endif /* HAVE_XPM */
1543 /**********************************************************************
1545 **********************************************************************/
1547 /* This is about to get redefined! */
1550 /* We have to define SYSV32 so that compface.h includes string.h
1551 instead of strings.h. */
1556 #include <compface.h>
1560 /* JMP_BUF cannot be used here because if it doesn't get defined
1561 to jmp_buf we end up with a conflicting type error with the
1562 definition in compface.h */ extern jmp_buf comp_env;
1566 x_xface_instantiate(Lisp_Object image_instance, Lisp_Object instantiator,
1567 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1568 int dest_mask, Lisp_Object domain)
1570 Lisp_Object data = find_keyword_in_vector(instantiator, Q_data);
1574 const char *volatile emsg = 0;
1575 char *volatile dstring;
1577 assert(!NILP(data));
1579 LISP_STRING_TO_EXTERNAL(data, dstring, Qbinary);
1581 if ((p = strchr(dstring, ':'))) {
1585 /* Must use setjmp not SETJMP because we used jmp_buf above not
1587 if (!(stattis = setjmp(comp_env))) {
1594 emsg = "uncompface: internal error";
1597 emsg = "uncompface: insufficient or invalid data";
1600 emsg = "uncompface: excess data ignored";
1607 signal_simple_error_2(emsg, data, Qimage);
1609 bp = bits = (char *)alloca(PIXELS / 8);
1611 /* the compface library exports char F[], which uses a single byte per
1612 pixel to represent a 48x48 bitmap. Yuck. */
1613 for (i = 0, p = F; i < (PIXELS / 8); ++i) {
1615 /* reverse the bit order of each byte... */
1616 for (b = n = 0; b < 8; ++b) {
1622 xbm_instantiate_1(image_instance, instantiator, pointer_fg,
1623 pointer_bg, dest_mask, 48, 48, bits);
1626 #endif /* HAVE_XFACE */
1628 /**********************************************************************
1630 **********************************************************************/
1632 static void autodetect_validate(Lisp_Object instantiator)
1634 data_must_be_present(instantiator);
1638 autodetect_normalize(Lisp_Object instantiator,
1639 Lisp_Object console_type, Lisp_Object dest_mask)
1641 Lisp_Object file = find_keyword_in_vector(instantiator, Q_data);
1642 Lisp_Object filename = Qnil;
1643 Lisp_Object data = Qnil;
1644 struct gcpro gcpro1, gcpro2, gcpro3;
1645 Lisp_Object alist = Qnil;
1647 GCPRO3(filename, data, alist);
1649 if (NILP(file)) /* no conversion necessary */
1650 RETURN_UNGCPRO(instantiator);
1652 alist = tagged_vector_to_alist(instantiator);
1654 filename = locate_pixmap_file(file);
1655 if (!NILP(filename)) {
1657 /* #### Apparently some versions of XpmReadFileToData, which is
1658 called by pixmap_to_lisp_data, don't return an error value if
1659 the given file is not a valid XPM file. Instead, they just
1660 seg fault. It is definitely caused by passing a bitmap. To
1661 try and avoid this we check for bitmaps first. */
1663 data = bitmap_to_lisp_data(filename, &xhot, &yhot, 1);
1665 if (!EQ(data, Qt)) {
1666 alist = remassq_no_quit(Q_data, alist);
1667 alist = Fcons(Fcons(Q_file, filename),
1668 Fcons(Fcons(Q_data, data), alist));
1670 alist = Fcons(Fcons(Q_hotspot_x, make_int(xhot)),
1674 alist = Fcons(Fcons(Q_hotspot_y,
1678 alist = xbm_mask_file_munging(alist, filename, Qnil,
1682 Lisp_Object result =
1683 alist_to_tagged_vector(Qxbm, alist);
1685 RETURN_UNGCPRO(result);
1689 data = pixmap_to_lisp_data(filename, 1);
1691 if (!EQ(data, Qt)) {
1692 alist = remassq_no_quit(Q_data, alist);
1693 alist = Fcons(Fcons(Q_file, filename),
1694 Fcons(Fcons(Q_data, data), alist));
1695 alist = Fcons(Fcons(Q_color_symbols,
1696 evaluate_xpm_color_symbols()),
1699 Lisp_Object result =
1700 alist_to_tagged_vector(Qxpm, alist);
1702 RETURN_UNGCPRO(result);
1708 /* If we couldn't convert it, just put it back as it is.
1709 We might try to further frob it later as a cursor-font
1710 specification. (We can't do that now because we don't know
1711 what dest-types it's going to be instantiated into.) */
1713 Lisp_Object result = alist_to_tagged_vector(Qautodetect, alist);
1715 RETURN_UNGCPRO(result);
1719 static int autodetect_possible_dest_types(void)
1722 IMAGE_MONO_PIXMAP_MASK |
1723 IMAGE_COLOR_PIXMAP_MASK | IMAGE_POINTER_MASK | IMAGE_TEXT_MASK;
1727 autodetect_instantiate(Lisp_Object image_instance,
1728 Lisp_Object instantiator,
1729 Lisp_Object pointer_fg,
1730 Lisp_Object pointer_bg,
1731 int dest_mask, Lisp_Object domain)
1733 Lisp_Object data = find_keyword_in_vector(instantiator, Q_data);
1734 struct gcpro gcpro1, gcpro2, gcpro3;
1735 Lisp_Object alist = Qnil;
1736 Lisp_Object result = Qnil;
1737 int is_cursor_font = 0;
1739 GCPRO3(data, alist, result);
1741 alist = tagged_vector_to_alist(instantiator);
1742 if (dest_mask & IMAGE_POINTER_MASK) {
1743 const char *name_ext;
1744 LISP_STRING_TO_EXTERNAL(data, name_ext, Qfile_name);
1745 if (XmuCursorNameToIndex(name_ext) != -1) {
1746 result = alist_to_tagged_vector(Qcursor_font, alist);
1751 if (!is_cursor_font)
1752 result = alist_to_tagged_vector(Qstring, alist);
1756 cursor_font_instantiate(image_instance, result, pointer_fg,
1757 pointer_bg, dest_mask, domain);
1759 string_instantiate(image_instance, result, pointer_fg,
1760 pointer_bg, dest_mask, domain);
1765 /**********************************************************************
1767 **********************************************************************/
1769 static void font_validate(Lisp_Object instantiator)
1771 data_must_be_present(instantiator);
1774 /* XmuCvtStringToCursor is bogus in the following ways:
1776 - When it can't convert the given string to a real cursor, it will
1777 sometimes return a "success" value, after triggering a BadPixmap
1778 error. It then gives you a cursor that will itself generate BadCursor
1779 errors. So we install this error handler to catch/notice the X error
1780 and take that as meaning "couldn't convert."
1782 - When you tell it to find a cursor file that doesn't exist, it prints
1783 an error message on stderr. You can't make it not do that.
1785 - Also, using Xmu means we can't properly hack Lisp_Image_Instance
1786 objects, or XPM files, or $XBMLANGPATH.
1789 /* Duplicate the behavior of XmuCvtStringToCursor() to bypass its bogusness. */
1791 static int XLoadFont_got_error;
1793 static int XLoadFont_error_handler(Display * dpy, XErrorEvent * xerror)
1795 XLoadFont_got_error = 1;
1799 static Font safe_XLoadFont(Display * dpy, char *name)
1802 int (*old_handler) (Display *, XErrorEvent *);
1803 XLoadFont_got_error = 0;
1805 old_handler = XSetErrorHandler(XLoadFont_error_handler);
1806 font = XLoadFont(dpy, name);
1808 XSetErrorHandler(old_handler);
1809 if (XLoadFont_got_error)
1814 static int font_possible_dest_types(void)
1816 return IMAGE_POINTER_MASK;
1820 font_instantiate(Lisp_Object image_instance, Lisp_Object instantiator,
1821 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1822 int dest_mask, Lisp_Object domain)
1824 /* This function can GC */
1825 Lisp_Object data = find_keyword_in_vector(instantiator, Q_data);
1826 Lisp_Image_Instance *ii = XIMAGE_INSTANCE(image_instance);
1827 Lisp_Object device = IMAGE_INSTANCE_DEVICE(ii);
1831 char source_name[MAXPATHLEN], mask_name[MAXPATHLEN], dummy;
1832 int source_char, mask_char;
1834 Lisp_Object foreground, background;
1836 if (!DEVICE_X_P(XDEVICE(device)))
1837 signal_simple_error("Not an X device", device);
1839 dpy = DEVICE_X_DISPLAY(XDEVICE(device));
1841 if (!STRINGP(data) || strncmp("FONT ", (char *)XSTRING_DATA(data), 5))
1842 signal_simple_error("Invalid font-glyph instantiator",
1845 if (!(dest_mask & IMAGE_POINTER_MASK))
1846 incompatible_image_types(instantiator, dest_mask,
1847 IMAGE_POINTER_MASK);
1849 foreground = find_keyword_in_vector(instantiator, Q_foreground);
1850 if (NILP(foreground))
1851 foreground = pointer_fg;
1852 background = find_keyword_in_vector(instantiator, Q_background);
1853 if (NILP(background))
1854 background = pointer_bg;
1856 generate_cursor_fg_bg(device, &foreground, &background, &fg, &bg);
1858 count = sscanf((char *)XSTRING_DATA(data),
1859 "FONT %s %d %s %d %c",
1860 source_name, &source_char,
1861 mask_name, &mask_char, &dummy);
1862 /* Allow "%s %d %d" as well... */
1863 if (count == 3 && (1 == sscanf(mask_name, "%d %c", &mask_char, &dummy)))
1864 count = 4, mask_name[0] = 0;
1866 if (count != 2 && count != 4)
1867 signal_simple_error("invalid cursor specification", data);
1868 source = safe_XLoadFont(dpy, source_name);
1870 signal_simple_error_2("couldn't load font",
1871 build_string(source_name), data);
1874 else if (!mask_name[0])
1877 mask = safe_XLoadFont(dpy, mask_name);
1881 list3(build_string("couldn't load font"),
1882 build_string(mask_name), data));
1887 /* #### call XQueryTextExtents() and check_pointer_sizes() here. */
1889 x_initialize_pixmap_image_instance(ii, 1, IMAGE_POINTER);
1890 IMAGE_INSTANCE_X_CURSOR(ii) =
1891 XCreateGlyphCursor(dpy, source, mask, source_char, mask_char,
1893 XIMAGE_INSTANCE_PIXMAP_FG(image_instance) = foreground;
1894 XIMAGE_INSTANCE_PIXMAP_BG(image_instance) = background;
1895 XUnloadFont(dpy, source);
1896 if (mask && mask != source)
1897 XUnloadFont(dpy, mask);
1900 /**********************************************************************
1902 **********************************************************************/
1904 static void cursor_font_validate(Lisp_Object instantiator)
1906 data_must_be_present(instantiator);
1909 static int cursor_font_possible_dest_types(void)
1911 return IMAGE_POINTER_MASK;
1915 cursor_font_instantiate(Lisp_Object image_instance, Lisp_Object instantiator,
1916 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1917 int dest_mask, Lisp_Object domain)
1919 /* This function can GC */
1920 Lisp_Object data = find_keyword_in_vector(instantiator, Q_data);
1921 Lisp_Image_Instance *ii = XIMAGE_INSTANCE(image_instance);
1922 Lisp_Object device = IMAGE_INSTANCE_DEVICE(ii);
1925 const char *name_ext;
1926 Lisp_Object foreground, background;
1928 if (!DEVICE_X_P(XDEVICE(device)))
1929 signal_simple_error("Not an X device", device);
1931 dpy = DEVICE_X_DISPLAY(XDEVICE(device));
1933 if (!(dest_mask & IMAGE_POINTER_MASK))
1934 incompatible_image_types(instantiator, dest_mask,
1935 IMAGE_POINTER_MASK);
1937 LISP_STRING_TO_EXTERNAL(data, name_ext, Qfile_name);
1938 if ((i = XmuCursorNameToIndex(name_ext)) == -1)
1939 signal_simple_error("Unrecognized cursor-font name", data);
1941 x_initialize_pixmap_image_instance(ii, 1, IMAGE_POINTER);
1942 IMAGE_INSTANCE_X_CURSOR(ii) = XCreateFontCursor(dpy, i);
1943 foreground = find_keyword_in_vector(instantiator, Q_foreground);
1944 if (NILP(foreground))
1945 foreground = pointer_fg;
1946 background = find_keyword_in_vector(instantiator, Q_background);
1947 if (NILP(background))
1948 background = pointer_bg;
1949 maybe_recolor_cursor(image_instance, foreground, background);
1953 x_colorize_image_instance(Lisp_Object image_instance,
1954 Lisp_Object foreground, Lisp_Object background)
1956 Lisp_Image_Instance *p;
1958 p = XIMAGE_INSTANCE(image_instance);
1960 switch (IMAGE_INSTANCE_TYPE(p)) {
1961 case IMAGE_MONO_PIXMAP:
1962 IMAGE_INSTANCE_TYPE(p) = IMAGE_COLOR_PIXMAP;
1963 /* Make sure there aren't two pointers to the same mask, causing
1964 it to get freed twice. */
1965 IMAGE_INSTANCE_PIXMAP_MASK(p) = 0;
1971 case IMAGE_SUBWINDOW:
1973 case IMAGE_COLOR_PIXMAP:
1981 DEVICE_X_DISPLAY(XDEVICE(IMAGE_INSTANCE_DEVICE(p)));
1983 XtWindow(DEVICE_XT_APP_SHELL
1984 (XDEVICE(IMAGE_INSTANCE_DEVICE(p))));
1985 Dimension d = DEVICE_X_DEPTH(XDEVICE(IMAGE_INSTANCE_DEVICE(p)));
1986 Pixmap new = XCreatePixmap(dpy, draw,
1987 IMAGE_INSTANCE_PIXMAP_WIDTH(p),
1988 IMAGE_INSTANCE_PIXMAP_HEIGHT(p), d);
1992 color = COLOR_INSTANCE_X_COLOR(XCOLOR_INSTANCE(foreground));
1993 gcv.foreground = color.pixel;
1994 color = COLOR_INSTANCE_X_COLOR(XCOLOR_INSTANCE(background));
1995 gcv.background = color.pixel;
1996 gc = XCreateGC(dpy, new, GCBackground | GCForeground, &gcv);
1997 XCopyPlane(dpy, IMAGE_INSTANCE_X_PIXMAP(p), new, gc, 0, 0,
1998 IMAGE_INSTANCE_PIXMAP_WIDTH(p),
1999 IMAGE_INSTANCE_PIXMAP_HEIGHT(p), 0, 0, 1);
2001 IMAGE_INSTANCE_X_PIXMAP(p) = new;
2002 IMAGE_INSTANCE_PIXMAP_DEPTH(p) = d;
2003 IMAGE_INSTANCE_PIXMAP_FG(p) = foreground;
2004 IMAGE_INSTANCE_PIXMAP_BG(p) = background;
2009 /************************************************************************/
2010 /* subwindow and widget support */
2011 /************************************************************************/
2013 /* unmap the image if it is a widget. This is used by redisplay via
2014 redisplay_unmap_subwindows */
2015 static void x_unmap_subwindow(Lisp_Image_Instance * p)
2017 if (IMAGE_INSTANCE_TYPE(p) == IMAGE_SUBWINDOW) {
2019 (IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY(p),
2020 IMAGE_INSTANCE_X_CLIPWINDOW(p));
2021 } else { /* must be a widget */
2023 /* Since we are being unmapped we want the enclosing frame to
2024 get focus. The losing with simple scrolling but is the safest
2026 emacs_Xt_handle_widget_losing_focus
2027 (XFRAME(IMAGE_INSTANCE_FRAME(p)),
2028 IMAGE_INSTANCE_X_WIDGET_ID(p));
2029 XtUnmapWidget(IMAGE_INSTANCE_X_CLIPWIDGET(p));
2033 /* map the subwindow. This is used by redisplay via
2034 redisplay_output_subwindow */
2036 x_map_subwindow(Lisp_Image_Instance * p, int x, int y,
2037 struct display_glyph_area *dga)
2039 assert(dga->width > 0 && dga->height > 0);
2040 if (IMAGE_INSTANCE_TYPE(p) == IMAGE_SUBWINDOW) {
2041 Window subwindow = IMAGE_INSTANCE_X_SUBWINDOW_ID(p);
2042 XMoveResizeWindow(IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY(p),
2043 IMAGE_INSTANCE_X_CLIPWINDOW(p),
2044 x, y, dga->width, dga->height);
2045 XMoveWindow(IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY(p),
2046 subwindow, -dga->xoffset, -dga->yoffset);
2047 if (!IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP(p))
2048 XMapWindow(IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY(p),
2049 IMAGE_INSTANCE_X_CLIPWINDOW(p));
2050 } else { /* must be a widget */
2052 XtConfigureWidget(IMAGE_INSTANCE_X_CLIPWIDGET(p),
2053 x + IMAGE_INSTANCE_X_WIDGET_XOFFSET(p),
2054 y + IMAGE_INSTANCE_X_WIDGET_YOFFSET(p),
2055 dga->width, dga->height, 0);
2056 XtMoveWidget(IMAGE_INSTANCE_X_WIDGET_ID(p),
2057 -dga->xoffset, -dga->yoffset);
2058 if (!IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP(p))
2059 XtMapWidget(IMAGE_INSTANCE_X_CLIPWIDGET(p));
2060 if (IMAGE_INSTANCE_WANTS_INITIAL_FOCUS(p)) {
2061 /* #### FIXME to pop-up the find dialog we map the text-field
2062 seven times! This doesn't show on a fast linux, though. */
2063 enqueue_focus_event(IMAGE_INSTANCE_X_WIDGET_ID(p),
2064 IMAGE_INSTANCE_FRAME(p), 1);
2069 /* when you click on a widget you may activate another widget this
2070 needs to be checked and all appropriate widgets updated */
2071 static void x_redisplay_subwindow(Lisp_Image_Instance * p)
2073 /* Update the subwindow size if necessary. */
2074 if (IMAGE_INSTANCE_SIZE_CHANGED(p)) {
2075 XResizeWindow(IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY(p),
2076 IMAGE_INSTANCE_X_SUBWINDOW_ID(p),
2077 IMAGE_INSTANCE_WIDTH(p),
2078 IMAGE_INSTANCE_HEIGHT(p));
2082 /* Update all attributes that have changed. Lwlib actually does most
2084 static void x_redisplay_widget(Lisp_Image_Instance * p)
2086 /* This function can GC if IN_REDISPLAY is false. */
2088 widget_value *wv = 0;
2090 /* First get the items if they have changed since this is a
2091 structural change. As such it will nuke all added values so we
2092 need to update most other things after the items have changed. */
2093 if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED(p)) {
2094 Lisp_Object image_instance;
2096 XSETIMAGE_INSTANCE(image_instance, p);
2097 wv = gui_items_to_widget_values
2098 (image_instance, IMAGE_INSTANCE_WIDGET_PENDING_ITEMS(p),
2099 /* #### this is not right; we need to keep track of which widgets
2100 want accelerators and which don't */ 0);
2101 wv->change = STRUCTURAL_CHANGE;
2103 /* Assume the lotus position, breath deeply and chant to
2104 yourself lwlibsux, lwlibsux ... lw_get_all_values returns a
2105 reference to the real values rather than a copy thus any
2106 changes we make to the values we get back will look like they
2107 have already been applied. If we rebuild the widget tree then
2108 we may lose properties. */
2109 wv = copy_widget_value_tree(lw_get_all_values
2110 (IMAGE_INSTANCE_X_WIDGET_LWID(p)),
2114 /* Possibly update the colors and font */
2115 if (IMAGE_INSTANCE_WIDGET_FACE_CHANGED(p)
2117 /* #### This is not sufficient because it will not cope with widgets
2118 that are not currently visible. Once redisplay has done the
2119 visible ones it will clear this flag so that when new ones
2120 become visible they will not be updated. */
2121 XFRAME(IMAGE_INSTANCE_FRAME(p))->faces_changed
2123 XFRAME(IMAGE_INSTANCE_FRAME(p))->frame_changed
2124 || IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED(p)) {
2125 update_widget_face(wv, p, IMAGE_INSTANCE_FRAME(p));
2128 /* Possibly update the text. */
2129 if (IMAGE_INSTANCE_TEXT_CHANGED(p)) {
2131 Lisp_Object val = IMAGE_INSTANCE_WIDGET_TEXT(p);
2132 LISP_STRING_TO_EXTERNAL(val, str, Qnative);
2136 /* Possibly update the size. */
2137 if (IMAGE_INSTANCE_SIZE_CHANGED(p)
2138 || IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED(p)
2139 || IMAGE_INSTANCE_TEXT_CHANGED(p)) {
2140 assert(IMAGE_INSTANCE_X_WIDGET_ID(p) &&
2141 IMAGE_INSTANCE_X_CLIPWIDGET(p));
2143 if (IMAGE_INSTANCE_X_WIDGET_ID(p)->core.being_destroyed
2144 || !XtIsManaged(IMAGE_INSTANCE_X_WIDGET_ID(p))) {
2146 XSETIMAGE_INSTANCE(sw, p);
2147 signal_simple_error("SXEmacs bug: subwindow is deleted",
2151 lw_add_widget_value_arg(wv, XtNwidth,
2152 IMAGE_INSTANCE_WIDTH(p));
2153 lw_add_widget_value_arg(wv, XtNheight,
2154 IMAGE_INSTANCE_HEIGHT(p));
2157 /* Adjust offsets within the frame. */
2158 if (XFRAME(IMAGE_INSTANCE_FRAME(p))->size_changed) {
2160 XtSetArg(al[0], XtNx, &IMAGE_INSTANCE_X_WIDGET_XOFFSET(p));
2161 XtSetArg(al[1], XtNy, &IMAGE_INSTANCE_X_WIDGET_YOFFSET(p));
2162 XtGetValues(FRAME_X_TEXT_WIDGET
2163 (XFRAME(IMAGE_INSTANCE_FRAME(p))), al, 2);
2166 /* now modify the widget */
2167 lw_modify_all_widgets(IMAGE_INSTANCE_X_WIDGET_LWID(p), wv, True);
2168 free_widget_value_tree(wv);
2172 /* instantiate and x type subwindow */
2174 x_subwindow_instantiate(Lisp_Object image_instance, Lisp_Object instantiator,
2175 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2176 int dest_mask, Lisp_Object domain)
2178 /* This function can GC */
2179 Lisp_Image_Instance *ii = XIMAGE_INSTANCE(image_instance);
2180 Lisp_Object device = IMAGE_INSTANCE_DEVICE(ii);
2181 Lisp_Object frame = DOMAIN_FRAME(domain);
2182 struct frame *f = XFRAME(frame);
2186 XSetWindowAttributes xswa;
2188 unsigned int w = IMAGE_INSTANCE_WIDTH(ii),
2189 h = IMAGE_INSTANCE_HEIGHT(ii);
2191 if (!DEVICE_X_P(XDEVICE(device)))
2192 signal_simple_error("Not an X device", device);
2194 dpy = DEVICE_X_DISPLAY(XDEVICE(device));
2195 xs = DefaultScreenOfDisplay(dpy);
2197 IMAGE_INSTANCE_TYPE(ii) = IMAGE_SUBWINDOW;
2199 pw = XtWindow(FRAME_X_TEXT_WIDGET(f));
2201 ii->data = xnew_and_zero(struct x_subwindow_data);
2203 IMAGE_INSTANCE_X_SUBWINDOW_PARENT(ii) = pw;
2204 IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY(ii) = DisplayOfScreen(xs);
2206 xswa.backing_store = Always;
2207 valueMask |= CWBackingStore;
2208 xswa.colormap = DefaultColormapOfScreen(xs);
2209 valueMask |= CWColormap;
2211 /* Create a window for clipping */
2212 IMAGE_INSTANCE_X_CLIPWINDOW(ii) =
2213 XCreateWindow(dpy, pw, 0, 0, w, h, 0, CopyFromParent,
2214 InputOutput, CopyFromParent, valueMask, &xswa);
2216 /* Now put the subwindow inside the clip window. */
2217 win = XCreateWindow(dpy, IMAGE_INSTANCE_X_CLIPWINDOW(ii),
2218 0, 0, w, h, 0, CopyFromParent,
2219 InputOutput, CopyFromParent, valueMask, &xswa);
2221 IMAGE_INSTANCE_SUBWINDOW_ID(ii) = (void *)win;
2224 /* Account for some of the limitations with widget images. */
2225 static int x_widget_border_width(void)
2227 return DEFAULT_WIDGET_BORDER_WIDTH * 2;
2231 x_subwindow_query_geometry(Lisp_Object image_instance,
2232 int *width, int *height);
2235 x_subwindow_query_geometry(Lisp_Object image_instance,
2236 int *width, int *height)
2238 Lisp_Image_Instance *ii = XIMAGE_INSTANCE(image_instance);
2241 unsigned int dbdw, dd, dw = 20, dh = 20;
2243 XGetGeometry(IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY(ii),
2244 (Window)IMAGE_INSTANCE_SUBWINDOW_ID(ii),
2245 &droot, &dx, &dy, &dw, &dh, &dbdw, &dd);
2253 /* #### Should this function exist? If there's any doubt I'm not implementing it --andyp */
2254 DEFUN("change-subwindow-property", Fchange_subwindow_property, 3, 3, 0, /*
2255 For the given SUBWINDOW, set PROPERTY to DATA, which is a string.
2256 Subwindows are not currently implemented.
2258 (subwindow, property, data))
2264 CHECK_SUBWINDOW(subwindow);
2265 CHECK_STRING(property);
2268 sw = XSUBWINDOW(subwindow);
2269 dpy = DisplayOfScreen(LISP_DEVICE_TO_X_SCREEN
2270 (FRAME_DEVICE(XFRAME(sw->frame))));
2272 property_atom = XInternAtom(dpy, (char *)XSTRING_DATA(property), False);
2273 XChangeProperty(dpy, sw->subwindow, property_atom, XA_STRING, 8,
2275 XSTRING_DATA(data), XSTRING_LENGTH(data));
2283 /************************************************************************/
2285 /************************************************************************/
2288 update_widget_face(widget_value * wv, Lisp_Image_Instance * ii,
2291 #ifdef LWLIB_WIDGETS_MOTIF
2292 XmFontList fontList;
2294 /* Update the foreground. */
2295 Lisp_Object pixel = FACE_FOREGROUND(IMAGE_INSTANCE_WIDGET_FACE(ii),
2297 XColor fcolor = COLOR_INSTANCE_X_COLOR(XCOLOR_INSTANCE(pixel)), bcolor;
2298 lw_add_widget_value_arg(wv, XtNforeground, fcolor.pixel);
2300 /* Update the background. */
2301 pixel = FACE_BACKGROUND(IMAGE_INSTANCE_WIDGET_FACE(ii), domain);
2302 bcolor = COLOR_INSTANCE_X_COLOR(XCOLOR_INSTANCE(pixel));
2303 lw_add_widget_value_arg(wv, XtNbackground, bcolor.pixel);
2305 #ifdef LWLIB_WIDGETS_MOTIF
2306 fontList = XmFontListCreate
2307 (FONT_INSTANCE_X_FONT
2308 (XFONT_INSTANCE(query_string_font
2309 (IMAGE_INSTANCE_WIDGET_TEXT(ii),
2310 IMAGE_INSTANCE_WIDGET_FACE(ii),
2311 domain))), XmSTRING_DEFAULT_CHARSET);
2312 lw_add_widget_value_arg(wv, XmNfontList, (XtArgVal) fontList);
2315 Lisp_Object tmp = query_string_font(
2316 IMAGE_INSTANCE_WIDGET_TEXT(ii),
2317 IMAGE_INSTANCE_WIDGET_FACE(ii), domain);
2318 lw_add_widget_value_arg(
2320 (XtArgVal)FONT_INSTANCE_X_FONT(XFONT_INSTANCE(tmp)));
2322 wv->change = VISIBLE_CHANGE;
2323 /* #### Megahack - but its just getting too complicated to do this
2324 in the right place. */
2325 if (EQ(IMAGE_INSTANCE_WIDGET_TYPE(ii), Qtab_control)) {
2326 update_tab_widget_face(wv, ii, domain);
2332 update_tab_widget_face(widget_value * wv, Lisp_Image_Instance * ii,
2336 widget_value *val = wv->contents, *cur;
2338 /* Give each child label the correct foreground color. */
2339 Lisp_Object pixel = FACE_FOREGROUND
2340 (IMAGE_INSTANCE_WIDGET_FACE(ii),
2342 XColor fcolor = COLOR_INSTANCE_X_COLOR(XCOLOR_INSTANCE(pixel));
2343 lw_add_widget_value_arg(val, XtNtabForeground, fcolor.pixel);
2344 wv->change = VISIBLE_CHANGE;
2345 val->change = VISIBLE_CHANGE;
2347 for (cur = val->next; cur; cur = cur->next) {
2348 cur->change = VISIBLE_CHANGE;
2350 lw_copy_widget_value_args(val, cur);
2357 x_widget_instantiate(Lisp_Object image_instance, Lisp_Object instantiator,
2358 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2359 int dest_mask, Lisp_Object domain,
2360 const char *type, widget_value * wv)
2362 Lisp_Image_Instance *ii = XIMAGE_INSTANCE(image_instance);
2363 Lisp_Object device = IMAGE_INSTANCE_DEVICE(ii), pixel;
2364 struct device *d = XDEVICE(device);
2365 Lisp_Object frame = DOMAIN_FRAME(domain);
2366 struct frame *f = XFRAME(frame);
2367 char *nm = 0; // unused
2371 int id = new_lwlib_id();
2372 widget_value *clip_wv;
2373 XColor fcolor, bcolor;
2376 signal_simple_error("Not an X device", device);
2378 /* have to set the type this late in case there is no device
2379 instantiation for a widget. But we can go ahead and do it without
2380 checking because there is always a generic instantiator. */
2381 IMAGE_INSTANCE_TYPE(ii) = IMAGE_WIDGET;
2383 if (!NILP(IMAGE_INSTANCE_WIDGET_TEXT(ii)))
2384 LISP_STRING_TO_EXTERNAL(IMAGE_INSTANCE_WIDGET_TEXT(ii), nm,
2389 ii->data = xnew_and_zero(struct x_subwindow_data);
2391 /* Create a clip window to contain the subwidget. Incredibly the
2392 SXEmacs manager seems to be the most appropriate widget for
2393 this. Nothing else is simple enough and yet does what is
2395 clip_wv = xmalloc_widget_value();
2397 lw_add_widget_value_arg(clip_wv, XtNresize, False);
2398 lw_add_widget_value_arg(clip_wv, XtNwidth,
2399 IMAGE_INSTANCE_WIDTH(ii));
2400 lw_add_widget_value_arg(clip_wv, XtNheight,
2401 IMAGE_INSTANCE_HEIGHT(ii));
2402 clip_wv->enabled = True;
2404 clip_wv->name = xstrdup("clip-window");
2405 clip_wv->value = xstrdup("clip-window");
2407 IMAGE_INSTANCE_X_CLIPWIDGET(ii)
2408 = lw_create_widget("clip-window", "clip-window", new_lwlib_id(),
2409 clip_wv, FRAME_X_CONTAINER_WIDGET(f),
2412 free_widget_value_tree(clip_wv);
2414 /* create a sensible name. */
2415 if (wv->name == 0 || strcmp(wv->name, "") == 0)
2416 wv->name = xstrdup(type);
2418 /* copy any args we were given */
2420 lw_add_value_args_to_args(wv, al, &ac);
2422 /* Fixup the colors. We have to do this *before* the widget gets
2423 created so that Motif will fix up the shadow colors
2424 correctly. Once the widget is created Motif won't do this
2426 pixel = FACE_FOREGROUND
2427 (IMAGE_INSTANCE_WIDGET_FACE(ii), IMAGE_INSTANCE_FRAME(ii));
2428 fcolor = COLOR_INSTANCE_X_COLOR(XCOLOR_INSTANCE(pixel));
2430 pixel = FACE_BACKGROUND
2431 (IMAGE_INSTANCE_WIDGET_FACE(ii), IMAGE_INSTANCE_FRAME(ii));
2432 bcolor = COLOR_INSTANCE_X_COLOR(XCOLOR_INSTANCE(pixel));
2434 lw_add_widget_value_arg(wv, XtNbackground, bcolor.pixel);
2435 lw_add_widget_value_arg(wv, XtNforeground, fcolor.pixel);
2436 /* we cannot allow widgets to resize themselves */
2437 lw_add_widget_value_arg(wv, XtNresize, False);
2438 lw_add_widget_value_arg(wv, XtNwidth, IMAGE_INSTANCE_WIDTH(ii));
2439 lw_add_widget_value_arg(wv, XtNheight, IMAGE_INSTANCE_HEIGHT(ii));
2440 /* update the font. */
2441 update_widget_face(wv, ii, domain);
2444 lw_create_widget(type, wv->name, id, wv,
2445 IMAGE_INSTANCE_X_CLIPWIDGET(ii), False, 0,
2446 popup_selection_callback, 0);
2448 IMAGE_INSTANCE_SUBWINDOW_ID(ii) = (void *)wid;
2449 IMAGE_INSTANCE_X_WIDGET_LWID(ii) = id;
2450 /* because the EmacsManager is the widgets parent we have to
2451 offset the redisplay of the widget by the amount the text
2452 widget is inside the manager. */
2454 XtSetArg(al[ac], XtNx, &IMAGE_INSTANCE_X_WIDGET_XOFFSET(ii));
2456 XtSetArg(al[ac], XtNy, &IMAGE_INSTANCE_X_WIDGET_YOFFSET(ii));
2458 XtGetValues(FRAME_X_TEXT_WIDGET(f), al, ac);
2460 XtSetMappedWhenManaged(wid, TRUE);
2462 free_widget_value_tree(wv);
2463 /* A kludgy but simple way to make sure the callback for a widget
2464 doesn't get deleted. */
2465 gcpro_popup_callbacks(id);
2468 /* get properties of a control */
2470 x_widget_property(Lisp_Object image_instance, Lisp_Object prop)
2472 Lisp_Image_Instance *ii = XIMAGE_INSTANCE(image_instance);
2473 /* get the text from a control */
2474 if (EQ(prop, Q_text)) {
2476 lw_get_all_values(IMAGE_INSTANCE_X_WIDGET_LWID(ii));
2477 return build_ext_string(wv->value, Qnative);
2482 /* Instantiate a layout control for putting other widgets in. */
2484 x_native_layout_instantiate(Lisp_Object image_instance,
2485 Lisp_Object instantiator, Lisp_Object pointer_fg,
2486 Lisp_Object pointer_bg, int dest_mask,
2489 x_widget_instantiate(image_instance, instantiator, pointer_fg,
2490 pointer_bg, dest_mask, domain, "layout", 0);
2493 /* Instantiate a button widget. Unfortunately instantiated widgets are
2494 particular to a frame since they need to have a parent. It's not
2495 like images where you just select the image into the context you
2496 want to display it in and BitBlt it. So images instances can have a
2497 many-to-one relationship with things you see, whereas widgets can
2498 only be one-to-one (i.e. per frame) */
2500 x_button_instantiate(Lisp_Object image_instance, Lisp_Object instantiator,
2501 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2502 int dest_mask, Lisp_Object domain)
2504 Lisp_Image_Instance *ii = XIMAGE_INSTANCE(image_instance);
2505 Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM(ii);
2506 Lisp_Object glyph = find_keyword_in_vector(instantiator, Q_image);
2507 widget_value *wv = gui_items_to_widget_values(image_instance, gui, 1);
2510 if (!IMAGE_INSTANCEP(glyph))
2512 glyph_image_instance(glyph, domain, ERROR_ME, 1);
2515 x_widget_instantiate(image_instance, instantiator, pointer_fg,
2516 pointer_bg, dest_mask, domain, "button", wv);
2518 /* add the image if one was given */
2519 if (!NILP(glyph) && IMAGE_INSTANCEP(glyph)
2520 && IMAGE_INSTANCE_PIXMAP_TYPE_P(XIMAGE_INSTANCE(glyph))) {
2523 #ifdef LWLIB_WIDGETS_MOTIF
2524 XtSetArg(al[ac], XmNlabelType, XmPIXMAP);
2526 XtSetArg(al[ac], XmNlabelPixmap,
2527 XIMAGE_INSTANCE_X_PIXMAP(glyph));
2530 XtSetArg(al[ac], XtNpixmap, XIMAGE_INSTANCE_X_PIXMAP(glyph));
2533 XtSetValues(IMAGE_INSTANCE_X_WIDGET_ID(ii), al, ac);
2537 /* Update a button's clicked state.
2539 #### This is overkill, but it works. Right now this causes all
2540 button instances to flash for some reason buried deep in lwlib. In
2541 theory this should be the Right Thing to do since lwlib should only
2542 merge in changed values - and if nothing has changed then nothing
2543 should get done. This may be because of the args stuff,
2544 i.e. although the arg contents may be the same the args look
2545 different and so are re-applied to the widget. */
2546 static void x_button_redisplay(Lisp_Object image_instance)
2548 /* This function can GC if IN_REDISPLAY is false. */
2549 Lisp_Image_Instance *p = XIMAGE_INSTANCE(image_instance);
2550 widget_value *wv = gui_items_to_widget_values(image_instance,
2551 IMAGE_INSTANCE_WIDGET_ITEMS
2554 /* now modify the widget */
2555 lw_modify_all_widgets(IMAGE_INSTANCE_X_WIDGET_LWID(p), wv, True);
2556 free_widget_value_tree(wv);
2559 /* get properties of a button */
2561 x_button_property(Lisp_Object image_instance, Lisp_Object prop)
2563 Lisp_Image_Instance *ii = XIMAGE_INSTANCE(image_instance);
2564 /* check the state of a button */
2565 if (EQ(prop, Q_selected)) {
2567 lw_get_all_values(IMAGE_INSTANCE_X_WIDGET_LWID(ii));
2577 /* instantiate a progress gauge */
2579 x_progress_gauge_instantiate(Lisp_Object image_instance,
2580 Lisp_Object instantiator, Lisp_Object pointer_fg,
2581 Lisp_Object pointer_bg, int dest_mask,
2584 Lisp_Image_Instance *ii = XIMAGE_INSTANCE(image_instance);
2585 Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM(ii);
2586 widget_value *wv = gui_items_to_widget_values(image_instance, gui, 0);
2588 x_widget_instantiate(image_instance, instantiator, pointer_fg,
2589 pointer_bg, dest_mask, domain, "progress", wv);
2592 /* set the properties of a progress gauge */
2593 static void x_progress_gauge_redisplay(Lisp_Object image_instance)
2595 Lisp_Image_Instance *ii = XIMAGE_INSTANCE(image_instance);
2597 if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED(ii)) {
2600 #ifdef ERROR_CHECK_GLYPHS
2601 assert(GUI_ITEMP(IMAGE_INSTANCE_WIDGET_PENDING_ITEMS(ii)));
2603 val = XGUI_ITEM(IMAGE_INSTANCE_WIDGET_PENDING_ITEMS(ii))->value;
2604 XtSetArg(al[0], XtNvalue, XINT(val));
2605 XtSetValues(IMAGE_INSTANCE_X_WIDGET_ID(ii), al, 1);
2609 /* instantiate an edit control */
2611 x_edit_field_instantiate(Lisp_Object image_instance, Lisp_Object instantiator,
2612 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2613 int dest_mask, Lisp_Object domain)
2615 Lisp_Image_Instance *ii = XIMAGE_INSTANCE(image_instance);
2616 Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM(ii);
2617 widget_value *wv = gui_items_to_widget_values(image_instance, gui, 0);
2619 x_widget_instantiate(image_instance, instantiator, pointer_fg,
2620 pointer_bg, dest_mask, domain, "text-field", wv);
2623 #if defined (LWLIB_WIDGETS_MOTIF) && XmVERSION > 1
2624 /* instantiate a combo control */
2626 x_combo_box_instantiate(Lisp_Object image_instance, Lisp_Object instantiator,
2627 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2628 int dest_mask, Lisp_Object domain)
2630 Lisp_Image_Instance *ii = XIMAGE_INSTANCE(image_instance);
2631 widget_value *wv = 0;
2632 /* This is not done generically because of sizing problems under
2633 mswindows. REVISE ME: We don't support windows, so? */
2634 widget_instantiate(image_instance, instantiator, pointer_fg,
2635 pointer_bg, dest_mask, domain);
2637 wv = gui_items_to_widget_values(image_instance,
2638 IMAGE_INSTANCE_WIDGET_ITEMS(ii), 0);
2640 x_widget_instantiate(image_instance, instantiator, pointer_fg,
2641 pointer_bg, dest_mask, domain, "combo-box", wv);
2646 x_tab_control_instantiate(Lisp_Object image_instance, Lisp_Object instantiator,
2647 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2648 int dest_mask, Lisp_Object domain)
2650 Lisp_Image_Instance *ii = XIMAGE_INSTANCE(image_instance);
2651 widget_value *wv = gui_items_to_widget_values(image_instance,
2652 IMAGE_INSTANCE_WIDGET_ITEMS
2654 update_tab_widget_face(wv, ii, IMAGE_INSTANCE_FRAME(ii));
2655 x_widget_instantiate(image_instance, instantiator, pointer_fg,
2656 pointer_bg, dest_mask, domain, "tab-control", wv);
2659 /* Set the properties of a tab control */
2660 static void x_tab_control_redisplay(Lisp_Object image_instance)
2662 Lisp_Image_Instance *ii = XIMAGE_INSTANCE(image_instance);
2664 if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED(ii)
2665 || IMAGE_INSTANCE_WIDGET_ACTION_OCCURRED(ii)) {
2666 /* If only the order has changed then simply select the first
2667 one of the pending set. This stops horrendous rebuilding -
2668 and hence flicker - of the tabs each time you click on
2670 if (tab_control_order_only_changed(image_instance)) {
2671 Lisp_Object rest, selected =
2672 gui_item_list_find_selected
2673 (NILP(IMAGE_INSTANCE_WIDGET_PENDING_ITEMS(ii)) ?
2674 XCDR(IMAGE_INSTANCE_WIDGET_ITEMS(ii)) :
2675 XCDR(IMAGE_INSTANCE_WIDGET_PENDING_ITEMS(ii)));
2677 LIST_LOOP(rest, XCDR(IMAGE_INSTANCE_WIDGET_ITEMS(ii))) {
2678 if (gui_item_equal_sans_selected
2679 (XCAR(rest), selected, 0)) {
2680 /* There may be an encapsulated way of doing this,
2681 but I couldn't find it. */
2682 Lisp_Object old_selected =
2683 gui_item_list_find_selected(XCDR
2684 (IMAGE_INSTANCE_WIDGET_ITEMS
2688 unsigned int num_children, i;
2691 LISP_STRING_TO_EXTERNAL(XGUI_ITEM
2695 /* The name may contain a `.' which confuses
2696 XtNameToWidget, so we do it ourselves. */
2699 (IMAGE_INSTANCE_X_WIDGET_ID(ii),
2701 for (i = 0; i < num_children; i++) {
2703 (XtName(children[i]),
2712 (IMAGE_INSTANCE_X_WIDGET_ID
2717 /* Pick up the new selected item. */
2718 XGUI_ITEM(old_selected)->selected =
2719 XGUI_ITEM(XCAR(rest))->selected;
2720 XGUI_ITEM(XCAR(rest))->selected =
2721 XGUI_ITEM(selected)->selected;
2722 /* We're not actually changing the items anymore. */
2723 IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED(ii)
2725 IMAGE_INSTANCE_WIDGET_PENDING_ITEMS(ii)
2732 /* Possibly update the face. */
2733 if (IMAGE_INSTANCE_WIDGET_FACE_CHANGED(ii)
2735 XFRAME(IMAGE_INSTANCE_FRAME(ii))->faces_changed
2736 || IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED(ii)) {
2737 /* See previous comments on the brokeness of lwlib.
2739 #### There's actually not much point in doing this here
2740 since, colors will have been set appropriately by
2741 x_redisplay_widget. */
2742 widget_value *wv = copy_widget_value_tree
2743 (lw_get_all_values(IMAGE_INSTANCE_X_WIDGET_LWID(ii)),
2746 update_tab_widget_face(wv, ii, IMAGE_INSTANCE_FRAME(ii));
2748 lw_modify_all_widgets(IMAGE_INSTANCE_X_WIDGET_LWID(ii), wv,
2750 free_widget_value_tree(wv);
2754 /* instantiate a static control possible for putting other things in */
2756 x_label_instantiate(Lisp_Object image_instance, Lisp_Object instantiator,
2757 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2758 int dest_mask, Lisp_Object domain)
2760 Lisp_Image_Instance *ii = XIMAGE_INSTANCE(image_instance);
2761 Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM(ii);
2762 widget_value *wv = gui_items_to_widget_values(image_instance, gui, 0);
2764 x_widget_instantiate(image_instance, instantiator, pointer_fg,
2765 pointer_bg, dest_mask, domain, "button", wv);
2767 #endif /* HAVE_WIDGETS */
2769 /************************************************************************/
2770 /* initialization */
2771 /************************************************************************/
2773 void syms_of_glyphs_x(void)
2776 DEFSUBR(Fchange_subwindow_property);
2780 void console_type_create_glyphs_x(void)
2784 CONSOLE_HAS_METHOD(x, print_image_instance);
2785 CONSOLE_HAS_METHOD(x, finalize_image_instance);
2786 CONSOLE_HAS_METHOD(x, image_instance_equal);
2787 CONSOLE_HAS_METHOD(x, image_instance_hash);
2788 CONSOLE_HAS_METHOD(x, colorize_image_instance);
2789 CONSOLE_HAS_METHOD(x, init_image_instance_from_eimage);
2790 CONSOLE_HAS_METHOD(x, locate_pixmap_file);
2791 CONSOLE_HAS_METHOD(x, unmap_subwindow);
2792 CONSOLE_HAS_METHOD(x, map_subwindow);
2793 CONSOLE_HAS_METHOD(x, redisplay_widget);
2794 CONSOLE_HAS_METHOD(x, redisplay_subwindow);
2795 CONSOLE_HAS_METHOD(x, widget_border_width);
2798 void image_instantiator_format_create_glyphs_x(void)
2800 IIFORMAT_VALID_CONSOLE(x, nothing);
2801 IIFORMAT_VALID_CONSOLE(x, string);
2803 IIFORMAT_VALID_CONSOLE(x, layout);
2805 IIFORMAT_VALID_CONSOLE(x, formatted_string);
2806 IIFORMAT_VALID_CONSOLE(x, inherit);
2808 INITIALIZE_DEVICE_IIFORMAT(x, xpm);
2809 IIFORMAT_HAS_DEVMETHOD(x, xpm, instantiate);
2812 IIFORMAT_VALID_CONSOLE(x, jpeg);
2815 IIFORMAT_VALID_CONSOLE(x, tiff);
2817 #if defined WITH_PNG && defined HAVE_PNG
2818 IIFORMAT_VALID_CONSOLE(x, png);
2821 IIFORMAT_VALID_CONSOLE(x, gif);
2824 IIFORMAT_VALID_CONSOLE(x, rawrgb);
2825 IIFORMAT_VALID_CONSOLE(x, rawrgba);
2828 INITIALIZE_DEVICE_IIFORMAT(x, xbm);
2829 IIFORMAT_HAS_DEVMETHOD(x, xbm, instantiate);
2831 INITIALIZE_DEVICE_IIFORMAT(x, subwindow);
2832 IIFORMAT_HAS_DEVMETHOD(x, subwindow, instantiate);
2835 INITIALIZE_DEVICE_IIFORMAT(x, native_layout);
2836 IIFORMAT_HAS_DEVMETHOD(x, native_layout, instantiate);
2838 INITIALIZE_DEVICE_IIFORMAT(x, button);
2839 IIFORMAT_HAS_DEVMETHOD(x, button, property);
2840 IIFORMAT_HAS_DEVMETHOD(x, button, instantiate);
2841 IIFORMAT_HAS_DEVMETHOD(x, button, redisplay);
2842 /* general widget methods. */
2843 INITIALIZE_DEVICE_IIFORMAT(x, widget);
2844 IIFORMAT_HAS_DEVMETHOD(x, widget, property);
2845 /* progress gauge */
2846 INITIALIZE_DEVICE_IIFORMAT(x, progress_gauge);
2847 IIFORMAT_HAS_DEVMETHOD(x, progress_gauge, redisplay);
2848 IIFORMAT_HAS_DEVMETHOD(x, progress_gauge, instantiate);
2850 INITIALIZE_DEVICE_IIFORMAT(x, edit_field);
2851 IIFORMAT_HAS_DEVMETHOD(x, edit_field, instantiate);
2852 #if defined (LWLIB_WIDGETS_MOTIF) && XmVERSION > 1
2854 INITIALIZE_DEVICE_IIFORMAT(x, combo_box);
2855 IIFORMAT_HAS_DEVMETHOD(x, combo_box, instantiate);
2856 IIFORMAT_HAS_SHARED_DEVMETHOD(x, combo_box, redisplay, tab_control);
2858 /* tab control widget */
2859 INITIALIZE_DEVICE_IIFORMAT(x, tab_control);
2860 IIFORMAT_HAS_DEVMETHOD(x, tab_control, instantiate);
2861 IIFORMAT_HAS_DEVMETHOD(x, tab_control, redisplay);
2863 INITIALIZE_DEVICE_IIFORMAT(x, label);
2864 IIFORMAT_HAS_DEVMETHOD(x, label, instantiate);
2866 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT(cursor_font, "cursor-font");
2867 IIFORMAT_VALID_CONSOLE(x, cursor_font);
2869 IIFORMAT_HAS_METHOD(cursor_font, validate);
2870 IIFORMAT_HAS_METHOD(cursor_font, possible_dest_types);
2871 IIFORMAT_HAS_METHOD(cursor_font, instantiate);
2873 IIFORMAT_VALID_KEYWORD(cursor_font, Q_data, check_valid_string);
2874 IIFORMAT_VALID_KEYWORD(cursor_font, Q_foreground, check_valid_string);
2875 IIFORMAT_VALID_KEYWORD(cursor_font, Q_background, check_valid_string);
2877 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT(font, "font");
2879 IIFORMAT_HAS_METHOD(font, validate);
2880 IIFORMAT_HAS_METHOD(font, possible_dest_types);
2881 IIFORMAT_HAS_METHOD(font, instantiate);
2882 IIFORMAT_VALID_CONSOLE(x, font);
2884 IIFORMAT_VALID_KEYWORD(font, Q_data, check_valid_string);
2885 IIFORMAT_VALID_KEYWORD(font, Q_foreground, check_valid_string);
2886 IIFORMAT_VALID_KEYWORD(font, Q_background, check_valid_string);
2889 INITIALIZE_DEVICE_IIFORMAT(x, xface);
2890 IIFORMAT_HAS_DEVMETHOD(x, xface, instantiate);
2893 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT(autodetect, "autodetect");
2895 IIFORMAT_HAS_METHOD(autodetect, validate);
2896 IIFORMAT_HAS_METHOD(autodetect, normalize);
2897 IIFORMAT_HAS_METHOD(autodetect, possible_dest_types);
2898 /* #### autodetect is flawed IMO:
2899 1. It makes the assumption that you can detect whether the user
2900 wanted a cursor or a string based on the data, since the data is a
2901 string you have to prioritise cursors. Instead we will force users
2902 to pick the appropriate image type, this is what we do under
2904 2. It doesn't fit with the new domain model - you cannot tell which
2905 domain it needs to be instantiated in until you've actually
2906 instantiated it, which mucks up caching.
2907 3. It only copes with cursors and strings which seems bogus. */
2908 IIFORMAT_HAS_SHARED_METHOD(autodetect, governing_domain, subwindow);
2909 IIFORMAT_HAS_METHOD(autodetect, instantiate);
2910 IIFORMAT_VALID_CONSOLE(x, autodetect);
2912 IIFORMAT_VALID_KEYWORD(autodetect, Q_data, check_valid_string);
2915 void vars_of_glyphs_x(void)
2917 DEFVAR_LISP("x-bitmap-file-path", &Vx_bitmap_file_path /*
2918 A list of the directories in which X bitmap files may be found.
2919 If nil, this is initialized from the "*bitmapFilePath" resource.
2920 This is used by the `make-image-instance' function (however, note that if
2921 the environment variable XBMLANGPATH is set, it is consulted first).
2923 Vx_bitmap_file_path = Qnil;
2926 void complex_vars_of_glyphs_x(void)
2928 #define BUILD_GLYPH_INST(variable, name) \
2929 Fadd_spec_to_specifier \
2930 (GLYPH_IMAGE (XGLYPH (variable)), \
2931 vector3 (Qxbm, Q_data, \
2932 list3 (make_int (name##_width), \
2933 make_int (name##_height), \
2934 make_ext_string ((Extbyte *) name##_bits, \
2935 sizeof (name##_bits), \
2939 BUILD_GLYPH_INST(Vtruncation_glyph, truncator);
2940 BUILD_GLYPH_INST(Vcontinuation_glyph, continuer);
2941 BUILD_GLYPH_INST(Vsxemacs_logo, sxemacs);
2942 BUILD_GLYPH_INST(Vhscroll_glyph, hscroll);
2944 #undef BUILD_GLYPH_INST