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);
874 image_instance_add_x_image(ii, ximage, slice,
882 XDestroyImage(ximage);
888 int read_bitmap_data_from_file(const char *filename, unsigned int *width,
889 unsigned int *height, unsigned char **datap,
890 int *x_hot, int *y_hot)
892 return XmuReadBitmapDataFromFile(filename, width, height,
893 datap, x_hot, y_hot);
896 /* Given inline data for a mono pixmap, create and return the
897 corresponding X object. */
900 pixmap_from_xbm_inline(Lisp_Object device, int width, int height,
901 /* Note that data is in ext-format! */
904 return XCreatePixmapFromBitmapData
905 (DEVICE_X_DISPLAY(XDEVICE(device)),
906 XtWindow(DEVICE_XT_APP_SHELL(XDEVICE(device))),
907 bits, width, height, 1, 0, 1);
910 /* Given inline data for a mono pixmap, initialize the given
911 image instance accordingly. */
914 init_image_instance_from_xbm_inline(Lisp_Image_Instance * ii,
915 int width, int height,
916 /* Note that data is in ext-format! */
918 Lisp_Object instantiator,
919 Lisp_Object pointer_fg,
920 Lisp_Object pointer_bg,
922 Pixmap mask, Lisp_Object mask_filename)
924 Lisp_Object device = IMAGE_INSTANCE_DEVICE(ii);
925 Lisp_Object foreground =
926 find_keyword_in_vector(instantiator, Q_foreground);
927 Lisp_Object background =
928 find_keyword_in_vector(instantiator, Q_background);
932 enum image_instance_type type;
934 if (!DEVICE_X_P(XDEVICE(device)))
935 signal_simple_error("Not an X device", device);
937 dpy = DEVICE_X_DISPLAY(XDEVICE(device));
938 draw = XtWindow(DEVICE_XT_APP_SHELL(XDEVICE(device)));
939 scr = DefaultScreenOfDisplay(dpy);
941 if ((dest_mask & IMAGE_MONO_PIXMAP_MASK) &&
942 (dest_mask & IMAGE_COLOR_PIXMAP_MASK)) {
943 if (!NILP(foreground) || !NILP(background))
944 type = IMAGE_COLOR_PIXMAP;
946 type = IMAGE_MONO_PIXMAP;
947 } else if (dest_mask & IMAGE_MONO_PIXMAP_MASK)
948 type = IMAGE_MONO_PIXMAP;
949 else if (dest_mask & IMAGE_COLOR_PIXMAP_MASK)
950 type = IMAGE_COLOR_PIXMAP;
951 else if (dest_mask & IMAGE_POINTER_MASK)
952 type = IMAGE_POINTER;
954 incompatible_image_types(instantiator, dest_mask,
955 IMAGE_MONO_PIXMAP_MASK |
956 IMAGE_COLOR_PIXMAP_MASK |
959 x_initialize_pixmap_image_instance(ii, 1, type);
960 IMAGE_INSTANCE_PIXMAP_WIDTH(ii) = width;
961 IMAGE_INSTANCE_PIXMAP_HEIGHT(ii) = height;
962 IMAGE_INSTANCE_PIXMAP_FILENAME(ii) =
963 find_keyword_in_vector(instantiator, Q_file);
966 case IMAGE_MONO_PIXMAP: {
967 IMAGE_INSTANCE_X_PIXMAP(ii) =
968 pixmap_from_xbm_inline(device, width, height,
973 case IMAGE_COLOR_PIXMAP: {
974 Dimension d = DEVICE_X_DEPTH(XDEVICE(device));
975 unsigned long fg = BlackPixelOfScreen(scr);
976 unsigned long bg = WhitePixelOfScreen(scr);
978 if (!NILP(foreground) && !COLOR_INSTANCEP(foreground))
980 Fmake_color_instance(foreground, device,
981 encode_error_behavior_flag
984 if (COLOR_INSTANCEP(foreground))
985 fg = COLOR_INSTANCE_X_COLOR(XCOLOR_INSTANCE
988 if (!NILP(background) && !COLOR_INSTANCEP(background))
990 Fmake_color_instance(background, device,
991 encode_error_behavior_flag
994 if (COLOR_INSTANCEP(background))
995 bg = COLOR_INSTANCE_X_COLOR(XCOLOR_INSTANCE
998 /* We used to duplicate the pixels using XAllocColor(), to protect
999 against their getting freed. Just as easy to just store the
1000 color instances here and GC-protect them, so this doesn't
1002 IMAGE_INSTANCE_PIXMAP_FG(ii) = foreground;
1003 IMAGE_INSTANCE_PIXMAP_BG(ii) = background;
1004 IMAGE_INSTANCE_X_PIXMAP(ii) =
1005 XCreatePixmapFromBitmapData(dpy, draw,
1006 (char *)bits, width,
1008 IMAGE_INSTANCE_PIXMAP_DEPTH(ii) = d;
1012 case IMAGE_POINTER: {
1013 XColor fg_color, bg_color;
1016 check_pointer_sizes(scr, width, height, instantiator);
1019 XCreatePixmapFromBitmapData(dpy, draw,
1020 (char *)bits, width,
1023 if (NILP(foreground))
1024 foreground = pointer_fg;
1025 if (NILP(background))
1026 background = pointer_bg;
1027 generate_cursor_fg_bg(device, &foreground, &background,
1028 &fg_color, &bg_color);
1030 IMAGE_INSTANCE_PIXMAP_FG(ii) = foreground;
1031 IMAGE_INSTANCE_PIXMAP_BG(ii) = background;
1032 IMAGE_INSTANCE_PIXMAP_HOTSPOT_X(ii) =
1033 find_keyword_in_vector(instantiator, Q_hotspot_x);
1034 IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y(ii) =
1035 find_keyword_in_vector(instantiator, Q_hotspot_y);
1036 IMAGE_INSTANCE_X_CURSOR(ii) =
1038 (dpy, source, mask, &fg_color, &bg_color,
1039 !NILP(IMAGE_INSTANCE_PIXMAP_HOTSPOT_X(ii)) ?
1040 XINT(IMAGE_INSTANCE_PIXMAP_HOTSPOT_X(ii)) : 0,
1041 !NILP(IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y(ii)) ?
1042 XINT(IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y(ii)) : 0);
1049 case IMAGE_SUBWINDOW:
1057 xbm_instantiate_1(Lisp_Object image_instance, Lisp_Object instantiator,
1058 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1059 int dest_mask, int width, int height,
1060 /* Note that data is in ext-format! */
1063 Lisp_Object mask_data =
1064 find_keyword_in_vector(instantiator, Q_mask_data);
1065 Lisp_Object mask_file =
1066 find_keyword_in_vector(instantiator, Q_mask_file);
1067 Lisp_Image_Instance *ii = XIMAGE_INSTANCE(image_instance);
1070 if (!NILP(mask_data)) {
1073 LISP_STRING_TO_EXTERNAL(XCAR(XCDR(XCDR(mask_data))), ext_data,
1075 mask = pixmap_from_xbm_inline(
1076 IMAGE_INSTANCE_DEVICE(ii),
1077 XINT(XCAR(mask_data)),
1078 XINT(XCAR(XCDR(mask_data))),
1082 init_image_instance_from_xbm_inline(ii, width, height, bits,
1083 instantiator, pointer_fg,
1084 pointer_bg, dest_mask, mask,
1088 /* Instantiate method for XBM's. */
1091 x_xbm_instantiate(Lisp_Object image_instance, Lisp_Object instantiator,
1092 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1093 int dest_mask, Lisp_Object domain)
1095 Lisp_Object data = find_keyword_in_vector(instantiator, Q_data);
1098 assert(!NILP(data));
1100 LISP_STRING_TO_EXTERNAL(XCAR(XCDR(XCDR(data))), ext_data, Qbinary);
1102 xbm_instantiate_1(image_instance, instantiator, pointer_fg,
1103 pointer_bg, dest_mask, XINT(XCAR(data)),
1104 XINT(XCAR(XCDR(data))), ext_data);
1109 /**********************************************************************
1111 **********************************************************************/
1112 /* xpm 3.2g and better has XpmCreatePixmapFromBuffer()...
1113 There was no version number in xpm.h before 3.3, but this should do.
1115 #if (XpmVersion >= 3) || defined(XpmExactColors)
1116 # define XPM_DOES_BUFFERS
1119 #ifndef XPM_DOES_BUFFERS
1120 Your version of XPM is too old.You cannot compile with it.
1121 Upgrade to version 3.2 g or better or compile with-- with - xpm = no.
1122 #endif /* !XPM_DOES_BUFFERS */
1123 static XpmColorSymbol *
1124 extract_xpm_color_names(XpmAttributes * xpmattrs, Lisp_Object device,
1126 Lisp_Object color_symbol_alist) {
1127 /* This function can GC */
1128 Display * dpy = DEVICE_X_DISPLAY(XDEVICE(device));
1129 Colormap cmap = DEVICE_X_COLORMAP(XDEVICE(device));
1132 Lisp_Object results = Qnil;
1134 XpmColorSymbol *symbols;
1135 struct gcpro gcpro1, gcpro2;
1137 GCPRO2(results, device);
1139 /* We built up results to be (("name" . #<color>) ...) so that if an
1140 error happens we don't lose any malloc()ed data, or more importantly,
1141 leave any pixels allocated in the server. */
1143 LIST_LOOP(rest, color_symbol_alist) {
1144 Lisp_Object cons = XCAR(rest);
1145 Lisp_Object name = XCAR(cons);
1146 Lisp_Object value = XCDR(cons);
1151 Fmake_color_instance
1153 encode_error_behavior_flag(ERROR_ME_NOT));
1155 assert(COLOR_SPECIFIERP(value));
1156 value = Fspecifier_instance(value, domain, Qnil, Qnil);
1160 results = noseeum_cons(noseeum_cons(name, value), results);
1163 UNGCPRO; /* no more evaluation */
1168 symbols = xnew_atomic_array(XpmColorSymbol, i);
1169 xpmattrs->valuemask |= XpmColorSymbols;
1170 xpmattrs->colorsymbols = symbols;
1171 xpmattrs->numsymbols = i;
1174 Lisp_Object cons = XCAR(results);
1175 color = COLOR_INSTANCE_X_COLOR(XCOLOR_INSTANCE(XCDR(cons)));
1176 /* Duplicate the pixel value so that we still have
1177 * a lock on it if the pixel we were passed is later freed. */
1178 if (!XAllocColor(dpy, cmap, &color)) {
1179 /* it must be allocable since we're
1180 * just duplicating it */
1184 symbols[i].name = (char *)XSTRING_DATA(XCAR(cons));
1185 symbols[i].pixel = color.pixel;
1186 symbols[i].value = 0;
1187 free_cons(XCONS(cons));
1189 results = XCDR(results);
1190 free_cons(XCONS(cons));
1195 static void xpm_free(XpmAttributes * xpmattrs)
1197 /* Could conceivably lose if XpmXXX returned an error without first
1198 initializing this structure, if we didn't know that initializing it
1199 to all zeros was ok (and also that it's ok to call XpmFreeAttributes()
1200 multiple times, since it zeros slots as it frees them...) */
1201 XpmFreeAttributes(xpmattrs);
1205 x_xpm_instantiate(Lisp_Object image_instance, Lisp_Object instantiator,
1206 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1207 int dest_mask, Lisp_Object domain)
1209 /* This function can GC */
1210 Lisp_Image_Instance *ii = XIMAGE_INSTANCE(image_instance);
1211 Lisp_Object device = IMAGE_INSTANCE_DEVICE(ii);
1212 Lisp_Object data = find_keyword_in_vector(instantiator, Q_data);
1220 XpmAttributes xpmattrs;
1222 XpmColorSymbol *color_symbols;
1223 Lisp_Object color_symbol_alist = find_keyword_in_vector(instantiator,
1225 enum image_instance_type type;
1229 if (!DEVICE_X_P(XDEVICE(device)))
1230 signal_simple_error("Not an X device", device);
1232 dpy = DEVICE_X_DISPLAY(XDEVICE(device));
1233 xs = DefaultScreenOfDisplay(dpy);
1235 if (dest_mask & IMAGE_COLOR_PIXMAP_MASK)
1236 type = IMAGE_COLOR_PIXMAP;
1237 else if (dest_mask & IMAGE_MONO_PIXMAP_MASK)
1238 type = IMAGE_MONO_PIXMAP;
1239 else if (dest_mask & IMAGE_POINTER_MASK)
1240 type = IMAGE_POINTER;
1242 incompatible_image_types(instantiator, dest_mask,
1243 IMAGE_MONO_PIXMAP_MASK |
1244 IMAGE_COLOR_PIXMAP_MASK |
1245 IMAGE_POINTER_MASK);
1246 force_mono = (type != IMAGE_COLOR_PIXMAP);
1249 /* Although I haven't found it documented yet, it appears that pointers are
1250 always colored via the default window colormap... Sigh. */
1251 if (type == IMAGE_POINTER) {
1252 cmap = DefaultColormap(dpy, DefaultScreen(dpy));
1253 depth = DefaultDepthOfScreen(xs);
1254 visual = DefaultVisualOfScreen(xs);
1256 cmap = DEVICE_X_COLORMAP(XDEVICE(device));
1257 depth = DEVICE_X_DEPTH(XDEVICE(device));
1258 visual = DEVICE_X_VISUAL(XDEVICE(device));
1261 cmap = DEVICE_X_COLORMAP(XDEVICE(device));
1262 depth = DEVICE_X_DEPTH(XDEVICE(device));
1263 visual = DEVICE_X_VISUAL(XDEVICE(device));
1266 x_initialize_pixmap_image_instance(ii, 1, type);
1268 assert(!NILP(data));
1272 xzero(xpmattrs); /* want XpmInitAttributes() */
1273 xpmattrs.valuemask = XpmReturnPixels;
1275 /* Without this, we get a 1-bit version of the color image, which
1276 isn't quite right. With this, we get the mono image, which might
1277 be very different looking. */
1278 xpmattrs.valuemask |= XpmColorKey;
1279 xpmattrs.color_key = XPM_MONO;
1281 xpmattrs.valuemask |= XpmDepth;
1283 xpmattrs.closeness = 65535;
1284 xpmattrs.valuemask |= XpmCloseness;
1285 xpmattrs.depth = depth;
1286 xpmattrs.valuemask |= XpmDepth;
1287 xpmattrs.visual = visual;
1288 xpmattrs.valuemask |= XpmVisual;
1289 xpmattrs.colormap = cmap;
1290 xpmattrs.valuemask |= XpmColormap;
1293 color_symbols = extract_xpm_color_names(&xpmattrs, device, domain,
1294 color_symbol_alist);
1296 result = XpmCreatePixmapFromBuffer(dpy,
1297 XtWindow(DEVICE_XT_APP_SHELL
1299 (char *)XSTRING_DATA(data), &pixmap,
1302 if (color_symbols) {
1303 xfree(color_symbols);
1304 xpmattrs.colorsymbols = 0; /* in case XpmFreeAttr is too smart... */
1305 xpmattrs.numsymbols = 0;
1311 case XpmFileInvalid:
1313 xpm_free(&xpmattrs);
1314 signal_image_error("invalid XPM data", data);
1316 case XpmColorFailed:
1319 xpm_free(&xpmattrs);
1321 /* second time; blow out. */
1322 signal_double_file_error("Reading pixmap data",
1323 "color allocation failed",
1326 if (!(dest_mask & IMAGE_MONO_PIXMAP_MASK)) {
1327 /* second time; blow out. */
1328 signal_double_file_error
1329 ("Reading pixmap data",
1330 "color allocation failed", data);
1333 IMAGE_INSTANCE_TYPE(ii) = IMAGE_MONO_PIXMAP;
1339 xpm_free(&xpmattrs);
1340 signal_double_file_error("Parsing pixmap data",
1341 "out of memory", data);
1345 xpm_free(&xpmattrs);
1346 signal_double_file_error_2("Parsing pixmap data",
1347 "unknown error code",
1348 make_int(result), data);
1353 h = xpmattrs.height;
1356 int npixels = xpmattrs.npixels;
1360 pixels = xnew_atomic_array(Pixel, npixels);
1361 memcpy(pixels, xpmattrs.pixels,
1362 npixels * sizeof(Pixel));
1367 IMAGE_INSTANCE_X_PIXMAP(ii) = pixmap;
1368 IMAGE_INSTANCE_PIXMAP_MASK(ii) = (void *)mask;
1369 IMAGE_INSTANCE_X_COLORMAP(ii) = cmap;
1370 IMAGE_INSTANCE_X_PIXELS(ii) = pixels;
1371 IMAGE_INSTANCE_X_NPIXELS(ii) = npixels;
1372 IMAGE_INSTANCE_PIXMAP_WIDTH(ii) = w;
1373 IMAGE_INSTANCE_PIXMAP_HEIGHT(ii) = h;
1374 IMAGE_INSTANCE_PIXMAP_FILENAME(ii) =
1375 find_keyword_in_vector(instantiator, Q_file);
1379 case IMAGE_MONO_PIXMAP:
1382 case IMAGE_COLOR_PIXMAP: {
1383 IMAGE_INSTANCE_PIXMAP_DEPTH(ii) = depth;
1387 case IMAGE_POINTER: {
1388 int npixels = xpmattrs.npixels;
1389 Pixel *pixels = xpmattrs.pixels;
1392 int xhot = 0, yhot = 0;
1394 if (xpmattrs.valuemask & XpmHotspot) {
1395 xhot = xpmattrs.x_hotspot;
1396 XSETINT(IMAGE_INSTANCE_PIXMAP_HOTSPOT_X(ii),
1397 xpmattrs.x_hotspot);
1399 if (xpmattrs.valuemask & XpmHotspot) {
1400 yhot = xpmattrs.y_hotspot;
1401 XSETINT(IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y(ii),
1402 xpmattrs.y_hotspot);
1404 check_pointer_sizes(xs, w, h, instantiator);
1406 /* If the loaded pixmap has colors allocated (meaning it came
1407 from an XPM file), then use those as the default colors for
1408 the cursor we create. Otherwise, default to pointer_fg and
1412 /* With an XBM file, it's obvious which bit is
1413 foreground and which is background, or rather, it's
1414 implicit: in an XBM file, a 1 bit is foreground, and
1415 a 0 bit is background.
1417 XCreatePixmapCursor() assumes this property of the
1418 pixmap it is called with as well; the `foreground'
1419 color argument is used for the 1 bits.
1421 With an XPM file, it's tricker, since the elements of
1422 the pixmap don't represent FG and BG, but are actual
1423 pixel values. So we need to figure out which of
1424 those pixels is the foreground color and which is the
1425 background. We do it by comparing RGB and assuming
1426 that the darker color is the foreground. This works
1427 with the result of xbmtopbm|ppmtoxpm, at least.
1429 It might be nice if there was some way to tag the
1430 colors in the XPM file with whether they are the
1431 foreground - perhaps with logical color names
1434 Once we have decided which color is the foreground,
1435 we need to ensure that that color corresponds to a
1436 `1' bit in the Pixmap. The XPM library wrote into
1437 the (1-bit) pixmap with XPutPixel, which will ignore
1438 all but the least significant bit.
1440 This means that a 1 bit in the image corresponds to
1441 `fg' only if `fg.pixel' is odd.
1443 (This also means that the image will be all the same
1444 color if both `fg' and `bg' are odd or even, but we
1445 can safely assume that that won't happen if the XPM
1446 file is sensible I think.)
1448 The desired result is that the image use `1' to
1449 represent the foreground color, and `0' to represent
1450 the background color. So, we may need to invert the
1451 image to accomplish this; we invert if fg is
1452 odd. (Remember that WhitePixel and BlackPixel are not
1453 necessarily 1 and 0 respectively, though I think it
1454 might be safe to assume that one of them is always 1
1455 and the other is always 0. We also pretty much need
1456 to assume that one is even and the other is odd.)
1459 fg.pixel = pixels[0]; /* pick a pixel at random. */
1460 bg.pixel = fg.pixel;
1461 for (i = 1; i < npixels; i++) {
1462 /* Look for an "other" pixel value. */
1463 bg.pixel = pixels[i];
1464 if (fg.pixel != bg.pixel)
1468 /* If (fg.pixel == bg.pixel) then probably something has
1469 gone wrong, but I don't think signalling an error
1470 would be appropriate. */
1472 XQueryColor(dpy, cmap, &fg);
1473 XQueryColor(dpy, cmap, &bg);
1475 /* If the foreground is lighter than the background,
1476 swap them. (This occurs semi-randomly, depending on
1477 the ordering of the color list in the XPM file.)
1480 unsigned short fg_total =
1481 ((fg.red / 3) + (fg.green / 3)
1483 unsigned short bg_total =
1484 ((bg.red / 3) + (bg.green / 3)
1486 if (fg_total > bg_total) {
1494 /* If the fg pixel corresponds to a `0' in the bitmap,
1495 invert it. (This occurs (only?) on servers with
1498 if ((fg.pixel & 1) == 0) {
1501 gcv.function = GXxor;
1503 gc = XCreateGC(dpy, pixmap,
1505 GCForeground), &gcv);
1506 XFillRectangle(dpy, pixmap, gc, 0, 0, w,
1511 generate_cursor_fg_bg(device, &pointer_fg,
1512 &pointer_bg, &fg, &bg);
1513 IMAGE_INSTANCE_PIXMAP_FG(ii) = pointer_fg;
1514 IMAGE_INSTANCE_PIXMAP_BG(ii) = pointer_bg;
1517 IMAGE_INSTANCE_X_CURSOR(ii) =
1519 (dpy, pixmap, mask, &fg, &bg, xhot, yhot);
1527 case IMAGE_SUBWINDOW:
1533 xpm_free(&xpmattrs); /* after we've read pixels and hotspot */
1536 #endif /* HAVE_XPM */
1540 /**********************************************************************
1542 **********************************************************************/
1544 /* This is about to get redefined! */
1547 /* We have to define SYSV32 so that compface.h includes string.h
1548 instead of strings.h. */
1553 #include <compface.h>
1557 /* JMP_BUF cannot be used here because if it doesn't get defined
1558 to jmp_buf we end up with a conflicting type error with the
1559 definition in compface.h */ extern jmp_buf comp_env;
1563 x_xface_instantiate(Lisp_Object image_instance, Lisp_Object instantiator,
1564 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1565 int dest_mask, Lisp_Object domain)
1567 Lisp_Object data = find_keyword_in_vector(instantiator, Q_data);
1571 const char *volatile emsg = 0;
1572 char *volatile dstring;
1574 assert(!NILP(data));
1576 LISP_STRING_TO_EXTERNAL(data, dstring, Qbinary);
1578 if ((p = strchr(dstring, ':'))) {
1582 /* Must use setjmp not SETJMP because we used jmp_buf above not
1584 if (!(stattis = setjmp(comp_env))) {
1591 emsg = "uncompface: internal error";
1594 emsg = "uncompface: insufficient or invalid data";
1597 emsg = "uncompface: excess data ignored";
1604 signal_simple_error_2(emsg, data, Qimage);
1606 bp = bits = (char *)alloca(PIXELS / 8);
1608 /* the compface library exports char F[], which uses a single byte per
1609 pixel to represent a 48x48 bitmap. Yuck. */
1610 for (i = 0, p = F; i < (PIXELS / 8); ++i) {
1612 /* reverse the bit order of each byte... */
1613 for (b = n = 0; b < 8; ++b) {
1619 xbm_instantiate_1(image_instance, instantiator, pointer_fg,
1620 pointer_bg, dest_mask, 48, 48, bits);
1623 #endif /* HAVE_XFACE */
1625 /**********************************************************************
1627 **********************************************************************/
1629 static void autodetect_validate(Lisp_Object instantiator)
1631 data_must_be_present(instantiator);
1635 autodetect_normalize(Lisp_Object instantiator,
1636 Lisp_Object console_type, Lisp_Object dest_mask)
1638 Lisp_Object file = find_keyword_in_vector(instantiator, Q_data);
1639 Lisp_Object filename = Qnil;
1640 Lisp_Object data = Qnil;
1641 struct gcpro gcpro1, gcpro2, gcpro3;
1642 Lisp_Object alist = Qnil;
1644 GCPRO3(filename, data, alist);
1646 if (NILP(file)) /* no conversion necessary */
1647 RETURN_UNGCPRO(instantiator);
1649 alist = tagged_vector_to_alist(instantiator);
1651 filename = locate_pixmap_file(file);
1652 if (!NILP(filename)) {
1654 /* #### Apparently some versions of XpmReadFileToData, which is
1655 called by pixmap_to_lisp_data, don't return an error value if
1656 the given file is not a valid XPM file. Instead, they just
1657 seg fault. It is definitely caused by passing a bitmap. To
1658 try and avoid this we check for bitmaps first. */
1660 data = bitmap_to_lisp_data(filename, &xhot, &yhot, 1);
1662 if (!EQ(data, Qt)) {
1663 alist = remassq_no_quit(Q_data, alist);
1664 alist = Fcons(Fcons(Q_file, filename),
1665 Fcons(Fcons(Q_data, data), alist));
1667 alist = Fcons(Fcons(Q_hotspot_x, make_int(xhot)),
1671 alist = Fcons(Fcons(Q_hotspot_y,
1675 alist = xbm_mask_file_munging(alist, filename, Qnil,
1679 Lisp_Object result =
1680 alist_to_tagged_vector(Qxbm, alist);
1682 RETURN_UNGCPRO(result);
1686 data = pixmap_to_lisp_data(filename, 1);
1688 if (!EQ(data, Qt)) {
1689 alist = remassq_no_quit(Q_data, alist);
1690 alist = Fcons(Fcons(Q_file, filename),
1691 Fcons(Fcons(Q_data, data), alist));
1692 alist = Fcons(Fcons(Q_color_symbols,
1693 evaluate_xpm_color_symbols()),
1696 Lisp_Object result =
1697 alist_to_tagged_vector(Qxpm, alist);
1699 RETURN_UNGCPRO(result);
1705 /* If we couldn't convert it, just put it back as it is.
1706 We might try to further frob it later as a cursor-font
1707 specification. (We can't do that now because we don't know
1708 what dest-types it's going to be instantiated into.) */
1710 Lisp_Object result = alist_to_tagged_vector(Qautodetect, alist);
1712 RETURN_UNGCPRO(result);
1716 static int autodetect_possible_dest_types(void)
1719 IMAGE_MONO_PIXMAP_MASK |
1720 IMAGE_COLOR_PIXMAP_MASK | IMAGE_POINTER_MASK | IMAGE_TEXT_MASK;
1724 autodetect_instantiate(Lisp_Object image_instance,
1725 Lisp_Object instantiator,
1726 Lisp_Object pointer_fg,
1727 Lisp_Object pointer_bg,
1728 int dest_mask, Lisp_Object domain)
1730 Lisp_Object data = find_keyword_in_vector(instantiator, Q_data);
1731 struct gcpro gcpro1, gcpro2, gcpro3;
1732 Lisp_Object alist = Qnil;
1733 Lisp_Object result = Qnil;
1734 int is_cursor_font = 0;
1736 GCPRO3(data, alist, result);
1738 alist = tagged_vector_to_alist(instantiator);
1739 if (dest_mask & IMAGE_POINTER_MASK) {
1740 const char *name_ext;
1741 LISP_STRING_TO_EXTERNAL(data, name_ext, Qfile_name);
1742 if (XmuCursorNameToIndex(name_ext) != -1) {
1743 result = alist_to_tagged_vector(Qcursor_font, alist);
1748 if (!is_cursor_font)
1749 result = alist_to_tagged_vector(Qstring, alist);
1753 cursor_font_instantiate(image_instance, result, pointer_fg,
1754 pointer_bg, dest_mask, domain);
1756 string_instantiate(image_instance, result, pointer_fg,
1757 pointer_bg, dest_mask, domain);
1762 /**********************************************************************
1764 **********************************************************************/
1766 static void font_validate(Lisp_Object instantiator)
1768 data_must_be_present(instantiator);
1771 /* XmuCvtStringToCursor is bogus in the following ways:
1773 - When it can't convert the given string to a real cursor, it will
1774 sometimes return a "success" value, after triggering a BadPixmap
1775 error. It then gives you a cursor that will itself generate BadCursor
1776 errors. So we install this error handler to catch/notice the X error
1777 and take that as meaning "couldn't convert."
1779 - When you tell it to find a cursor file that doesn't exist, it prints
1780 an error message on stderr. You can't make it not do that.
1782 - Also, using Xmu means we can't properly hack Lisp_Image_Instance
1783 objects, or XPM files, or $XBMLANGPATH.
1786 /* Duplicate the behavior of XmuCvtStringToCursor() to bypass its bogusness. */
1788 static int XLoadFont_got_error;
1790 static int XLoadFont_error_handler(Display * dpy, XErrorEvent * xerror)
1792 XLoadFont_got_error = 1;
1796 static Font safe_XLoadFont(Display * dpy, char *name)
1799 int (*old_handler) (Display *, XErrorEvent *);
1800 XLoadFont_got_error = 0;
1802 old_handler = XSetErrorHandler(XLoadFont_error_handler);
1803 font = XLoadFont(dpy, name);
1805 XSetErrorHandler(old_handler);
1806 if (XLoadFont_got_error)
1811 static int font_possible_dest_types(void)
1813 return IMAGE_POINTER_MASK;
1817 font_instantiate(Lisp_Object image_instance, Lisp_Object instantiator,
1818 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1819 int dest_mask, Lisp_Object domain)
1821 /* This function can GC */
1822 Lisp_Object data = find_keyword_in_vector(instantiator, Q_data);
1823 Lisp_Image_Instance *ii = XIMAGE_INSTANCE(image_instance);
1824 Lisp_Object device = IMAGE_INSTANCE_DEVICE(ii);
1828 char source_name[MAXPATHLEN], mask_name[MAXPATHLEN], dummy;
1829 int source_char, mask_char;
1831 Lisp_Object foreground, background;
1833 if (!DEVICE_X_P(XDEVICE(device)))
1834 signal_simple_error("Not an X device", device);
1836 dpy = DEVICE_X_DISPLAY(XDEVICE(device));
1838 if (!STRINGP(data) || strncmp("FONT ", (char *)XSTRING_DATA(data), 5))
1839 signal_simple_error("Invalid font-glyph instantiator",
1842 if (!(dest_mask & IMAGE_POINTER_MASK))
1843 incompatible_image_types(instantiator, dest_mask,
1844 IMAGE_POINTER_MASK);
1846 foreground = find_keyword_in_vector(instantiator, Q_foreground);
1847 if (NILP(foreground))
1848 foreground = pointer_fg;
1849 background = find_keyword_in_vector(instantiator, Q_background);
1850 if (NILP(background))
1851 background = pointer_bg;
1853 generate_cursor_fg_bg(device, &foreground, &background, &fg, &bg);
1855 count = sscanf((char *)XSTRING_DATA(data),
1856 "FONT %s %d %s %d %c",
1857 source_name, &source_char,
1858 mask_name, &mask_char, &dummy);
1859 /* Allow "%s %d %d" as well... */
1860 if (count == 3 && (1 == sscanf(mask_name, "%d %c", &mask_char, &dummy)))
1861 count = 4, mask_name[0] = 0;
1863 if (count != 2 && count != 4)
1864 signal_simple_error("invalid cursor specification", data);
1865 source = safe_XLoadFont(dpy, source_name);
1867 signal_simple_error_2("couldn't load font",
1868 build_string(source_name), data);
1871 else if (!mask_name[0])
1874 mask = safe_XLoadFont(dpy, mask_name);
1878 list3(build_string("couldn't load font"),
1879 build_string(mask_name), data));
1884 /* #### call XQueryTextExtents() and check_pointer_sizes() here. */
1886 x_initialize_pixmap_image_instance(ii, 1, IMAGE_POINTER);
1887 IMAGE_INSTANCE_X_CURSOR(ii) =
1888 XCreateGlyphCursor(dpy, source, mask, source_char, mask_char,
1890 XIMAGE_INSTANCE_PIXMAP_FG(image_instance) = foreground;
1891 XIMAGE_INSTANCE_PIXMAP_BG(image_instance) = background;
1892 XUnloadFont(dpy, source);
1893 if (mask && mask != source)
1894 XUnloadFont(dpy, mask);
1897 /**********************************************************************
1899 **********************************************************************/
1901 static void cursor_font_validate(Lisp_Object instantiator)
1903 data_must_be_present(instantiator);
1906 static int cursor_font_possible_dest_types(void)
1908 return IMAGE_POINTER_MASK;
1912 cursor_font_instantiate(Lisp_Object image_instance, Lisp_Object instantiator,
1913 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1914 int dest_mask, Lisp_Object domain)
1916 /* This function can GC */
1917 Lisp_Object data = find_keyword_in_vector(instantiator, Q_data);
1918 Lisp_Image_Instance *ii = XIMAGE_INSTANCE(image_instance);
1919 Lisp_Object device = IMAGE_INSTANCE_DEVICE(ii);
1922 const char *name_ext;
1923 Lisp_Object foreground, background;
1925 if (!DEVICE_X_P(XDEVICE(device)))
1926 signal_simple_error("Not an X device", device);
1928 dpy = DEVICE_X_DISPLAY(XDEVICE(device));
1930 if (!(dest_mask & IMAGE_POINTER_MASK))
1931 incompatible_image_types(instantiator, dest_mask,
1932 IMAGE_POINTER_MASK);
1934 LISP_STRING_TO_EXTERNAL(data, name_ext, Qfile_name);
1935 if ((i = XmuCursorNameToIndex(name_ext)) == -1)
1936 signal_simple_error("Unrecognized cursor-font name", data);
1938 x_initialize_pixmap_image_instance(ii, 1, IMAGE_POINTER);
1939 IMAGE_INSTANCE_X_CURSOR(ii) = XCreateFontCursor(dpy, i);
1940 foreground = find_keyword_in_vector(instantiator, Q_foreground);
1941 if (NILP(foreground))
1942 foreground = pointer_fg;
1943 background = find_keyword_in_vector(instantiator, Q_background);
1944 if (NILP(background))
1945 background = pointer_bg;
1946 maybe_recolor_cursor(image_instance, foreground, background);
1950 x_colorize_image_instance(Lisp_Object image_instance,
1951 Lisp_Object foreground, Lisp_Object background)
1953 Lisp_Image_Instance *p;
1955 p = XIMAGE_INSTANCE(image_instance);
1957 switch (IMAGE_INSTANCE_TYPE(p)) {
1958 case IMAGE_MONO_PIXMAP:
1959 IMAGE_INSTANCE_TYPE(p) = IMAGE_COLOR_PIXMAP;
1960 /* Make sure there aren't two pointers to the same mask, causing
1961 it to get freed twice. */
1962 IMAGE_INSTANCE_PIXMAP_MASK(p) = 0;
1968 case IMAGE_SUBWINDOW:
1970 case IMAGE_COLOR_PIXMAP:
1978 DEVICE_X_DISPLAY(XDEVICE(IMAGE_INSTANCE_DEVICE(p)));
1980 XtWindow(DEVICE_XT_APP_SHELL
1981 (XDEVICE(IMAGE_INSTANCE_DEVICE(p))));
1982 Dimension d = DEVICE_X_DEPTH(XDEVICE(IMAGE_INSTANCE_DEVICE(p)));
1983 Pixmap new = XCreatePixmap(dpy, draw,
1984 IMAGE_INSTANCE_PIXMAP_WIDTH(p),
1985 IMAGE_INSTANCE_PIXMAP_HEIGHT(p), d);
1989 color = COLOR_INSTANCE_X_COLOR(XCOLOR_INSTANCE(foreground));
1990 gcv.foreground = color.pixel;
1991 color = COLOR_INSTANCE_X_COLOR(XCOLOR_INSTANCE(background));
1992 gcv.background = color.pixel;
1993 gc = XCreateGC(dpy, new, GCBackground | GCForeground, &gcv);
1994 XCopyPlane(dpy, IMAGE_INSTANCE_X_PIXMAP(p), new, gc, 0, 0,
1995 IMAGE_INSTANCE_PIXMAP_WIDTH(p),
1996 IMAGE_INSTANCE_PIXMAP_HEIGHT(p), 0, 0, 1);
1998 IMAGE_INSTANCE_X_PIXMAP(p) = new;
1999 IMAGE_INSTANCE_PIXMAP_DEPTH(p) = d;
2000 IMAGE_INSTANCE_PIXMAP_FG(p) = foreground;
2001 IMAGE_INSTANCE_PIXMAP_BG(p) = background;
2006 /************************************************************************/
2007 /* subwindow and widget support */
2008 /************************************************************************/
2010 /* unmap the image if it is a widget. This is used by redisplay via
2011 redisplay_unmap_subwindows */
2012 static void x_unmap_subwindow(Lisp_Image_Instance * p)
2014 if (IMAGE_INSTANCE_TYPE(p) == IMAGE_SUBWINDOW) {
2016 (IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY(p),
2017 IMAGE_INSTANCE_X_CLIPWINDOW(p));
2018 } else { /* must be a widget */
2020 /* Since we are being unmapped we want the enclosing frame to
2021 get focus. The losing with simple scrolling but is the safest
2023 emacs_Xt_handle_widget_losing_focus
2024 (XFRAME(IMAGE_INSTANCE_FRAME(p)),
2025 IMAGE_INSTANCE_X_WIDGET_ID(p));
2026 XtUnmapWidget(IMAGE_INSTANCE_X_CLIPWIDGET(p));
2030 /* map the subwindow. This is used by redisplay via
2031 redisplay_output_subwindow */
2033 x_map_subwindow(Lisp_Image_Instance * p, int x, int y,
2034 struct display_glyph_area *dga)
2036 assert(dga->width > 0 && dga->height > 0);
2037 if (IMAGE_INSTANCE_TYPE(p) == IMAGE_SUBWINDOW) {
2038 Window subwindow = IMAGE_INSTANCE_X_SUBWINDOW_ID(p);
2039 XMoveResizeWindow(IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY(p),
2040 IMAGE_INSTANCE_X_CLIPWINDOW(p),
2041 x, y, dga->width, dga->height);
2042 XMoveWindow(IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY(p),
2043 subwindow, -dga->xoffset, -dga->yoffset);
2044 if (!IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP(p))
2045 XMapWindow(IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY(p),
2046 IMAGE_INSTANCE_X_CLIPWINDOW(p));
2047 } else { /* must be a widget */
2049 XtConfigureWidget(IMAGE_INSTANCE_X_CLIPWIDGET(p),
2050 x + IMAGE_INSTANCE_X_WIDGET_XOFFSET(p),
2051 y + IMAGE_INSTANCE_X_WIDGET_YOFFSET(p),
2052 dga->width, dga->height, 0);
2053 XtMoveWidget(IMAGE_INSTANCE_X_WIDGET_ID(p),
2054 -dga->xoffset, -dga->yoffset);
2055 if (!IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP(p))
2056 XtMapWidget(IMAGE_INSTANCE_X_CLIPWIDGET(p));
2057 if (IMAGE_INSTANCE_WANTS_INITIAL_FOCUS(p)) {
2058 /* #### FIXME to pop-up the find dialog we map the text-field
2059 seven times! This doesn't show on a fast linux, though. */
2060 enqueue_focus_event(IMAGE_INSTANCE_X_WIDGET_ID(p),
2061 IMAGE_INSTANCE_FRAME(p), 1);
2066 /* when you click on a widget you may activate another widget this
2067 needs to be checked and all appropriate widgets updated */
2068 static void x_redisplay_subwindow(Lisp_Image_Instance * p)
2070 /* Update the subwindow size if necessary. */
2071 if (IMAGE_INSTANCE_SIZE_CHANGED(p)) {
2072 XResizeWindow(IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY(p),
2073 IMAGE_INSTANCE_X_SUBWINDOW_ID(p),
2074 IMAGE_INSTANCE_WIDTH(p),
2075 IMAGE_INSTANCE_HEIGHT(p));
2079 /* Update all attributes that have changed. Lwlib actually does most
2081 static void x_redisplay_widget(Lisp_Image_Instance * p)
2083 /* This function can GC if IN_REDISPLAY is false. */
2085 widget_value *wv = 0;
2087 /* First get the items if they have changed since this is a
2088 structural change. As such it will nuke all added values so we
2089 need to update most other things after the items have changed. */
2090 if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED(p)) {
2091 Lisp_Object image_instance;
2093 XSETIMAGE_INSTANCE(image_instance, p);
2094 wv = gui_items_to_widget_values
2095 (image_instance, IMAGE_INSTANCE_WIDGET_PENDING_ITEMS(p),
2096 /* #### this is not right; we need to keep track of which widgets
2097 want accelerators and which don't */ 0);
2098 wv->change = STRUCTURAL_CHANGE;
2100 /* Assume the lotus position, breath deeply and chant to
2101 yourself lwlibsux, lwlibsux ... lw_get_all_values returns a
2102 reference to the real values rather than a copy thus any
2103 changes we make to the values we get back will look like they
2104 have already been applied. If we rebuild the widget tree then
2105 we may lose properties. */
2106 wv = copy_widget_value_tree(lw_get_all_values
2107 (IMAGE_INSTANCE_X_WIDGET_LWID(p)),
2111 /* Possibly update the colors and font */
2112 if (IMAGE_INSTANCE_WIDGET_FACE_CHANGED(p)
2114 /* #### This is not sufficient because it will not cope with widgets
2115 that are not currently visible. Once redisplay has done the
2116 visible ones it will clear this flag so that when new ones
2117 become visible they will not be updated. */
2118 XFRAME(IMAGE_INSTANCE_FRAME(p))->faces_changed
2120 XFRAME(IMAGE_INSTANCE_FRAME(p))->frame_changed
2121 || IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED(p)) {
2122 update_widget_face(wv, p, IMAGE_INSTANCE_FRAME(p));
2125 /* Possibly update the text. */
2126 if (IMAGE_INSTANCE_TEXT_CHANGED(p)) {
2128 Lisp_Object val = IMAGE_INSTANCE_WIDGET_TEXT(p);
2129 LISP_STRING_TO_EXTERNAL(val, str, Qnative);
2133 /* Possibly update the size. */
2134 if (IMAGE_INSTANCE_SIZE_CHANGED(p)
2135 || IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED(p)
2136 || IMAGE_INSTANCE_TEXT_CHANGED(p)) {
2137 assert(IMAGE_INSTANCE_X_WIDGET_ID(p) &&
2138 IMAGE_INSTANCE_X_CLIPWIDGET(p));
2140 if (IMAGE_INSTANCE_X_WIDGET_ID(p)->core.being_destroyed
2141 || !XtIsManaged(IMAGE_INSTANCE_X_WIDGET_ID(p))) {
2143 XSETIMAGE_INSTANCE(sw, p);
2144 signal_simple_error("SXEmacs bug: subwindow is deleted",
2148 lw_add_widget_value_arg(wv, XtNwidth,
2149 IMAGE_INSTANCE_WIDTH(p));
2150 lw_add_widget_value_arg(wv, XtNheight,
2151 IMAGE_INSTANCE_HEIGHT(p));
2154 /* Adjust offsets within the frame. */
2155 if (XFRAME(IMAGE_INSTANCE_FRAME(p))->size_changed) {
2157 XtSetArg(al[0], XtNx, &IMAGE_INSTANCE_X_WIDGET_XOFFSET(p));
2158 XtSetArg(al[1], XtNy, &IMAGE_INSTANCE_X_WIDGET_YOFFSET(p));
2159 XtGetValues(FRAME_X_TEXT_WIDGET
2160 (XFRAME(IMAGE_INSTANCE_FRAME(p))), al, 2);
2163 /* now modify the widget */
2164 lw_modify_all_widgets(IMAGE_INSTANCE_X_WIDGET_LWID(p), wv, True);
2165 free_widget_value_tree(wv);
2169 /* instantiate and x type subwindow */
2171 x_subwindow_instantiate(Lisp_Object image_instance, Lisp_Object instantiator,
2172 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2173 int dest_mask, Lisp_Object domain)
2175 /* This function can GC */
2176 Lisp_Image_Instance *ii = XIMAGE_INSTANCE(image_instance);
2177 Lisp_Object device = IMAGE_INSTANCE_DEVICE(ii);
2178 Lisp_Object frame = DOMAIN_FRAME(domain);
2179 struct frame *f = XFRAME(frame);
2183 XSetWindowAttributes xswa;
2185 unsigned int w = IMAGE_INSTANCE_WIDTH(ii),
2186 h = IMAGE_INSTANCE_HEIGHT(ii);
2188 if (!DEVICE_X_P(XDEVICE(device)))
2189 signal_simple_error("Not an X device", device);
2191 dpy = DEVICE_X_DISPLAY(XDEVICE(device));
2192 xs = DefaultScreenOfDisplay(dpy);
2194 IMAGE_INSTANCE_TYPE(ii) = IMAGE_SUBWINDOW;
2196 pw = XtWindow(FRAME_X_TEXT_WIDGET(f));
2198 ii->data = xnew_and_zero(struct x_subwindow_data);
2200 IMAGE_INSTANCE_X_SUBWINDOW_PARENT(ii) = pw;
2201 IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY(ii) = DisplayOfScreen(xs);
2203 xswa.backing_store = Always;
2204 valueMask |= CWBackingStore;
2205 xswa.colormap = DefaultColormapOfScreen(xs);
2206 valueMask |= CWColormap;
2208 /* Create a window for clipping */
2209 IMAGE_INSTANCE_X_CLIPWINDOW(ii) =
2210 XCreateWindow(dpy, pw, 0, 0, w, h, 0, CopyFromParent,
2211 InputOutput, CopyFromParent, valueMask, &xswa);
2213 /* Now put the subwindow inside the clip window. */
2214 win = XCreateWindow(dpy, IMAGE_INSTANCE_X_CLIPWINDOW(ii),
2215 0, 0, w, h, 0, CopyFromParent,
2216 InputOutput, CopyFromParent, valueMask, &xswa);
2218 IMAGE_INSTANCE_SUBWINDOW_ID(ii) = (void *)win;
2221 /* Account for some of the limitations with widget images. */
2222 static int x_widget_border_width(void)
2224 return DEFAULT_WIDGET_BORDER_WIDTH * 2;
2228 x_subwindow_query_geometry(Lisp_Object image_instance,
2229 int *width, int *height);
2232 x_subwindow_query_geometry(Lisp_Object image_instance,
2233 int *width, int *height)
2235 Lisp_Image_Instance *ii = XIMAGE_INSTANCE(image_instance);
2238 unsigned int dbdw, dd, dw = 20, dh = 20;
2240 XGetGeometry(IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY(ii),
2241 (Window)IMAGE_INSTANCE_SUBWINDOW_ID(ii),
2242 &droot, &dx, &dy, &dw, &dh, &dbdw, &dd);
2250 /* #### Should this function exist? If there's any doubt I'm not implementing it --andyp */
2251 DEFUN("change-subwindow-property", Fchange_subwindow_property, 3, 3, 0, /*
2252 For the given SUBWINDOW, set PROPERTY to DATA, which is a string.
2253 Subwindows are not currently implemented.
2255 (subwindow, property, data))
2261 CHECK_SUBWINDOW(subwindow);
2262 CHECK_STRING(property);
2265 sw = XSUBWINDOW(subwindow);
2266 dpy = DisplayOfScreen(LISP_DEVICE_TO_X_SCREEN
2267 (FRAME_DEVICE(XFRAME(sw->frame))));
2269 property_atom = XInternAtom(dpy, (char *)XSTRING_DATA(property), False);
2270 XChangeProperty(dpy, sw->subwindow, property_atom, XA_STRING, 8,
2272 XSTRING_DATA(data), XSTRING_LENGTH(data));
2280 /************************************************************************/
2282 /************************************************************************/
2285 update_widget_face(widget_value * wv, Lisp_Image_Instance * ii,
2288 #ifdef LWLIB_WIDGETS_MOTIF
2289 XmFontList fontList;
2291 /* Update the foreground. */
2292 Lisp_Object pixel = FACE_FOREGROUND(IMAGE_INSTANCE_WIDGET_FACE(ii),
2294 XColor fcolor = COLOR_INSTANCE_X_COLOR(XCOLOR_INSTANCE(pixel)), bcolor;
2295 lw_add_widget_value_arg(wv, XtNforeground, fcolor.pixel);
2297 /* Update the background. */
2298 pixel = FACE_BACKGROUND(IMAGE_INSTANCE_WIDGET_FACE(ii), domain);
2299 bcolor = COLOR_INSTANCE_X_COLOR(XCOLOR_INSTANCE(pixel));
2300 lw_add_widget_value_arg(wv, XtNbackground, bcolor.pixel);
2302 #ifdef LWLIB_WIDGETS_MOTIF
2303 fontList = XmFontListCreate
2304 (FONT_INSTANCE_X_FONT
2305 (XFONT_INSTANCE(query_string_font
2306 (IMAGE_INSTANCE_WIDGET_TEXT(ii),
2307 IMAGE_INSTANCE_WIDGET_FACE(ii),
2308 domain))), XmSTRING_DEFAULT_CHARSET);
2309 lw_add_widget_value_arg(wv, XmNfontList, (XtArgVal) fontList);
2312 Lisp_Object tmp = query_string_font(
2313 IMAGE_INSTANCE_WIDGET_TEXT(ii),
2314 IMAGE_INSTANCE_WIDGET_FACE(ii), domain);
2315 lw_add_widget_value_arg(
2317 (XtArgVal)FONT_INSTANCE_X_FONT(XFONT_INSTANCE(tmp)));
2319 wv->change = VISIBLE_CHANGE;
2320 /* #### Megahack - but its just getting too complicated to do this
2321 in the right place. */
2322 if (EQ(IMAGE_INSTANCE_WIDGET_TYPE(ii), Qtab_control)) {
2323 update_tab_widget_face(wv, ii, domain);
2329 update_tab_widget_face(widget_value * wv, Lisp_Image_Instance * ii,
2333 widget_value *val = wv->contents, *cur;
2335 /* Give each child label the correct foreground color. */
2336 Lisp_Object pixel = FACE_FOREGROUND
2337 (IMAGE_INSTANCE_WIDGET_FACE(ii),
2339 XColor fcolor = COLOR_INSTANCE_X_COLOR(XCOLOR_INSTANCE(pixel));
2340 lw_add_widget_value_arg(val, XtNtabForeground, fcolor.pixel);
2341 wv->change = VISIBLE_CHANGE;
2342 val->change = VISIBLE_CHANGE;
2344 for (cur = val->next; cur; cur = cur->next) {
2345 cur->change = VISIBLE_CHANGE;
2347 lw_copy_widget_value_args(val, cur);
2354 x_widget_instantiate(Lisp_Object image_instance, Lisp_Object instantiator,
2355 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2356 int dest_mask, Lisp_Object domain,
2357 const char *type, widget_value * wv)
2359 Lisp_Image_Instance *ii = XIMAGE_INSTANCE(image_instance);
2360 Lisp_Object device = IMAGE_INSTANCE_DEVICE(ii), pixel;
2361 struct device *d = XDEVICE(device);
2362 Lisp_Object frame = DOMAIN_FRAME(domain);
2363 struct frame *f = XFRAME(frame);
2368 int id = new_lwlib_id();
2369 widget_value *clip_wv;
2370 XColor fcolor, bcolor;
2373 signal_simple_error("Not an X device", device);
2375 /* have to set the type this late in case there is no device
2376 instantiation for a widget. But we can go ahead and do it without
2377 checking because there is always a generic instantiator. */
2378 IMAGE_INSTANCE_TYPE(ii) = IMAGE_WIDGET;
2380 if (!NILP(IMAGE_INSTANCE_WIDGET_TEXT(ii)))
2381 LISP_STRING_TO_EXTERNAL(IMAGE_INSTANCE_WIDGET_TEXT(ii), nm,
2384 ii->data = xnew_and_zero(struct x_subwindow_data);
2386 /* Create a clip window to contain the subwidget. Incredibly the
2387 SXEmacs manager seems to be the most appropriate widget for
2388 this. Nothing else is simple enough and yet does what is
2390 clip_wv = xmalloc_widget_value();
2392 lw_add_widget_value_arg(clip_wv, XtNresize, False);
2393 lw_add_widget_value_arg(clip_wv, XtNwidth,
2394 IMAGE_INSTANCE_WIDTH(ii));
2395 lw_add_widget_value_arg(clip_wv, XtNheight,
2396 IMAGE_INSTANCE_HEIGHT(ii));
2397 clip_wv->enabled = True;
2399 clip_wv->name = xstrdup("clip-window");
2400 clip_wv->value = xstrdup("clip-window");
2402 IMAGE_INSTANCE_X_CLIPWIDGET(ii)
2403 = lw_create_widget("clip-window", "clip-window", new_lwlib_id(),
2404 clip_wv, FRAME_X_CONTAINER_WIDGET(f),
2407 free_widget_value_tree(clip_wv);
2409 /* create a sensible name. */
2410 if (wv->name == 0 || strcmp(wv->name, "") == 0)
2411 wv->name = xstrdup(type);
2413 /* copy any args we were given */
2415 lw_add_value_args_to_args(wv, al, &ac);
2417 /* Fixup the colors. We have to do this *before* the widget gets
2418 created so that Motif will fix up the shadow colors
2419 correctly. Once the widget is created Motif won't do this
2421 pixel = FACE_FOREGROUND
2422 (IMAGE_INSTANCE_WIDGET_FACE(ii), IMAGE_INSTANCE_FRAME(ii));
2423 fcolor = COLOR_INSTANCE_X_COLOR(XCOLOR_INSTANCE(pixel));
2425 pixel = FACE_BACKGROUND
2426 (IMAGE_INSTANCE_WIDGET_FACE(ii), IMAGE_INSTANCE_FRAME(ii));
2427 bcolor = COLOR_INSTANCE_X_COLOR(XCOLOR_INSTANCE(pixel));
2429 lw_add_widget_value_arg(wv, XtNbackground, bcolor.pixel);
2430 lw_add_widget_value_arg(wv, XtNforeground, fcolor.pixel);
2431 /* we cannot allow widgets to resize themselves */
2432 lw_add_widget_value_arg(wv, XtNresize, False);
2433 lw_add_widget_value_arg(wv, XtNwidth, IMAGE_INSTANCE_WIDTH(ii));
2434 lw_add_widget_value_arg(wv, XtNheight, IMAGE_INSTANCE_HEIGHT(ii));
2435 /* update the font. */
2436 update_widget_face(wv, ii, domain);
2439 lw_create_widget(type, wv->name, id, wv,
2440 IMAGE_INSTANCE_X_CLIPWIDGET(ii), False, 0,
2441 popup_selection_callback, 0);
2443 IMAGE_INSTANCE_SUBWINDOW_ID(ii) = (void *)wid;
2444 IMAGE_INSTANCE_X_WIDGET_LWID(ii) = id;
2445 /* because the EmacsManager is the widgets parent we have to
2446 offset the redisplay of the widget by the amount the text
2447 widget is inside the manager. */
2449 XtSetArg(al[ac], XtNx, &IMAGE_INSTANCE_X_WIDGET_XOFFSET(ii));
2451 XtSetArg(al[ac], XtNy, &IMAGE_INSTANCE_X_WIDGET_YOFFSET(ii));
2453 XtGetValues(FRAME_X_TEXT_WIDGET(f), al, ac);
2455 XtSetMappedWhenManaged(wid, TRUE);
2457 free_widget_value_tree(wv);
2458 /* A kludgy but simple way to make sure the callback for a widget
2459 doesn't get deleted. */
2460 gcpro_popup_callbacks(id);
2463 /* get properties of a control */
2465 x_widget_property(Lisp_Object image_instance, Lisp_Object prop)
2467 Lisp_Image_Instance *ii = XIMAGE_INSTANCE(image_instance);
2468 /* get the text from a control */
2469 if (EQ(prop, Q_text)) {
2471 lw_get_all_values(IMAGE_INSTANCE_X_WIDGET_LWID(ii));
2472 return build_ext_string(wv->value, Qnative);
2477 /* Instantiate a layout control for putting other widgets in. */
2479 x_native_layout_instantiate(Lisp_Object image_instance,
2480 Lisp_Object instantiator, Lisp_Object pointer_fg,
2481 Lisp_Object pointer_bg, int dest_mask,
2484 x_widget_instantiate(image_instance, instantiator, pointer_fg,
2485 pointer_bg, dest_mask, domain, "layout", 0);
2488 /* Instantiate a button widget. Unfortunately instantiated widgets are
2489 particular to a frame since they need to have a parent. It's not
2490 like images where you just select the image into the context you
2491 want to display it in and BitBlt it. So images instances can have a
2492 many-to-one relationship with things you see, whereas widgets can
2493 only be one-to-one (i.e. per frame) */
2495 x_button_instantiate(Lisp_Object image_instance, Lisp_Object instantiator,
2496 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2497 int dest_mask, Lisp_Object domain)
2499 Lisp_Image_Instance *ii = XIMAGE_INSTANCE(image_instance);
2500 Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM(ii);
2501 Lisp_Object glyph = find_keyword_in_vector(instantiator, Q_image);
2502 widget_value *wv = gui_items_to_widget_values(image_instance, gui, 1);
2505 if (!IMAGE_INSTANCEP(glyph))
2507 glyph_image_instance(glyph, domain, ERROR_ME, 1);
2510 x_widget_instantiate(image_instance, instantiator, pointer_fg,
2511 pointer_bg, dest_mask, domain, "button", wv);
2513 /* add the image if one was given */
2514 if (!NILP(glyph) && IMAGE_INSTANCEP(glyph)
2515 && IMAGE_INSTANCE_PIXMAP_TYPE_P(XIMAGE_INSTANCE(glyph))) {
2518 #ifdef LWLIB_WIDGETS_MOTIF
2519 XtSetArg(al[ac], XmNlabelType, XmPIXMAP);
2521 XtSetArg(al[ac], XmNlabelPixmap,
2522 XIMAGE_INSTANCE_X_PIXMAP(glyph));
2525 XtSetArg(al[ac], XtNpixmap, XIMAGE_INSTANCE_X_PIXMAP(glyph));
2528 XtSetValues(IMAGE_INSTANCE_X_WIDGET_ID(ii), al, ac);
2532 /* Update a button's clicked state.
2534 #### This is overkill, but it works. Right now this causes all
2535 button instances to flash for some reason buried deep in lwlib. In
2536 theory this should be the Right Thing to do since lwlib should only
2537 merge in changed values - and if nothing has changed then nothing
2538 should get done. This may be because of the args stuff,
2539 i.e. although the arg contents may be the same the args look
2540 different and so are re-applied to the widget. */
2541 static void x_button_redisplay(Lisp_Object image_instance)
2543 /* This function can GC if IN_REDISPLAY is false. */
2544 Lisp_Image_Instance *p = XIMAGE_INSTANCE(image_instance);
2545 widget_value *wv = gui_items_to_widget_values(image_instance,
2546 IMAGE_INSTANCE_WIDGET_ITEMS
2549 /* now modify the widget */
2550 lw_modify_all_widgets(IMAGE_INSTANCE_X_WIDGET_LWID(p), wv, True);
2551 free_widget_value_tree(wv);
2554 /* get properties of a button */
2556 x_button_property(Lisp_Object image_instance, Lisp_Object prop)
2558 Lisp_Image_Instance *ii = XIMAGE_INSTANCE(image_instance);
2559 /* check the state of a button */
2560 if (EQ(prop, Q_selected)) {
2562 lw_get_all_values(IMAGE_INSTANCE_X_WIDGET_LWID(ii));
2572 /* instantiate a progress gauge */
2574 x_progress_gauge_instantiate(Lisp_Object image_instance,
2575 Lisp_Object instantiator, Lisp_Object pointer_fg,
2576 Lisp_Object pointer_bg, int dest_mask,
2579 Lisp_Image_Instance *ii = XIMAGE_INSTANCE(image_instance);
2580 Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM(ii);
2581 widget_value *wv = gui_items_to_widget_values(image_instance, gui, 0);
2583 x_widget_instantiate(image_instance, instantiator, pointer_fg,
2584 pointer_bg, dest_mask, domain, "progress", wv);
2587 /* set the properties of a progress gauge */
2588 static void x_progress_gauge_redisplay(Lisp_Object image_instance)
2590 Lisp_Image_Instance *ii = XIMAGE_INSTANCE(image_instance);
2592 if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED(ii)) {
2595 #ifdef ERROR_CHECK_GLYPHS
2596 assert(GUI_ITEMP(IMAGE_INSTANCE_WIDGET_PENDING_ITEMS(ii)));
2598 val = XGUI_ITEM(IMAGE_INSTANCE_WIDGET_PENDING_ITEMS(ii))->value;
2599 XtSetArg(al[0], XtNvalue, XINT(val));
2600 XtSetValues(IMAGE_INSTANCE_X_WIDGET_ID(ii), al, 1);
2604 /* instantiate an edit control */
2606 x_edit_field_instantiate(Lisp_Object image_instance, Lisp_Object instantiator,
2607 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2608 int dest_mask, Lisp_Object domain)
2610 Lisp_Image_Instance *ii = XIMAGE_INSTANCE(image_instance);
2611 Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM(ii);
2612 widget_value *wv = gui_items_to_widget_values(image_instance, gui, 0);
2614 x_widget_instantiate(image_instance, instantiator, pointer_fg,
2615 pointer_bg, dest_mask, domain, "text-field", wv);
2618 #if defined (LWLIB_WIDGETS_MOTIF) && XmVERSION > 1
2619 /* instantiate a combo control */
2621 x_combo_box_instantiate(Lisp_Object image_instance, Lisp_Object instantiator,
2622 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2623 int dest_mask, Lisp_Object domain)
2625 Lisp_Image_Instance *ii = XIMAGE_INSTANCE(image_instance);
2626 widget_value *wv = 0;
2627 /* This is not done generically because of sizing problems under
2628 mswindows. REVISE ME: We don't support windows, so? */
2629 widget_instantiate(image_instance, instantiator, pointer_fg,
2630 pointer_bg, dest_mask, domain);
2632 wv = gui_items_to_widget_values(image_instance,
2633 IMAGE_INSTANCE_WIDGET_ITEMS(ii), 0);
2635 x_widget_instantiate(image_instance, instantiator, pointer_fg,
2636 pointer_bg, dest_mask, domain, "combo-box", wv);
2641 x_tab_control_instantiate(Lisp_Object image_instance, Lisp_Object instantiator,
2642 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2643 int dest_mask, Lisp_Object domain)
2645 Lisp_Image_Instance *ii = XIMAGE_INSTANCE(image_instance);
2646 widget_value *wv = gui_items_to_widget_values(image_instance,
2647 IMAGE_INSTANCE_WIDGET_ITEMS
2649 update_tab_widget_face(wv, ii, IMAGE_INSTANCE_FRAME(ii));
2650 x_widget_instantiate(image_instance, instantiator, pointer_fg,
2651 pointer_bg, dest_mask, domain, "tab-control", wv);
2654 /* Set the properties of a tab control */
2655 static void x_tab_control_redisplay(Lisp_Object image_instance)
2657 Lisp_Image_Instance *ii = XIMAGE_INSTANCE(image_instance);
2659 if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED(ii)
2660 || IMAGE_INSTANCE_WIDGET_ACTION_OCCURRED(ii)) {
2661 /* If only the order has changed then simply select the first
2662 one of the pending set. This stops horrendous rebuilding -
2663 and hence flicker - of the tabs each time you click on
2665 if (tab_control_order_only_changed(image_instance)) {
2666 Lisp_Object rest, selected =
2667 gui_item_list_find_selected
2668 (NILP(IMAGE_INSTANCE_WIDGET_PENDING_ITEMS(ii)) ?
2669 XCDR(IMAGE_INSTANCE_WIDGET_ITEMS(ii)) :
2670 XCDR(IMAGE_INSTANCE_WIDGET_PENDING_ITEMS(ii)));
2672 LIST_LOOP(rest, XCDR(IMAGE_INSTANCE_WIDGET_ITEMS(ii))) {
2673 if (gui_item_equal_sans_selected
2674 (XCAR(rest), selected, 0)) {
2675 /* There may be an encapsulated way of doing this,
2676 but I couldn't find it. */
2677 Lisp_Object old_selected =
2678 gui_item_list_find_selected(XCDR
2679 (IMAGE_INSTANCE_WIDGET_ITEMS
2683 unsigned int num_children, i;
2686 LISP_STRING_TO_EXTERNAL(XGUI_ITEM
2690 /* The name may contain a `.' which confuses
2691 XtNameToWidget, so we do it ourselves. */
2694 (IMAGE_INSTANCE_X_WIDGET_ID(ii),
2696 for (i = 0; i < num_children; i++) {
2698 (XtName(children[i]),
2707 (IMAGE_INSTANCE_X_WIDGET_ID
2712 /* Pick up the new selected item. */
2713 XGUI_ITEM(old_selected)->selected =
2714 XGUI_ITEM(XCAR(rest))->selected;
2715 XGUI_ITEM(XCAR(rest))->selected =
2716 XGUI_ITEM(selected)->selected;
2717 /* We're not actually changing the items anymore. */
2718 IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED(ii)
2720 IMAGE_INSTANCE_WIDGET_PENDING_ITEMS(ii)
2727 /* Possibly update the face. */
2728 if (IMAGE_INSTANCE_WIDGET_FACE_CHANGED(ii)
2730 XFRAME(IMAGE_INSTANCE_FRAME(ii))->faces_changed
2731 || IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED(ii)) {
2732 /* See previous comments on the brokeness of lwlib.
2734 #### There's actually not much point in doing this here
2735 since, colors will have been set appropriately by
2736 x_redisplay_widget. */
2737 widget_value *wv = copy_widget_value_tree
2738 (lw_get_all_values(IMAGE_INSTANCE_X_WIDGET_LWID(ii)),
2741 update_tab_widget_face(wv, ii, IMAGE_INSTANCE_FRAME(ii));
2743 lw_modify_all_widgets(IMAGE_INSTANCE_X_WIDGET_LWID(ii), wv,
2745 free_widget_value_tree(wv);
2749 /* instantiate a static control possible for putting other things in */
2751 x_label_instantiate(Lisp_Object image_instance, Lisp_Object instantiator,
2752 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2753 int dest_mask, Lisp_Object domain)
2755 Lisp_Image_Instance *ii = XIMAGE_INSTANCE(image_instance);
2756 Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM(ii);
2757 widget_value *wv = gui_items_to_widget_values(image_instance, gui, 0);
2759 x_widget_instantiate(image_instance, instantiator, pointer_fg,
2760 pointer_bg, dest_mask, domain, "button", wv);
2762 #endif /* HAVE_WIDGETS */
2764 /************************************************************************/
2765 /* initialization */
2766 /************************************************************************/
2768 void syms_of_glyphs_x(void)
2771 DEFSUBR(Fchange_subwindow_property);
2775 void console_type_create_glyphs_x(void)
2779 CONSOLE_HAS_METHOD(x, print_image_instance);
2780 CONSOLE_HAS_METHOD(x, finalize_image_instance);
2781 CONSOLE_HAS_METHOD(x, image_instance_equal);
2782 CONSOLE_HAS_METHOD(x, image_instance_hash);
2783 CONSOLE_HAS_METHOD(x, colorize_image_instance);
2784 CONSOLE_HAS_METHOD(x, init_image_instance_from_eimage);
2785 CONSOLE_HAS_METHOD(x, locate_pixmap_file);
2786 CONSOLE_HAS_METHOD(x, unmap_subwindow);
2787 CONSOLE_HAS_METHOD(x, map_subwindow);
2788 CONSOLE_HAS_METHOD(x, redisplay_widget);
2789 CONSOLE_HAS_METHOD(x, redisplay_subwindow);
2790 CONSOLE_HAS_METHOD(x, widget_border_width);
2793 void image_instantiator_format_create_glyphs_x(void)
2795 IIFORMAT_VALID_CONSOLE(x, nothing);
2796 IIFORMAT_VALID_CONSOLE(x, string);
2798 IIFORMAT_VALID_CONSOLE(x, layout);
2800 IIFORMAT_VALID_CONSOLE(x, formatted_string);
2801 IIFORMAT_VALID_CONSOLE(x, inherit);
2803 INITIALIZE_DEVICE_IIFORMAT(x, xpm);
2804 IIFORMAT_HAS_DEVMETHOD(x, xpm, instantiate);
2807 IIFORMAT_VALID_CONSOLE(x, jpeg);
2810 IIFORMAT_VALID_CONSOLE(x, tiff);
2812 #if defined WITH_PNG && defined HAVE_PNG
2813 IIFORMAT_VALID_CONSOLE(x, png);
2816 IIFORMAT_VALID_CONSOLE(x, gif);
2819 IIFORMAT_VALID_CONSOLE(x, rawrgb);
2820 IIFORMAT_VALID_CONSOLE(x, rawrgba);
2823 INITIALIZE_DEVICE_IIFORMAT(x, xbm);
2824 IIFORMAT_HAS_DEVMETHOD(x, xbm, instantiate);
2826 INITIALIZE_DEVICE_IIFORMAT(x, subwindow);
2827 IIFORMAT_HAS_DEVMETHOD(x, subwindow, instantiate);
2830 INITIALIZE_DEVICE_IIFORMAT(x, native_layout);
2831 IIFORMAT_HAS_DEVMETHOD(x, native_layout, instantiate);
2833 INITIALIZE_DEVICE_IIFORMAT(x, button);
2834 IIFORMAT_HAS_DEVMETHOD(x, button, property);
2835 IIFORMAT_HAS_DEVMETHOD(x, button, instantiate);
2836 IIFORMAT_HAS_DEVMETHOD(x, button, redisplay);
2837 /* general widget methods. */
2838 INITIALIZE_DEVICE_IIFORMAT(x, widget);
2839 IIFORMAT_HAS_DEVMETHOD(x, widget, property);
2840 /* progress gauge */
2841 INITIALIZE_DEVICE_IIFORMAT(x, progress_gauge);
2842 IIFORMAT_HAS_DEVMETHOD(x, progress_gauge, redisplay);
2843 IIFORMAT_HAS_DEVMETHOD(x, progress_gauge, instantiate);
2845 INITIALIZE_DEVICE_IIFORMAT(x, edit_field);
2846 IIFORMAT_HAS_DEVMETHOD(x, edit_field, instantiate);
2847 #if defined (LWLIB_WIDGETS_MOTIF) && XmVERSION > 1
2849 INITIALIZE_DEVICE_IIFORMAT(x, combo_box);
2850 IIFORMAT_HAS_DEVMETHOD(x, combo_box, instantiate);
2851 IIFORMAT_HAS_SHARED_DEVMETHOD(x, combo_box, redisplay, tab_control);
2853 /* tab control widget */
2854 INITIALIZE_DEVICE_IIFORMAT(x, tab_control);
2855 IIFORMAT_HAS_DEVMETHOD(x, tab_control, instantiate);
2856 IIFORMAT_HAS_DEVMETHOD(x, tab_control, redisplay);
2858 INITIALIZE_DEVICE_IIFORMAT(x, label);
2859 IIFORMAT_HAS_DEVMETHOD(x, label, instantiate);
2861 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT(cursor_font, "cursor-font");
2862 IIFORMAT_VALID_CONSOLE(x, cursor_font);
2864 IIFORMAT_HAS_METHOD(cursor_font, validate);
2865 IIFORMAT_HAS_METHOD(cursor_font, possible_dest_types);
2866 IIFORMAT_HAS_METHOD(cursor_font, instantiate);
2868 IIFORMAT_VALID_KEYWORD(cursor_font, Q_data, check_valid_string);
2869 IIFORMAT_VALID_KEYWORD(cursor_font, Q_foreground, check_valid_string);
2870 IIFORMAT_VALID_KEYWORD(cursor_font, Q_background, check_valid_string);
2872 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT(font, "font");
2874 IIFORMAT_HAS_METHOD(font, validate);
2875 IIFORMAT_HAS_METHOD(font, possible_dest_types);
2876 IIFORMAT_HAS_METHOD(font, instantiate);
2877 IIFORMAT_VALID_CONSOLE(x, font);
2879 IIFORMAT_VALID_KEYWORD(font, Q_data, check_valid_string);
2880 IIFORMAT_VALID_KEYWORD(font, Q_foreground, check_valid_string);
2881 IIFORMAT_VALID_KEYWORD(font, Q_background, check_valid_string);
2884 INITIALIZE_DEVICE_IIFORMAT(x, xface);
2885 IIFORMAT_HAS_DEVMETHOD(x, xface, instantiate);
2888 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT(autodetect, "autodetect");
2890 IIFORMAT_HAS_METHOD(autodetect, validate);
2891 IIFORMAT_HAS_METHOD(autodetect, normalize);
2892 IIFORMAT_HAS_METHOD(autodetect, possible_dest_types);
2893 /* #### autodetect is flawed IMO:
2894 1. It makes the assumption that you can detect whether the user
2895 wanted a cursor or a string based on the data, since the data is a
2896 string you have to prioritise cursors. Instead we will force users
2897 to pick the appropriate image type, this is what we do under
2899 2. It doesn't fit with the new domain model - you cannot tell which
2900 domain it needs to be instantiated in until you've actually
2901 instantiated it, which mucks up caching.
2902 3. It only copes with cursors and strings which seems bogus. */
2903 IIFORMAT_HAS_SHARED_METHOD(autodetect, governing_domain, subwindow);
2904 IIFORMAT_HAS_METHOD(autodetect, instantiate);
2905 IIFORMAT_VALID_CONSOLE(x, autodetect);
2907 IIFORMAT_VALID_KEYWORD(autodetect, Q_data, check_valid_string);
2910 void vars_of_glyphs_x(void)
2912 DEFVAR_LISP("x-bitmap-file-path", &Vx_bitmap_file_path /*
2913 A list of the directories in which X bitmap files may be found.
2914 If nil, this is initialized from the "*bitmapFilePath" resource.
2915 This is used by the `make-image-instance' function (however, note that if
2916 the environment variable XBMLANGPATH is set, it is consulted first).
2918 Vx_bitmap_file_path = Qnil;
2921 void complex_vars_of_glyphs_x(void)
2923 #define BUILD_GLYPH_INST(variable, name) \
2924 Fadd_spec_to_specifier \
2925 (GLYPH_IMAGE (XGLYPH (variable)), \
2926 vector3 (Qxbm, Q_data, \
2927 list3 (make_int (name##_width), \
2928 make_int (name##_height), \
2929 make_ext_string ((Extbyte *) name##_bits, \
2930 sizeof (name##_bits), \
2934 BUILD_GLYPH_INST(Vtruncation_glyph, truncator);
2935 BUILD_GLYPH_INST(Vcontinuation_glyph, continuer);
2936 BUILD_GLYPH_INST(Vsxemacs_logo, sxemacs);
2937 BUILD_GLYPH_INST(Vhscroll_glyph, hscroll);
2939 #undef BUILD_GLYPH_INST