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
8 This file is part of XEmacs.
10 XEmacs is free software; you can redistribute it and/or modify it
11 under the terms of the GNU General Public License as published by the
12 Free Software Foundation; either version 2, or (at your option) any
15 XEmacs is distributed in the hope that it will be useful, but WITHOUT
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 You should have received a copy of the GNU General Public License
21 along with XEmacs; see the file COPYING. If not, write to
22 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23 Boston, MA 02111-1307, USA. */
25 /* Synched up with: Not in FSF. */
27 /* Original author: Jamie Zawinski for 19.8
28 font-truename stuff added by Jamie Zawinski for 19.10
29 subwindow support added by Chuck Thompson
30 additional XPM support added by Chuck Thompson
31 initial X-Face support added by Stig
32 rewritten/restructured by Ben Wing for 19.12/19.13
33 GIF/JPEG support added by Ben Wing for 19.14
34 PNG support added by Bill Perry for 19.14
35 Improved GIF/JPEG support added by Bill Perry for 19.14
36 Cleanup/simplification of error handling by Ben Wing for 19.14
37 Pointer/icon overhaul, more restructuring by Ben Wing for 19.14
38 GIF support changed to external GIFlib 3.1 by Jareth Hein for 21.0
39 Many changes for color work and optimizations by Jareth Hein for 21.0
40 Switch of GIF/JPEG/PNG to new EImage intermediate code by Jareth Hein for 21.0
41 TIFF code by Jareth Hein for 21.0
42 GIF/JPEG/PNG/TIFF code moved to new glyph-eimage.c for 21.0
45 Convert images.el to C and stick it in here?
51 #include "console-x.h"
53 #include "objects-x.h"
68 #include "file-coding.h"
72 # define FOUR_BYTE_TYPE unsigned int
74 # define FOUR_BYTE_TYPE unsigned long
76 # define FOUR_BYTE_TYPE unsigned short
78 #error What kind of strange-ass system are we running on?
81 #define LISP_DEVICE_TO_X_SCREEN(dev) XDefaultScreenOfDisplay (DEVICE_X_DISPLAY (XDEVICE (dev)))
84 DEFINE_IMAGE_INSTANTIATOR_FORMAT (xface);
88 DEFINE_IMAGE_INSTANTIATOR_FORMAT (cursor_font);
89 Lisp_Object Qcursor_font;
91 DEFINE_IMAGE_INSTANTIATOR_FORMAT (font);
93 DEFINE_IMAGE_INSTANTIATOR_FORMAT (autodetect);
95 static void cursor_font_instantiate (Lisp_Object image_instance,
96 Lisp_Object instantiator,
97 Lisp_Object pointer_fg,
98 Lisp_Object pointer_bg,
105 /************************************************************************/
106 /* image instance methods */
107 /************************************************************************/
109 /************************************************************************/
110 /* convert from a series of RGB triples to an XImage formated for the */
112 /************************************************************************/
114 convert_EImage_to_XImage (Lisp_Object device, int width, int height,
115 unsigned char *pic, unsigned long **pixtbl,
122 int depth, bitmap_pad, byte_cnt, i, j;
124 unsigned char *data, *ip, *dp;
131 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
132 cmap = DEVICE_X_COLORMAP (XDEVICE(device));
133 vis = DEVICE_X_VISUAL (XDEVICE(device));
134 depth = DEVICE_X_DEPTH(XDEVICE(device));
136 if (vis->class == PseudoColor)
138 /* Quantize the image and get a histogram while we're at it.
139 Do this first to save memory */
140 qtable = build_EImage_quantable(pic, width, height, 256);
141 if (qtable == NULL) return NULL;
144 bitmap_pad = ((depth > 16) ? 32 :
147 byte_cnt = bitmap_pad >> 3;
149 outimg = XCreateImage (dpy, vis,
150 depth, ZPixmap, 0, 0, width, height,
152 if (!outimg) return NULL;
154 data = (unsigned char *) xmalloc (outimg->bytes_per_line * height);
157 XDestroyImage (outimg);
160 outimg->data = (char *) data;
162 if (vis->class == PseudoColor)
164 unsigned long pixarray[256];
166 /* use our quantize table to allocate the colors */
168 *pixtbl = xnew_array (unsigned long, pixcount);
171 /* ### should implement a sort by popularity to assure proper allocation */
173 for (i = 0; i < qtable->num_active_colors; i++)
178 color.red = qtable->rm[i] ? qtable->rm[i] << 8 : 0;
179 color.green = qtable->gm[i] ? qtable->gm[i] << 8 : 0;
180 color.blue = qtable->bm[i] ? qtable->bm[i] << 8 : 0;
181 color.flags = DoRed | DoGreen | DoBlue;
182 res = allocate_nearest_color (dpy, cmap, vis, &color);
183 if (res > 0 && res < 3)
185 DO_REALLOC(*pixtbl, pixcount, n+1, unsigned long);
186 (*pixtbl)[n] = color.pixel;
189 pixarray[i] = color.pixel;
193 for (i = 0; i < height; i++)
195 dp = data + (i * outimg->bytes_per_line);
196 for (j = 0; j < width; j++)
201 conv.val = pixarray[QUANT_GET_COLOR(qtable,rd,gr,bl)];
203 if (outimg->byte_order == MSBFirst)
204 for (q = 4-byte_cnt; q < 4; q++) *dp++ = conv.cp[q];
206 for (q = 3; q >= 4-byte_cnt; q--) *dp++ = conv.cp[q];
208 if (outimg->byte_order == MSBFirst)
209 for (q = byte_cnt-1; q >= 0; q--) *dp++ = conv.cp[q];
211 for (q = 0; q < byte_cnt; q++) *dp++ = conv.cp[q];
217 unsigned long rshift,gshift,bshift,rbits,gbits,bbits,junk;
218 junk = vis->red_mask;
220 while ((junk & 0x1) == 0)
231 junk = vis->green_mask;
233 while ((junk & 0x1) == 0)
244 junk = vis->blue_mask;
246 while ((junk & 0x1) == 0)
258 for (i = 0; i < height; i++)
260 dp = data + (i * outimg->bytes_per_line);
261 for (j = 0; j < width; j++)
264 rd = *ip++ << (rbits - 8);
266 rd = *ip++ >> (8 - rbits);
268 gr = *ip++ << (gbits - 8);
270 gr = *ip++ >> (8 - gbits);
272 bl = *ip++ << (bbits - 8);
274 bl = *ip++ >> (8 - bbits);
276 conv.val = (rd << rshift) | (gr << gshift) | (bl << bshift);
278 if (outimg->byte_order == MSBFirst)
279 for (q = 4-byte_cnt; q < 4; q++) *dp++ = conv.cp[q];
281 for (q = 3; q >= 4-byte_cnt; q--) *dp++ = conv.cp[q];
283 if (outimg->byte_order == MSBFirst)
284 for (q = byte_cnt-1; q >= 0; q--) *dp++ = conv.cp[q];
286 for (q = 0; q < byte_cnt; q++) *dp++ = conv.cp[q];
297 x_print_image_instance (struct Lisp_Image_Instance *p,
298 Lisp_Object printcharfun,
303 switch (IMAGE_INSTANCE_TYPE (p))
305 case IMAGE_MONO_PIXMAP:
306 case IMAGE_COLOR_PIXMAP:
308 sprintf (buf, " (0x%lx", (unsigned long) IMAGE_INSTANCE_X_PIXMAP (p));
309 write_c_string (buf, printcharfun);
310 if (IMAGE_INSTANCE_X_MASK (p))
312 sprintf (buf, "/0x%lx", (unsigned long) IMAGE_INSTANCE_X_MASK (p));
313 write_c_string (buf, printcharfun);
315 write_c_string (")", printcharfun);
318 case IMAGE_SUBWINDOW:
319 /* #### implement me */
327 x_finalize_image_instance (struct Lisp_Image_Instance *p)
332 if (DEVICE_LIVE_P (XDEVICE (p->device)))
334 Display *dpy = DEVICE_X_DISPLAY (XDEVICE (p->device));
336 if (IMAGE_INSTANCE_X_PIXMAP (p))
337 XFreePixmap (dpy, IMAGE_INSTANCE_X_PIXMAP (p));
338 if (IMAGE_INSTANCE_X_MASK (p) &&
339 IMAGE_INSTANCE_X_MASK (p) != IMAGE_INSTANCE_X_PIXMAP (p))
340 XFreePixmap (dpy, IMAGE_INSTANCE_X_MASK (p));
341 IMAGE_INSTANCE_X_PIXMAP (p) = 0;
342 IMAGE_INSTANCE_X_MASK (p) = 0;
344 if (IMAGE_INSTANCE_X_CURSOR (p))
346 XFreeCursor (dpy, IMAGE_INSTANCE_X_CURSOR (p));
347 IMAGE_INSTANCE_X_CURSOR (p) = 0;
350 if (IMAGE_INSTANCE_X_NPIXELS (p) != 0)
353 IMAGE_INSTANCE_X_COLORMAP (p),
354 IMAGE_INSTANCE_X_PIXELS (p),
355 IMAGE_INSTANCE_X_NPIXELS (p), 0);
356 IMAGE_INSTANCE_X_NPIXELS (p) = 0;
359 if (IMAGE_INSTANCE_X_PIXELS (p))
361 xfree (IMAGE_INSTANCE_X_PIXELS (p));
362 IMAGE_INSTANCE_X_PIXELS (p) = 0;
370 x_image_instance_equal (struct Lisp_Image_Instance *p1,
371 struct Lisp_Image_Instance *p2, int depth)
373 switch (IMAGE_INSTANCE_TYPE (p1))
375 case IMAGE_MONO_PIXMAP:
376 case IMAGE_COLOR_PIXMAP:
378 if (IMAGE_INSTANCE_X_COLORMAP (p1) != IMAGE_INSTANCE_X_COLORMAP (p2) ||
379 IMAGE_INSTANCE_X_NPIXELS (p1) != IMAGE_INSTANCE_X_NPIXELS (p2))
382 case IMAGE_SUBWINDOW:
383 /* #### implement me */
394 x_image_instance_hash (struct Lisp_Image_Instance *p, int depth)
396 switch (IMAGE_INSTANCE_TYPE (p))
398 case IMAGE_MONO_PIXMAP:
399 case IMAGE_COLOR_PIXMAP:
401 return IMAGE_INSTANCE_X_NPIXELS (p);
403 case IMAGE_SUBWINDOW:
404 /* #### implement me */
412 /* Set all the slots in an image instance structure to reasonable
413 default values. This is used somewhere within an instantiate
414 method. It is assumed that the device slot within the image
415 instance is already set -- this is the case when instantiate
416 methods are called. */
419 x_initialize_pixmap_image_instance (struct Lisp_Image_Instance *ii,
420 enum image_instance_type type)
422 ii->data = xnew_and_zero (struct x_image_instance_data);
423 IMAGE_INSTANCE_TYPE (ii) = type;
424 IMAGE_INSTANCE_PIXMAP_FILENAME (ii) = Qnil;
425 IMAGE_INSTANCE_PIXMAP_MASK_FILENAME (ii) = Qnil;
426 IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii) = Qnil;
427 IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii) = Qnil;
428 IMAGE_INSTANCE_PIXMAP_FG (ii) = Qnil;
429 IMAGE_INSTANCE_PIXMAP_BG (ii) = Qnil;
433 /************************************************************************/
434 /* pixmap file functions */
435 /************************************************************************/
437 /* Where bitmaps are; initialized from resource database */
438 Lisp_Object Vx_bitmap_file_path;
441 #define BITMAPDIR "/usr/include/X11/bitmaps"
444 #define USE_XBMLANGPATH
446 /* Given a pixmap filename, look through all of the "standard" places
447 where the file might be located. Return a full pathname if found;
448 otherwise, return Qnil. */
451 x_locate_pixmap_file (Lisp_Object name)
453 /* This function can GC if IN_REDISPLAY is false */
456 /* Check non-absolute pathnames with a directory component relative to
457 the search path; that's the way Xt does it. */
458 /* #### Unix-specific */
459 if (XSTRING_BYTE (name, 0) == '/' ||
460 (XSTRING_BYTE (name, 0) == '.' &&
461 (XSTRING_BYTE (name, 1) == '/' ||
462 (XSTRING_BYTE (name, 1) == '.' &&
463 (XSTRING_BYTE (name, 2) == '/')))))
465 if (!NILP (Ffile_readable_p (name)))
471 if (NILP (Vdefault_x_device))
472 /* This may occur during intialization. */
475 /* We only check the bitmapFilePath resource on the original X device. */
476 display = DEVICE_X_DISPLAY (XDEVICE (Vdefault_x_device));
478 #ifdef USE_XBMLANGPATH
480 char *path = egetenv ("XBMLANGPATH");
481 SubstitutionRec subs[1];
483 subs[0].substitution = (char *) XSTRING_DATA (name);
484 /* #### Motif uses a big hairy default if $XBMLANGPATH isn't set.
485 We don't. If you want it used, set it. */
487 (path = XtResolvePathname (display, "bitmaps", 0, 0, path,
488 subs, XtNumber (subs), 0)))
490 name = build_string (path);
497 if (NILP (Vx_bitmap_file_path))
501 if (XrmGetResource (XtDatabase (display),
502 "bitmapFilePath", "BitmapFilePath", &type, &value)
503 && !strcmp (type, "String"))
504 Vx_bitmap_file_path = decode_env_path (0, (char *) value.addr);
505 Vx_bitmap_file_path = nconc2 (Vx_bitmap_file_path,
506 (decode_path (BITMAPDIR)));
511 if (locate_file (Vx_bitmap_file_path, name, "", &found, R_OK) < 0)
513 Lisp_Object temp = list1 (Vdata_directory);
517 locate_file (temp, name, "", &found, R_OK);
526 locate_pixmap_file (Lisp_Object name)
528 return x_locate_pixmap_file (name);
533 write_lisp_string_to_temp_file (Lisp_Object string, char *filename_out)
535 Lisp_Object instream, outstream;
536 Lstream *istr, *ostr;
537 char tempbuf[1024]; /* some random amount */
540 static Extbyte_dynarr *conversion_out_dynarr;
541 Bytecount bstart, bend;
542 struct gcpro gcpro1, gcpro2;
544 Lisp_Object conv_out_stream;
549 /* This function can GC */
550 if (!conversion_out_dynarr)
551 conversion_out_dynarr = Dynarr_new (Extbyte);
553 Dynarr_reset (conversion_out_dynarr);
555 /* Create the temporary file ... */
556 sprintf (filename_out, "/tmp/emacs%d.XXXXXX", (int) getpid ());
557 mktemp (filename_out);
558 tmpfil = fopen (filename_out, "w");
563 int old_errno = errno;
565 unlink (filename_out);
568 report_file_error ("Creating temp file",
569 list1 (build_string (filename_out)));
572 CHECK_STRING (string);
573 get_string_range_byte (string, Qnil, Qnil, &bstart, &bend,
574 GB_HISTORICAL_STRING_BEHAVIOR);
575 instream = make_lisp_string_input_stream (string, bstart, bend);
576 istr = XLSTREAM (instream);
577 /* setup the out stream */
578 outstream = make_dynarr_output_stream((unsigned_char_dynarr *)conversion_out_dynarr);
579 ostr = XLSTREAM (outstream);
581 /* setup the conversion stream */
582 conv_out_stream = make_encoding_output_stream (ostr, Fget_coding_system(Qbinary));
583 costr = XLSTREAM (conv_out_stream);
584 GCPRO3 (instream, outstream, conv_out_stream);
586 GCPRO2 (instream, outstream);
589 /* Get the data while doing the conversion */
592 int size_in_bytes = Lstream_read (istr, tempbuf, sizeof (tempbuf));
595 /* It does seem the flushes are necessary... */
597 Lstream_write (costr, tempbuf, size_in_bytes);
598 Lstream_flush (costr);
600 Lstream_write (ostr, tempbuf, size_in_bytes);
602 Lstream_flush (ostr);
603 if (fwrite ((unsigned char *)Dynarr_atp(conversion_out_dynarr, 0),
604 Dynarr_length(conversion_out_dynarr), 1, tmpfil) != 1)
609 /* reset the dynarr */
610 Lstream_rewind(ostr);
613 if (fclose (tmpfil) != 0)
615 Lstream_close (istr);
617 Lstream_close (costr);
619 Lstream_close (ostr);
622 Lstream_delete (istr);
623 Lstream_delete (ostr);
625 Lstream_delete (costr);
629 report_file_error ("Writing temp file",
630 list1 (build_string (filename_out)));
635 /************************************************************************/
636 /* cursor functions */
637 /************************************************************************/
639 /* Check that this server supports cursors of size WIDTH * HEIGHT. If
640 not, signal an error. INSTANTIATOR is only used in the error
644 check_pointer_sizes (Screen *xs, unsigned int width, unsigned int height,
645 Lisp_Object instantiator)
647 unsigned int best_width, best_height;
648 if (! XQueryBestCursor (DisplayOfScreen (xs), RootWindowOfScreen (xs),
649 width, height, &best_width, &best_height))
650 /* this means that an X error of some sort occurred (we trap
651 these so they're not fatal). */
652 signal_simple_error ("XQueryBestCursor() failed?", instantiator);
654 if (width > best_width || height > best_height)
655 error_with_frob (instantiator,
656 "pointer too large (%dx%d): "
657 "server requires %dx%d or smaller",
658 width, height, best_width, best_height);
663 generate_cursor_fg_bg (Lisp_Object device, Lisp_Object *foreground,
664 Lisp_Object *background, XColor *xfg, XColor *xbg)
666 if (!NILP (*foreground) && !COLOR_INSTANCEP (*foreground))
668 Fmake_color_instance (*foreground, device,
669 encode_error_behavior_flag (ERROR_ME));
670 if (COLOR_INSTANCEP (*foreground))
671 *xfg = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (*foreground));
675 xfg->red = xfg->green = xfg->blue = 0;
678 if (!NILP (*background) && !COLOR_INSTANCEP (*background))
680 Fmake_color_instance (*background, device,
681 encode_error_behavior_flag (ERROR_ME));
682 if (COLOR_INSTANCEP (*background))
683 *xbg = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (*background));
687 xbg->red = xbg->green = xbg->blue = ~0;
692 maybe_recolor_cursor (Lisp_Object image_instance, Lisp_Object foreground,
693 Lisp_Object background)
695 Lisp_Object device = XIMAGE_INSTANCE_DEVICE (image_instance);
698 generate_cursor_fg_bg (device, &foreground, &background, &xfg, &xbg);
699 if (!NILP (foreground) || !NILP (background))
701 XRecolorCursor (DEVICE_X_DISPLAY (XDEVICE (device)),
702 XIMAGE_INSTANCE_X_CURSOR (image_instance),
704 XIMAGE_INSTANCE_PIXMAP_FG (image_instance) = foreground;
705 XIMAGE_INSTANCE_PIXMAP_BG (image_instance) = background;
710 /************************************************************************/
711 /* color pixmap functions */
712 /************************************************************************/
714 /* Initialize an image instance from an XImage.
716 DEST_MASK specifies the mask of allowed image types.
718 PIXELS and NPIXELS specify an array of pixels that are used in
719 the image. These need to be kept around for the duration of the
720 image. When the image instance is freed, XFreeColors() will
721 automatically be called on all the pixels specified here; thus,
722 you should have allocated the pixels yourself using XAllocColor()
723 or the like. The array passed in is used directly without
724 being copied, so it should be heap data created with xmalloc().
725 It will be freed using xfree() when the image instance is
728 If this fails, signal an error. INSTANTIATOR is only used
729 in the error message.
731 #### This should be able to handle conversion into `pointer'.
732 Use the same code as for `xpm'. */
735 init_image_instance_from_x_image (struct Lisp_Image_Instance *ii,
739 unsigned long *pixels,
741 Lisp_Object instantiator)
743 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
749 if (!DEVICE_X_P (XDEVICE (device)))
750 signal_simple_error ("Not an X device", device);
752 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
753 d = XtWindow(DEVICE_XT_APP_SHELL (XDEVICE (device)));
755 if (!(dest_mask & IMAGE_COLOR_PIXMAP_MASK))
756 incompatible_image_types (instantiator, dest_mask,
757 IMAGE_COLOR_PIXMAP_MASK);
759 pixmap = XCreatePixmap (dpy, d, ximage->width,
760 ximage->height, ximage->depth);
762 signal_simple_error ("Unable to create pixmap", instantiator);
764 gc = XCreateGC (dpy, pixmap, 0, NULL);
767 XFreePixmap (dpy, pixmap);
768 signal_simple_error ("Unable to create GC", instantiator);
771 XPutImage (dpy, pixmap, gc, ximage, 0, 0, 0, 0,
772 ximage->width, ximage->height);
776 x_initialize_pixmap_image_instance (ii, IMAGE_COLOR_PIXMAP);
778 IMAGE_INSTANCE_PIXMAP_FILENAME (ii) =
779 find_keyword_in_vector (instantiator, Q_file);
781 IMAGE_INSTANCE_X_PIXMAP (ii) = pixmap;
782 IMAGE_INSTANCE_X_MASK (ii) = 0;
783 IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = ximage->width;
784 IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = ximage->height;
785 IMAGE_INSTANCE_PIXMAP_DEPTH (ii) = ximage->depth;
786 IMAGE_INSTANCE_X_COLORMAP (ii) = cmap;
787 IMAGE_INSTANCE_X_PIXELS (ii) = pixels;
788 IMAGE_INSTANCE_X_NPIXELS (ii) = npixels;
792 x_init_image_instance_from_eimage (struct Lisp_Image_Instance *ii,
793 int width, int height,
794 unsigned char *eimage,
796 Lisp_Object instantiator,
799 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
800 Colormap cmap = DEVICE_X_COLORMAP (XDEVICE(device));
801 unsigned long *pixtbl = NULL;
805 ximage = convert_EImage_to_XImage (device, width, height, eimage,
809 if (pixtbl) xfree (pixtbl);
810 signal_image_error("EImage to XImage conversion failed", instantiator);
813 /* Now create the pixmap and set up the image instance */
814 init_image_instance_from_x_image (ii, ximage, dest_mask,
815 cmap, pixtbl, npixels,
822 xfree (ximage->data);
825 XDestroyImage (ximage);
829 int read_bitmap_data_from_file (CONST char *filename, unsigned int *width,
830 unsigned int *height, unsigned char **datap,
831 int *x_hot, int *y_hot)
833 return XmuReadBitmapDataFromFile (filename, width, height,
834 datap, x_hot, y_hot);
837 /* Given inline data for a mono pixmap, create and return the
838 corresponding X object. */
841 pixmap_from_xbm_inline (Lisp_Object device, int width, int height,
842 /* Note that data is in ext-format! */
845 return XCreatePixmapFromBitmapData (DEVICE_X_DISPLAY (XDEVICE(device)),
846 XtWindow (DEVICE_XT_APP_SHELL (XDEVICE (device))),
847 (char *) bits, width, height,
851 /* Given inline data for a mono pixmap, initialize the given
852 image instance accordingly. */
855 init_image_instance_from_xbm_inline (struct Lisp_Image_Instance *ii,
856 int width, int height,
857 /* Note that data is in ext-format! */
859 Lisp_Object instantiator,
860 Lisp_Object pointer_fg,
861 Lisp_Object pointer_bg,
864 Lisp_Object mask_filename)
866 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
867 Lisp_Object foreground = find_keyword_in_vector (instantiator, Q_foreground);
868 Lisp_Object background = find_keyword_in_vector (instantiator, Q_background);
872 enum image_instance_type type;
874 if (!DEVICE_X_P (XDEVICE (device)))
875 signal_simple_error ("Not an X device", device);
877 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
878 draw = XtWindow(DEVICE_XT_APP_SHELL (XDEVICE (device)));
879 scr = DefaultScreenOfDisplay (dpy);
881 if ((dest_mask & IMAGE_MONO_PIXMAP_MASK) &&
882 (dest_mask & IMAGE_COLOR_PIXMAP_MASK))
884 if (!NILP (foreground) || !NILP (background))
885 type = IMAGE_COLOR_PIXMAP;
887 type = IMAGE_MONO_PIXMAP;
889 else if (dest_mask & IMAGE_MONO_PIXMAP_MASK)
890 type = IMAGE_MONO_PIXMAP;
891 else if (dest_mask & IMAGE_COLOR_PIXMAP_MASK)
892 type = IMAGE_COLOR_PIXMAP;
893 else if (dest_mask & IMAGE_POINTER_MASK)
894 type = IMAGE_POINTER;
896 incompatible_image_types (instantiator, dest_mask,
897 IMAGE_MONO_PIXMAP_MASK | IMAGE_COLOR_PIXMAP_MASK
898 | IMAGE_POINTER_MASK);
900 x_initialize_pixmap_image_instance (ii, type);
901 IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = width;
902 IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = height;
903 IMAGE_INSTANCE_PIXMAP_FILENAME (ii) =
904 find_keyword_in_vector (instantiator, Q_file);
908 case IMAGE_MONO_PIXMAP:
910 IMAGE_INSTANCE_X_PIXMAP (ii) =
911 pixmap_from_xbm_inline (device, width, height, (Extbyte *) bits);
915 case IMAGE_COLOR_PIXMAP:
917 Dimension d = DEVICE_X_DEPTH (XDEVICE(device));
918 unsigned long fg = BlackPixelOfScreen (scr);
919 unsigned long bg = WhitePixelOfScreen (scr);
921 if (!NILP (foreground) && !COLOR_INSTANCEP (foreground))
923 Fmake_color_instance (foreground, device,
924 encode_error_behavior_flag (ERROR_ME));
926 if (COLOR_INSTANCEP (foreground))
927 fg = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (foreground)).pixel;
929 if (!NILP (background) && !COLOR_INSTANCEP (background))
931 Fmake_color_instance (background, device,
932 encode_error_behavior_flag (ERROR_ME));
934 if (COLOR_INSTANCEP (background))
935 bg = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (background)).pixel;
937 /* We used to duplicate the pixels using XAllocColor(), to protect
938 against their getting freed. Just as easy to just store the
939 color instances here and GC-protect them, so this doesn't
941 IMAGE_INSTANCE_PIXMAP_FG (ii) = foreground;
942 IMAGE_INSTANCE_PIXMAP_BG (ii) = background;
943 IMAGE_INSTANCE_X_PIXMAP (ii) =
944 XCreatePixmapFromBitmapData (dpy, draw,
945 (char *) bits, width, height,
947 IMAGE_INSTANCE_PIXMAP_DEPTH (ii) = d;
953 XColor fg_color, bg_color;
956 check_pointer_sizes (scr, width, height, instantiator);
959 XCreatePixmapFromBitmapData (dpy, draw,
960 (char *) bits, width, height,
963 if (NILP (foreground))
964 foreground = pointer_fg;
965 if (NILP (background))
966 background = pointer_bg;
967 generate_cursor_fg_bg (device, &foreground, &background,
968 &fg_color, &bg_color);
970 IMAGE_INSTANCE_PIXMAP_FG (ii) = foreground;
971 IMAGE_INSTANCE_PIXMAP_BG (ii) = background;
972 IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii) =
973 find_keyword_in_vector (instantiator, Q_hotspot_x);
974 IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii) =
975 find_keyword_in_vector (instantiator, Q_hotspot_y);
976 IMAGE_INSTANCE_X_CURSOR (ii) =
978 (dpy, source, mask, &fg_color, &bg_color,
979 !NILP (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii)) ?
980 XINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii)) : 0,
981 !NILP (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii)) ?
982 XINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii)) : 0);
992 xbm_instantiate_1 (Lisp_Object image_instance, Lisp_Object instantiator,
993 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
994 int dest_mask, int width, int height,
995 /* Note that data is in ext-format! */
998 Lisp_Object mask_data = find_keyword_in_vector (instantiator, Q_mask_data);
999 Lisp_Object mask_file = find_keyword_in_vector (instantiator, Q_mask_file);
1000 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1002 CONST char *gcc_may_you_rot_in_hell;
1004 if (!NILP (mask_data))
1006 GET_C_STRING_BINARY_DATA_ALLOCA (XCAR (XCDR (XCDR (mask_data))),
1007 gcc_may_you_rot_in_hell);
1009 pixmap_from_xbm_inline (IMAGE_INSTANCE_DEVICE (ii),
1010 XINT (XCAR (mask_data)),
1011 XINT (XCAR (XCDR (mask_data))),
1012 (CONST unsigned char *)
1013 gcc_may_you_rot_in_hell);
1016 init_image_instance_from_xbm_inline (ii, width, height, bits,
1017 instantiator, pointer_fg, pointer_bg,
1018 dest_mask, mask, mask_file);
1021 /* Instantiate method for XBM's. */
1024 x_xbm_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1025 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1026 int dest_mask, Lisp_Object domain)
1028 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1029 CONST char *gcc_go_home;
1031 assert (!NILP (data));
1033 GET_C_STRING_BINARY_DATA_ALLOCA (XCAR (XCDR (XCDR (data))),
1036 xbm_instantiate_1 (image_instance, instantiator, pointer_fg,
1037 pointer_bg, dest_mask, XINT (XCAR (data)),
1038 XINT (XCAR (XCDR (data))), gcc_go_home);
1044 /**********************************************************************
1046 **********************************************************************/
1047 /* xpm 3.2g and better has XpmCreatePixmapFromBuffer()...
1048 There was no version number in xpm.h before 3.3, but this should do.
1050 #if (XpmVersion >= 3) || defined(XpmExactColors)
1051 # define XPM_DOES_BUFFERS
1054 #ifndef XPM_DOES_BUFFERS
1055 Your version of XPM is too old. You cannot compile with it.
1056 Upgrade to version 3.2g or better or compile with --with-xpm=no.
1057 #endif /* !XPM_DOES_BUFFERS */
1059 static XpmColorSymbol *
1060 extract_xpm_color_names (XpmAttributes *xpmattrs, Lisp_Object device,
1062 Lisp_Object color_symbol_alist)
1064 /* This function can GC */
1065 Display *dpy = DEVICE_X_DISPLAY (XDEVICE(device));
1066 Colormap cmap = DEVICE_X_COLORMAP (XDEVICE(device));
1069 Lisp_Object results = Qnil;
1071 XpmColorSymbol *symbols;
1072 struct gcpro gcpro1, gcpro2;
1074 GCPRO2 (results, device);
1076 /* We built up results to be (("name" . #<color>) ...) so that if an
1077 error happens we don't lose any malloc()ed data, or more importantly,
1078 leave any pixels allocated in the server. */
1080 LIST_LOOP (rest, color_symbol_alist)
1082 Lisp_Object cons = XCAR (rest);
1083 Lisp_Object name = XCAR (cons);
1084 Lisp_Object value = XCDR (cons);
1087 if (STRINGP (value))
1089 Fmake_color_instance
1090 (value, device, encode_error_behavior_flag (ERROR_ME_NOT));
1093 assert (COLOR_SPECIFIERP (value));
1094 value = Fspecifier_instance (value, domain, Qnil, Qnil);
1098 results = noseeum_cons (noseeum_cons (name, value), results);
1101 UNGCPRO; /* no more evaluation */
1103 if (i == 0) return 0;
1105 symbols = xnew_array (XpmColorSymbol, i);
1106 xpmattrs->valuemask |= XpmColorSymbols;
1107 xpmattrs->colorsymbols = symbols;
1108 xpmattrs->numsymbols = i;
1112 Lisp_Object cons = XCAR (results);
1113 color = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (XCDR (cons)));
1114 /* Duplicate the pixel value so that we still have a lock on it if
1115 the pixel we were passed is later freed. */
1116 if (! XAllocColor (dpy, cmap, &color))
1117 abort (); /* it must be allocable since we're just duplicating it */
1119 symbols [i].name = (char *) XSTRING_DATA (XCAR (cons));
1120 symbols [i].pixel = color.pixel;
1121 symbols [i].value = 0;
1122 free_cons (XCONS (cons));
1124 results = XCDR (results);
1125 free_cons (XCONS (cons));
1131 xpm_free (XpmAttributes *xpmattrs)
1133 /* Could conceivably lose if XpmXXX returned an error without first
1134 initializing this structure, if we didn't know that initializing it
1135 to all zeros was ok (and also that it's ok to call XpmFreeAttributes()
1136 multiple times, since it zeros slots as it frees them...) */
1137 XpmFreeAttributes (xpmattrs);
1141 x_xpm_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1142 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1143 int dest_mask, Lisp_Object domain)
1145 /* This function can GC */
1146 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1147 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
1148 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1156 XpmAttributes xpmattrs;
1158 XpmColorSymbol *color_symbols;
1159 Lisp_Object color_symbol_alist = find_keyword_in_vector (instantiator,
1161 enum image_instance_type type;
1165 if (!DEVICE_X_P (XDEVICE (device)))
1166 signal_simple_error ("Not an X device", device);
1168 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
1169 xs = DefaultScreenOfDisplay (dpy);
1171 if (dest_mask & IMAGE_COLOR_PIXMAP_MASK)
1172 type = IMAGE_COLOR_PIXMAP;
1173 else if (dest_mask & IMAGE_MONO_PIXMAP_MASK)
1174 type = IMAGE_MONO_PIXMAP;
1175 else if (dest_mask & IMAGE_POINTER_MASK)
1176 type = IMAGE_POINTER;
1178 incompatible_image_types (instantiator, dest_mask,
1179 IMAGE_MONO_PIXMAP_MASK | IMAGE_COLOR_PIXMAP_MASK
1180 | IMAGE_POINTER_MASK);
1181 force_mono = (type != IMAGE_COLOR_PIXMAP);
1184 /* Although I haven't found it documented yet, it appears that pointers are
1185 always colored via the default window colormap... Sigh. */
1186 if (type == IMAGE_POINTER)
1188 cmap = DefaultColormap(dpy, DefaultScreen(dpy));
1189 depth = DefaultDepthOfScreen (xs);
1190 visual = DefaultVisualOfScreen (xs);
1194 cmap = DEVICE_X_COLORMAP (XDEVICE(device));
1195 depth = DEVICE_X_DEPTH (XDEVICE(device));
1196 visual = DEVICE_X_VISUAL (XDEVICE(device));
1199 cmap = DEVICE_X_COLORMAP (XDEVICE(device));
1200 depth = DEVICE_X_DEPTH (XDEVICE(device));
1201 visual = DEVICE_X_VISUAL (XDEVICE(device));
1204 x_initialize_pixmap_image_instance (ii, type);
1206 assert (!NILP (data));
1210 xzero (xpmattrs); /* want XpmInitAttributes() */
1211 xpmattrs.valuemask = XpmReturnPixels;
1214 /* Without this, we get a 1-bit version of the color image, which
1215 isn't quite right. With this, we get the mono image, which might
1216 be very different looking. */
1217 xpmattrs.valuemask |= XpmColorKey;
1218 xpmattrs.color_key = XPM_MONO;
1220 xpmattrs.valuemask |= XpmDepth;
1224 xpmattrs.closeness = 65535;
1225 xpmattrs.valuemask |= XpmCloseness;
1226 xpmattrs.depth = depth;
1227 xpmattrs.valuemask |= XpmDepth;
1228 xpmattrs.visual = visual;
1229 xpmattrs.valuemask |= XpmVisual;
1230 xpmattrs.colormap = cmap;
1231 xpmattrs.valuemask |= XpmColormap;
1234 color_symbols = extract_xpm_color_names (&xpmattrs, device, domain,
1235 color_symbol_alist);
1237 result = XpmCreatePixmapFromBuffer (dpy,
1238 XtWindow(DEVICE_XT_APP_SHELL (XDEVICE(device))),
1239 (char *) XSTRING_DATA (data),
1240 &pixmap, &mask, &xpmattrs);
1244 xfree (color_symbols);
1245 xpmattrs.colorsymbols = 0; /* in case XpmFreeAttr is too smart... */
1246 xpmattrs.numsymbols = 0;
1253 case XpmFileInvalid:
1255 xpm_free (&xpmattrs);
1256 signal_image_error ("invalid XPM data", data);
1258 case XpmColorFailed:
1261 xpm_free (&xpmattrs);
1264 /* second time; blow out. */
1265 signal_double_file_error ("Reading pixmap data",
1266 "color allocation failed",
1271 if (! (dest_mask & IMAGE_MONO_PIXMAP_MASK))
1273 /* second time; blow out. */
1274 signal_double_file_error ("Reading pixmap data",
1275 "color allocation failed",
1279 IMAGE_INSTANCE_TYPE (ii) = IMAGE_MONO_PIXMAP;
1285 xpm_free (&xpmattrs);
1286 signal_double_file_error ("Parsing pixmap data",
1287 "out of memory", data);
1291 xpm_free (&xpmattrs);
1292 signal_double_file_error_2 ("Parsing pixmap data",
1293 "unknown error code",
1294 make_int (result), data);
1299 h = xpmattrs.height;
1302 int npixels = xpmattrs.npixels;
1307 pixels = xnew_array (Pixel, npixels);
1308 memcpy (pixels, xpmattrs.pixels, npixels * sizeof (Pixel));
1313 IMAGE_INSTANCE_X_PIXMAP (ii) = pixmap;
1314 IMAGE_INSTANCE_X_MASK (ii) = mask;
1315 IMAGE_INSTANCE_X_COLORMAP (ii) = cmap;
1316 IMAGE_INSTANCE_X_PIXELS (ii) = pixels;
1317 IMAGE_INSTANCE_X_NPIXELS (ii) = npixels;
1318 IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = w;
1319 IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = h;
1320 IMAGE_INSTANCE_PIXMAP_FILENAME (ii) =
1321 find_keyword_in_vector (instantiator, Q_file);
1326 case IMAGE_MONO_PIXMAP:
1329 case IMAGE_COLOR_PIXMAP:
1331 IMAGE_INSTANCE_PIXMAP_DEPTH (ii) = depth;
1337 int npixels = xpmattrs.npixels;
1338 Pixel *pixels = xpmattrs.pixels;
1341 int xhot = 0, yhot = 0;
1343 if (xpmattrs.valuemask & XpmHotspot)
1345 xhot = xpmattrs.x_hotspot;
1346 XSETINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii), xpmattrs.x_hotspot);
1348 if (xpmattrs.valuemask & XpmHotspot)
1350 yhot = xpmattrs.y_hotspot;
1351 XSETINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii), xpmattrs.y_hotspot);
1353 check_pointer_sizes (xs, w, h, instantiator);
1355 /* If the loaded pixmap has colors allocated (meaning it came from an
1356 XPM file), then use those as the default colors for the cursor we
1357 create. Otherwise, default to pointer_fg and pointer_bg.
1361 /* With an XBM file, it's obvious which bit is foreground
1362 and which is background, or rather, it's implicit: in
1363 an XBM file, a 1 bit is foreground, and a 0 bit is
1366 XCreatePixmapCursor() assumes this property of the
1367 pixmap it is called with as well; the `foreground'
1368 color argument is used for the 1 bits.
1370 With an XPM file, it's tricker, since the elements of
1371 the pixmap don't represent FG and BG, but are actual
1372 pixel values. So we need to figure out which of those
1373 pixels is the foreground color and which is the
1374 background. We do it by comparing RGB and assuming
1375 that the darker color is the foreground. This works
1376 with the result of xbmtopbm|ppmtoxpm, at least.
1378 It might be nice if there was some way to tag the
1379 colors in the XPM file with whether they are the
1380 foreground - perhaps with logical color names somehow?
1382 Once we have decided which color is the foreground, we
1383 need to ensure that that color corresponds to a `1' bit
1384 in the Pixmap. The XPM library wrote into the (1-bit)
1385 pixmap with XPutPixel, which will ignore all but the
1386 least significant bit.
1388 This means that a 1 bit in the image corresponds to
1389 `fg' only if `fg.pixel' is odd.
1391 (This also means that the image will be all the same
1392 color if both `fg' and `bg' are odd or even, but we can
1393 safely assume that that won't happen if the XPM file is
1396 The desired result is that the image use `1' to
1397 represent the foreground color, and `0' to represent
1398 the background color. So, we may need to invert the
1399 image to accomplish this; we invert if fg is
1400 odd. (Remember that WhitePixel and BlackPixel are not
1401 necessarily 1 and 0 respectively, though I think it
1402 might be safe to assume that one of them is always 1
1403 and the other is always 0. We also pretty much need to
1404 assume that one is even and the other is odd.)
1407 fg.pixel = pixels[0]; /* pick a pixel at random. */
1408 bg.pixel = fg.pixel;
1409 for (i = 1; i < npixels; i++) /* Look for an "other" pixel value.*/
1411 bg.pixel = pixels[i];
1412 if (fg.pixel != bg.pixel)
1416 /* If (fg.pixel == bg.pixel) then probably something has
1417 gone wrong, but I don't think signalling an error would
1420 XQueryColor (dpy, cmap, &fg);
1421 XQueryColor (dpy, cmap, &bg);
1423 /* If the foreground is lighter than the background, swap them.
1424 (This occurs semi-randomly, depending on the ordering of the
1425 color list in the XPM file.)
1428 unsigned short fg_total = ((fg.red / 3) + (fg.green / 3)
1430 unsigned short bg_total = ((bg.red / 3) + (bg.green / 3)
1432 if (fg_total > bg_total)
1441 /* If the fg pixel corresponds to a `0' in the bitmap, invert it.
1442 (This occurs (only?) on servers with Black=0, White=1.)
1444 if ((fg.pixel & 1) == 0)
1448 gcv.function = GXxor;
1450 gc = XCreateGC (dpy, pixmap, (GCFunction | GCForeground),
1452 XFillRectangle (dpy, pixmap, gc, 0, 0, w, h);
1458 generate_cursor_fg_bg (device, &pointer_fg, &pointer_bg,
1460 IMAGE_INSTANCE_PIXMAP_FG (ii) = pointer_fg;
1461 IMAGE_INSTANCE_PIXMAP_BG (ii) = pointer_bg;
1464 IMAGE_INSTANCE_X_CURSOR (ii) =
1466 (dpy, pixmap, mask, &fg, &bg, xhot, yhot);
1475 xpm_free (&xpmattrs); /* after we've read pixels and hotspot */
1478 #endif /* HAVE_XPM */
1483 /**********************************************************************
1485 **********************************************************************/
1488 xface_validate (Lisp_Object instantiator)
1490 file_or_data_must_be_present (instantiator);
1494 xface_normalize (Lisp_Object inst, Lisp_Object console_type)
1496 /* This funcation can call lisp */
1497 Lisp_Object file = Qnil, mask_file = Qnil;
1498 struct gcpro gcpro1, gcpro2, gcpro3;
1499 Lisp_Object alist = Qnil;
1501 GCPRO3 (file, mask_file, alist);
1503 /* Now, convert any file data into inline data for both the regular
1504 data and the mask data. At the end of this, `data' will contain
1505 the inline data (if any) or Qnil, and `file' will contain
1506 the name this data was derived from (if known) or Qnil.
1507 Likewise for `mask_file' and `mask_data'.
1509 Note that if we cannot generate any regular inline data, we
1512 file = potential_pixmap_file_instantiator (inst, Q_file, Q_data,
1514 mask_file = potential_pixmap_file_instantiator (inst, Q_mask_file,
1515 Q_mask_data, console_type);
1517 if (CONSP (file)) /* failure locating filename */
1518 signal_double_file_error ("Opening bitmap file",
1519 "no such file or directory",
1522 if (NILP (file) && NILP (mask_file)) /* no conversion necessary */
1523 RETURN_UNGCPRO (inst);
1525 alist = tagged_vector_to_alist (inst);
1528 Lisp_Object data = make_string_from_file (file);
1529 alist = remassq_no_quit (Q_file, alist);
1530 /* there can't be a :data at this point. */
1531 alist = Fcons (Fcons (Q_file, file),
1532 Fcons (Fcons (Q_data, data), alist));
1535 alist = xbm_mask_file_munging (alist, file, mask_file, console_type);
1538 Lisp_Object result = alist_to_tagged_vector (Qxface, alist);
1540 RETURN_UNGCPRO (result);
1545 xface_possible_dest_types (void)
1548 IMAGE_MONO_PIXMAP_MASK |
1549 IMAGE_COLOR_PIXMAP_MASK |
1554 /* This is about to get redefined! */
1557 /* We have to define SYSV32 so that compface.h includes string.h
1558 instead of strings.h. */
1563 #include <compface.h>
1567 /* JMP_BUF cannot be used here because if it doesn't get defined
1568 to jmp_buf we end up with a conflicting type error with the
1569 definition in compface.h */
1570 extern jmp_buf comp_env;
1574 xface_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1575 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1576 int dest_mask, Lisp_Object domain)
1578 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1580 char *p, *bits, *bp;
1581 CONST char * volatile emsg = 0;
1582 CONST char * volatile dstring;
1584 assert (!NILP (data));
1586 GET_C_STRING_BINARY_DATA_ALLOCA (data, dstring);
1588 if ((p = strchr (dstring, ':')))
1593 /* Must use setjmp not SETJMP because we used jmp_buf above not JMP_BUF */
1594 if (!(stattis = setjmp (comp_env)))
1596 UnCompAll ((char *) dstring);
1603 emsg = "uncompface: internal error";
1606 emsg = "uncompface: insufficient or invalid data";
1609 emsg = "uncompface: excess data ignored";
1614 signal_simple_error_2 (emsg, data, Qimage);
1616 bp = bits = (char *) alloca (PIXELS / 8);
1618 /* the compface library exports char F[], which uses a single byte per
1619 pixel to represent a 48x48 bitmap. Yuck. */
1620 for (i = 0, p = F; i < (PIXELS / 8); ++i)
1623 /* reverse the bit order of each byte... */
1624 for (b = n = 0; b < 8; ++b)
1631 xbm_instantiate_1 (image_instance, instantiator, pointer_fg,
1632 pointer_bg, dest_mask, 48, 48, bits);
1635 #endif /* HAVE_XFACE */
1638 /**********************************************************************
1640 **********************************************************************/
1643 autodetect_validate (Lisp_Object instantiator)
1645 data_must_be_present (instantiator);
1649 autodetect_normalize (Lisp_Object instantiator,
1650 Lisp_Object console_type)
1652 Lisp_Object file = find_keyword_in_vector (instantiator, Q_data);
1653 Lisp_Object filename = Qnil;
1654 Lisp_Object data = Qnil;
1655 struct gcpro gcpro1, gcpro2, gcpro3;
1656 Lisp_Object alist = Qnil;
1658 GCPRO3 (filename, data, alist);
1660 if (NILP (file)) /* no conversion necessary */
1661 RETURN_UNGCPRO (instantiator);
1663 alist = tagged_vector_to_alist (instantiator);
1665 filename = locate_pixmap_file (file);
1666 if (!NILP (filename))
1669 /* #### Apparently some versions of XpmReadFileToData, which is
1670 called by pixmap_to_lisp_data, don't return an error value
1671 if the given file is not a valid XPM file. Instead, they
1672 just seg fault. It is definitely caused by passing a
1673 bitmap. To try and avoid this we check for bitmaps first. */
1675 data = bitmap_to_lisp_data (filename, &xhot, &yhot, 1);
1679 alist = remassq_no_quit (Q_data, alist);
1680 alist = Fcons (Fcons (Q_file, filename),
1681 Fcons (Fcons (Q_data, data), alist));
1683 alist = Fcons (Fcons (Q_hotspot_x, make_int (xhot)),
1686 alist = Fcons (Fcons (Q_hotspot_y, make_int (yhot)),
1689 alist = xbm_mask_file_munging (alist, filename, Qnil, console_type);
1692 Lisp_Object result = alist_to_tagged_vector (Qxbm, alist);
1694 RETURN_UNGCPRO (result);
1699 data = pixmap_to_lisp_data (filename, 1);
1703 alist = remassq_no_quit (Q_data, alist);
1704 alist = Fcons (Fcons (Q_file, filename),
1705 Fcons (Fcons (Q_data, data), alist));
1706 alist = Fcons (Fcons (Q_color_symbols,
1707 evaluate_xpm_color_symbols ()),
1710 Lisp_Object result = alist_to_tagged_vector (Qxpm, alist);
1712 RETURN_UNGCPRO (result);
1718 /* If we couldn't convert it, just put it back as it is.
1719 We might try to further frob it later as a cursor-font
1720 specification. (We can't do that now because we don't know
1721 what dest-types it's going to be instantiated into.) */
1723 Lisp_Object result = alist_to_tagged_vector (Qautodetect, alist);
1725 RETURN_UNGCPRO (result);
1730 autodetect_possible_dest_types (void)
1733 IMAGE_MONO_PIXMAP_MASK |
1734 IMAGE_COLOR_PIXMAP_MASK |
1735 IMAGE_POINTER_MASK |
1740 autodetect_instantiate (Lisp_Object image_instance,
1741 Lisp_Object instantiator,
1742 Lisp_Object pointer_fg,
1743 Lisp_Object pointer_bg,
1744 int dest_mask, Lisp_Object domain)
1746 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1747 struct gcpro gcpro1, gcpro2, gcpro3;
1748 Lisp_Object alist = Qnil;
1749 Lisp_Object result = Qnil;
1750 int is_cursor_font = 0;
1752 GCPRO3 (data, alist, result);
1754 alist = tagged_vector_to_alist (instantiator);
1755 if (dest_mask & IMAGE_POINTER_MASK)
1757 CONST char *name_ext;
1758 GET_C_STRING_FILENAME_DATA_ALLOCA (data, name_ext);
1759 if (XmuCursorNameToIndex (name_ext) != -1)
1761 result = alist_to_tagged_vector (Qcursor_font, alist);
1766 if (!is_cursor_font)
1767 result = alist_to_tagged_vector (Qstring, alist);
1771 cursor_font_instantiate (image_instance, result, pointer_fg,
1772 pointer_bg, dest_mask, domain);
1774 string_instantiate (image_instance, result, pointer_fg,
1775 pointer_bg, dest_mask, domain);
1781 /**********************************************************************
1783 **********************************************************************/
1786 font_validate (Lisp_Object instantiator)
1788 data_must_be_present (instantiator);
1791 /* XmuCvtStringToCursor is bogus in the following ways:
1793 - When it can't convert the given string to a real cursor, it will
1794 sometimes return a "success" value, after triggering a BadPixmap
1795 error. It then gives you a cursor that will itself generate BadCursor
1796 errors. So we install this error handler to catch/notice the X error
1797 and take that as meaning "couldn't convert."
1799 - When you tell it to find a cursor file that doesn't exist, it prints
1800 an error message on stderr. You can't make it not do that.
1802 - Also, using Xmu means we can't properly hack Lisp_Image_Instance
1803 objects, or XPM files, or $XBMLANGPATH.
1806 /* Duplicate the behavior of XmuCvtStringToCursor() to bypass its bogusness. */
1808 static int XLoadFont_got_error;
1811 XLoadFont_error_handler (Display *dpy, XErrorEvent *xerror)
1813 XLoadFont_got_error = 1;
1818 safe_XLoadFont (Display *dpy, char *name)
1821 int (*old_handler) (Display *, XErrorEvent *);
1822 XLoadFont_got_error = 0;
1824 old_handler = XSetErrorHandler (XLoadFont_error_handler);
1825 font = XLoadFont (dpy, name);
1827 XSetErrorHandler (old_handler);
1828 if (XLoadFont_got_error) return 0;
1833 font_possible_dest_types (void)
1835 return IMAGE_POINTER_MASK;
1839 font_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1840 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1841 int dest_mask, Lisp_Object domain)
1843 /* This function can GC */
1844 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1845 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1846 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
1850 char source_name[MAXPATHLEN], mask_name[MAXPATHLEN], dummy;
1851 int source_char, mask_char;
1853 Lisp_Object foreground, background;
1855 if (!DEVICE_X_P (XDEVICE (device)))
1856 signal_simple_error ("Not an X device", device);
1858 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
1860 if (!STRINGP (data) ||
1861 strncmp ("FONT ", (char *) XSTRING_DATA (data), 5))
1862 signal_simple_error ("Invalid font-glyph instantiator",
1865 if (!(dest_mask & IMAGE_POINTER_MASK))
1866 incompatible_image_types (instantiator, dest_mask, IMAGE_POINTER_MASK);
1868 foreground = find_keyword_in_vector (instantiator, Q_foreground);
1869 if (NILP (foreground))
1870 foreground = pointer_fg;
1871 background = find_keyword_in_vector (instantiator, Q_background);
1872 if (NILP (background))
1873 background = pointer_bg;
1875 generate_cursor_fg_bg (device, &foreground, &background, &fg, &bg);
1877 count = sscanf ((char *) XSTRING_DATA (data),
1878 "FONT %s %d %s %d %c",
1879 source_name, &source_char,
1880 mask_name, &mask_char, &dummy);
1881 /* Allow "%s %d %d" as well... */
1882 if (count == 3 && (1 == sscanf (mask_name, "%d %c", &mask_char, &dummy)))
1883 count = 4, mask_name[0] = 0;
1885 if (count != 2 && count != 4)
1886 signal_simple_error ("invalid cursor specification", data);
1887 source = safe_XLoadFont (dpy, source_name);
1889 signal_simple_error_2 ("couldn't load font",
1890 build_string (source_name),
1894 else if (!mask_name[0])
1898 mask = safe_XLoadFont (dpy, mask_name);
1901 Fsignal (Qerror, list3 (build_string ("couldn't load font"),
1902 build_string (mask_name), data));
1907 /* #### call XQueryTextExtents() and check_pointer_sizes() here. */
1909 x_initialize_pixmap_image_instance (ii, IMAGE_POINTER);
1910 IMAGE_INSTANCE_X_CURSOR (ii) =
1911 XCreateGlyphCursor (dpy, source, mask, source_char, mask_char,
1913 XIMAGE_INSTANCE_PIXMAP_FG (image_instance) = foreground;
1914 XIMAGE_INSTANCE_PIXMAP_BG (image_instance) = background;
1915 XUnloadFont (dpy, source);
1916 if (mask && mask != source) XUnloadFont (dpy, mask);
1920 /**********************************************************************
1922 **********************************************************************/
1925 cursor_font_validate (Lisp_Object instantiator)
1927 data_must_be_present (instantiator);
1931 cursor_font_possible_dest_types (void)
1933 return IMAGE_POINTER_MASK;
1937 cursor_font_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1938 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1939 int dest_mask, Lisp_Object domain)
1941 /* This function can GC */
1942 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1943 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1944 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
1947 CONST char *name_ext;
1948 Lisp_Object foreground, background;
1950 if (!DEVICE_X_P (XDEVICE (device)))
1951 signal_simple_error ("Not an X device", device);
1953 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
1955 if (!(dest_mask & IMAGE_POINTER_MASK))
1956 incompatible_image_types (instantiator, dest_mask, IMAGE_POINTER_MASK);
1958 GET_C_STRING_FILENAME_DATA_ALLOCA (data, name_ext);
1959 if ((i = XmuCursorNameToIndex (name_ext)) == -1)
1960 signal_simple_error ("Unrecognized cursor-font name", data);
1962 x_initialize_pixmap_image_instance (ii, IMAGE_POINTER);
1963 IMAGE_INSTANCE_X_CURSOR (ii) = XCreateFontCursor (dpy, i);
1964 foreground = find_keyword_in_vector (instantiator, Q_foreground);
1965 if (NILP (foreground))
1966 foreground = pointer_fg;
1967 background = find_keyword_in_vector (instantiator, Q_background);
1968 if (NILP (background))
1969 background = pointer_bg;
1970 maybe_recolor_cursor (image_instance, foreground, background);
1974 x_colorize_image_instance (Lisp_Object image_instance,
1975 Lisp_Object foreground, Lisp_Object background)
1977 struct Lisp_Image_Instance *p;
1979 p = XIMAGE_INSTANCE (image_instance);
1981 switch (IMAGE_INSTANCE_TYPE (p))
1983 case IMAGE_MONO_PIXMAP:
1984 IMAGE_INSTANCE_TYPE (p) = IMAGE_COLOR_PIXMAP;
1985 /* Make sure there aren't two pointers to the same mask, causing
1986 it to get freed twice. */
1987 IMAGE_INSTANCE_X_MASK (p) = 0;
1995 Display *dpy = DEVICE_X_DISPLAY (XDEVICE (IMAGE_INSTANCE_DEVICE (p)));
1996 Drawable draw = XtWindow(DEVICE_XT_APP_SHELL (XDEVICE (IMAGE_INSTANCE_DEVICE (p))));
1997 Dimension d = DEVICE_X_DEPTH (XDEVICE (IMAGE_INSTANCE_DEVICE (p)));
1998 Pixmap new = XCreatePixmap (dpy, draw,
1999 IMAGE_INSTANCE_PIXMAP_WIDTH (p),
2000 IMAGE_INSTANCE_PIXMAP_HEIGHT (p), d);
2004 color = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (foreground));
2005 gcv.foreground = color.pixel;
2006 color = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (background));
2007 gcv.background = color.pixel;
2008 gc = XCreateGC (dpy, new, GCBackground|GCForeground, &gcv);
2009 XCopyPlane (dpy, IMAGE_INSTANCE_X_PIXMAP (p), new, gc, 0, 0,
2010 IMAGE_INSTANCE_PIXMAP_WIDTH (p),
2011 IMAGE_INSTANCE_PIXMAP_HEIGHT (p),
2014 IMAGE_INSTANCE_X_PIXMAP (p) = new;
2015 IMAGE_INSTANCE_PIXMAP_DEPTH (p) = d;
2016 IMAGE_INSTANCE_PIXMAP_FG (p) = foreground;
2017 IMAGE_INSTANCE_PIXMAP_BG (p) = background;
2024 /************************************************************************/
2026 /************************************************************************/
2028 Lisp_Object Qsubwindowp;
2031 mark_subwindow (Lisp_Object obj, void (*markobj) (Lisp_Object))
2033 struct Lisp_Subwindow *sw = XSUBWINDOW (obj);
2038 print_subwindow (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
2041 struct Lisp_Subwindow *sw = XSUBWINDOW (obj);
2042 struct frame *frm = XFRAME (sw->frame);
2045 error ("printing unreadable object #<subwindow 0x%x>",
2048 write_c_string ("#<subwindow", printcharfun);
2049 sprintf (buf, " %dx%d", sw->width, sw->height);
2050 write_c_string (buf, printcharfun);
2052 /* This is stolen from frame.c. Subwindows are strange in that they
2053 are specific to a particular frame so we want to print in their
2054 description what that frame is. */
2056 write_c_string (" on #<", printcharfun);
2057 if (!FRAME_LIVE_P (frm))
2058 write_c_string ("dead", printcharfun);
2059 else if (FRAME_TTY_P (frm))
2060 write_c_string ("tty", printcharfun);
2061 else if (FRAME_X_P (frm))
2062 write_c_string ("x", printcharfun);
2064 write_c_string ("UNKNOWN", printcharfun);
2065 write_c_string ("-frame ", printcharfun);
2066 print_internal (frm->name, printcharfun, 1);
2067 sprintf (buf, " 0x%x>", frm->header.uid);
2068 write_c_string (buf, printcharfun);
2070 sprintf (buf, ") 0x%x>", sw->header.uid);
2071 write_c_string (buf, printcharfun);
2075 finalize_subwindow (void *header, int for_disksave)
2077 struct Lisp_Subwindow *sw = (struct Lisp_Subwindow *) header;
2078 if (for_disksave) finalose (sw);
2081 XDestroyWindow (DisplayOfScreen (sw->xscreen), sw->subwindow);
2086 /* subwindows are equal iff they have the same window XID */
2088 subwindow_equal (Lisp_Object o1, Lisp_Object o2, int depth)
2090 return (XSUBWINDOW (o1)->subwindow == XSUBWINDOW (o2)->subwindow);
2093 static unsigned long
2094 subwindow_hash (Lisp_Object obj, int depth)
2096 return XSUBWINDOW (obj)->subwindow;
2099 DEFINE_LRECORD_IMPLEMENTATION ("subwindow", subwindow,
2100 mark_subwindow, print_subwindow,
2101 finalize_subwindow, subwindow_equal,
2102 subwindow_hash, struct Lisp_Subwindow);
2104 /* #### PROBLEM: The display routines assume that the glyph is only
2105 being displayed in one buffer. If it is in two different buffers
2106 which are both being displayed simultaneously you will lose big time.
2107 This can be dealt with in the new redisplay. */
2109 /* #### These are completely un-re-implemented in 19.14. Get it done
2112 DEFUN ("make-subwindow", Fmake_subwindow, 0, 3, 0, /*
2113 Creates a new `subwindow' object of size WIDTH x HEIGHT.
2114 The default is a window of size 1x1, which is also the minimum allowed
2115 window size. Subwindows are per-frame. A buffer being shown in two
2116 different frames will only display a subwindow glyph in the frame in
2117 which it was actually created. If two windows on the same frame are
2118 displaying the buffer then the most recently used window will actually
2119 display the window. If the frame is not specified, the selected frame
2122 Subwindows are not currently implemented.
2124 (width, height, frame))
2130 unsigned int iw, ih;
2131 XSetWindowAttributes xswa;
2134 error ("subwindows are not functional in 20.2; they may be again someday");
2136 f = decode_x_frame (frame);
2138 xs = LISP_DEVICE_TO_X_SCREEN (FRAME_DEVICE (f));
2139 dpy = DisplayOfScreen (xs);
2140 pw = XtWindow (FRAME_X_TEXT_WIDGET (f));
2160 struct Lisp_Subwindow *sw =
2161 alloc_lcrecord_type (struct Lisp_Subwindow, lrecord_subwindow);
2165 sw->parent_window = pw;
2169 xswa.backing_store = Always;
2170 valueMask |= CWBackingStore;
2172 xswa.colormap = DefaultColormapOfScreen (xs);
2173 valueMask |= CWColormap;
2175 sw->subwindow = XCreateWindow (dpy, pw, 0, 0, iw, ih, 0, CopyFromParent,
2176 InputOutput, CopyFromParent, valueMask,
2179 XSETSUBWINDOW (val, sw);
2184 /* #### Should this function exist? */
2185 DEFUN ("change-subwindow-property", Fchange_subwindow_property, 3, 3, 0, /*
2186 For the given SUBWINDOW, set PROPERTY to DATA, which is a string.
2187 Subwindows are not currently implemented.
2189 (subwindow, property, data))
2192 struct Lisp_Subwindow *sw;
2195 CHECK_SUBWINDOW (subwindow);
2196 CHECK_STRING (property);
2197 CHECK_STRING (data);
2199 sw = XSUBWINDOW (subwindow);
2200 dpy = DisplayOfScreen (LISP_DEVICE_TO_X_SCREEN
2201 (FRAME_DEVICE (XFRAME (sw->frame))));
2203 property_atom = XInternAtom (dpy, (char *) XSTRING_DATA (property), False);
2204 XChangeProperty (dpy, sw->subwindow, property_atom, XA_STRING, 8,
2206 XSTRING_DATA (data),
2207 XSTRING_LENGTH (data));
2212 DEFUN ("subwindowp", Fsubwindowp, 1, 1, 0, /*
2213 Return non-nil if OBJECT is a subwindow.
2214 Subwindows are not currently implemented.
2218 return SUBWINDOWP (object) ? Qt : Qnil;
2221 DEFUN ("subwindow-width", Fsubwindow_width, 1, 1, 0, /*
2223 Subwindows are not currently implemented.
2227 CHECK_SUBWINDOW (subwindow);
2228 return make_int (XSUBWINDOW (subwindow)->width);
2231 DEFUN ("subwindow-height", Fsubwindow_height, 1, 1, 0, /*
2232 Height of SUBWINDOW.
2233 Subwindows are not currently implemented.
2237 CHECK_SUBWINDOW (subwindow);
2238 return make_int (XSUBWINDOW (subwindow)->height);
2241 DEFUN ("subwindow-xid", Fsubwindow_xid, 1, 1, 0, /*
2242 Return the xid of SUBWINDOW as a number.
2243 Subwindows are not currently implemented.
2247 CHECK_SUBWINDOW (subwindow);
2248 return make_int (XSUBWINDOW (subwindow)->subwindow);
2251 DEFUN ("resize-subwindow", Fresize_subwindow, 1, 3, 0, /*
2252 Resize SUBWINDOW to WIDTH x HEIGHT.
2253 If a value is nil that parameter is not changed.
2254 Subwindows are not currently implemented.
2256 (subwindow, width, height))
2259 struct Lisp_Subwindow *sw;
2261 CHECK_SUBWINDOW (subwindow);
2262 sw = XSUBWINDOW (subwindow);
2267 neww = XINT (width);
2272 newh = XINT (height);
2274 XResizeWindow (DisplayOfScreen (sw->xscreen), sw->subwindow, neww, newh);
2282 DEFUN ("force-subwindow-map", Fforce_subwindow_map, 1, 1, 0, /*
2283 Generate a Map event for SUBWINDOW.
2284 Subwindows are not currently implemented.
2288 CHECK_SUBWINDOW (subwindow);
2290 XMapWindow (DisplayOfScreen (XSUBWINDOW (subwindow)->xscreen),
2291 XSUBWINDOW (subwindow)->subwindow);
2297 /************************************************************************/
2298 /* initialization */
2299 /************************************************************************/
2302 syms_of_glyphs_x (void)
2305 defsymbol (&Qsubwindowp, "subwindowp");
2307 DEFSUBR (Fmake_subwindow);
2308 DEFSUBR (Fchange_subwindow_property);
2309 DEFSUBR (Fsubwindowp);
2310 DEFSUBR (Fsubwindow_width);
2311 DEFSUBR (Fsubwindow_height);
2312 DEFSUBR (Fsubwindow_xid);
2313 DEFSUBR (Fresize_subwindow);
2314 DEFSUBR (Fforce_subwindow_map);
2319 console_type_create_glyphs_x (void)
2323 CONSOLE_HAS_METHOD (x, print_image_instance);
2324 CONSOLE_HAS_METHOD (x, finalize_image_instance);
2325 CONSOLE_HAS_METHOD (x, image_instance_equal);
2326 CONSOLE_HAS_METHOD (x, image_instance_hash);
2327 CONSOLE_HAS_METHOD (x, colorize_image_instance);
2328 CONSOLE_HAS_METHOD (x, init_image_instance_from_eimage);
2329 CONSOLE_HAS_METHOD (x, locate_pixmap_file);
2331 CONSOLE_HAS_METHOD (x, xpm_instantiate);
2333 CONSOLE_HAS_METHOD (x, xbm_instantiate);
2337 image_instantiator_format_create_glyphs_x (void)
2340 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (cursor_font, "cursor-font");
2342 IIFORMAT_HAS_METHOD (cursor_font, validate);
2343 IIFORMAT_HAS_METHOD (cursor_font, possible_dest_types);
2344 IIFORMAT_HAS_METHOD (cursor_font, instantiate);
2346 IIFORMAT_VALID_KEYWORD (cursor_font, Q_data, check_valid_string);
2347 IIFORMAT_VALID_KEYWORD (cursor_font, Q_foreground, check_valid_string);
2348 IIFORMAT_VALID_KEYWORD (cursor_font, Q_background, check_valid_string);
2350 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (font, "font");
2352 IIFORMAT_HAS_METHOD (font, validate);
2353 IIFORMAT_HAS_METHOD (font, possible_dest_types);
2354 IIFORMAT_HAS_METHOD (font, instantiate);
2356 IIFORMAT_VALID_KEYWORD (font, Q_data, check_valid_string);
2357 IIFORMAT_VALID_KEYWORD (font, Q_foreground, check_valid_string);
2358 IIFORMAT_VALID_KEYWORD (font, Q_background, check_valid_string);
2361 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (xface, "xface");
2363 IIFORMAT_HAS_METHOD (xface, validate);
2364 IIFORMAT_HAS_METHOD (xface, normalize);
2365 IIFORMAT_HAS_METHOD (xface, possible_dest_types);
2366 IIFORMAT_HAS_METHOD (xface, instantiate);
2368 IIFORMAT_VALID_KEYWORD (xface, Q_data, check_valid_string);
2369 IIFORMAT_VALID_KEYWORD (xface, Q_file, check_valid_string);
2370 IIFORMAT_VALID_KEYWORD (xface, Q_hotspot_x, check_valid_int);
2371 IIFORMAT_VALID_KEYWORD (xface, Q_hotspot_y, check_valid_int);
2372 IIFORMAT_VALID_KEYWORD (xface, Q_foreground, check_valid_string);
2373 IIFORMAT_VALID_KEYWORD (xface, Q_background, check_valid_string);
2376 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (autodetect,
2379 IIFORMAT_HAS_METHOD (autodetect, validate);
2380 IIFORMAT_HAS_METHOD (autodetect, normalize);
2381 IIFORMAT_HAS_METHOD (autodetect, possible_dest_types);
2382 IIFORMAT_HAS_METHOD (autodetect, instantiate);
2384 IIFORMAT_VALID_KEYWORD (autodetect, Q_data, check_valid_string);
2388 vars_of_glyphs_x (void)
2394 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path /*
2395 A list of the directories in which X bitmap files may be found.
2396 If nil, this is initialized from the "*bitmapFilePath" resource.
2397 This is used by the `make-image-instance' function (however, note that if
2398 the environment variable XBMLANGPATH is set, it is consulted first).
2400 Vx_bitmap_file_path = Qnil;
2404 complex_vars_of_glyphs_x (void)
2406 #define BUILD_GLYPH_INST(variable, name) \
2407 Fadd_spec_to_specifier \
2408 (GLYPH_IMAGE (XGLYPH (variable)), \
2409 vector3 (Qxbm, Q_data, \
2410 list3 (make_int (name##_width), \
2411 make_int (name##_height), \
2412 make_ext_string (name##_bits, \
2413 sizeof (name##_bits), \
2417 BUILD_GLYPH_INST (Vtruncation_glyph, truncator);
2418 BUILD_GLYPH_INST (Vcontinuation_glyph, continuer);
2419 BUILD_GLYPH_INST (Vxemacs_logo, xemacs);
2420 BUILD_GLYPH_INST (Vhscroll_glyph, hscroll);
2422 #undef BUILD_GLYPH_INST