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
44 Convert images.el to C and stick it in here?
50 #include "console-x.h"
52 #include "objects-x.h"
67 #include "file-coding.h"
71 # define FOUR_BYTE_TYPE unsigned int
73 # define FOUR_BYTE_TYPE unsigned long
75 # define FOUR_BYTE_TYPE unsigned short
77 #error What kind of strange-ass system are we running on?
80 #define LISP_DEVICE_TO_X_SCREEN(dev) XDefaultScreenOfDisplay (DEVICE_X_DISPLAY (XDEVICE (dev)))
83 DEFINE_IMAGE_INSTANTIATOR_FORMAT (xface);
87 DEFINE_IMAGE_INSTANTIATOR_FORMAT (cursor_font);
88 Lisp_Object Qcursor_font;
90 DEFINE_IMAGE_INSTANTIATOR_FORMAT (font);
92 DEFINE_IMAGE_INSTANTIATOR_FORMAT (autodetect);
94 static void cursor_font_instantiate (Lisp_Object image_instance,
95 Lisp_Object instantiator,
96 Lisp_Object pointer_fg,
97 Lisp_Object pointer_bg,
104 /************************************************************************/
105 /* image instance methods */
106 /************************************************************************/
108 /************************************************************************/
109 /* convert from a series of RGB triples to an XImage formated for the */
111 /************************************************************************/
113 convert_EImage_to_XImage (Lisp_Object device, int width, int height,
114 unsigned char *pic, unsigned long **pixtbl,
121 int depth, bitmap_pad, byte_cnt, i, j;
123 unsigned char *data, *ip, *dp;
130 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
131 cmap = DEVICE_X_COLORMAP (XDEVICE(device));
132 vis = DEVICE_X_VISUAL (XDEVICE(device));
133 depth = DEVICE_X_DEPTH(XDEVICE(device));
135 if (vis->class == PseudoColor)
137 /* Quantize the image and get a histogram while we're at it.
138 Do this first to save memory */
139 qtable = build_EImage_quantable(pic, width, height, 256);
140 if (qtable == NULL) return NULL;
143 bitmap_pad = ((depth > 16) ? 32 :
146 byte_cnt = bitmap_pad >> 3;
148 outimg = XCreateImage (dpy, vis,
149 depth, ZPixmap, 0, 0, width, height,
151 if (!outimg) return NULL;
153 data = (unsigned char *) xmalloc (outimg->bytes_per_line * height);
156 XDestroyImage (outimg);
159 outimg->data = (char *) data;
161 if (vis->class == PseudoColor)
163 unsigned long pixarray[256];
165 /* use our quantize table to allocate the colors */
167 *pixtbl = xnew_array (unsigned long, pixcount);
170 /* ### should implement a sort by popularity to assure proper allocation */
172 for (i = 0; i < qtable->num_active_colors; i++)
177 color.red = qtable->rm[i] ? qtable->rm[i] << 8 : 0;
178 color.green = qtable->gm[i] ? qtable->gm[i] << 8 : 0;
179 color.blue = qtable->bm[i] ? qtable->bm[i] << 8 : 0;
180 color.flags = DoRed | DoGreen | DoBlue;
181 res = allocate_nearest_color (dpy, cmap, vis, &color);
182 if (res > 0 && res < 3)
184 DO_REALLOC(*pixtbl, pixcount, n+1, unsigned long);
185 (*pixtbl)[n] = color.pixel;
188 pixarray[i] = color.pixel;
192 for (i = 0; i < height; i++)
194 dp = data + (i * outimg->bytes_per_line);
195 for (j = 0; j < width; j++)
200 conv.val = pixarray[QUANT_GET_COLOR(qtable,rd,gr,bl)];
202 if (outimg->byte_order == MSBFirst)
203 for (q = 4-byte_cnt; q < 4; q++) *dp++ = conv.cp[q];
205 for (q = 3; q >= 4-byte_cnt; q--) *dp++ = conv.cp[q];
207 if (outimg->byte_order == MSBFirst)
208 for (q = byte_cnt-1; q >= 0; q--) *dp++ = conv.cp[q];
210 for (q = 0; q < byte_cnt; q++) *dp++ = conv.cp[q];
216 unsigned long rshift,gshift,bshift,rbits,gbits,bbits,junk;
217 junk = vis->red_mask;
219 while ((junk & 0x1) == 0)
230 junk = vis->green_mask;
232 while ((junk & 0x1) == 0)
243 junk = vis->blue_mask;
245 while ((junk & 0x1) == 0)
257 for (i = 0; i < height; i++)
259 dp = data + (i * outimg->bytes_per_line);
260 for (j = 0; j < width; j++)
263 rd = *ip++ << (rbits - 8);
265 rd = *ip++ >> (8 - rbits);
267 gr = *ip++ << (gbits - 8);
269 gr = *ip++ >> (8 - gbits);
271 bl = *ip++ << (bbits - 8);
273 bl = *ip++ >> (8 - bbits);
275 conv.val = (rd << rshift) | (gr << gshift) | (bl << bshift);
277 if (outimg->byte_order == MSBFirst)
278 for (q = 4-byte_cnt; q < 4; q++) *dp++ = conv.cp[q];
280 for (q = 3; q >= 4-byte_cnt; q--) *dp++ = conv.cp[q];
282 if (outimg->byte_order == MSBFirst)
283 for (q = byte_cnt-1; q >= 0; q--) *dp++ = conv.cp[q];
285 for (q = 0; q < byte_cnt; q++) *dp++ = conv.cp[q];
296 x_print_image_instance (struct Lisp_Image_Instance *p,
297 Lisp_Object printcharfun,
302 switch (IMAGE_INSTANCE_TYPE (p))
304 case IMAGE_MONO_PIXMAP:
305 case IMAGE_COLOR_PIXMAP:
307 sprintf (buf, " (0x%lx", (unsigned long) IMAGE_INSTANCE_X_PIXMAP (p));
308 write_c_string (buf, printcharfun);
309 if (IMAGE_INSTANCE_X_MASK (p))
311 sprintf (buf, "/0x%lx", (unsigned long) IMAGE_INSTANCE_X_MASK (p));
312 write_c_string (buf, printcharfun);
314 write_c_string (")", printcharfun);
317 case IMAGE_SUBWINDOW:
318 /* #### implement me */
326 x_finalize_image_instance (struct Lisp_Image_Instance *p)
331 if (DEVICE_LIVE_P (XDEVICE (p->device)))
333 Display *dpy = DEVICE_X_DISPLAY (XDEVICE (p->device));
335 if (IMAGE_INSTANCE_X_PIXMAP (p))
336 XFreePixmap (dpy, IMAGE_INSTANCE_X_PIXMAP (p));
337 if (IMAGE_INSTANCE_X_MASK (p) &&
338 IMAGE_INSTANCE_X_MASK (p) != IMAGE_INSTANCE_X_PIXMAP (p))
339 XFreePixmap (dpy, IMAGE_INSTANCE_X_MASK (p));
340 IMAGE_INSTANCE_X_PIXMAP (p) = 0;
341 IMAGE_INSTANCE_X_MASK (p) = 0;
343 if (IMAGE_INSTANCE_X_CURSOR (p))
345 XFreeCursor (dpy, IMAGE_INSTANCE_X_CURSOR (p));
346 IMAGE_INSTANCE_X_CURSOR (p) = 0;
349 if (IMAGE_INSTANCE_X_NPIXELS (p) != 0)
352 IMAGE_INSTANCE_X_COLORMAP (p),
353 IMAGE_INSTANCE_X_PIXELS (p),
354 IMAGE_INSTANCE_X_NPIXELS (p), 0);
355 IMAGE_INSTANCE_X_NPIXELS (p) = 0;
358 if (IMAGE_INSTANCE_X_PIXELS (p))
360 xfree (IMAGE_INSTANCE_X_PIXELS (p));
361 IMAGE_INSTANCE_X_PIXELS (p) = 0;
369 x_image_instance_equal (struct Lisp_Image_Instance *p1,
370 struct Lisp_Image_Instance *p2, int depth)
372 switch (IMAGE_INSTANCE_TYPE (p1))
374 case IMAGE_MONO_PIXMAP:
375 case IMAGE_COLOR_PIXMAP:
377 if (IMAGE_INSTANCE_X_COLORMAP (p1) != IMAGE_INSTANCE_X_COLORMAP (p2) ||
378 IMAGE_INSTANCE_X_NPIXELS (p1) != IMAGE_INSTANCE_X_NPIXELS (p2))
381 case IMAGE_SUBWINDOW:
382 /* #### implement me */
393 x_image_instance_hash (struct Lisp_Image_Instance *p, int depth)
395 switch (IMAGE_INSTANCE_TYPE (p))
397 case IMAGE_MONO_PIXMAP:
398 case IMAGE_COLOR_PIXMAP:
400 return IMAGE_INSTANCE_X_NPIXELS (p);
402 case IMAGE_SUBWINDOW:
403 /* #### implement me */
411 /* Set all the slots in an image instance structure to reasonable
412 default values. This is used somewhere within an instantiate
413 method. It is assumed that the device slot within the image
414 instance is already set -- this is the case when instantiate
415 methods are called. */
418 x_initialize_pixmap_image_instance (struct Lisp_Image_Instance *ii,
419 enum image_instance_type type)
421 ii->data = xnew_and_zero (struct x_image_instance_data);
422 IMAGE_INSTANCE_TYPE (ii) = type;
423 IMAGE_INSTANCE_PIXMAP_FILENAME (ii) = Qnil;
424 IMAGE_INSTANCE_PIXMAP_MASK_FILENAME (ii) = Qnil;
425 IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii) = Qnil;
426 IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii) = Qnil;
427 IMAGE_INSTANCE_PIXMAP_FG (ii) = Qnil;
428 IMAGE_INSTANCE_PIXMAP_BG (ii) = Qnil;
432 /************************************************************************/
433 /* pixmap file functions */
434 /************************************************************************/
436 /* Where bitmaps are; initialized from resource database */
437 Lisp_Object Vx_bitmap_file_path;
440 #define BITMAPDIR "/usr/include/X11/bitmaps"
443 #define USE_XBMLANGPATH
445 /* Given a pixmap filename, look through all of the "standard" places
446 where the file might be located. Return a full pathname if found;
447 otherwise, return Qnil. */
450 x_locate_pixmap_file (Lisp_Object name)
452 /* This function can GC if IN_REDISPLAY is false */
455 /* Check non-absolute pathnames with a directory component relative to
456 the search path; that's the way Xt does it. */
457 /* #### Unix-specific */
458 if (XSTRING_BYTE (name, 0) == '/' ||
459 (XSTRING_BYTE (name, 0) == '.' &&
460 (XSTRING_BYTE (name, 1) == '/' ||
461 (XSTRING_BYTE (name, 1) == '.' &&
462 (XSTRING_BYTE (name, 2) == '/')))))
464 if (!NILP (Ffile_readable_p (name)))
470 if (NILP (Vdefault_x_device))
471 /* This may occur during intialization. */
474 /* We only check the bitmapFilePath resource on the original X device. */
475 display = DEVICE_X_DISPLAY (XDEVICE (Vdefault_x_device));
477 #ifdef USE_XBMLANGPATH
479 char *path = egetenv ("XBMLANGPATH");
480 SubstitutionRec subs[1];
482 subs[0].substitution = (char *) XSTRING_DATA (name);
483 /* #### Motif uses a big hairy default if $XBMLANGPATH isn't set.
484 We don't. If you want it used, set it. */
486 (path = XtResolvePathname (display, "bitmaps", 0, 0, path,
487 subs, XtNumber (subs), 0)))
489 name = build_string (path);
496 if (NILP (Vx_bitmap_file_path))
500 if (XrmGetResource (XtDatabase (display),
501 "bitmapFilePath", "BitmapFilePath", &type, &value)
502 && !strcmp (type, "String"))
503 Vx_bitmap_file_path = decode_env_path (0, (char *) value.addr);
504 Vx_bitmap_file_path = nconc2 (Vx_bitmap_file_path,
505 (decode_path (BITMAPDIR)));
510 if (locate_file (Vx_bitmap_file_path, name, "", &found, R_OK) < 0)
512 Lisp_Object temp = list1 (Vdata_directory);
516 locate_file (temp, name, "", &found, R_OK);
525 locate_pixmap_file (Lisp_Object name)
527 return x_locate_pixmap_file (name);
532 write_lisp_string_to_temp_file (Lisp_Object string, char *filename_out)
534 Lisp_Object instream, outstream;
535 Lstream *istr, *ostr;
536 char tempbuf[1024]; /* some random amount */
539 static Extbyte_dynarr *conversion_out_dynarr;
540 Bytecount bstart, bend;
541 struct gcpro gcpro1, gcpro2;
543 Lisp_Object conv_out_stream;
548 /* This function can GC */
549 if (!conversion_out_dynarr)
550 conversion_out_dynarr = Dynarr_new (Extbyte);
552 Dynarr_reset (conversion_out_dynarr);
554 /* Create the temporary file ... */
555 sprintf (filename_out, "/tmp/emacs%d.XXXXXX", (int) getpid ());
556 mktemp (filename_out);
557 tmpfil = fopen (filename_out, "w");
562 int old_errno = errno;
564 unlink (filename_out);
567 report_file_error ("Creating temp file",
568 list1 (build_string (filename_out)));
571 CHECK_STRING (string);
572 get_string_range_byte (string, Qnil, Qnil, &bstart, &bend,
573 GB_HISTORICAL_STRING_BEHAVIOR);
574 instream = make_lisp_string_input_stream (string, bstart, bend);
575 istr = XLSTREAM (instream);
576 /* setup the out stream */
577 outstream = make_dynarr_output_stream((unsigned_char_dynarr *)conversion_out_dynarr);
578 ostr = XLSTREAM (outstream);
580 /* setup the conversion stream */
581 conv_out_stream = make_encoding_output_stream (ostr, Fget_coding_system(Qbinary));
582 costr = XLSTREAM (conv_out_stream);
583 GCPRO3 (instream, outstream, conv_out_stream);
585 GCPRO2 (instream, outstream);
588 /* Get the data while doing the conversion */
591 int size_in_bytes = Lstream_read (istr, tempbuf, sizeof (tempbuf));
594 /* It does seem the flushes are necessary... */
596 Lstream_write (costr, tempbuf, size_in_bytes);
597 Lstream_flush (costr);
599 Lstream_write (ostr, tempbuf, size_in_bytes);
601 Lstream_flush (ostr);
602 if (fwrite ((unsigned char *)Dynarr_atp(conversion_out_dynarr, 0),
603 Dynarr_length(conversion_out_dynarr), 1, tmpfil) != 1)
608 /* reset the dynarr */
609 Lstream_rewind(ostr);
612 if (fclose (tmpfil) != 0)
614 Lstream_close (istr);
616 Lstream_close (costr);
618 Lstream_close (ostr);
621 Lstream_delete (istr);
622 Lstream_delete (ostr);
624 Lstream_delete (costr);
628 report_file_error ("Writing temp file",
629 list1 (build_string (filename_out)));
634 /************************************************************************/
635 /* cursor functions */
636 /************************************************************************/
638 /* Check that this server supports cursors of size WIDTH * HEIGHT. If
639 not, signal an error. INSTANTIATOR is only used in the error
643 check_pointer_sizes (Screen *xs, unsigned int width, unsigned int height,
644 Lisp_Object instantiator)
646 unsigned int best_width, best_height;
647 if (! XQueryBestCursor (DisplayOfScreen (xs), RootWindowOfScreen (xs),
648 width, height, &best_width, &best_height))
649 /* this means that an X error of some sort occurred (we trap
650 these so they're not fatal). */
651 signal_simple_error ("XQueryBestCursor() failed?", instantiator);
653 if (width > best_width || height > best_height)
654 error_with_frob (instantiator,
655 "pointer too large (%dx%d): "
656 "server requires %dx%d or smaller",
657 width, height, best_width, best_height);
662 generate_cursor_fg_bg (Lisp_Object device, Lisp_Object *foreground,
663 Lisp_Object *background, XColor *xfg, XColor *xbg)
665 if (!NILP (*foreground) && !COLOR_INSTANCEP (*foreground))
667 Fmake_color_instance (*foreground, device,
668 encode_error_behavior_flag (ERROR_ME));
669 if (COLOR_INSTANCEP (*foreground))
670 *xfg = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (*foreground));
674 xfg->red = xfg->green = xfg->blue = 0;
677 if (!NILP (*background) && !COLOR_INSTANCEP (*background))
679 Fmake_color_instance (*background, device,
680 encode_error_behavior_flag (ERROR_ME));
681 if (COLOR_INSTANCEP (*background))
682 *xbg = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (*background));
686 xbg->red = xbg->green = xbg->blue = ~0;
691 maybe_recolor_cursor (Lisp_Object image_instance, Lisp_Object foreground,
692 Lisp_Object background)
694 Lisp_Object device = XIMAGE_INSTANCE_DEVICE (image_instance);
697 generate_cursor_fg_bg (device, &foreground, &background, &xfg, &xbg);
698 if (!NILP (foreground) || !NILP (background))
700 XRecolorCursor (DEVICE_X_DISPLAY (XDEVICE (device)),
701 XIMAGE_INSTANCE_X_CURSOR (image_instance),
703 XIMAGE_INSTANCE_PIXMAP_FG (image_instance) = foreground;
704 XIMAGE_INSTANCE_PIXMAP_BG (image_instance) = background;
709 /************************************************************************/
710 /* color pixmap functions */
711 /************************************************************************/
713 /* Initialize an image instance from an XImage.
715 DEST_MASK specifies the mask of allowed image types.
717 PIXELS and NPIXELS specify an array of pixels that are used in
718 the image. These need to be kept around for the duration of the
719 image. When the image instance is freed, XFreeColors() will
720 automatically be called on all the pixels specified here; thus,
721 you should have allocated the pixels yourself using XAllocColor()
722 or the like. The array passed in is used directly without
723 being copied, so it should be heap data created with xmalloc().
724 It will be freed using xfree() when the image instance is
727 If this fails, signal an error. INSTANTIATOR is only used
728 in the error message.
730 #### This should be able to handle conversion into `pointer'.
731 Use the same code as for `xpm'. */
734 init_image_instance_from_x_image (struct Lisp_Image_Instance *ii,
738 unsigned long *pixels,
740 Lisp_Object instantiator)
742 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
748 if (!DEVICE_X_P (XDEVICE (device)))
749 signal_simple_error ("Not an X device", device);
751 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
752 d = XtWindow(DEVICE_XT_APP_SHELL (XDEVICE (device)));
754 if (!(dest_mask & IMAGE_COLOR_PIXMAP_MASK))
755 incompatible_image_types (instantiator, dest_mask,
756 IMAGE_COLOR_PIXMAP_MASK);
758 pixmap = XCreatePixmap (dpy, d, ximage->width,
759 ximage->height, ximage->depth);
761 signal_simple_error ("Unable to create pixmap", instantiator);
763 gc = XCreateGC (dpy, pixmap, 0, NULL);
766 XFreePixmap (dpy, pixmap);
767 signal_simple_error ("Unable to create GC", instantiator);
770 XPutImage (dpy, pixmap, gc, ximage, 0, 0, 0, 0,
771 ximage->width, ximage->height);
775 x_initialize_pixmap_image_instance (ii, IMAGE_COLOR_PIXMAP);
777 IMAGE_INSTANCE_PIXMAP_FILENAME (ii) =
778 find_keyword_in_vector (instantiator, Q_file);
780 IMAGE_INSTANCE_X_PIXMAP (ii) = pixmap;
781 IMAGE_INSTANCE_X_MASK (ii) = 0;
782 IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = ximage->width;
783 IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = ximage->height;
784 IMAGE_INSTANCE_PIXMAP_DEPTH (ii) = ximage->depth;
785 IMAGE_INSTANCE_X_COLORMAP (ii) = cmap;
786 IMAGE_INSTANCE_X_PIXELS (ii) = pixels;
787 IMAGE_INSTANCE_X_NPIXELS (ii) = npixels;
791 x_init_image_instance_from_eimage (struct Lisp_Image_Instance *ii,
792 int width, int height,
793 unsigned char *eimage,
795 Lisp_Object instantiator,
798 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
799 Colormap cmap = DEVICE_X_COLORMAP (XDEVICE(device));
800 unsigned long *pixtbl = NULL;
804 ximage = convert_EImage_to_XImage (device, width, height, eimage,
808 if (pixtbl) xfree (pixtbl);
809 signal_image_error("EImage to XImage conversion failed", instantiator);
812 /* Now create the pixmap and set up the image instance */
813 init_image_instance_from_x_image (ii, ximage, dest_mask,
814 cmap, pixtbl, npixels,
821 xfree (ximage->data);
824 XDestroyImage (ximage);
828 int read_bitmap_data_from_file (CONST char *filename, unsigned int *width,
829 unsigned int *height, unsigned char **datap,
830 int *x_hot, int *y_hot)
832 return XmuReadBitmapDataFromFile (filename, width, height,
833 datap, x_hot, y_hot);
836 /* Given inline data for a mono pixmap, create and return the
837 corresponding X object. */
840 pixmap_from_xbm_inline (Lisp_Object device, int width, int height,
841 /* Note that data is in ext-format! */
844 return XCreatePixmapFromBitmapData (DEVICE_X_DISPLAY (XDEVICE(device)),
845 XtWindow (DEVICE_XT_APP_SHELL (XDEVICE (device))),
846 (char *) bits, width, height,
850 /* Given inline data for a mono pixmap, initialize the given
851 image instance accordingly. */
854 init_image_instance_from_xbm_inline (struct Lisp_Image_Instance *ii,
855 int width, int height,
856 /* Note that data is in ext-format! */
858 Lisp_Object instantiator,
859 Lisp_Object pointer_fg,
860 Lisp_Object pointer_bg,
863 Lisp_Object mask_filename)
865 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
866 Lisp_Object foreground = find_keyword_in_vector (instantiator, Q_foreground);
867 Lisp_Object background = find_keyword_in_vector (instantiator, Q_background);
871 enum image_instance_type type;
873 if (!DEVICE_X_P (XDEVICE (device)))
874 signal_simple_error ("Not an X device", device);
876 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
877 draw = XtWindow(DEVICE_XT_APP_SHELL (XDEVICE (device)));
878 scr = DefaultScreenOfDisplay (dpy);
880 if ((dest_mask & IMAGE_MONO_PIXMAP_MASK) &&
881 (dest_mask & IMAGE_COLOR_PIXMAP_MASK))
883 if (!NILP (foreground) || !NILP (background))
884 type = IMAGE_COLOR_PIXMAP;
886 type = IMAGE_MONO_PIXMAP;
888 else if (dest_mask & IMAGE_MONO_PIXMAP_MASK)
889 type = IMAGE_MONO_PIXMAP;
890 else if (dest_mask & IMAGE_COLOR_PIXMAP_MASK)
891 type = IMAGE_COLOR_PIXMAP;
892 else if (dest_mask & IMAGE_POINTER_MASK)
893 type = IMAGE_POINTER;
895 incompatible_image_types (instantiator, dest_mask,
896 IMAGE_MONO_PIXMAP_MASK | IMAGE_COLOR_PIXMAP_MASK
897 | IMAGE_POINTER_MASK);
899 x_initialize_pixmap_image_instance (ii, type);
900 IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = width;
901 IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = height;
902 IMAGE_INSTANCE_PIXMAP_FILENAME (ii) =
903 find_keyword_in_vector (instantiator, Q_file);
907 case IMAGE_MONO_PIXMAP:
909 IMAGE_INSTANCE_X_PIXMAP (ii) =
910 pixmap_from_xbm_inline (device, width, height, (Extbyte *) bits);
914 case IMAGE_COLOR_PIXMAP:
916 Dimension d = DEVICE_X_DEPTH (XDEVICE(device));
917 unsigned long fg = BlackPixelOfScreen (scr);
918 unsigned long bg = WhitePixelOfScreen (scr);
920 if (!NILP (foreground) && !COLOR_INSTANCEP (foreground))
922 Fmake_color_instance (foreground, device,
923 encode_error_behavior_flag (ERROR_ME));
925 if (COLOR_INSTANCEP (foreground))
926 fg = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (foreground)).pixel;
928 if (!NILP (background) && !COLOR_INSTANCEP (background))
930 Fmake_color_instance (background, device,
931 encode_error_behavior_flag (ERROR_ME));
933 if (COLOR_INSTANCEP (background))
934 bg = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (background)).pixel;
936 /* We used to duplicate the pixels using XAllocColor(), to protect
937 against their getting freed. Just as easy to just store the
938 color instances here and GC-protect them, so this doesn't
940 IMAGE_INSTANCE_PIXMAP_FG (ii) = foreground;
941 IMAGE_INSTANCE_PIXMAP_BG (ii) = background;
942 IMAGE_INSTANCE_X_PIXMAP (ii) =
943 XCreatePixmapFromBitmapData (dpy, draw,
944 (char *) bits, width, height,
946 IMAGE_INSTANCE_PIXMAP_DEPTH (ii) = d;
952 XColor fg_color, bg_color;
955 check_pointer_sizes (scr, width, height, instantiator);
958 XCreatePixmapFromBitmapData (dpy, draw,
959 (char *) bits, width, height,
962 if (NILP (foreground))
963 foreground = pointer_fg;
964 if (NILP (background))
965 background = pointer_bg;
966 generate_cursor_fg_bg (device, &foreground, &background,
967 &fg_color, &bg_color);
969 IMAGE_INSTANCE_PIXMAP_FG (ii) = foreground;
970 IMAGE_INSTANCE_PIXMAP_BG (ii) = background;
971 IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii) =
972 find_keyword_in_vector (instantiator, Q_hotspot_x);
973 IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii) =
974 find_keyword_in_vector (instantiator, Q_hotspot_y);
975 IMAGE_INSTANCE_X_CURSOR (ii) =
977 (dpy, source, mask, &fg_color, &bg_color,
978 !NILP (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii)) ?
979 XINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii)) : 0,
980 !NILP (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii)) ?
981 XINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii)) : 0);
991 xbm_instantiate_1 (Lisp_Object image_instance, Lisp_Object instantiator,
992 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
993 int dest_mask, int width, int height,
994 /* Note that data is in ext-format! */
997 Lisp_Object mask_data = find_keyword_in_vector (instantiator, Q_mask_data);
998 Lisp_Object mask_file = find_keyword_in_vector (instantiator, Q_mask_file);
999 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1001 CONST char *gcc_may_you_rot_in_hell;
1003 if (!NILP (mask_data))
1005 GET_C_STRING_BINARY_DATA_ALLOCA (XCAR (XCDR (XCDR (mask_data))),
1006 gcc_may_you_rot_in_hell);
1008 pixmap_from_xbm_inline (IMAGE_INSTANCE_DEVICE (ii),
1009 XINT (XCAR (mask_data)),
1010 XINT (XCAR (XCDR (mask_data))),
1011 (CONST unsigned char *)
1012 gcc_may_you_rot_in_hell);
1015 init_image_instance_from_xbm_inline (ii, width, height, bits,
1016 instantiator, pointer_fg, pointer_bg,
1017 dest_mask, mask, mask_file);
1020 /* Instantiate method for XBM's. */
1023 x_xbm_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1024 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1025 int dest_mask, Lisp_Object domain)
1027 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1028 CONST char *gcc_go_home;
1030 assert (!NILP (data));
1032 GET_C_STRING_BINARY_DATA_ALLOCA (XCAR (XCDR (XCDR (data))),
1035 xbm_instantiate_1 (image_instance, instantiator, pointer_fg,
1036 pointer_bg, dest_mask, XINT (XCAR (data)),
1037 XINT (XCAR (XCDR (data))), gcc_go_home);
1043 /**********************************************************************
1045 **********************************************************************/
1046 /* xpm 3.2g and better has XpmCreatePixmapFromBuffer()...
1047 There was no version number in xpm.h before 3.3, but this should do.
1049 #if (XpmVersion >= 3) || defined(XpmExactColors)
1050 # define XPM_DOES_BUFFERS
1053 #ifndef XPM_DOES_BUFFERS
1054 Your version of XPM is too old. You cannot compile with it.
1055 Upgrade to version 3.2g or better or compile with --with-xpm=no.
1056 #endif /* !XPM_DOES_BUFFERS */
1058 static XpmColorSymbol *
1059 extract_xpm_color_names (XpmAttributes *xpmattrs, Lisp_Object device,
1061 Lisp_Object color_symbol_alist)
1063 /* This function can GC */
1064 Display *dpy = DEVICE_X_DISPLAY (XDEVICE(device));
1065 Colormap cmap = DEVICE_X_COLORMAP (XDEVICE(device));
1068 Lisp_Object results = Qnil;
1070 XpmColorSymbol *symbols;
1071 struct gcpro gcpro1, gcpro2;
1073 GCPRO2 (results, device);
1075 /* We built up results to be (("name" . #<color>) ...) so that if an
1076 error happens we don't lose any malloc()ed data, or more importantly,
1077 leave any pixels allocated in the server. */
1079 LIST_LOOP (rest, color_symbol_alist)
1081 Lisp_Object cons = XCAR (rest);
1082 Lisp_Object name = XCAR (cons);
1083 Lisp_Object value = XCDR (cons);
1086 if (STRINGP (value))
1088 Fmake_color_instance
1089 (value, device, encode_error_behavior_flag (ERROR_ME_NOT));
1092 assert (COLOR_SPECIFIERP (value));
1093 value = Fspecifier_instance (value, domain, Qnil, Qnil);
1097 results = noseeum_cons (noseeum_cons (name, value), results);
1100 UNGCPRO; /* no more evaluation */
1102 if (i == 0) return 0;
1104 symbols = xnew_array (XpmColorSymbol, i);
1105 xpmattrs->valuemask |= XpmColorSymbols;
1106 xpmattrs->colorsymbols = symbols;
1107 xpmattrs->numsymbols = i;
1111 Lisp_Object cons = XCAR (results);
1112 color = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (XCDR (cons)));
1113 /* Duplicate the pixel value so that we still have a lock on it if
1114 the pixel we were passed is later freed. */
1115 if (! XAllocColor (dpy, cmap, &color))
1116 abort (); /* it must be allocable since we're just duplicating it */
1118 symbols [i].name = (char *) XSTRING_DATA (XCAR (cons));
1119 symbols [i].pixel = color.pixel;
1120 symbols [i].value = 0;
1121 free_cons (XCONS (cons));
1123 results = XCDR (results);
1124 free_cons (XCONS (cons));
1130 xpm_free (XpmAttributes *xpmattrs)
1132 /* Could conceivably lose if XpmXXX returned an error without first
1133 initializing this structure, if we didn't know that initializing it
1134 to all zeros was ok (and also that it's ok to call XpmFreeAttributes()
1135 multiple times, since it zeros slots as it frees them...) */
1136 XpmFreeAttributes (xpmattrs);
1140 x_xpm_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1141 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1142 int dest_mask, Lisp_Object domain)
1144 /* This function can GC */
1145 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1146 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
1147 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1155 XpmAttributes xpmattrs;
1157 XpmColorSymbol *color_symbols;
1158 Lisp_Object color_symbol_alist = find_keyword_in_vector (instantiator,
1160 enum image_instance_type type;
1164 if (!DEVICE_X_P (XDEVICE (device)))
1165 signal_simple_error ("Not an X device", device);
1167 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
1168 xs = DefaultScreenOfDisplay (dpy);
1170 if (dest_mask & IMAGE_COLOR_PIXMAP_MASK)
1171 type = IMAGE_COLOR_PIXMAP;
1172 else if (dest_mask & IMAGE_MONO_PIXMAP_MASK)
1173 type = IMAGE_MONO_PIXMAP;
1174 else if (dest_mask & IMAGE_POINTER_MASK)
1175 type = IMAGE_POINTER;
1177 incompatible_image_types (instantiator, dest_mask,
1178 IMAGE_MONO_PIXMAP_MASK | IMAGE_COLOR_PIXMAP_MASK
1179 | IMAGE_POINTER_MASK);
1180 force_mono = (type != IMAGE_COLOR_PIXMAP);
1183 /* Although I haven't found it documented yet, it appears that pointers are
1184 always colored via the default window colormap... Sigh. */
1185 if (type == IMAGE_POINTER)
1187 cmap = DefaultColormap(dpy, DefaultScreen(dpy));
1188 depth = DefaultDepthOfScreen (xs);
1189 visual = DefaultVisualOfScreen (xs);
1193 cmap = DEVICE_X_COLORMAP (XDEVICE(device));
1194 depth = DEVICE_X_DEPTH (XDEVICE(device));
1195 visual = DEVICE_X_VISUAL (XDEVICE(device));
1198 cmap = DEVICE_X_COLORMAP (XDEVICE(device));
1199 depth = DEVICE_X_DEPTH (XDEVICE(device));
1200 visual = DEVICE_X_VISUAL (XDEVICE(device));
1203 x_initialize_pixmap_image_instance (ii, type);
1205 assert (!NILP (data));
1209 xzero (xpmattrs); /* want XpmInitAttributes() */
1210 xpmattrs.valuemask = XpmReturnPixels;
1213 /* Without this, we get a 1-bit version of the color image, which
1214 isn't quite right. With this, we get the mono image, which might
1215 be very different looking. */
1216 xpmattrs.valuemask |= XpmColorKey;
1217 xpmattrs.color_key = XPM_MONO;
1219 xpmattrs.valuemask |= XpmDepth;
1223 xpmattrs.closeness = 65535;
1224 xpmattrs.valuemask |= XpmCloseness;
1225 xpmattrs.depth = depth;
1226 xpmattrs.valuemask |= XpmDepth;
1227 xpmattrs.visual = visual;
1228 xpmattrs.valuemask |= XpmVisual;
1229 xpmattrs.colormap = cmap;
1230 xpmattrs.valuemask |= XpmColormap;
1233 color_symbols = extract_xpm_color_names (&xpmattrs, device, domain,
1234 color_symbol_alist);
1236 result = XpmCreatePixmapFromBuffer (dpy,
1237 XtWindow(DEVICE_XT_APP_SHELL (XDEVICE(device))),
1238 (char *) XSTRING_DATA (data),
1239 &pixmap, &mask, &xpmattrs);
1243 xfree (color_symbols);
1244 xpmattrs.colorsymbols = 0; /* in case XpmFreeAttr is too smart... */
1245 xpmattrs.numsymbols = 0;
1252 case XpmFileInvalid:
1254 xpm_free (&xpmattrs);
1255 signal_image_error ("invalid XPM data", data);
1257 case XpmColorFailed:
1260 xpm_free (&xpmattrs);
1263 /* second time; blow out. */
1264 signal_double_file_error ("Reading pixmap data",
1265 "color allocation failed",
1270 if (! (dest_mask & IMAGE_MONO_PIXMAP_MASK))
1272 /* second time; blow out. */
1273 signal_double_file_error ("Reading pixmap data",
1274 "color allocation failed",
1278 IMAGE_INSTANCE_TYPE (ii) = IMAGE_MONO_PIXMAP;
1284 xpm_free (&xpmattrs);
1285 signal_double_file_error ("Parsing pixmap data",
1286 "out of memory", data);
1290 xpm_free (&xpmattrs);
1291 signal_double_file_error_2 ("Parsing pixmap data",
1292 "unknown error code",
1293 make_int (result), data);
1298 h = xpmattrs.height;
1301 int npixels = xpmattrs.npixels;
1306 pixels = xnew_array (Pixel, npixels);
1307 memcpy (pixels, xpmattrs.pixels, npixels * sizeof (Pixel));
1312 IMAGE_INSTANCE_X_PIXMAP (ii) = pixmap;
1313 IMAGE_INSTANCE_X_MASK (ii) = mask;
1314 IMAGE_INSTANCE_X_COLORMAP (ii) = cmap;
1315 IMAGE_INSTANCE_X_PIXELS (ii) = pixels;
1316 IMAGE_INSTANCE_X_NPIXELS (ii) = npixels;
1317 IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = w;
1318 IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = h;
1319 IMAGE_INSTANCE_PIXMAP_FILENAME (ii) =
1320 find_keyword_in_vector (instantiator, Q_file);
1325 case IMAGE_MONO_PIXMAP:
1328 case IMAGE_COLOR_PIXMAP:
1330 IMAGE_INSTANCE_PIXMAP_DEPTH (ii) = depth;
1336 int npixels = xpmattrs.npixels;
1337 Pixel *pixels = xpmattrs.pixels;
1340 int xhot = 0, yhot = 0;
1342 if (xpmattrs.valuemask & XpmHotspot)
1344 xhot = xpmattrs.x_hotspot;
1345 XSETINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii), xpmattrs.x_hotspot);
1347 if (xpmattrs.valuemask & XpmHotspot)
1349 yhot = xpmattrs.y_hotspot;
1350 XSETINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii), xpmattrs.y_hotspot);
1352 check_pointer_sizes (xs, w, h, instantiator);
1354 /* If the loaded pixmap has colors allocated (meaning it came from an
1355 XPM file), then use those as the default colors for the cursor we
1356 create. Otherwise, default to pointer_fg and pointer_bg.
1360 /* With an XBM file, it's obvious which bit is foreground
1361 and which is background, or rather, it's implicit: in
1362 an XBM file, a 1 bit is foreground, and a 0 bit is
1365 XCreatePixmapCursor() assumes this property of the
1366 pixmap it is called with as well; the `foreground'
1367 color argument is used for the 1 bits.
1369 With an XPM file, it's tricker, since the elements of
1370 the pixmap don't represent FG and BG, but are actual
1371 pixel values. So we need to figure out which of those
1372 pixels is the foreground color and which is the
1373 background. We do it by comparing RGB and assuming
1374 that the darker color is the foreground. This works
1375 with the result of xbmtopbm|ppmtoxpm, at least.
1377 It might be nice if there was some way to tag the
1378 colors in the XPM file with whether they are the
1379 foreground - perhaps with logical color names somehow?
1381 Once we have decided which color is the foreground, we
1382 need to ensure that that color corresponds to a `1' bit
1383 in the Pixmap. The XPM library wrote into the (1-bit)
1384 pixmap with XPutPixel, which will ignore all but the
1385 least significant bit.
1387 This means that a 1 bit in the image corresponds to
1388 `fg' only if `fg.pixel' is odd.
1390 (This also means that the image will be all the same
1391 color if both `fg' and `bg' are odd or even, but we can
1392 safely assume that that won't happen if the XPM file is
1395 The desired result is that the image use `1' to
1396 represent the foreground color, and `0' to represent
1397 the background color. So, we may need to invert the
1398 image to accomplish this; we invert if fg is
1399 odd. (Remember that WhitePixel and BlackPixel are not
1400 necessarily 1 and 0 respectively, though I think it
1401 might be safe to assume that one of them is always 1
1402 and the other is always 0. We also pretty much need to
1403 assume that one is even and the other is odd.)
1406 fg.pixel = pixels[0]; /* pick a pixel at random. */
1407 bg.pixel = fg.pixel;
1408 for (i = 1; i < npixels; i++) /* Look for an "other" pixel value.*/
1410 bg.pixel = pixels[i];
1411 if (fg.pixel != bg.pixel)
1415 /* If (fg.pixel == bg.pixel) then probably something has
1416 gone wrong, but I don't think signalling an error would
1419 XQueryColor (dpy, cmap, &fg);
1420 XQueryColor (dpy, cmap, &bg);
1422 /* If the foreground is lighter than the background, swap them.
1423 (This occurs semi-randomly, depending on the ordering of the
1424 color list in the XPM file.)
1427 unsigned short fg_total = ((fg.red / 3) + (fg.green / 3)
1429 unsigned short bg_total = ((bg.red / 3) + (bg.green / 3)
1431 if (fg_total > bg_total)
1440 /* If the fg pixel corresponds to a `0' in the bitmap, invert it.
1441 (This occurs (only?) on servers with Black=0, White=1.)
1443 if ((fg.pixel & 1) == 0)
1447 gcv.function = GXxor;
1449 gc = XCreateGC (dpy, pixmap, (GCFunction | GCForeground),
1451 XFillRectangle (dpy, pixmap, gc, 0, 0, w, h);
1457 generate_cursor_fg_bg (device, &pointer_fg, &pointer_bg,
1459 IMAGE_INSTANCE_PIXMAP_FG (ii) = pointer_fg;
1460 IMAGE_INSTANCE_PIXMAP_BG (ii) = pointer_bg;
1463 IMAGE_INSTANCE_X_CURSOR (ii) =
1465 (dpy, pixmap, mask, &fg, &bg, xhot, yhot);
1474 xpm_free (&xpmattrs); /* after we've read pixels and hotspot */
1477 #endif /* HAVE_XPM */
1482 /**********************************************************************
1484 **********************************************************************/
1487 xface_validate (Lisp_Object instantiator)
1489 file_or_data_must_be_present (instantiator);
1493 xface_normalize (Lisp_Object inst, Lisp_Object console_type)
1495 /* This funcation can call lisp */
1496 Lisp_Object file = Qnil, mask_file = Qnil;
1497 struct gcpro gcpro1, gcpro2, gcpro3;
1498 Lisp_Object alist = Qnil;
1500 GCPRO3 (file, mask_file, alist);
1502 /* Now, convert any file data into inline data for both the regular
1503 data and the mask data. At the end of this, `data' will contain
1504 the inline data (if any) or Qnil, and `file' will contain
1505 the name this data was derived from (if known) or Qnil.
1506 Likewise for `mask_file' and `mask_data'.
1508 Note that if we cannot generate any regular inline data, we
1511 file = potential_pixmap_file_instantiator (inst, Q_file, Q_data,
1513 mask_file = potential_pixmap_file_instantiator (inst, Q_mask_file,
1514 Q_mask_data, console_type);
1516 if (CONSP (file)) /* failure locating filename */
1517 signal_double_file_error ("Opening bitmap file",
1518 "no such file or directory",
1521 if (NILP (file) && NILP (mask_file)) /* no conversion necessary */
1522 RETURN_UNGCPRO (inst);
1524 alist = tagged_vector_to_alist (inst);
1527 Lisp_Object data = make_string_from_file (file);
1528 alist = remassq_no_quit (Q_file, alist);
1529 /* there can't be a :data at this point. */
1530 alist = Fcons (Fcons (Q_file, file),
1531 Fcons (Fcons (Q_data, data), alist));
1534 alist = xbm_mask_file_munging (alist, file, mask_file, console_type);
1537 Lisp_Object result = alist_to_tagged_vector (Qxface, alist);
1539 RETURN_UNGCPRO (result);
1544 xface_possible_dest_types (void)
1547 IMAGE_MONO_PIXMAP_MASK |
1548 IMAGE_COLOR_PIXMAP_MASK |
1553 /* This is about to get redefined! */
1556 /* We have to define SYSV32 so that compface.h includes string.h
1557 instead of strings.h. */
1562 #include <compface.h>
1566 /* JMP_BUF cannot be used here because if it doesn't get defined
1567 to jmp_buf we end up with a conflicting type error with the
1568 definition in compface.h */
1569 extern jmp_buf comp_env;
1573 xface_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1574 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1575 int dest_mask, Lisp_Object domain)
1577 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1579 char *p, *bits, *bp;
1580 CONST char * volatile emsg = 0;
1581 CONST char * volatile dstring;
1583 assert (!NILP (data));
1585 GET_C_STRING_BINARY_DATA_ALLOCA (data, dstring);
1587 if ((p = strchr (dstring, ':')))
1592 /* Must use setjmp not SETJMP because we used jmp_buf above not JMP_BUF */
1593 if (!(stattis = setjmp (comp_env)))
1595 UnCompAll ((char *) dstring);
1602 emsg = "uncompface: internal error";
1605 emsg = "uncompface: insufficient or invalid data";
1608 emsg = "uncompface: excess data ignored";
1613 signal_simple_error_2 (emsg, data, Qimage);
1615 bp = bits = (char *) alloca (PIXELS / 8);
1617 /* the compface library exports char F[], which uses a single byte per
1618 pixel to represent a 48x48 bitmap. Yuck. */
1619 for (i = 0, p = F; i < (PIXELS / 8); ++i)
1622 /* reverse the bit order of each byte... */
1623 for (b = n = 0; b < 8; ++b)
1630 xbm_instantiate_1 (image_instance, instantiator, pointer_fg,
1631 pointer_bg, dest_mask, 48, 48, bits);
1634 #endif /* HAVE_XFACE */
1637 /**********************************************************************
1639 **********************************************************************/
1642 autodetect_validate (Lisp_Object instantiator)
1644 data_must_be_present (instantiator);
1648 autodetect_normalize (Lisp_Object instantiator,
1649 Lisp_Object console_type)
1651 Lisp_Object file = find_keyword_in_vector (instantiator, Q_data);
1652 Lisp_Object filename = Qnil;
1653 Lisp_Object data = Qnil;
1654 struct gcpro gcpro1, gcpro2, gcpro3;
1655 Lisp_Object alist = Qnil;
1657 GCPRO3 (filename, data, alist);
1659 if (NILP (file)) /* no conversion necessary */
1660 RETURN_UNGCPRO (instantiator);
1662 alist = tagged_vector_to_alist (instantiator);
1664 filename = locate_pixmap_file (file);
1665 if (!NILP (filename))
1668 /* #### Apparently some versions of XpmReadFileToData, which is
1669 called by pixmap_to_lisp_data, don't return an error value
1670 if the given file is not a valid XPM file. Instead, they
1671 just seg fault. It is definitely caused by passing a
1672 bitmap. To try and avoid this we check for bitmaps first. */
1674 data = bitmap_to_lisp_data (filename, &xhot, &yhot, 1);
1678 alist = remassq_no_quit (Q_data, alist);
1679 alist = Fcons (Fcons (Q_file, filename),
1680 Fcons (Fcons (Q_data, data), alist));
1682 alist = Fcons (Fcons (Q_hotspot_x, make_int (xhot)),
1685 alist = Fcons (Fcons (Q_hotspot_y, make_int (yhot)),
1688 alist = xbm_mask_file_munging (alist, filename, Qnil, console_type);
1691 Lisp_Object result = alist_to_tagged_vector (Qxbm, alist);
1693 RETURN_UNGCPRO (result);
1698 data = pixmap_to_lisp_data (filename, 1);
1702 alist = remassq_no_quit (Q_data, alist);
1703 alist = Fcons (Fcons (Q_file, filename),
1704 Fcons (Fcons (Q_data, data), alist));
1705 alist = Fcons (Fcons (Q_color_symbols,
1706 evaluate_xpm_color_symbols ()),
1709 Lisp_Object result = alist_to_tagged_vector (Qxpm, alist);
1711 RETURN_UNGCPRO (result);
1717 /* If we couldn't convert it, just put it back as it is.
1718 We might try to further frob it later as a cursor-font
1719 specification. (We can't do that now because we don't know
1720 what dest-types it's going to be instantiated into.) */
1722 Lisp_Object result = alist_to_tagged_vector (Qautodetect, alist);
1724 RETURN_UNGCPRO (result);
1729 autodetect_possible_dest_types (void)
1732 IMAGE_MONO_PIXMAP_MASK |
1733 IMAGE_COLOR_PIXMAP_MASK |
1734 IMAGE_POINTER_MASK |
1739 autodetect_instantiate (Lisp_Object image_instance,
1740 Lisp_Object instantiator,
1741 Lisp_Object pointer_fg,
1742 Lisp_Object pointer_bg,
1743 int dest_mask, Lisp_Object domain)
1745 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1746 struct gcpro gcpro1, gcpro2, gcpro3;
1747 Lisp_Object alist = Qnil;
1748 Lisp_Object result = Qnil;
1749 int is_cursor_font = 0;
1751 GCPRO3 (data, alist, result);
1753 alist = tagged_vector_to_alist (instantiator);
1754 if (dest_mask & IMAGE_POINTER_MASK)
1756 CONST char *name_ext;
1757 GET_C_STRING_FILENAME_DATA_ALLOCA (data, name_ext);
1758 if (XmuCursorNameToIndex (name_ext) != -1)
1760 result = alist_to_tagged_vector (Qcursor_font, alist);
1765 if (!is_cursor_font)
1766 result = alist_to_tagged_vector (Qstring, alist);
1770 cursor_font_instantiate (image_instance, result, pointer_fg,
1771 pointer_bg, dest_mask, domain);
1773 string_instantiate (image_instance, result, pointer_fg,
1774 pointer_bg, dest_mask, domain);
1780 /**********************************************************************
1782 **********************************************************************/
1785 font_validate (Lisp_Object instantiator)
1787 data_must_be_present (instantiator);
1790 /* XmuCvtStringToCursor is bogus in the following ways:
1792 - When it can't convert the given string to a real cursor, it will
1793 sometimes return a "success" value, after triggering a BadPixmap
1794 error. It then gives you a cursor that will itself generate BadCursor
1795 errors. So we install this error handler to catch/notice the X error
1796 and take that as meaning "couldn't convert."
1798 - When you tell it to find a cursor file that doesn't exist, it prints
1799 an error message on stderr. You can't make it not do that.
1801 - Also, using Xmu means we can't properly hack Lisp_Image_Instance
1802 objects, or XPM files, or $XBMLANGPATH.
1805 /* Duplicate the behavior of XmuCvtStringToCursor() to bypass its bogusness. */
1807 static int XLoadFont_got_error;
1810 XLoadFont_error_handler (Display *dpy, XErrorEvent *xerror)
1812 XLoadFont_got_error = 1;
1817 safe_XLoadFont (Display *dpy, char *name)
1820 int (*old_handler) (Display *, XErrorEvent *);
1821 XLoadFont_got_error = 0;
1823 old_handler = XSetErrorHandler (XLoadFont_error_handler);
1824 font = XLoadFont (dpy, name);
1826 XSetErrorHandler (old_handler);
1827 if (XLoadFont_got_error) return 0;
1832 font_possible_dest_types (void)
1834 return IMAGE_POINTER_MASK;
1838 font_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1839 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1840 int dest_mask, Lisp_Object domain)
1842 /* This function can GC */
1843 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1844 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1845 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
1849 char source_name[MAXPATHLEN], mask_name[MAXPATHLEN], dummy;
1850 int source_char, mask_char;
1852 Lisp_Object foreground, background;
1854 if (!DEVICE_X_P (XDEVICE (device)))
1855 signal_simple_error ("Not an X device", device);
1857 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
1859 if (!STRINGP (data) ||
1860 strncmp ("FONT ", (char *) XSTRING_DATA (data), 5))
1861 signal_simple_error ("Invalid font-glyph instantiator",
1864 if (!(dest_mask & IMAGE_POINTER_MASK))
1865 incompatible_image_types (instantiator, dest_mask, IMAGE_POINTER_MASK);
1867 foreground = find_keyword_in_vector (instantiator, Q_foreground);
1868 if (NILP (foreground))
1869 foreground = pointer_fg;
1870 background = find_keyword_in_vector (instantiator, Q_background);
1871 if (NILP (background))
1872 background = pointer_bg;
1874 generate_cursor_fg_bg (device, &foreground, &background, &fg, &bg);
1876 count = sscanf ((char *) XSTRING_DATA (data),
1877 "FONT %s %d %s %d %c",
1878 source_name, &source_char,
1879 mask_name, &mask_char, &dummy);
1880 /* Allow "%s %d %d" as well... */
1881 if (count == 3 && (1 == sscanf (mask_name, "%d %c", &mask_char, &dummy)))
1882 count = 4, mask_name[0] = 0;
1884 if (count != 2 && count != 4)
1885 signal_simple_error ("invalid cursor specification", data);
1886 source = safe_XLoadFont (dpy, source_name);
1888 signal_simple_error_2 ("couldn't load font",
1889 build_string (source_name),
1893 else if (!mask_name[0])
1897 mask = safe_XLoadFont (dpy, mask_name);
1900 Fsignal (Qerror, list3 (build_string ("couldn't load font"),
1901 build_string (mask_name), data));
1906 /* #### call XQueryTextExtents() and check_pointer_sizes() here. */
1908 x_initialize_pixmap_image_instance (ii, IMAGE_POINTER);
1909 IMAGE_INSTANCE_X_CURSOR (ii) =
1910 XCreateGlyphCursor (dpy, source, mask, source_char, mask_char,
1912 XIMAGE_INSTANCE_PIXMAP_FG (image_instance) = foreground;
1913 XIMAGE_INSTANCE_PIXMAP_BG (image_instance) = background;
1914 XUnloadFont (dpy, source);
1915 if (mask && mask != source) XUnloadFont (dpy, mask);
1919 /**********************************************************************
1921 **********************************************************************/
1924 cursor_font_validate (Lisp_Object instantiator)
1926 data_must_be_present (instantiator);
1930 cursor_font_possible_dest_types (void)
1932 return IMAGE_POINTER_MASK;
1936 cursor_font_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1937 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1938 int dest_mask, Lisp_Object domain)
1940 /* This function can GC */
1941 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1942 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1943 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
1946 CONST char *name_ext;
1947 Lisp_Object foreground, background;
1949 if (!DEVICE_X_P (XDEVICE (device)))
1950 signal_simple_error ("Not an X device", device);
1952 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
1954 if (!(dest_mask & IMAGE_POINTER_MASK))
1955 incompatible_image_types (instantiator, dest_mask, IMAGE_POINTER_MASK);
1957 GET_C_STRING_FILENAME_DATA_ALLOCA (data, name_ext);
1958 if ((i = XmuCursorNameToIndex (name_ext)) == -1)
1959 signal_simple_error ("Unrecognized cursor-font name", data);
1961 x_initialize_pixmap_image_instance (ii, IMAGE_POINTER);
1962 IMAGE_INSTANCE_X_CURSOR (ii) = XCreateFontCursor (dpy, i);
1963 foreground = find_keyword_in_vector (instantiator, Q_foreground);
1964 if (NILP (foreground))
1965 foreground = pointer_fg;
1966 background = find_keyword_in_vector (instantiator, Q_background);
1967 if (NILP (background))
1968 background = pointer_bg;
1969 maybe_recolor_cursor (image_instance, foreground, background);
1973 x_colorize_image_instance (Lisp_Object image_instance,
1974 Lisp_Object foreground, Lisp_Object background)
1976 struct Lisp_Image_Instance *p;
1978 p = XIMAGE_INSTANCE (image_instance);
1980 switch (IMAGE_INSTANCE_TYPE (p))
1982 case IMAGE_MONO_PIXMAP:
1983 IMAGE_INSTANCE_TYPE (p) = IMAGE_COLOR_PIXMAP;
1984 /* Make sure there aren't two pointers to the same mask, causing
1985 it to get freed twice. */
1986 IMAGE_INSTANCE_X_MASK (p) = 0;
1994 Display *dpy = DEVICE_X_DISPLAY (XDEVICE (IMAGE_INSTANCE_DEVICE (p)));
1995 Drawable draw = XtWindow(DEVICE_XT_APP_SHELL (XDEVICE (IMAGE_INSTANCE_DEVICE (p))));
1996 Dimension d = DEVICE_X_DEPTH (XDEVICE (IMAGE_INSTANCE_DEVICE (p)));
1997 Pixmap new = XCreatePixmap (dpy, draw,
1998 IMAGE_INSTANCE_PIXMAP_WIDTH (p),
1999 IMAGE_INSTANCE_PIXMAP_HEIGHT (p), d);
2003 color = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (foreground));
2004 gcv.foreground = color.pixel;
2005 color = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (background));
2006 gcv.background = color.pixel;
2007 gc = XCreateGC (dpy, new, GCBackground|GCForeground, &gcv);
2008 XCopyPlane (dpy, IMAGE_INSTANCE_X_PIXMAP (p), new, gc, 0, 0,
2009 IMAGE_INSTANCE_PIXMAP_WIDTH (p),
2010 IMAGE_INSTANCE_PIXMAP_HEIGHT (p),
2013 IMAGE_INSTANCE_X_PIXMAP (p) = new;
2014 IMAGE_INSTANCE_PIXMAP_DEPTH (p) = d;
2015 IMAGE_INSTANCE_PIXMAP_FG (p) = foreground;
2016 IMAGE_INSTANCE_PIXMAP_BG (p) = background;
2023 /************************************************************************/
2025 /************************************************************************/
2027 Lisp_Object Qsubwindowp;
2030 mark_subwindow (Lisp_Object obj, void (*markobj) (Lisp_Object))
2032 struct Lisp_Subwindow *sw = XSUBWINDOW (obj);
2037 print_subwindow (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
2040 struct Lisp_Subwindow *sw = XSUBWINDOW (obj);
2041 struct frame *frm = XFRAME (sw->frame);
2044 error ("printing unreadable object #<subwindow 0x%x>",
2047 write_c_string ("#<subwindow", printcharfun);
2048 sprintf (buf, " %dx%d", sw->width, sw->height);
2049 write_c_string (buf, printcharfun);
2051 /* This is stolen from frame.c. Subwindows are strange in that they
2052 are specific to a particular frame so we want to print in their
2053 description what that frame is. */
2055 write_c_string (" on #<", printcharfun);
2056 if (!FRAME_LIVE_P (frm))
2057 write_c_string ("dead", printcharfun);
2058 else if (FRAME_TTY_P (frm))
2059 write_c_string ("tty", printcharfun);
2060 else if (FRAME_X_P (frm))
2061 write_c_string ("x", printcharfun);
2063 write_c_string ("UNKNOWN", printcharfun);
2064 write_c_string ("-frame ", printcharfun);
2065 print_internal (frm->name, printcharfun, 1);
2066 sprintf (buf, " 0x%x>", frm->header.uid);
2067 write_c_string (buf, printcharfun);
2069 sprintf (buf, ") 0x%x>", sw->header.uid);
2070 write_c_string (buf, printcharfun);
2074 finalize_subwindow (void *header, int for_disksave)
2076 struct Lisp_Subwindow *sw = (struct Lisp_Subwindow *) header;
2077 if (for_disksave) finalose (sw);
2080 XDestroyWindow (DisplayOfScreen (sw->xscreen), sw->subwindow);
2085 /* subwindows are equal iff they have the same window XID */
2087 subwindow_equal (Lisp_Object o1, Lisp_Object o2, int depth)
2089 return (XSUBWINDOW (o1)->subwindow == XSUBWINDOW (o2)->subwindow);
2092 static unsigned long
2093 subwindow_hash (Lisp_Object obj, int depth)
2095 return XSUBWINDOW (obj)->subwindow;
2098 DEFINE_LRECORD_IMPLEMENTATION ("subwindow", subwindow,
2099 mark_subwindow, print_subwindow,
2100 finalize_subwindow, subwindow_equal,
2101 subwindow_hash, struct Lisp_Subwindow);
2103 /* #### PROBLEM: The display routines assume that the glyph is only
2104 being displayed in one buffer. If it is in two different buffers
2105 which are both being displayed simultaneously you will lose big time.
2106 This can be dealt with in the new redisplay. */
2108 /* #### These are completely un-re-implemented in 19.14. Get it done
2111 DEFUN ("make-subwindow", Fmake_subwindow, 0, 3, 0, /*
2112 Creates a new `subwindow' object of size WIDTH x HEIGHT.
2113 The default is a window of size 1x1, which is also the minimum allowed
2114 window size. Subwindows are per-frame. A buffer being shown in two
2115 different frames will only display a subwindow glyph in the frame in
2116 which it was actually created. If two windows on the same frame are
2117 displaying the buffer then the most recently used window will actually
2118 display the window. If the frame is not specified, the selected frame
2121 Subwindows are not currently implemented.
2123 (width, height, frame))
2129 unsigned int iw, ih;
2130 XSetWindowAttributes xswa;
2133 error ("subwindows are not functional in 20.2; they may be again someday");
2135 f = decode_x_frame (frame);
2137 xs = LISP_DEVICE_TO_X_SCREEN (FRAME_DEVICE (f));
2138 dpy = DisplayOfScreen (xs);
2139 pw = XtWindow (FRAME_X_TEXT_WIDGET (f));
2159 struct Lisp_Subwindow *sw =
2160 alloc_lcrecord_type (struct Lisp_Subwindow, lrecord_subwindow);
2164 sw->parent_window = pw;
2168 xswa.backing_store = Always;
2169 valueMask |= CWBackingStore;
2171 xswa.colormap = DefaultColormapOfScreen (xs);
2172 valueMask |= CWColormap;
2174 sw->subwindow = XCreateWindow (dpy, pw, 0, 0, iw, ih, 0, CopyFromParent,
2175 InputOutput, CopyFromParent, valueMask,
2178 XSETSUBWINDOW (val, sw);
2183 /* #### Should this function exist? */
2184 DEFUN ("change-subwindow-property", Fchange_subwindow_property, 3, 3, 0, /*
2185 For the given SUBWINDOW, set PROPERTY to DATA, which is a string.
2186 Subwindows are not currently implemented.
2188 (subwindow, property, data))
2191 struct Lisp_Subwindow *sw;
2194 CHECK_SUBWINDOW (subwindow);
2195 CHECK_STRING (property);
2196 CHECK_STRING (data);
2198 sw = XSUBWINDOW (subwindow);
2199 dpy = DisplayOfScreen (LISP_DEVICE_TO_X_SCREEN
2200 (FRAME_DEVICE (XFRAME (sw->frame))));
2202 property_atom = XInternAtom (dpy, (char *) XSTRING_DATA (property), False);
2203 XChangeProperty (dpy, sw->subwindow, property_atom, XA_STRING, 8,
2205 XSTRING_DATA (data),
2206 XSTRING_LENGTH (data));
2211 DEFUN ("subwindowp", Fsubwindowp, 1, 1, 0, /*
2212 Return non-nil if OBJECT is a subwindow.
2213 Subwindows are not currently implemented.
2217 return SUBWINDOWP (object) ? Qt : Qnil;
2220 DEFUN ("subwindow-width", Fsubwindow_width, 1, 1, 0, /*
2222 Subwindows are not currently implemented.
2226 CHECK_SUBWINDOW (subwindow);
2227 return make_int (XSUBWINDOW (subwindow)->width);
2230 DEFUN ("subwindow-height", Fsubwindow_height, 1, 1, 0, /*
2231 Height of SUBWINDOW.
2232 Subwindows are not currently implemented.
2236 CHECK_SUBWINDOW (subwindow);
2237 return make_int (XSUBWINDOW (subwindow)->height);
2240 DEFUN ("subwindow-xid", Fsubwindow_xid, 1, 1, 0, /*
2241 Return the xid of SUBWINDOW as a number.
2242 Subwindows are not currently implemented.
2246 CHECK_SUBWINDOW (subwindow);
2247 return make_int (XSUBWINDOW (subwindow)->subwindow);
2250 DEFUN ("resize-subwindow", Fresize_subwindow, 1, 3, 0, /*
2251 Resize SUBWINDOW to WIDTH x HEIGHT.
2252 If a value is nil that parameter is not changed.
2253 Subwindows are not currently implemented.
2255 (subwindow, width, height))
2258 struct Lisp_Subwindow *sw;
2260 CHECK_SUBWINDOW (subwindow);
2261 sw = XSUBWINDOW (subwindow);
2266 neww = XINT (width);
2271 newh = XINT (height);
2273 XResizeWindow (DisplayOfScreen (sw->xscreen), sw->subwindow, neww, newh);
2281 DEFUN ("force-subwindow-map", Fforce_subwindow_map, 1, 1, 0, /*
2282 Generate a Map event for SUBWINDOW.
2283 Subwindows are not currently implemented.
2287 CHECK_SUBWINDOW (subwindow);
2289 XMapWindow (DisplayOfScreen (XSUBWINDOW (subwindow)->xscreen),
2290 XSUBWINDOW (subwindow)->subwindow);
2296 /************************************************************************/
2297 /* initialization */
2298 /************************************************************************/
2301 syms_of_glyphs_x (void)
2304 defsymbol (&Qsubwindowp, "subwindowp");
2306 DEFSUBR (Fmake_subwindow);
2307 DEFSUBR (Fchange_subwindow_property);
2308 DEFSUBR (Fsubwindowp);
2309 DEFSUBR (Fsubwindow_width);
2310 DEFSUBR (Fsubwindow_height);
2311 DEFSUBR (Fsubwindow_xid);
2312 DEFSUBR (Fresize_subwindow);
2313 DEFSUBR (Fforce_subwindow_map);
2318 console_type_create_glyphs_x (void)
2322 CONSOLE_HAS_METHOD (x, print_image_instance);
2323 CONSOLE_HAS_METHOD (x, finalize_image_instance);
2324 CONSOLE_HAS_METHOD (x, image_instance_equal);
2325 CONSOLE_HAS_METHOD (x, image_instance_hash);
2326 CONSOLE_HAS_METHOD (x, colorize_image_instance);
2327 CONSOLE_HAS_METHOD (x, init_image_instance_from_eimage);
2328 CONSOLE_HAS_METHOD (x, locate_pixmap_file);
2330 CONSOLE_HAS_METHOD (x, xpm_instantiate);
2332 CONSOLE_HAS_METHOD (x, xbm_instantiate);
2336 image_instantiator_format_create_glyphs_x (void)
2339 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (cursor_font, "cursor-font");
2341 IIFORMAT_HAS_METHOD (cursor_font, validate);
2342 IIFORMAT_HAS_METHOD (cursor_font, possible_dest_types);
2343 IIFORMAT_HAS_METHOD (cursor_font, instantiate);
2345 IIFORMAT_VALID_KEYWORD (cursor_font, Q_data, check_valid_string);
2346 IIFORMAT_VALID_KEYWORD (cursor_font, Q_foreground, check_valid_string);
2347 IIFORMAT_VALID_KEYWORD (cursor_font, Q_background, check_valid_string);
2349 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (font, "font");
2351 IIFORMAT_HAS_METHOD (font, validate);
2352 IIFORMAT_HAS_METHOD (font, possible_dest_types);
2353 IIFORMAT_HAS_METHOD (font, instantiate);
2355 IIFORMAT_VALID_KEYWORD (font, Q_data, check_valid_string);
2356 IIFORMAT_VALID_KEYWORD (font, Q_foreground, check_valid_string);
2357 IIFORMAT_VALID_KEYWORD (font, Q_background, check_valid_string);
2360 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (xface, "xface");
2362 IIFORMAT_HAS_METHOD (xface, validate);
2363 IIFORMAT_HAS_METHOD (xface, normalize);
2364 IIFORMAT_HAS_METHOD (xface, possible_dest_types);
2365 IIFORMAT_HAS_METHOD (xface, instantiate);
2367 IIFORMAT_VALID_KEYWORD (xface, Q_data, check_valid_string);
2368 IIFORMAT_VALID_KEYWORD (xface, Q_file, check_valid_string);
2369 IIFORMAT_VALID_KEYWORD (xface, Q_hotspot_x, check_valid_int);
2370 IIFORMAT_VALID_KEYWORD (xface, Q_hotspot_y, check_valid_int);
2371 IIFORMAT_VALID_KEYWORD (xface, Q_foreground, check_valid_string);
2372 IIFORMAT_VALID_KEYWORD (xface, Q_background, check_valid_string);
2375 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (autodetect,
2378 IIFORMAT_HAS_METHOD (autodetect, validate);
2379 IIFORMAT_HAS_METHOD (autodetect, normalize);
2380 IIFORMAT_HAS_METHOD (autodetect, possible_dest_types);
2381 IIFORMAT_HAS_METHOD (autodetect, instantiate);
2383 IIFORMAT_VALID_KEYWORD (autodetect, Q_data, check_valid_string);
2387 vars_of_glyphs_x (void)
2393 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path /*
2394 A list of the directories in which X bitmap files may be found.
2395 If nil, this is initialized from the "*bitmapFilePath" resource.
2396 This is used by the `make-image-instance' function (however, note that if
2397 the environment variable XBMLANGPATH is set, it is consulted first).
2399 Vx_bitmap_file_path = Qnil;
2403 complex_vars_of_glyphs_x (void)
2405 #define BUILD_GLYPH_INST(variable, name) \
2406 Fadd_spec_to_specifier \
2407 (GLYPH_IMAGE (XGLYPH (variable)), \
2408 vector3 (Qxbm, Q_data, \
2409 list3 (make_int (name##_width), \
2410 make_int (name##_height), \
2411 make_ext_string (name##_bits, \
2412 sizeof (name##_bits), \
2416 BUILD_GLYPH_INST (Vtruncation_glyph, truncator);
2417 BUILD_GLYPH_INST (Vcontinuation_glyph, continuer);
2418 BUILD_GLYPH_INST (Vxemacs_logo, xemacs);
2419 BUILD_GLYPH_INST (Vhscroll_glyph, hscroll);
2421 #undef BUILD_GLYPH_INST