1 /* X-specific Lisp objects.
2 Copyright (C) 1993, 1994 Free Software Foundation, Inc.
3 Copyright (C) 1995 Board of Trustees, University of Illinois.
4 Copyright (C) 1995 Tinker Systems
5 Copyright (C) 1995, 1996 Ben Wing
6 Copyright (C) 1995 Sun Microsystems
7 Copyright (C) 1999, 2000 Andy Piper
9 This file is part of XEmacs.
11 XEmacs is free software; you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by the
13 Free Software Foundation; either version 2, or (at your option) any
16 XEmacs is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 You should have received a copy of the GNU General Public License
22 along with XEmacs; see the file COPYING. If not, write to
23 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
24 Boston, MA 02111-1307, USA. */
26 /* Synched up with: Not in FSF. */
28 /* Original author: Jamie Zawinski for 19.8
29 font-truename stuff added by Jamie Zawinski for 19.10
30 subwindow support added by Chuck Thompson
31 additional XPM support added by Chuck Thompson
32 initial X-Face support added by Stig
33 rewritten/restructured by Ben Wing for 19.12/19.13
34 GIF/JPEG support added by Ben Wing for 19.14
35 PNG support added by Bill Perry for 19.14
36 Improved GIF/JPEG support added by Bill Perry for 19.14
37 Cleanup/simplification of error handling by Ben Wing for 19.14
38 Pointer/icon overhaul, more restructuring by Ben Wing for 19.14
39 GIF support changed to external GIFlib 3.1 by Jareth Hein for 21.0
40 Many changes for color work and optimizations by Jareth Hein for 21.0
41 Switch of GIF/JPEG/PNG to new EImage intermediate code by Jareth Hein for 21.0
42 TIFF code by Jareth Hein for 21.0
43 GIF/JPEG/PNG/TIFF code moved to new glyph-eimage.c by Andy Piper for 21.0
44 Subwindow and Widget support by Andy Piper for 21.2
47 Support the GrayScale, StaticColor and StaticGray visual classes.
48 Convert images.el to C and stick it in here?
54 #include "console-x.h"
56 #include "objects-x.h"
77 #include "file-coding.h"
80 #ifdef LWLIB_WIDGETS_MOTIF
83 #include <X11/IntrinsicP.h>
86 # define FOUR_BYTE_TYPE unsigned int
88 # define FOUR_BYTE_TYPE unsigned long
90 # define FOUR_BYTE_TYPE unsigned short
92 #error What kind of strange-ass system are we running on?
95 #define LISP_DEVICE_TO_X_SCREEN(dev) XDefaultScreenOfDisplay (DEVICE_X_DISPLAY (XDEVICE (dev)))
97 DECLARE_IMAGE_INSTANTIATOR_FORMAT (nothing);
98 DECLARE_IMAGE_INSTANTIATOR_FORMAT (string);
99 DECLARE_IMAGE_INSTANTIATOR_FORMAT (formatted_string);
100 DECLARE_IMAGE_INSTANTIATOR_FORMAT (inherit);
102 DECLARE_IMAGE_INSTANTIATOR_FORMAT (jpeg);
105 DECLARE_IMAGE_INSTANTIATOR_FORMAT (tiff);
108 DECLARE_IMAGE_INSTANTIATOR_FORMAT (png);
111 DECLARE_IMAGE_INSTANTIATOR_FORMAT (gif);
114 DEFINE_DEVICE_IIFORMAT (x, xpm);
116 DEFINE_DEVICE_IIFORMAT (x, xbm);
117 DEFINE_DEVICE_IIFORMAT (x, subwindow);
119 DEFINE_DEVICE_IIFORMAT (x, xface);
122 DEFINE_IMAGE_INSTANTIATOR_FORMAT (cursor_font);
123 Lisp_Object Qcursor_font;
125 DEFINE_IMAGE_INSTANTIATOR_FORMAT (font);
127 DEFINE_IMAGE_INSTANTIATOR_FORMAT (autodetect);
130 DECLARE_IMAGE_INSTANTIATOR_FORMAT (layout);
131 DEFINE_DEVICE_IIFORMAT (x, widget);
132 DEFINE_DEVICE_IIFORMAT (x, native_layout);
133 DEFINE_DEVICE_IIFORMAT (x, button);
134 DEFINE_DEVICE_IIFORMAT (x, progress_gauge);
135 DEFINE_DEVICE_IIFORMAT (x, edit_field);
136 #if defined (LWLIB_WIDGETS_MOTIF) && XmVERSION > 1
137 DEFINE_DEVICE_IIFORMAT (x, combo_box);
139 DEFINE_DEVICE_IIFORMAT (x, tab_control);
140 DEFINE_DEVICE_IIFORMAT (x, label);
143 static void cursor_font_instantiate (Lisp_Object image_instance,
144 Lisp_Object instantiator,
145 Lisp_Object pointer_fg,
146 Lisp_Object pointer_bg,
152 update_widget_face (widget_value* wv,
153 Lisp_Image_Instance* ii, Lisp_Object domain);
155 update_tab_widget_face (widget_value* wv,
156 Lisp_Image_Instance* ii, Lisp_Object domain);
162 /************************************************************************/
163 /* image instance methods */
164 /************************************************************************/
166 /************************************************************************/
167 /* convert from a series of RGB triples to an XImage formated for the */
169 /************************************************************************/
171 convert_EImage_to_XImage (Lisp_Object device, int width, int height,
172 unsigned char *pic, unsigned long **pixtbl,
179 int depth, bitmap_pad, bits_per_pixel, byte_cnt, i, j;
181 unsigned char *data, *ip, *dp;
182 quant_table *qtable = 0;
188 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
189 cmap = DEVICE_X_COLORMAP (XDEVICE(device));
190 vis = DEVICE_X_VISUAL (XDEVICE(device));
191 depth = DEVICE_X_DEPTH(XDEVICE(device));
193 if (vis->class == GrayScale || vis->class == StaticColor ||
194 vis->class == StaticGray)
196 /* #### Implement me!!! */
200 if (vis->class == PseudoColor)
202 /* Quantize the image and get a histogram while we're at it.
203 Do this first to save memory */
204 qtable = build_EImage_quantable(pic, width, height, 256);
205 if (qtable == NULL) return NULL;
208 bitmap_pad = ((depth > 16) ? 32 :
212 outimg = XCreateImage (dpy, vis,
213 depth, ZPixmap, 0, 0, width, height,
215 if (!outimg) return NULL;
217 bits_per_pixel = outimg->bits_per_pixel;
218 byte_cnt = bits_per_pixel >> 3;
220 data = (unsigned char *) xmalloc (outimg->bytes_per_line * height);
223 XDestroyImage (outimg);
226 outimg->data = (char *) data;
228 if (vis->class == PseudoColor)
230 unsigned long pixarray[256];
232 /* use our quantize table to allocate the colors */
234 *pixtbl = xnew_array (unsigned long, pixcount);
237 /* #### should implement a sort by popularity to assure proper allocation */
239 for (i = 0; i < qtable->num_active_colors; i++)
244 color.red = qtable->rm[i] ? qtable->rm[i] << 8 : 0;
245 color.green = qtable->gm[i] ? qtable->gm[i] << 8 : 0;
246 color.blue = qtable->bm[i] ? qtable->bm[i] << 8 : 0;
247 color.flags = DoRed | DoGreen | DoBlue;
248 res = allocate_nearest_color (dpy, cmap, vis, &color);
249 if (res > 0 && res < 3)
251 DO_REALLOC(*pixtbl, pixcount, n+1, unsigned long);
252 (*pixtbl)[n] = color.pixel;
255 pixarray[i] = color.pixel;
259 for (i = 0; i < height; i++)
261 dp = data + (i * outimg->bytes_per_line);
262 for (j = 0; j < width; j++)
267 conv.val = pixarray[QUANT_GET_COLOR(qtable,rd,gr,bl)];
268 #ifdef WORDS_BIGENDIAN
269 if (outimg->byte_order == MSBFirst)
270 for (q = 4-byte_cnt; q < 4; q++) *dp++ = conv.cp[q];
272 for (q = 3; q >= 4-byte_cnt; q--) *dp++ = conv.cp[q];
274 if (outimg->byte_order == MSBFirst)
275 for (q = byte_cnt-1; q >= 0; q--) *dp++ = conv.cp[q];
277 for (q = 0; q < byte_cnt; q++) *dp++ = conv.cp[q];
283 unsigned long rshift,gshift,bshift,rbits,gbits,bbits,junk;
284 junk = vis->red_mask;
286 while ((junk & 0x1) == 0)
297 junk = vis->green_mask;
299 while ((junk & 0x1) == 0)
310 junk = vis->blue_mask;
312 while ((junk & 0x1) == 0)
324 for (i = 0; i < height; i++)
326 dp = data + (i * outimg->bytes_per_line);
327 for (j = 0; j < width; j++)
330 rd = *ip++ << (rbits - 8);
332 rd = *ip++ >> (8 - rbits);
334 gr = *ip++ << (gbits - 8);
336 gr = *ip++ >> (8 - gbits);
338 bl = *ip++ << (bbits - 8);
340 bl = *ip++ >> (8 - bbits);
342 conv.val = (rd << rshift) | (gr << gshift) | (bl << bshift);
343 #ifdef WORDS_BIGENDIAN
344 if (outimg->byte_order == MSBFirst)
345 for (q = 4-byte_cnt; q < 4; q++) *dp++ = conv.cp[q];
347 for (q = 3; q >= 4-byte_cnt; q--) *dp++ = conv.cp[q];
349 if (outimg->byte_order == MSBFirst)
350 for (q = byte_cnt-1; q >= 0; q--) *dp++ = conv.cp[q];
352 for (q = 0; q < byte_cnt; q++) *dp++ = conv.cp[q];
363 x_print_image_instance (Lisp_Image_Instance *p,
364 Lisp_Object printcharfun,
369 switch (IMAGE_INSTANCE_TYPE (p))
371 case IMAGE_MONO_PIXMAP:
372 case IMAGE_COLOR_PIXMAP:
374 sprintf (buf, " (0x%lx", (unsigned long) IMAGE_INSTANCE_X_PIXMAP (p));
375 write_c_string (buf, printcharfun);
376 if (IMAGE_INSTANCE_X_MASK (p))
378 sprintf (buf, "/0x%lx", (unsigned long) IMAGE_INSTANCE_X_MASK (p));
379 write_c_string (buf, printcharfun);
381 write_c_string (")", printcharfun);
389 extern int debug_widget_instances;
393 x_finalize_image_instance (Lisp_Image_Instance *p)
398 if (DEVICE_LIVE_P (XDEVICE (IMAGE_INSTANCE_DEVICE (p))))
400 Display *dpy = DEVICE_X_DISPLAY
401 (XDEVICE (IMAGE_INSTANCE_DEVICE (p)));
405 else if (IMAGE_INSTANCE_TYPE (p) == IMAGE_WIDGET)
407 if (IMAGE_INSTANCE_SUBWINDOW_ID (p))
410 debug_widget_instances--;
411 stderr_out ("widget destroyed, %d left\n", debug_widget_instances);
413 lw_destroy_widget (IMAGE_INSTANCE_X_WIDGET_ID (p));
414 lw_destroy_widget (IMAGE_INSTANCE_X_CLIPWIDGET (p));
416 /* We can release the callbacks again. */
417 ungcpro_popup_callbacks (IMAGE_INSTANCE_X_WIDGET_LWID (p));
419 IMAGE_INSTANCE_X_WIDGET_ID (p) = 0;
420 IMAGE_INSTANCE_X_CLIPWIDGET (p) = 0;
424 else if (IMAGE_INSTANCE_TYPE (p) == IMAGE_SUBWINDOW)
426 if (IMAGE_INSTANCE_SUBWINDOW_ID (p))
427 XDestroyWindow (dpy, IMAGE_INSTANCE_X_SUBWINDOW_ID (p));
428 IMAGE_INSTANCE_SUBWINDOW_ID (p) = 0;
433 if (IMAGE_INSTANCE_PIXMAP_TIMEOUT (p))
434 disable_glyph_animated_timeout (IMAGE_INSTANCE_PIXMAP_TIMEOUT (p));
436 if (IMAGE_INSTANCE_X_MASK (p) &&
437 IMAGE_INSTANCE_X_MASK (p) != IMAGE_INSTANCE_X_PIXMAP (p))
438 XFreePixmap (dpy, IMAGE_INSTANCE_X_MASK (p));
439 IMAGE_INSTANCE_PIXMAP_MASK (p) = 0;
441 if (IMAGE_INSTANCE_X_PIXMAP_SLICES (p))
443 for (i = 0; i < IMAGE_INSTANCE_PIXMAP_MAXSLICE (p); i++)
444 if (IMAGE_INSTANCE_X_PIXMAP_SLICE (p,i))
446 XFreePixmap (dpy, IMAGE_INSTANCE_X_PIXMAP_SLICE (p,i));
447 IMAGE_INSTANCE_X_PIXMAP_SLICE (p, i) = 0;
449 xfree (IMAGE_INSTANCE_X_PIXMAP_SLICES (p));
450 IMAGE_INSTANCE_X_PIXMAP_SLICES (p) = 0;
453 if (IMAGE_INSTANCE_X_CURSOR (p))
455 XFreeCursor (dpy, IMAGE_INSTANCE_X_CURSOR (p));
456 IMAGE_INSTANCE_X_CURSOR (p) = 0;
459 if (IMAGE_INSTANCE_X_NPIXELS (p) != 0)
462 IMAGE_INSTANCE_X_COLORMAP (p),
463 IMAGE_INSTANCE_X_PIXELS (p),
464 IMAGE_INSTANCE_X_NPIXELS (p), 0);
465 IMAGE_INSTANCE_X_NPIXELS (p) = 0;
469 /* You can sometimes have pixels without a live device. I forget
470 why, but that's why we free them here if we have a pixmap type
471 image instance. It probably means that we might also get a memory
472 leak with widgets. */
473 if (IMAGE_INSTANCE_TYPE (p) != IMAGE_WIDGET
474 && IMAGE_INSTANCE_TYPE (p) != IMAGE_SUBWINDOW
475 && IMAGE_INSTANCE_X_PIXELS (p))
477 xfree (IMAGE_INSTANCE_X_PIXELS (p));
478 IMAGE_INSTANCE_X_PIXELS (p) = 0;
486 x_image_instance_equal (Lisp_Image_Instance *p1,
487 Lisp_Image_Instance *p2, int depth)
489 switch (IMAGE_INSTANCE_TYPE (p1))
491 case IMAGE_MONO_PIXMAP:
492 case IMAGE_COLOR_PIXMAP:
494 if (IMAGE_INSTANCE_X_COLORMAP (p1) != IMAGE_INSTANCE_X_COLORMAP (p2) ||
495 IMAGE_INSTANCE_X_NPIXELS (p1) != IMAGE_INSTANCE_X_NPIXELS (p2))
506 x_image_instance_hash (Lisp_Image_Instance *p, int depth)
508 switch (IMAGE_INSTANCE_TYPE (p))
510 case IMAGE_MONO_PIXMAP:
511 case IMAGE_COLOR_PIXMAP:
513 return IMAGE_INSTANCE_X_NPIXELS (p);
519 /* Set all the slots in an image instance structure to reasonable
520 default values. This is used somewhere within an instantiate
521 method. It is assumed that the device slot within the image
522 instance is already set -- this is the case when instantiate
523 methods are called. */
526 x_initialize_pixmap_image_instance (Lisp_Image_Instance *ii,
528 enum image_instance_type type)
530 ii->data = xnew_and_zero (struct x_image_instance_data);
531 IMAGE_INSTANCE_PIXMAP_MAXSLICE (ii) = slices;
532 IMAGE_INSTANCE_X_PIXMAP_SLICES (ii) =
533 xnew_array_and_zero (Pixmap, slices);
534 IMAGE_INSTANCE_TYPE (ii) = type;
535 IMAGE_INSTANCE_PIXMAP_FILENAME (ii) = Qnil;
536 IMAGE_INSTANCE_PIXMAP_MASK_FILENAME (ii) = Qnil;
537 IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii) = Qnil;
538 IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii) = Qnil;
539 IMAGE_INSTANCE_PIXMAP_FG (ii) = Qnil;
540 IMAGE_INSTANCE_PIXMAP_BG (ii) = Qnil;
544 /************************************************************************/
545 /* pixmap file functions */
546 /************************************************************************/
548 /* Where bitmaps are; initialized from resource database */
549 Lisp_Object Vx_bitmap_file_path;
552 #define BITMAPDIR "/usr/include/X11/bitmaps"
555 #define USE_XBMLANGPATH
557 /* Given a pixmap filename, look through all of the "standard" places
558 where the file might be located. Return a full pathname if found;
559 otherwise, return Qnil. */
562 x_locate_pixmap_file (Lisp_Object name)
564 /* This function can GC if IN_REDISPLAY is false */
567 /* Check non-absolute pathnames with a directory component relative to
568 the search path; that's the way Xt does it. */
569 /* #### Unix-specific */
570 if (XSTRING_BYTE (name, 0) == '/' ||
571 (XSTRING_BYTE (name, 0) == '.' &&
572 (XSTRING_BYTE (name, 1) == '/' ||
573 (XSTRING_BYTE (name, 1) == '.' &&
574 (XSTRING_BYTE (name, 2) == '/')))))
576 if (!NILP (Ffile_readable_p (name)))
577 return Fexpand_file_name (name, Qnil);
582 if (NILP (Vdefault_x_device))
583 /* This may occur during initialization. */
586 /* We only check the bitmapFilePath resource on the original X device. */
587 display = DEVICE_X_DISPLAY (XDEVICE (Vdefault_x_device));
589 #ifdef USE_XBMLANGPATH
591 char *path = egetenv ("XBMLANGPATH");
592 SubstitutionRec subs[1];
594 subs[0].substitution = (char *) XSTRING_DATA (name);
595 /* #### Motif uses a big hairy default if $XBMLANGPATH isn't set.
596 We don't. If you want it used, set it. */
598 (path = XtResolvePathname (display, "bitmaps", 0, 0, path,
599 subs, XtNumber (subs), 0)))
601 name = build_string (path);
608 if (NILP (Vx_bitmap_file_path))
612 if (XrmGetResource (XtDatabase (display),
613 "bitmapFilePath", "BitmapFilePath", &type, &value)
614 && !strcmp (type, "String"))
615 Vx_bitmap_file_path = decode_env_path (0, (char *) value.addr);
616 Vx_bitmap_file_path = nconc2 (Vx_bitmap_file_path,
617 (decode_path (BITMAPDIR)));
622 if (locate_file (Vx_bitmap_file_path, name, Qnil, &found, R_OK) < 0)
624 Lisp_Object temp = list1 (Vdata_directory);
628 locate_file (temp, name, Qnil, &found, R_OK);
637 locate_pixmap_file (Lisp_Object name)
639 return x_locate_pixmap_file (name);
644 write_lisp_string_to_temp_file (Lisp_Object string, char *filename_out)
646 Lisp_Object instream, outstream;
647 Lstream *istr, *ostr;
648 char tempbuf[1024]; /* some random amount */
651 static Extbyte_dynarr *conversion_out_dynarr;
652 Bytecount bstart, bend;
653 struct gcpro gcpro1, gcpro2;
655 Lisp_Object conv_out_stream;
660 /* This function can GC */
661 if (!conversion_out_dynarr)
662 conversion_out_dynarr = Dynarr_new (Extbyte);
664 Dynarr_reset (conversion_out_dynarr);
666 /* Create the temporary file ... */
667 sprintf (filename_out, "/tmp/emacs%d.XXXXXX", (int) getpid ());
668 mktemp (filename_out);
669 tmpfil = fopen (filename_out, "w");
674 int old_errno = errno;
676 unlink (filename_out);
679 report_file_error ("Creating temp file",
680 list1 (build_string (filename_out)));
683 CHECK_STRING (string);
684 get_string_range_byte (string, Qnil, Qnil, &bstart, &bend,
685 GB_HISTORICAL_STRING_BEHAVIOR);
686 instream = make_lisp_string_input_stream (string, bstart, bend);
687 istr = XLSTREAM (instream);
688 /* setup the out stream */
689 outstream = make_dynarr_output_stream((unsigned_char_dynarr *)conversion_out_dynarr);
690 ostr = XLSTREAM (outstream);
692 /* setup the conversion stream */
693 conv_out_stream = make_encoding_output_stream (ostr, Fget_coding_system(Qbinary));
694 costr = XLSTREAM (conv_out_stream);
695 GCPRO3 (instream, outstream, conv_out_stream);
697 GCPRO2 (instream, outstream);
700 /* Get the data while doing the conversion */
703 ssize_t size_in_bytes = Lstream_read (istr, tempbuf, sizeof (tempbuf));
706 /* It does seem the flushes are necessary... */
708 Lstream_write (costr, tempbuf, size_in_bytes);
709 Lstream_flush (costr);
711 Lstream_write (ostr, tempbuf, size_in_bytes);
713 Lstream_flush (ostr);
714 if (fwrite ((unsigned char *)Dynarr_atp(conversion_out_dynarr, 0),
715 Dynarr_length(conversion_out_dynarr), 1, tmpfil) != 1)
720 /* reset the dynarr */
721 Lstream_rewind(ostr);
724 if (fclose (tmpfil) != 0)
726 Lstream_close (istr);
728 Lstream_close (costr);
730 Lstream_close (ostr);
733 Lstream_delete (istr);
734 Lstream_delete (ostr);
736 Lstream_delete (costr);
740 report_file_error ("Writing temp file",
741 list1 (build_string (filename_out)));
746 /************************************************************************/
747 /* cursor functions */
748 /************************************************************************/
750 /* Check that this server supports cursors of size WIDTH * HEIGHT. If
751 not, signal an error. INSTANTIATOR is only used in the error
755 check_pointer_sizes (Screen *xs, unsigned int width, unsigned int height,
756 Lisp_Object instantiator)
758 unsigned int best_width, best_height;
759 if (! XQueryBestCursor (DisplayOfScreen (xs), RootWindowOfScreen (xs),
760 width, height, &best_width, &best_height))
761 /* this means that an X error of some sort occurred (we trap
762 these so they're not fatal). */
763 signal_simple_error ("XQueryBestCursor() failed?", instantiator);
765 if (width > best_width || height > best_height)
766 error_with_frob (instantiator,
767 "pointer too large (%dx%d): "
768 "server requires %dx%d or smaller",
769 width, height, best_width, best_height);
774 generate_cursor_fg_bg (Lisp_Object device, Lisp_Object *foreground,
775 Lisp_Object *background, XColor *xfg, XColor *xbg)
777 if (!NILP (*foreground) && !COLOR_INSTANCEP (*foreground))
779 Fmake_color_instance (*foreground, device,
780 encode_error_behavior_flag (ERROR_ME));
781 if (COLOR_INSTANCEP (*foreground))
782 *xfg = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (*foreground));
786 xfg->red = xfg->green = xfg->blue = 0;
789 if (!NILP (*background) && !COLOR_INSTANCEP (*background))
791 Fmake_color_instance (*background, device,
792 encode_error_behavior_flag (ERROR_ME));
793 if (COLOR_INSTANCEP (*background))
794 *xbg = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (*background));
798 xbg->red = xbg->green = xbg->blue = ~0;
803 maybe_recolor_cursor (Lisp_Object image_instance, Lisp_Object foreground,
804 Lisp_Object background)
806 Lisp_Object device = XIMAGE_INSTANCE_DEVICE (image_instance);
809 generate_cursor_fg_bg (device, &foreground, &background, &xfg, &xbg);
810 if (!NILP (foreground) || !NILP (background))
812 XRecolorCursor (DEVICE_X_DISPLAY (XDEVICE (device)),
813 XIMAGE_INSTANCE_X_CURSOR (image_instance),
815 XIMAGE_INSTANCE_PIXMAP_FG (image_instance) = foreground;
816 XIMAGE_INSTANCE_PIXMAP_BG (image_instance) = background;
821 /************************************************************************/
822 /* color pixmap functions */
823 /************************************************************************/
825 /* Initialize an image instance from an XImage.
827 DEST_MASK specifies the mask of allowed image types.
829 PIXELS and NPIXELS specify an array of pixels that are used in
830 the image. These need to be kept around for the duration of the
831 image. When the image instance is freed, XFreeColors() will
832 automatically be called on all the pixels specified here; thus,
833 you should have allocated the pixels yourself using XAllocColor()
834 or the like. The array passed in is used directly without
835 being copied, so it should be heap data created with xmalloc().
836 It will be freed using xfree() when the image instance is
839 If this fails, signal an error. INSTANTIATOR is only used
840 in the error message.
842 #### This should be able to handle conversion into `pointer'.
843 Use the same code as for `xpm'. */
846 init_image_instance_from_x_image (Lisp_Image_Instance *ii,
850 unsigned long *pixels,
853 Lisp_Object instantiator)
855 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
861 if (!DEVICE_X_P (XDEVICE (device)))
862 signal_simple_error ("Not an X device", device);
864 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
865 d = XtWindow(DEVICE_XT_APP_SHELL (XDEVICE (device)));
867 if (!(dest_mask & IMAGE_COLOR_PIXMAP_MASK))
868 incompatible_image_types (instantiator, dest_mask,
869 IMAGE_COLOR_PIXMAP_MASK);
871 pixmap = XCreatePixmap (dpy, d, ximage->width,
872 ximage->height, ximage->depth);
874 signal_simple_error ("Unable to create pixmap", instantiator);
876 gc = XCreateGC (dpy, pixmap, 0, NULL);
879 XFreePixmap (dpy, pixmap);
880 signal_simple_error ("Unable to create GC", instantiator);
883 XPutImage (dpy, pixmap, gc, ximage, 0, 0, 0, 0,
884 ximage->width, ximage->height);
888 x_initialize_pixmap_image_instance (ii, slices, IMAGE_COLOR_PIXMAP);
890 IMAGE_INSTANCE_PIXMAP_FILENAME (ii) =
891 find_keyword_in_vector (instantiator, Q_file);
893 /* Fixup a set of pixmaps. */
894 IMAGE_INSTANCE_X_PIXMAP (ii) = pixmap;
896 IMAGE_INSTANCE_PIXMAP_MASK (ii) = 0;
897 IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = ximage->width;
898 IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = ximage->height;
899 IMAGE_INSTANCE_PIXMAP_DEPTH (ii) = ximage->depth;
900 IMAGE_INSTANCE_X_COLORMAP (ii) = cmap;
901 IMAGE_INSTANCE_X_PIXELS (ii) = pixels;
902 IMAGE_INSTANCE_X_NPIXELS (ii) = npixels;
906 image_instance_add_x_image (Lisp_Image_Instance *ii,
909 Lisp_Object instantiator)
911 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
917 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
918 d = XtWindow(DEVICE_XT_APP_SHELL (XDEVICE (device)));
920 pixmap = XCreatePixmap (dpy, d, ximage->width,
921 ximage->height, ximage->depth);
923 signal_simple_error ("Unable to create pixmap", instantiator);
925 gc = XCreateGC (dpy, pixmap, 0, NULL);
928 XFreePixmap (dpy, pixmap);
929 signal_simple_error ("Unable to create GC", instantiator);
932 XPutImage (dpy, pixmap, gc, ximage, 0, 0, 0, 0,
933 ximage->width, ximage->height);
937 IMAGE_INSTANCE_X_PIXMAP_SLICE (ii, slice) = pixmap;
941 x_init_image_instance_from_eimage (Lisp_Image_Instance *ii,
942 int width, int height,
944 unsigned char *eimage,
946 Lisp_Object instantiator,
949 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
950 Colormap cmap = DEVICE_X_COLORMAP (XDEVICE(device));
951 unsigned long *pixtbl = NULL;
956 for (slice = 0; slice < slices; slice++)
958 ximage = convert_EImage_to_XImage (device, width, height,
959 eimage + (width * height * 3 * slice),
963 if (pixtbl) xfree (pixtbl);
964 signal_image_error("EImage to XImage conversion failed", instantiator);
967 /* Now create the pixmap and set up the image instance */
969 init_image_instance_from_x_image (ii, ximage, dest_mask,
970 cmap, pixtbl, npixels, slices,
973 image_instance_add_x_image (ii, ximage, slice, instantiator);
979 xfree (ximage->data);
982 XDestroyImage (ximage);
988 int read_bitmap_data_from_file (const char *filename, unsigned int *width,
989 unsigned int *height, unsigned char **datap,
990 int *x_hot, int *y_hot)
992 return XmuReadBitmapDataFromFile (filename, width, height,
993 datap, x_hot, y_hot);
996 /* Given inline data for a mono pixmap, create and return the
997 corresponding X object. */
1000 pixmap_from_xbm_inline (Lisp_Object device, int width, int height,
1001 /* Note that data is in ext-format! */
1002 const Extbyte *bits)
1004 return XCreatePixmapFromBitmapData (DEVICE_X_DISPLAY (XDEVICE(device)),
1005 XtWindow (DEVICE_XT_APP_SHELL (XDEVICE (device))),
1006 (char *) bits, width, height,
1010 /* Given inline data for a mono pixmap, initialize the given
1011 image instance accordingly. */
1014 init_image_instance_from_xbm_inline (Lisp_Image_Instance *ii,
1015 int width, int height,
1016 /* Note that data is in ext-format! */
1018 Lisp_Object instantiator,
1019 Lisp_Object pointer_fg,
1020 Lisp_Object pointer_bg,
1023 Lisp_Object mask_filename)
1025 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
1026 Lisp_Object foreground = find_keyword_in_vector (instantiator, Q_foreground);
1027 Lisp_Object background = find_keyword_in_vector (instantiator, Q_background);
1031 enum image_instance_type type;
1033 if (!DEVICE_X_P (XDEVICE (device)))
1034 signal_simple_error ("Not an X device", device);
1036 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
1037 draw = XtWindow(DEVICE_XT_APP_SHELL (XDEVICE (device)));
1038 scr = DefaultScreenOfDisplay (dpy);
1040 if ((dest_mask & IMAGE_MONO_PIXMAP_MASK) &&
1041 (dest_mask & IMAGE_COLOR_PIXMAP_MASK))
1043 if (!NILP (foreground) || !NILP (background))
1044 type = IMAGE_COLOR_PIXMAP;
1046 type = IMAGE_MONO_PIXMAP;
1048 else if (dest_mask & IMAGE_MONO_PIXMAP_MASK)
1049 type = IMAGE_MONO_PIXMAP;
1050 else if (dest_mask & IMAGE_COLOR_PIXMAP_MASK)
1051 type = IMAGE_COLOR_PIXMAP;
1052 else if (dest_mask & IMAGE_POINTER_MASK)
1053 type = IMAGE_POINTER;
1055 incompatible_image_types (instantiator, dest_mask,
1056 IMAGE_MONO_PIXMAP_MASK | IMAGE_COLOR_PIXMAP_MASK
1057 | IMAGE_POINTER_MASK);
1059 x_initialize_pixmap_image_instance (ii, 1, type);
1060 IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = width;
1061 IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = height;
1062 IMAGE_INSTANCE_PIXMAP_FILENAME (ii) =
1063 find_keyword_in_vector (instantiator, Q_file);
1067 case IMAGE_MONO_PIXMAP:
1069 IMAGE_INSTANCE_X_PIXMAP (ii) =
1070 pixmap_from_xbm_inline (device, width, height, (Extbyte *) bits);
1074 case IMAGE_COLOR_PIXMAP:
1076 Dimension d = DEVICE_X_DEPTH (XDEVICE(device));
1077 unsigned long fg = BlackPixelOfScreen (scr);
1078 unsigned long bg = WhitePixelOfScreen (scr);
1080 if (!NILP (foreground) && !COLOR_INSTANCEP (foreground))
1082 Fmake_color_instance (foreground, device,
1083 encode_error_behavior_flag (ERROR_ME));
1085 if (COLOR_INSTANCEP (foreground))
1086 fg = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (foreground)).pixel;
1088 if (!NILP (background) && !COLOR_INSTANCEP (background))
1090 Fmake_color_instance (background, device,
1091 encode_error_behavior_flag (ERROR_ME));
1093 if (COLOR_INSTANCEP (background))
1094 bg = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (background)).pixel;
1096 /* We used to duplicate the pixels using XAllocColor(), to protect
1097 against their getting freed. Just as easy to just store the
1098 color instances here and GC-protect them, so this doesn't
1100 IMAGE_INSTANCE_PIXMAP_FG (ii) = foreground;
1101 IMAGE_INSTANCE_PIXMAP_BG (ii) = background;
1102 IMAGE_INSTANCE_X_PIXMAP (ii) =
1103 XCreatePixmapFromBitmapData (dpy, draw,
1104 (char *) bits, width, height,
1106 IMAGE_INSTANCE_PIXMAP_DEPTH (ii) = d;
1112 XColor fg_color, bg_color;
1115 check_pointer_sizes (scr, width, height, instantiator);
1118 XCreatePixmapFromBitmapData (dpy, draw,
1119 (char *) bits, width, height,
1122 if (NILP (foreground))
1123 foreground = pointer_fg;
1124 if (NILP (background))
1125 background = pointer_bg;
1126 generate_cursor_fg_bg (device, &foreground, &background,
1127 &fg_color, &bg_color);
1129 IMAGE_INSTANCE_PIXMAP_FG (ii) = foreground;
1130 IMAGE_INSTANCE_PIXMAP_BG (ii) = background;
1131 IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii) =
1132 find_keyword_in_vector (instantiator, Q_hotspot_x);
1133 IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii) =
1134 find_keyword_in_vector (instantiator, Q_hotspot_y);
1135 IMAGE_INSTANCE_X_CURSOR (ii) =
1137 (dpy, source, mask, &fg_color, &bg_color,
1138 !NILP (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii)) ?
1139 XINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii)) : 0,
1140 !NILP (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii)) ?
1141 XINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii)) : 0);
1151 xbm_instantiate_1 (Lisp_Object image_instance, Lisp_Object instantiator,
1152 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1153 int dest_mask, int width, int height,
1154 /* Note that data is in ext-format! */
1157 Lisp_Object mask_data = find_keyword_in_vector (instantiator, Q_mask_data);
1158 Lisp_Object mask_file = find_keyword_in_vector (instantiator, Q_mask_file);
1159 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1162 if (!NILP (mask_data))
1164 const char *ext_data;
1166 TO_EXTERNAL_FORMAT (LISP_STRING, XCAR (XCDR (XCDR (mask_data))),
1167 C_STRING_ALLOCA, ext_data,
1169 mask = pixmap_from_xbm_inline (IMAGE_INSTANCE_DEVICE (ii),
1170 XINT (XCAR (mask_data)),
1171 XINT (XCAR (XCDR (mask_data))),
1172 (const unsigned char *) ext_data);
1175 init_image_instance_from_xbm_inline (ii, width, height, bits,
1176 instantiator, pointer_fg, pointer_bg,
1177 dest_mask, mask, mask_file);
1180 /* Instantiate method for XBM's. */
1183 x_xbm_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1184 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1185 int dest_mask, Lisp_Object domain)
1187 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1188 const char *ext_data;
1190 assert (!NILP (data));
1192 TO_EXTERNAL_FORMAT (LISP_STRING, XCAR (XCDR (XCDR (data))),
1193 C_STRING_ALLOCA, ext_data,
1196 xbm_instantiate_1 (image_instance, instantiator, pointer_fg,
1197 pointer_bg, dest_mask, XINT (XCAR (data)),
1198 XINT (XCAR (XCDR (data))), ext_data);
1204 /**********************************************************************
1206 **********************************************************************/
1207 /* xpm 3.2g and better has XpmCreatePixmapFromBuffer()...
1208 There was no version number in xpm.h before 3.3, but this should do.
1210 #if (XpmVersion >= 3) || defined(XpmExactColors)
1211 # define XPM_DOES_BUFFERS
1214 #ifndef XPM_DOES_BUFFERS
1215 Your version of XPM is too old. You cannot compile with it.
1216 Upgrade to version 3.2g or better or compile with --with-xpm=no.
1217 #endif /* !XPM_DOES_BUFFERS */
1219 static XpmColorSymbol *
1220 extract_xpm_color_names (XpmAttributes *xpmattrs, Lisp_Object device,
1222 Lisp_Object color_symbol_alist)
1224 /* This function can GC */
1225 Display *dpy = DEVICE_X_DISPLAY (XDEVICE(device));
1226 Colormap cmap = DEVICE_X_COLORMAP (XDEVICE(device));
1229 Lisp_Object results = Qnil;
1231 XpmColorSymbol *symbols;
1232 struct gcpro gcpro1, gcpro2;
1234 GCPRO2 (results, device);
1236 /* We built up results to be (("name" . #<color>) ...) so that if an
1237 error happens we don't lose any malloc()ed data, or more importantly,
1238 leave any pixels allocated in the server. */
1240 LIST_LOOP (rest, color_symbol_alist)
1242 Lisp_Object cons = XCAR (rest);
1243 Lisp_Object name = XCAR (cons);
1244 Lisp_Object value = XCDR (cons);
1247 if (STRINGP (value))
1249 Fmake_color_instance
1250 (value, device, encode_error_behavior_flag (ERROR_ME_NOT));
1253 assert (COLOR_SPECIFIERP (value));
1254 value = Fspecifier_instance (value, domain, Qnil, Qnil);
1258 results = noseeum_cons (noseeum_cons (name, value), results);
1261 UNGCPRO; /* no more evaluation */
1263 if (i == 0) return 0;
1265 symbols = xnew_array (XpmColorSymbol, i);
1266 xpmattrs->valuemask |= XpmColorSymbols;
1267 xpmattrs->colorsymbols = symbols;
1268 xpmattrs->numsymbols = i;
1272 Lisp_Object cons = XCAR (results);
1273 color = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (XCDR (cons)));
1274 /* Duplicate the pixel value so that we still have a lock on it if
1275 the pixel we were passed is later freed. */
1276 if (! XAllocColor (dpy, cmap, &color))
1277 abort (); /* it must be allocable since we're just duplicating it */
1279 symbols [i].name = (char *) XSTRING_DATA (XCAR (cons));
1280 symbols [i].pixel = color.pixel;
1281 symbols [i].value = 0;
1282 free_cons (XCONS (cons));
1284 results = XCDR (results);
1285 free_cons (XCONS (cons));
1291 xpm_free (XpmAttributes *xpmattrs)
1293 /* Could conceivably lose if XpmXXX returned an error without first
1294 initializing this structure, if we didn't know that initializing it
1295 to all zeros was ok (and also that it's ok to call XpmFreeAttributes()
1296 multiple times, since it zeros slots as it frees them...) */
1297 XpmFreeAttributes (xpmattrs);
1301 x_xpm_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1302 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1303 int dest_mask, Lisp_Object domain)
1305 /* This function can GC */
1306 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1307 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
1308 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1316 XpmAttributes xpmattrs;
1318 XpmColorSymbol *color_symbols;
1319 Lisp_Object color_symbol_alist = find_keyword_in_vector (instantiator,
1321 enum image_instance_type type;
1325 if (!DEVICE_X_P (XDEVICE (device)))
1326 signal_simple_error ("Not an X device", device);
1328 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
1329 xs = DefaultScreenOfDisplay (dpy);
1331 if (dest_mask & IMAGE_COLOR_PIXMAP_MASK)
1332 type = IMAGE_COLOR_PIXMAP;
1333 else if (dest_mask & IMAGE_MONO_PIXMAP_MASK)
1334 type = IMAGE_MONO_PIXMAP;
1335 else if (dest_mask & IMAGE_POINTER_MASK)
1336 type = IMAGE_POINTER;
1338 incompatible_image_types (instantiator, dest_mask,
1339 IMAGE_MONO_PIXMAP_MASK | IMAGE_COLOR_PIXMAP_MASK
1340 | IMAGE_POINTER_MASK);
1341 force_mono = (type != IMAGE_COLOR_PIXMAP);
1344 /* Although I haven't found it documented yet, it appears that pointers are
1345 always colored via the default window colormap... Sigh. */
1346 if (type == IMAGE_POINTER)
1348 cmap = DefaultColormap(dpy, DefaultScreen(dpy));
1349 depth = DefaultDepthOfScreen (xs);
1350 visual = DefaultVisualOfScreen (xs);
1354 cmap = DEVICE_X_COLORMAP (XDEVICE(device));
1355 depth = DEVICE_X_DEPTH (XDEVICE(device));
1356 visual = DEVICE_X_VISUAL (XDEVICE(device));
1359 cmap = DEVICE_X_COLORMAP (XDEVICE(device));
1360 depth = DEVICE_X_DEPTH (XDEVICE(device));
1361 visual = DEVICE_X_VISUAL (XDEVICE(device));
1364 x_initialize_pixmap_image_instance (ii, 1, type);
1366 assert (!NILP (data));
1370 xzero (xpmattrs); /* want XpmInitAttributes() */
1371 xpmattrs.valuemask = XpmReturnPixels;
1374 /* Without this, we get a 1-bit version of the color image, which
1375 isn't quite right. With this, we get the mono image, which might
1376 be very different looking. */
1377 xpmattrs.valuemask |= XpmColorKey;
1378 xpmattrs.color_key = XPM_MONO;
1380 xpmattrs.valuemask |= XpmDepth;
1384 xpmattrs.closeness = 65535;
1385 xpmattrs.valuemask |= XpmCloseness;
1386 xpmattrs.depth = depth;
1387 xpmattrs.valuemask |= XpmDepth;
1388 xpmattrs.visual = visual;
1389 xpmattrs.valuemask |= XpmVisual;
1390 xpmattrs.colormap = cmap;
1391 xpmattrs.valuemask |= XpmColormap;
1394 color_symbols = extract_xpm_color_names (&xpmattrs, device, domain,
1395 color_symbol_alist);
1397 result = XpmCreatePixmapFromBuffer (dpy,
1398 XtWindow(DEVICE_XT_APP_SHELL (XDEVICE(device))),
1399 (char *) XSTRING_DATA (data),
1400 &pixmap, &mask, &xpmattrs);
1404 xfree (color_symbols);
1405 xpmattrs.colorsymbols = 0; /* in case XpmFreeAttr is too smart... */
1406 xpmattrs.numsymbols = 0;
1413 case XpmFileInvalid:
1415 xpm_free (&xpmattrs);
1416 signal_image_error ("invalid XPM data", data);
1418 case XpmColorFailed:
1421 xpm_free (&xpmattrs);
1424 /* second time; blow out. */
1425 signal_double_file_error ("Reading pixmap data",
1426 "color allocation failed",
1431 if (! (dest_mask & IMAGE_MONO_PIXMAP_MASK))
1433 /* second time; blow out. */
1434 signal_double_file_error ("Reading pixmap data",
1435 "color allocation failed",
1439 IMAGE_INSTANCE_TYPE (ii) = IMAGE_MONO_PIXMAP;
1445 xpm_free (&xpmattrs);
1446 signal_double_file_error ("Parsing pixmap data",
1447 "out of memory", data);
1451 xpm_free (&xpmattrs);
1452 signal_double_file_error_2 ("Parsing pixmap data",
1453 "unknown error code",
1454 make_int (result), data);
1459 h = xpmattrs.height;
1462 int npixels = xpmattrs.npixels;
1467 pixels = xnew_array (Pixel, npixels);
1468 memcpy (pixels, xpmattrs.pixels, npixels * sizeof (Pixel));
1473 IMAGE_INSTANCE_X_PIXMAP (ii) = pixmap;
1474 IMAGE_INSTANCE_PIXMAP_MASK (ii) = (void*)mask;
1475 IMAGE_INSTANCE_X_COLORMAP (ii) = cmap;
1476 IMAGE_INSTANCE_X_PIXELS (ii) = pixels;
1477 IMAGE_INSTANCE_X_NPIXELS (ii) = npixels;
1478 IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = w;
1479 IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = h;
1480 IMAGE_INSTANCE_PIXMAP_FILENAME (ii) =
1481 find_keyword_in_vector (instantiator, Q_file);
1486 case IMAGE_MONO_PIXMAP:
1489 case IMAGE_COLOR_PIXMAP:
1491 IMAGE_INSTANCE_PIXMAP_DEPTH (ii) = depth;
1497 int npixels = xpmattrs.npixels;
1498 Pixel *pixels = xpmattrs.pixels;
1501 int xhot = 0, yhot = 0;
1503 if (xpmattrs.valuemask & XpmHotspot)
1505 xhot = xpmattrs.x_hotspot;
1506 XSETINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii), xpmattrs.x_hotspot);
1508 if (xpmattrs.valuemask & XpmHotspot)
1510 yhot = xpmattrs.y_hotspot;
1511 XSETINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii), xpmattrs.y_hotspot);
1513 check_pointer_sizes (xs, w, h, instantiator);
1515 /* If the loaded pixmap has colors allocated (meaning it came from an
1516 XPM file), then use those as the default colors for the cursor we
1517 create. Otherwise, default to pointer_fg and pointer_bg.
1521 /* With an XBM file, it's obvious which bit is foreground
1522 and which is background, or rather, it's implicit: in
1523 an XBM file, a 1 bit is foreground, and a 0 bit is
1526 XCreatePixmapCursor() assumes this property of the
1527 pixmap it is called with as well; the `foreground'
1528 color argument is used for the 1 bits.
1530 With an XPM file, it's tricker, since the elements of
1531 the pixmap don't represent FG and BG, but are actual
1532 pixel values. So we need to figure out which of those
1533 pixels is the foreground color and which is the
1534 background. We do it by comparing RGB and assuming
1535 that the darker color is the foreground. This works
1536 with the result of xbmtopbm|ppmtoxpm, at least.
1538 It might be nice if there was some way to tag the
1539 colors in the XPM file with whether they are the
1540 foreground - perhaps with logical color names somehow?
1542 Once we have decided which color is the foreground, we
1543 need to ensure that that color corresponds to a `1' bit
1544 in the Pixmap. The XPM library wrote into the (1-bit)
1545 pixmap with XPutPixel, which will ignore all but the
1546 least significant bit.
1548 This means that a 1 bit in the image corresponds to
1549 `fg' only if `fg.pixel' is odd.
1551 (This also means that the image will be all the same
1552 color if both `fg' and `bg' are odd or even, but we can
1553 safely assume that that won't happen if the XPM file is
1556 The desired result is that the image use `1' to
1557 represent the foreground color, and `0' to represent
1558 the background color. So, we may need to invert the
1559 image to accomplish this; we invert if fg is
1560 odd. (Remember that WhitePixel and BlackPixel are not
1561 necessarily 1 and 0 respectively, though I think it
1562 might be safe to assume that one of them is always 1
1563 and the other is always 0. We also pretty much need to
1564 assume that one is even and the other is odd.)
1567 fg.pixel = pixels[0]; /* pick a pixel at random. */
1568 bg.pixel = fg.pixel;
1569 for (i = 1; i < npixels; i++) /* Look for an "other" pixel value.*/
1571 bg.pixel = pixels[i];
1572 if (fg.pixel != bg.pixel)
1576 /* If (fg.pixel == bg.pixel) then probably something has
1577 gone wrong, but I don't think signalling an error would
1580 XQueryColor (dpy, cmap, &fg);
1581 XQueryColor (dpy, cmap, &bg);
1583 /* If the foreground is lighter than the background, swap them.
1584 (This occurs semi-randomly, depending on the ordering of the
1585 color list in the XPM file.)
1588 unsigned short fg_total = ((fg.red / 3) + (fg.green / 3)
1590 unsigned short bg_total = ((bg.red / 3) + (bg.green / 3)
1592 if (fg_total > bg_total)
1601 /* If the fg pixel corresponds to a `0' in the bitmap, invert it.
1602 (This occurs (only?) on servers with Black=0, White=1.)
1604 if ((fg.pixel & 1) == 0)
1608 gcv.function = GXxor;
1610 gc = XCreateGC (dpy, pixmap, (GCFunction | GCForeground),
1612 XFillRectangle (dpy, pixmap, gc, 0, 0, w, h);
1618 generate_cursor_fg_bg (device, &pointer_fg, &pointer_bg,
1620 IMAGE_INSTANCE_PIXMAP_FG (ii) = pointer_fg;
1621 IMAGE_INSTANCE_PIXMAP_BG (ii) = pointer_bg;
1624 IMAGE_INSTANCE_X_CURSOR (ii) =
1626 (dpy, pixmap, mask, &fg, &bg, xhot, yhot);
1635 xpm_free (&xpmattrs); /* after we've read pixels and hotspot */
1638 #endif /* HAVE_XPM */
1643 /**********************************************************************
1645 **********************************************************************/
1647 /* This is about to get redefined! */
1650 /* We have to define SYSV32 so that compface.h includes string.h
1651 instead of strings.h. */
1656 #include <compface.h>
1660 /* JMP_BUF cannot be used here because if it doesn't get defined
1661 to jmp_buf we end up with a conflicting type error with the
1662 definition in compface.h */
1663 extern jmp_buf comp_env;
1667 x_xface_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1668 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1669 int dest_mask, Lisp_Object domain)
1671 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1673 char *p, *bits, *bp;
1674 const char * volatile emsg = 0;
1675 const char * volatile dstring;
1677 assert (!NILP (data));
1679 TO_EXTERNAL_FORMAT (LISP_STRING, data,
1680 C_STRING_ALLOCA, dstring,
1683 if ((p = strchr (dstring, ':')))
1688 /* Must use setjmp not SETJMP because we used jmp_buf above not JMP_BUF */
1689 if (!(stattis = setjmp (comp_env)))
1691 UnCompAll ((char *) dstring);
1698 emsg = "uncompface: internal error";
1701 emsg = "uncompface: insufficient or invalid data";
1704 emsg = "uncompface: excess data ignored";
1709 signal_simple_error_2 (emsg, data, Qimage);
1711 bp = bits = (char *) alloca (PIXELS / 8);
1713 /* the compface library exports char F[], which uses a single byte per
1714 pixel to represent a 48x48 bitmap. Yuck. */
1715 for (i = 0, p = F; i < (PIXELS / 8); ++i)
1718 /* reverse the bit order of each byte... */
1719 for (b = n = 0; b < 8; ++b)
1726 xbm_instantiate_1 (image_instance, instantiator, pointer_fg,
1727 pointer_bg, dest_mask, 48, 48, bits);
1730 #endif /* HAVE_XFACE */
1733 /**********************************************************************
1735 **********************************************************************/
1738 autodetect_validate (Lisp_Object instantiator)
1740 data_must_be_present (instantiator);
1744 autodetect_normalize (Lisp_Object instantiator,
1745 Lisp_Object console_type)
1747 Lisp_Object file = find_keyword_in_vector (instantiator, Q_data);
1748 Lisp_Object filename = Qnil;
1749 Lisp_Object data = Qnil;
1750 struct gcpro gcpro1, gcpro2, gcpro3;
1751 Lisp_Object alist = Qnil;
1753 GCPRO3 (filename, data, alist);
1755 if (NILP (file)) /* no conversion necessary */
1756 RETURN_UNGCPRO (instantiator);
1758 alist = tagged_vector_to_alist (instantiator);
1760 filename = locate_pixmap_file (file);
1761 if (!NILP (filename))
1764 /* #### Apparently some versions of XpmReadFileToData, which is
1765 called by pixmap_to_lisp_data, don't return an error value
1766 if the given file is not a valid XPM file. Instead, they
1767 just seg fault. It is definitely caused by passing a
1768 bitmap. To try and avoid this we check for bitmaps first. */
1770 data = bitmap_to_lisp_data (filename, &xhot, &yhot, 1);
1774 alist = remassq_no_quit (Q_data, alist);
1775 alist = Fcons (Fcons (Q_file, filename),
1776 Fcons (Fcons (Q_data, data), alist));
1778 alist = Fcons (Fcons (Q_hotspot_x, make_int (xhot)),
1781 alist = Fcons (Fcons (Q_hotspot_y, make_int (yhot)),
1784 alist = xbm_mask_file_munging (alist, filename, Qnil, console_type);
1787 Lisp_Object result = alist_to_tagged_vector (Qxbm, alist);
1789 RETURN_UNGCPRO (result);
1794 data = pixmap_to_lisp_data (filename, 1);
1798 alist = remassq_no_quit (Q_data, alist);
1799 alist = Fcons (Fcons (Q_file, filename),
1800 Fcons (Fcons (Q_data, data), alist));
1801 alist = Fcons (Fcons (Q_color_symbols,
1802 evaluate_xpm_color_symbols ()),
1805 Lisp_Object result = alist_to_tagged_vector (Qxpm, alist);
1807 RETURN_UNGCPRO (result);
1813 /* If we couldn't convert it, just put it back as it is.
1814 We might try to further frob it later as a cursor-font
1815 specification. (We can't do that now because we don't know
1816 what dest-types it's going to be instantiated into.) */
1818 Lisp_Object result = alist_to_tagged_vector (Qautodetect, alist);
1820 RETURN_UNGCPRO (result);
1825 autodetect_possible_dest_types (void)
1828 IMAGE_MONO_PIXMAP_MASK |
1829 IMAGE_COLOR_PIXMAP_MASK |
1830 IMAGE_POINTER_MASK |
1835 autodetect_instantiate (Lisp_Object image_instance,
1836 Lisp_Object instantiator,
1837 Lisp_Object pointer_fg,
1838 Lisp_Object pointer_bg,
1839 int dest_mask, Lisp_Object domain)
1841 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1842 struct gcpro gcpro1, gcpro2, gcpro3;
1843 Lisp_Object alist = Qnil;
1844 Lisp_Object result = Qnil;
1845 int is_cursor_font = 0;
1847 GCPRO3 (data, alist, result);
1849 alist = tagged_vector_to_alist (instantiator);
1850 if (dest_mask & IMAGE_POINTER_MASK)
1852 const char *name_ext;
1853 TO_EXTERNAL_FORMAT (LISP_STRING, data,
1854 C_STRING_ALLOCA, name_ext,
1856 if (XmuCursorNameToIndex (name_ext) != -1)
1858 result = alist_to_tagged_vector (Qcursor_font, alist);
1863 if (!is_cursor_font)
1864 result = alist_to_tagged_vector (Qstring, alist);
1868 cursor_font_instantiate (image_instance, result, pointer_fg,
1869 pointer_bg, dest_mask, domain);
1871 string_instantiate (image_instance, result, pointer_fg,
1872 pointer_bg, dest_mask, domain);
1878 /**********************************************************************
1880 **********************************************************************/
1883 font_validate (Lisp_Object instantiator)
1885 data_must_be_present (instantiator);
1888 /* XmuCvtStringToCursor is bogus in the following ways:
1890 - When it can't convert the given string to a real cursor, it will
1891 sometimes return a "success" value, after triggering a BadPixmap
1892 error. It then gives you a cursor that will itself generate BadCursor
1893 errors. So we install this error handler to catch/notice the X error
1894 and take that as meaning "couldn't convert."
1896 - When you tell it to find a cursor file that doesn't exist, it prints
1897 an error message on stderr. You can't make it not do that.
1899 - Also, using Xmu means we can't properly hack Lisp_Image_Instance
1900 objects, or XPM files, or $XBMLANGPATH.
1903 /* Duplicate the behavior of XmuCvtStringToCursor() to bypass its bogusness. */
1905 static int XLoadFont_got_error;
1908 XLoadFont_error_handler (Display *dpy, XErrorEvent *xerror)
1910 XLoadFont_got_error = 1;
1915 safe_XLoadFont (Display *dpy, char *name)
1918 int (*old_handler) (Display *, XErrorEvent *);
1919 XLoadFont_got_error = 0;
1921 old_handler = XSetErrorHandler (XLoadFont_error_handler);
1922 font = XLoadFont (dpy, name);
1924 XSetErrorHandler (old_handler);
1925 if (XLoadFont_got_error) return 0;
1930 font_possible_dest_types (void)
1932 return IMAGE_POINTER_MASK;
1936 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 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1943 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
1947 char source_name[MAXPATHLEN], mask_name[MAXPATHLEN], dummy;
1948 int source_char, mask_char;
1950 Lisp_Object foreground, background;
1952 if (!DEVICE_X_P (XDEVICE (device)))
1953 signal_simple_error ("Not an X device", device);
1955 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
1957 if (!STRINGP (data) ||
1958 strncmp ("FONT ", (char *) XSTRING_DATA (data), 5))
1959 signal_simple_error ("Invalid font-glyph instantiator",
1962 if (!(dest_mask & IMAGE_POINTER_MASK))
1963 incompatible_image_types (instantiator, dest_mask, IMAGE_POINTER_MASK);
1965 foreground = find_keyword_in_vector (instantiator, Q_foreground);
1966 if (NILP (foreground))
1967 foreground = pointer_fg;
1968 background = find_keyword_in_vector (instantiator, Q_background);
1969 if (NILP (background))
1970 background = pointer_bg;
1972 generate_cursor_fg_bg (device, &foreground, &background, &fg, &bg);
1974 count = sscanf ((char *) XSTRING_DATA (data),
1975 "FONT %s %d %s %d %c",
1976 source_name, &source_char,
1977 mask_name, &mask_char, &dummy);
1978 /* Allow "%s %d %d" as well... */
1979 if (count == 3 && (1 == sscanf (mask_name, "%d %c", &mask_char, &dummy)))
1980 count = 4, mask_name[0] = 0;
1982 if (count != 2 && count != 4)
1983 signal_simple_error ("invalid cursor specification", data);
1984 source = safe_XLoadFont (dpy, source_name);
1986 signal_simple_error_2 ("couldn't load font",
1987 build_string (source_name),
1991 else if (!mask_name[0])
1995 mask = safe_XLoadFont (dpy, mask_name);
1998 Fsignal (Qerror, list3 (build_string ("couldn't load font"),
1999 build_string (mask_name), data));
2004 /* #### call XQueryTextExtents() and check_pointer_sizes() here. */
2006 x_initialize_pixmap_image_instance (ii, 1, IMAGE_POINTER);
2007 IMAGE_INSTANCE_X_CURSOR (ii) =
2008 XCreateGlyphCursor (dpy, source, mask, source_char, mask_char,
2010 XIMAGE_INSTANCE_PIXMAP_FG (image_instance) = foreground;
2011 XIMAGE_INSTANCE_PIXMAP_BG (image_instance) = background;
2012 XUnloadFont (dpy, source);
2013 if (mask && mask != source) XUnloadFont (dpy, mask);
2017 /**********************************************************************
2019 **********************************************************************/
2022 cursor_font_validate (Lisp_Object instantiator)
2024 data_must_be_present (instantiator);
2028 cursor_font_possible_dest_types (void)
2030 return IMAGE_POINTER_MASK;
2034 cursor_font_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2035 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2036 int dest_mask, Lisp_Object domain)
2038 /* This function can GC */
2039 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
2040 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2041 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
2044 const char *name_ext;
2045 Lisp_Object foreground, background;
2047 if (!DEVICE_X_P (XDEVICE (device)))
2048 signal_simple_error ("Not an X device", device);
2050 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
2052 if (!(dest_mask & IMAGE_POINTER_MASK))
2053 incompatible_image_types (instantiator, dest_mask, IMAGE_POINTER_MASK);
2055 TO_EXTERNAL_FORMAT (LISP_STRING, data,
2056 C_STRING_ALLOCA, name_ext,
2058 if ((i = XmuCursorNameToIndex (name_ext)) == -1)
2059 signal_simple_error ("Unrecognized cursor-font name", data);
2061 x_initialize_pixmap_image_instance (ii, 1, IMAGE_POINTER);
2062 IMAGE_INSTANCE_X_CURSOR (ii) = XCreateFontCursor (dpy, i);
2063 foreground = find_keyword_in_vector (instantiator, Q_foreground);
2064 if (NILP (foreground))
2065 foreground = pointer_fg;
2066 background = find_keyword_in_vector (instantiator, Q_background);
2067 if (NILP (background))
2068 background = pointer_bg;
2069 maybe_recolor_cursor (image_instance, foreground, background);
2073 x_colorize_image_instance (Lisp_Object image_instance,
2074 Lisp_Object foreground, Lisp_Object background)
2076 Lisp_Image_Instance *p;
2078 p = XIMAGE_INSTANCE (image_instance);
2080 switch (IMAGE_INSTANCE_TYPE (p))
2082 case IMAGE_MONO_PIXMAP:
2083 IMAGE_INSTANCE_TYPE (p) = IMAGE_COLOR_PIXMAP;
2084 /* Make sure there aren't two pointers to the same mask, causing
2085 it to get freed twice. */
2086 IMAGE_INSTANCE_PIXMAP_MASK (p) = 0;
2094 Display *dpy = DEVICE_X_DISPLAY (XDEVICE (IMAGE_INSTANCE_DEVICE (p)));
2095 Drawable draw = XtWindow(DEVICE_XT_APP_SHELL (XDEVICE (IMAGE_INSTANCE_DEVICE (p))));
2096 Dimension d = DEVICE_X_DEPTH (XDEVICE (IMAGE_INSTANCE_DEVICE (p)));
2097 Pixmap new = XCreatePixmap (dpy, draw,
2098 IMAGE_INSTANCE_PIXMAP_WIDTH (p),
2099 IMAGE_INSTANCE_PIXMAP_HEIGHT (p), d);
2103 color = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (foreground));
2104 gcv.foreground = color.pixel;
2105 color = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (background));
2106 gcv.background = color.pixel;
2107 gc = XCreateGC (dpy, new, GCBackground|GCForeground, &gcv);
2108 XCopyPlane (dpy, IMAGE_INSTANCE_X_PIXMAP (p), new, gc, 0, 0,
2109 IMAGE_INSTANCE_PIXMAP_WIDTH (p),
2110 IMAGE_INSTANCE_PIXMAP_HEIGHT (p),
2113 IMAGE_INSTANCE_X_PIXMAP (p) = new;
2114 IMAGE_INSTANCE_PIXMAP_DEPTH (p) = d;
2115 IMAGE_INSTANCE_PIXMAP_FG (p) = foreground;
2116 IMAGE_INSTANCE_PIXMAP_BG (p) = background;
2122 /************************************************************************/
2123 /* subwindow and widget support */
2124 /************************************************************************/
2126 /* unmap the image if it is a widget. This is used by redisplay via
2127 redisplay_unmap_subwindows */
2129 x_unmap_subwindow (Lisp_Image_Instance *p)
2131 if (IMAGE_INSTANCE_TYPE (p) == IMAGE_SUBWINDOW)
2134 (IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY (p),
2135 IMAGE_INSTANCE_X_CLIPWINDOW (p));
2137 else /* must be a widget */
2139 XtUnmapWidget (IMAGE_INSTANCE_X_CLIPWIDGET (p));
2143 /* map the subwindow. This is used by redisplay via
2144 redisplay_output_subwindow */
2146 x_map_subwindow (Lisp_Image_Instance *p, int x, int y,
2147 struct display_glyph_area* dga)
2149 if (IMAGE_INSTANCE_TYPE (p) == IMAGE_SUBWINDOW)
2151 Window subwindow = IMAGE_INSTANCE_X_SUBWINDOW_ID (p);
2152 XMoveResizeWindow (IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY (p),
2153 IMAGE_INSTANCE_X_CLIPWINDOW (p),
2154 x, y, dga->width, dga->height);
2155 XMoveWindow (IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY (p),
2156 subwindow, -dga->xoffset, -dga->yoffset);
2157 XMapWindow (IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY (p),
2158 IMAGE_INSTANCE_X_CLIPWINDOW (p));
2160 else /* must be a widget */
2162 XtConfigureWidget (IMAGE_INSTANCE_X_CLIPWIDGET (p),
2163 x + IMAGE_INSTANCE_X_WIDGET_XOFFSET (p),
2164 y + IMAGE_INSTANCE_X_WIDGET_YOFFSET (p),
2165 dga->width, dga->height, 0);
2166 XtMoveWidget (IMAGE_INSTANCE_X_WIDGET_ID (p),
2167 -dga->xoffset, -dga->yoffset);
2168 XtMapWidget (IMAGE_INSTANCE_X_CLIPWIDGET (p));
2172 /* when you click on a widget you may activate another widget this
2173 needs to be checked and all appropriate widgets updated */
2175 x_update_subwindow (Lisp_Image_Instance *p)
2177 /* Update the subwindow size if necessary. */
2178 if (IMAGE_INSTANCE_SIZE_CHANGED (p))
2180 XResizeWindow (IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY (p),
2181 IMAGE_INSTANCE_X_SUBWINDOW_ID (p),
2182 IMAGE_INSTANCE_WIDTH (p),
2183 IMAGE_INSTANCE_HEIGHT (p));
2187 /* Update all attributes that have changed. Lwlib actually does most
2190 x_update_widget (Lisp_Image_Instance *p)
2192 /* This function can GC if IN_REDISPLAY is false. */
2194 widget_value* wv = 0;
2196 /* First get the items if they have changed since this is a
2197 structural change. As such it will nuke all added values so we
2198 need to update most other things after the items have changed.*/
2199 if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (p))
2201 Lisp_Object image_instance;
2203 XSETIMAGE_INSTANCE (image_instance, p);
2204 wv = gui_items_to_widget_values
2205 (image_instance, IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (p));
2206 wv->change = STRUCTURAL_CHANGE;
2207 /* now modify the widget */
2208 lw_modify_all_widgets (IMAGE_INSTANCE_X_WIDGET_LWID (p),
2210 free_widget_value_tree (wv);
2213 /* Now do non structural updates. */
2214 wv = lw_get_all_values (IMAGE_INSTANCE_X_WIDGET_LWID (p));
2219 /* Possibly update the colors and font */
2220 if (IMAGE_INSTANCE_WIDGET_FACE_CHANGED (p)
2222 XFRAME (IMAGE_INSTANCE_FRAME (p))->faces_changed
2224 IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (p))
2226 update_widget_face (wv, p, IMAGE_INSTANCE_FRAME (p));
2229 /* Possibly update the text. */
2230 if (IMAGE_INSTANCE_TEXT_CHANGED (p))
2233 Lisp_Object val = IMAGE_INSTANCE_WIDGET_TEXT (p);
2234 TO_EXTERNAL_FORMAT (LISP_STRING, val,
2235 C_STRING_ALLOCA, str,
2240 /* Possibly update the size. */
2241 if (IMAGE_INSTANCE_SIZE_CHANGED (p)
2243 IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (p)
2245 IMAGE_INSTANCE_TEXT_CHANGED (p))
2247 assert (IMAGE_INSTANCE_X_WIDGET_ID (p) &&
2248 IMAGE_INSTANCE_X_CLIPWIDGET (p)) ;
2250 if (IMAGE_INSTANCE_X_WIDGET_ID (p)->core.being_destroyed
2251 || !XtIsManaged(IMAGE_INSTANCE_X_WIDGET_ID (p)))
2254 XSETIMAGE_INSTANCE (sw, p);
2255 signal_simple_error ("XEmacs bug: subwindow is deleted", sw);
2258 lw_add_widget_value_arg (wv, XtNwidth,
2259 (Dimension)IMAGE_INSTANCE_WIDTH (p));
2260 lw_add_widget_value_arg (wv, XtNheight,
2261 (Dimension)IMAGE_INSTANCE_HEIGHT (p));
2264 /* now modify the widget */
2265 lw_modify_all_widgets (IMAGE_INSTANCE_X_WIDGET_LWID (p),
2270 /* instantiate and x type subwindow */
2272 x_subwindow_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2273 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2274 int dest_mask, Lisp_Object domain)
2276 /* This function can GC */
2277 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2278 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
2279 Lisp_Object frame = DOMAIN_FRAME (domain);
2280 struct frame* f = XFRAME (frame);
2284 XSetWindowAttributes xswa;
2286 unsigned int w = IMAGE_INSTANCE_WIDTH (ii),
2287 h = IMAGE_INSTANCE_HEIGHT (ii);
2289 if (!DEVICE_X_P (XDEVICE (device)))
2290 signal_simple_error ("Not an X device", device);
2292 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
2293 xs = DefaultScreenOfDisplay (dpy);
2295 IMAGE_INSTANCE_TYPE (ii) = IMAGE_SUBWINDOW;
2297 pw = XtWindow (FRAME_X_TEXT_WIDGET (f));
2299 ii->data = xnew_and_zero (struct x_subwindow_data);
2301 IMAGE_INSTANCE_X_SUBWINDOW_PARENT (ii) = pw;
2302 IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY (ii) = DisplayOfScreen (xs);
2304 xswa.backing_store = Always;
2305 valueMask |= CWBackingStore;
2306 xswa.colormap = DefaultColormapOfScreen (xs);
2307 valueMask |= CWColormap;
2309 /* Create a window for clipping */
2310 IMAGE_INSTANCE_X_CLIPWINDOW (ii) =
2311 XCreateWindow (dpy, pw, 0, 0, w, h, 0, CopyFromParent,
2312 InputOutput, CopyFromParent, valueMask,
2315 /* Now put the subwindow inside the clip window. */
2316 win = XCreateWindow (dpy, IMAGE_INSTANCE_X_CLIPWINDOW (ii),
2317 0, 0, w, h, 0, CopyFromParent,
2318 InputOutput, CopyFromParent, valueMask,
2321 IMAGE_INSTANCE_SUBWINDOW_ID (ii) = (void*)win;
2325 /* #### Should this function exist? If there's any doubt I'm not implementing it --andyp */
2326 DEFUN ("change-subwindow-property", Fchange_subwindow_property, 3, 3, 0, /*
2327 For the given SUBWINDOW, set PROPERTY to DATA, which is a string.
2328 Subwindows are not currently implemented.
2330 (subwindow, property, data))
2336 CHECK_SUBWINDOW (subwindow);
2337 CHECK_STRING (property);
2338 CHECK_STRING (data);
2340 sw = XSUBWINDOW (subwindow);
2341 dpy = DisplayOfScreen (LISP_DEVICE_TO_X_SCREEN
2342 (FRAME_DEVICE (XFRAME (sw->frame))));
2344 property_atom = XInternAtom (dpy, (char *) XSTRING_DATA (property), False);
2345 XChangeProperty (dpy, sw->subwindow, property_atom, XA_STRING, 8,
2347 XSTRING_DATA (data),
2348 XSTRING_LENGTH (data));
2357 /************************************************************************/
2359 /************************************************************************/
2362 update_widget_face (widget_value* wv, Lisp_Image_Instance *ii,
2365 #ifdef LWLIB_WIDGETS_MOTIF
2366 XmFontList fontList;
2368 /* Update the foreground. */
2369 Lisp_Object pixel = FACE_FOREGROUND
2370 (IMAGE_INSTANCE_WIDGET_FACE (ii),
2372 XColor fcolor = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (pixel)), bcolor;
2373 lw_add_widget_value_arg (wv, XtNforeground, fcolor.pixel);
2375 /* Update the background. */
2376 pixel = FACE_BACKGROUND (IMAGE_INSTANCE_WIDGET_FACE (ii),
2378 bcolor = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (pixel));
2379 lw_add_widget_value_arg (wv, XtNbackground, bcolor.pixel);
2381 #ifdef LWLIB_WIDGETS_MOTIF
2382 fontList = XmFontListCreate
2383 (FONT_INSTANCE_X_FONT
2384 (XFONT_INSTANCE (query_string_font
2385 (IMAGE_INSTANCE_WIDGET_TEXT (ii),
2386 IMAGE_INSTANCE_WIDGET_FACE (ii),
2387 domain))), XmSTRING_DEFAULT_CHARSET);
2388 lw_add_widget_value_arg (wv, XmNfontList, (XtArgVal)fontList);
2390 lw_add_widget_value_arg
2391 (wv, XtNfont, (XtArgVal)FONT_INSTANCE_X_FONT
2392 (XFONT_INSTANCE (query_string_font
2393 (IMAGE_INSTANCE_WIDGET_TEXT (ii),
2394 IMAGE_INSTANCE_WIDGET_FACE (ii),
2399 update_tab_widget_face (widget_value* wv, Lisp_Image_Instance *ii,
2404 widget_value* val = wv->contents, *cur;
2406 /* Give each child label the correct foreground color. */
2407 Lisp_Object pixel = FACE_FOREGROUND
2408 (IMAGE_INSTANCE_WIDGET_FACE (ii),
2410 XColor fcolor = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (pixel));
2411 lw_add_widget_value_arg (val, XtNtabForeground, fcolor.pixel);
2413 for (cur = val->next; cur; cur = cur->next)
2417 lw_copy_widget_value_args (val, cur);
2424 x_widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2425 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2426 int dest_mask, Lisp_Object domain,
2427 const char* type, widget_value* wv)
2429 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2430 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii), pixel;
2431 struct device* d = XDEVICE (device);
2432 Lisp_Object frame = DOMAIN_FRAME (domain);
2433 struct frame* f = XFRAME (frame);
2438 int id = new_lwlib_id ();
2439 widget_value* clip_wv;
2440 XColor fcolor, bcolor;
2442 if (!DEVICE_X_P (d))
2443 signal_simple_error ("Not an X device", device);
2445 /* have to set the type this late in case there is no device
2446 instantiation for a widget. But we can go ahead and do it without
2447 checking because there is always a generic instantiator. */
2448 IMAGE_INSTANCE_TYPE (ii) = IMAGE_WIDGET;
2450 if (!NILP (IMAGE_INSTANCE_WIDGET_TEXT (ii)))
2451 TO_EXTERNAL_FORMAT (LISP_STRING, IMAGE_INSTANCE_WIDGET_TEXT (ii),
2452 C_STRING_ALLOCA, nm,
2455 ii->data = xnew_and_zero (struct x_subwindow_data);
2457 /* Create a clip window to contain the subwidget. Incredibly the
2458 XEmacs manager seems to be the most appropriate widget for
2459 this. Nothing else is simple enough and yet does what is
2461 clip_wv = xmalloc_widget_value ();
2463 lw_add_widget_value_arg (clip_wv, XtNresize, False);
2464 lw_add_widget_value_arg (clip_wv, XtNwidth,
2465 (Dimension)IMAGE_INSTANCE_WIDTH (ii));
2466 lw_add_widget_value_arg (clip_wv, XtNheight,
2467 (Dimension)IMAGE_INSTANCE_HEIGHT (ii));
2468 clip_wv->enabled = True;
2470 clip_wv->name = xstrdup ("clip-window");
2471 clip_wv->value = xstrdup ("clip-window");
2473 IMAGE_INSTANCE_X_CLIPWIDGET (ii)
2474 = lw_create_widget ("clip-window", "clip-window", new_lwlib_id (),
2475 clip_wv, FRAME_X_CONTAINER_WIDGET (f),
2478 free_widget_value_tree (clip_wv);
2480 /* copy any args we were given */
2482 lw_add_value_args_to_args (wv, al, &ac);
2484 /* Fixup the colors. We have to do this *before* the widget gets
2485 created so that Motif will fix up the shadow colors
2486 correctly. Once the widget is created Motif won't do this
2488 pixel = FACE_FOREGROUND
2489 (IMAGE_INSTANCE_WIDGET_FACE (ii),
2490 IMAGE_INSTANCE_FRAME (ii));
2491 fcolor = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (pixel));
2493 pixel = FACE_BACKGROUND
2494 (IMAGE_INSTANCE_WIDGET_FACE (ii),
2495 IMAGE_INSTANCE_FRAME (ii));
2496 bcolor = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (pixel));
2498 lw_add_widget_value_arg (wv, XtNbackground, bcolor.pixel);
2499 lw_add_widget_value_arg (wv, XtNforeground, fcolor.pixel);
2500 /* we cannot allow widgets to resize themselves */
2501 lw_add_widget_value_arg (wv, XtNresize, False);
2502 lw_add_widget_value_arg (wv, XtNwidth,
2503 (Dimension)IMAGE_INSTANCE_WIDTH (ii));
2504 lw_add_widget_value_arg (wv, XtNheight,
2505 (Dimension)IMAGE_INSTANCE_HEIGHT (ii));
2506 /* update the font. */
2507 update_widget_face (wv, ii, domain);
2509 wid = lw_create_widget (type, wv->name, id, wv, IMAGE_INSTANCE_X_CLIPWIDGET (ii),
2510 False, 0, popup_selection_callback, 0);
2512 IMAGE_INSTANCE_SUBWINDOW_ID (ii) = (void*)wid;
2513 IMAGE_INSTANCE_X_WIDGET_LWID (ii) = id;
2514 /* because the EmacsManager is the widgets parent we have to
2515 offset the redisplay of the widget by the amount the text
2516 widget is inside the manager. */
2518 XtSetArg (al [ac], XtNx, &IMAGE_INSTANCE_X_WIDGET_XOFFSET (ii)); ac++;
2519 XtSetArg (al [ac], XtNy, &IMAGE_INSTANCE_X_WIDGET_YOFFSET (ii)); ac++;
2520 XtGetValues (FRAME_X_TEXT_WIDGET (f), al, ac);
2522 XtSetMappedWhenManaged (wid, TRUE);
2524 free_widget_value_tree (wv);
2525 /* A kludgy but simple way to make sure the callback for a widget
2526 doesn't get deleted. */
2527 gcpro_popup_callbacks (id);
2530 /* get properties of a control */
2532 x_widget_property (Lisp_Object image_instance, Lisp_Object prop)
2534 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2535 /* get the text from a control */
2536 if (EQ (prop, Q_text))
2538 widget_value* wv = lw_get_all_values (IMAGE_INSTANCE_X_WIDGET_LWID (ii));
2539 return build_ext_string (wv->value, Qnative);
2544 /* Instantiate a layout control for putting other widgets in. */
2546 x_native_layout_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2547 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2548 int dest_mask, Lisp_Object domain)
2550 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2552 x_widget_instantiate (image_instance, instantiator, pointer_fg,
2553 pointer_bg, dest_mask, domain, "layout", 0);
2556 /* Instantiate a button widget. Unfortunately instantiated widgets are
2557 particular to a frame since they need to have a parent. It's not
2558 like images where you just select the image into the context you
2559 want to display it in and BitBlt it. So images instances can have a
2560 many-to-one relationship with things you see, whereas widgets can
2561 only be one-to-one (i.e. per frame) */
2563 x_button_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2564 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2565 int dest_mask, Lisp_Object domain)
2567 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2568 Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM (ii);
2569 Lisp_Object glyph = find_keyword_in_vector (instantiator, Q_image);
2570 widget_value* wv = gui_items_to_widget_values (image_instance, gui);
2574 if (!IMAGE_INSTANCEP (glyph))
2575 glyph = glyph_image_instance (glyph, domain, ERROR_ME, 1);
2578 x_widget_instantiate (image_instance, instantiator, pointer_fg,
2579 pointer_bg, dest_mask, domain, "button", wv);
2581 /* add the image if one was given */
2582 if (!NILP (glyph) && IMAGE_INSTANCEP (glyph)
2583 && IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (glyph)))
2587 #ifdef LWLIB_WIDGETS_MOTIF
2588 XtSetArg (al [ac], XmNlabelType, XmPIXMAP); ac++;
2589 XtSetArg (al [ac], XmNlabelPixmap, XIMAGE_INSTANCE_X_PIXMAP (glyph));ac++;
2591 XtSetArg (al [ac], XtNpixmap, XIMAGE_INSTANCE_X_PIXMAP (glyph)); ac++;
2593 XtSetValues (IMAGE_INSTANCE_X_WIDGET_ID (ii), al, ac);
2597 /* Update a button's clicked state.
2599 #### This is overkill, but it works. Right now this causes all
2600 button instances to flash for some reason buried deep in lwlib. In
2601 theory this should be the Right Thing to do since lwlib should only
2602 merge in changed values - and if nothing has changed then nothing
2603 should get done. This may be because of the args stuff,
2604 i.e. although the arg contents may be the same the args look
2605 different and so are re-applied to the widget. */
2607 x_button_update (Lisp_Object image_instance)
2609 /* This function can GC if IN_REDISPLAY is false. */
2610 Lisp_Image_Instance *p = XIMAGE_INSTANCE (image_instance);
2612 gui_items_to_widget_values (image_instance,
2613 IMAGE_INSTANCE_WIDGET_ITEMS (p));
2615 /* now modify the widget */
2616 lw_modify_all_widgets (IMAGE_INSTANCE_X_WIDGET_LWID (p),
2618 free_widget_value_tree (wv);
2621 /* get properties of a button */
2623 x_button_property (Lisp_Object image_instance, Lisp_Object prop)
2625 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2626 /* check the state of a button */
2627 if (EQ (prop, Q_selected))
2629 widget_value* wv = lw_get_all_values (IMAGE_INSTANCE_X_WIDGET_LWID (ii));
2639 /* instantiate a progress gauge */
2641 x_progress_gauge_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2642 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2643 int dest_mask, Lisp_Object domain)
2645 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2646 Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM (ii);
2647 widget_value* wv = gui_items_to_widget_values (image_instance, gui);
2649 x_widget_instantiate (image_instance, instantiator, pointer_fg,
2650 pointer_bg, dest_mask, domain, "progress", wv);
2653 /* set the properties of a progres guage */
2655 x_progress_gauge_update (Lisp_Object image_instance)
2657 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2659 if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii))
2663 #ifdef ERROR_CHECK_GLYPHS
2664 assert (GUI_ITEMP (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii)));
2666 val = XGUI_ITEM (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii))->value;
2667 XtSetArg (al[0], XtNvalue, XINT (val));
2668 XtSetValues (IMAGE_INSTANCE_X_WIDGET_ID (ii), al, 1);
2672 /* instantiate an edit control */
2674 x_edit_field_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2675 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2676 int dest_mask, Lisp_Object domain)
2678 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2679 Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM (ii);
2680 widget_value* wv = gui_items_to_widget_values (image_instance, gui);
2682 x_widget_instantiate (image_instance, instantiator, pointer_fg,
2683 pointer_bg, dest_mask, domain, "text-field", wv);
2686 #if defined (LWLIB_WIDGETS_MOTIF) && XmVERSION > 1
2687 /* instantiate a combo control */
2689 x_combo_box_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2690 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2691 int dest_mask, Lisp_Object domain)
2693 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2694 widget_value * wv = 0;
2695 /* This is not done generically because of sizing problems under
2697 widget_instantiate (image_instance, instantiator, pointer_fg,
2698 pointer_bg, dest_mask, domain);
2700 wv = gui_items_to_widget_values (image_instance,
2701 IMAGE_INSTANCE_WIDGET_ITEMS (ii));
2703 x_widget_instantiate (image_instance, instantiator, pointer_fg,
2704 pointer_bg, dest_mask, domain, "combo-box", wv);
2709 x_tab_control_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2710 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2711 int dest_mask, Lisp_Object domain)
2713 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2715 gui_items_to_widget_values (image_instance,
2716 IMAGE_INSTANCE_WIDGET_ITEMS (ii));
2718 update_tab_widget_face (wv, ii,
2719 IMAGE_INSTANCE_FRAME (ii));
2721 x_widget_instantiate (image_instance, instantiator, pointer_fg,
2722 pointer_bg, dest_mask, domain, "tab-control", wv);
2725 /* set the properties of a tab control */
2727 x_tab_control_update (Lisp_Object image_instance)
2729 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2731 /* Possibly update the face. */
2732 if (IMAGE_INSTANCE_WIDGET_FACE_CHANGED (ii)
2734 XFRAME (IMAGE_INSTANCE_FRAME (ii))->faces_changed
2736 IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii))
2738 widget_value* wv = lw_get_all_values (IMAGE_INSTANCE_X_WIDGET_LWID (ii));
2740 /* #### I don't know why this can occur. */
2744 update_tab_widget_face (wv, ii,
2745 IMAGE_INSTANCE_FRAME (ii));
2747 lw_modify_all_widgets (IMAGE_INSTANCE_X_WIDGET_LWID (ii), wv, True);
2751 /* instantiate a static control possible for putting other things in */
2753 x_label_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2754 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2755 int dest_mask, Lisp_Object domain)
2757 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2758 Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM (ii);
2759 widget_value* wv = gui_items_to_widget_values (image_instance, gui);
2761 x_widget_instantiate (image_instance, instantiator, pointer_fg,
2762 pointer_bg, dest_mask, domain, "button", wv);
2764 #endif /* HAVE_WIDGETS */
2767 /************************************************************************/
2768 /* initialization */
2769 /************************************************************************/
2772 syms_of_glyphs_x (void)
2775 DEFSUBR (Fchange_subwindow_property);
2780 console_type_create_glyphs_x (void)
2784 CONSOLE_HAS_METHOD (x, print_image_instance);
2785 CONSOLE_HAS_METHOD (x, finalize_image_instance);
2786 CONSOLE_HAS_METHOD (x, image_instance_equal);
2787 CONSOLE_HAS_METHOD (x, image_instance_hash);
2788 CONSOLE_HAS_METHOD (x, colorize_image_instance);
2789 CONSOLE_HAS_METHOD (x, init_image_instance_from_eimage);
2790 CONSOLE_HAS_METHOD (x, locate_pixmap_file);
2791 CONSOLE_HAS_METHOD (x, unmap_subwindow);
2792 CONSOLE_HAS_METHOD (x, map_subwindow);
2793 CONSOLE_HAS_METHOD (x, update_widget);
2794 CONSOLE_HAS_METHOD (x, update_subwindow);
2798 image_instantiator_format_create_glyphs_x (void)
2800 IIFORMAT_VALID_CONSOLE (x, nothing);
2801 IIFORMAT_VALID_CONSOLE (x, string);
2803 IIFORMAT_VALID_CONSOLE (x, layout);
2805 IIFORMAT_VALID_CONSOLE (x, formatted_string);
2806 IIFORMAT_VALID_CONSOLE (x, inherit);
2808 INITIALIZE_DEVICE_IIFORMAT (x, xpm);
2809 IIFORMAT_HAS_DEVMETHOD (x, xpm, instantiate);
2812 IIFORMAT_VALID_CONSOLE (x, jpeg);
2815 IIFORMAT_VALID_CONSOLE (x, tiff);
2818 IIFORMAT_VALID_CONSOLE (x, png);
2821 IIFORMAT_VALID_CONSOLE (x, gif);
2823 INITIALIZE_DEVICE_IIFORMAT (x, xbm);
2824 IIFORMAT_HAS_DEVMETHOD (x, xbm, instantiate);
2826 INITIALIZE_DEVICE_IIFORMAT (x, subwindow);
2827 IIFORMAT_HAS_DEVMETHOD (x, subwindow, instantiate);
2830 INITIALIZE_DEVICE_IIFORMAT (x, native_layout);
2831 IIFORMAT_HAS_DEVMETHOD (x, native_layout, instantiate);
2833 INITIALIZE_DEVICE_IIFORMAT (x, button);
2834 IIFORMAT_HAS_DEVMETHOD (x, button, property);
2835 IIFORMAT_HAS_DEVMETHOD (x, button, instantiate);
2836 IIFORMAT_HAS_DEVMETHOD (x, button, update);
2837 /* general widget methods. */
2838 INITIALIZE_DEVICE_IIFORMAT (x, widget);
2839 IIFORMAT_HAS_DEVMETHOD (x, widget, property);
2840 /* progress gauge */
2841 INITIALIZE_DEVICE_IIFORMAT (x, progress_gauge);
2842 IIFORMAT_HAS_DEVMETHOD (x, progress_gauge, update);
2843 IIFORMAT_HAS_DEVMETHOD (x, progress_gauge, instantiate);
2845 INITIALIZE_DEVICE_IIFORMAT (x, edit_field);
2846 IIFORMAT_HAS_DEVMETHOD (x, edit_field, instantiate);
2847 #if defined (LWLIB_WIDGETS_MOTIF) && XmVERSION > 1
2849 INITIALIZE_DEVICE_IIFORMAT (x, combo_box);
2850 IIFORMAT_HAS_DEVMETHOD (x, combo_box, instantiate);
2851 IIFORMAT_HAS_SHARED_DEVMETHOD (x, combo_box, update, tab_control);
2853 /* tab control widget */
2854 INITIALIZE_DEVICE_IIFORMAT (x, tab_control);
2855 IIFORMAT_HAS_DEVMETHOD (x, tab_control, instantiate);
2856 IIFORMAT_HAS_DEVMETHOD (x, tab_control, update);
2858 INITIALIZE_DEVICE_IIFORMAT (x, label);
2859 IIFORMAT_HAS_DEVMETHOD (x, label, instantiate);
2861 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (cursor_font, "cursor-font");
2862 IIFORMAT_VALID_CONSOLE (x, cursor_font);
2864 IIFORMAT_HAS_METHOD (cursor_font, validate);
2865 IIFORMAT_HAS_METHOD (cursor_font, possible_dest_types);
2866 IIFORMAT_HAS_METHOD (cursor_font, instantiate);
2868 IIFORMAT_VALID_KEYWORD (cursor_font, Q_data, check_valid_string);
2869 IIFORMAT_VALID_KEYWORD (cursor_font, Q_foreground, check_valid_string);
2870 IIFORMAT_VALID_KEYWORD (cursor_font, Q_background, check_valid_string);
2872 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (font, "font");
2874 IIFORMAT_HAS_METHOD (font, validate);
2875 IIFORMAT_HAS_METHOD (font, possible_dest_types);
2876 IIFORMAT_HAS_METHOD (font, instantiate);
2877 IIFORMAT_VALID_CONSOLE (x, font);
2879 IIFORMAT_VALID_KEYWORD (font, Q_data, check_valid_string);
2880 IIFORMAT_VALID_KEYWORD (font, Q_foreground, check_valid_string);
2881 IIFORMAT_VALID_KEYWORD (font, Q_background, check_valid_string);
2884 INITIALIZE_DEVICE_IIFORMAT (x, xface);
2885 IIFORMAT_HAS_DEVMETHOD (x, xface, instantiate);
2888 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (autodetect,
2891 IIFORMAT_HAS_METHOD (autodetect, validate);
2892 IIFORMAT_HAS_METHOD (autodetect, normalize);
2893 IIFORMAT_HAS_METHOD (autodetect, possible_dest_types);
2894 IIFORMAT_HAS_METHOD (autodetect, instantiate);
2895 IIFORMAT_VALID_CONSOLE (x, autodetect);
2897 IIFORMAT_VALID_KEYWORD (autodetect, Q_data, check_valid_string);
2901 vars_of_glyphs_x (void)
2903 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path /*
2904 A list of the directories in which X bitmap files may be found.
2905 If nil, this is initialized from the "*bitmapFilePath" resource.
2906 This is used by the `make-image-instance' function (however, note that if
2907 the environment variable XBMLANGPATH is set, it is consulted first).
2909 Vx_bitmap_file_path = Qnil;
2913 complex_vars_of_glyphs_x (void)
2915 #define BUILD_GLYPH_INST(variable, name) \
2916 Fadd_spec_to_specifier \
2917 (GLYPH_IMAGE (XGLYPH (variable)), \
2918 vector3 (Qxbm, Q_data, \
2919 list3 (make_int (name##_width), \
2920 make_int (name##_height), \
2921 make_ext_string (name##_bits, \
2922 sizeof (name##_bits), \
2926 BUILD_GLYPH_INST (Vtruncation_glyph, truncator);
2927 BUILD_GLYPH_INST (Vcontinuation_glyph, continuer);
2928 BUILD_GLYPH_INST (Vxemacs_logo, xemacs);
2929 BUILD_GLYPH_INST (Vhscroll_glyph, hscroll);
2931 #undef BUILD_GLYPH_INST