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 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 for 21.0
46 Convert images.el to C and stick it in here?
52 #include "console-x.h"
54 #include "objects-x.h"
73 #include "file-coding.h"
76 #ifdef LWLIB_USES_MOTIF
79 #include <X11/IntrinsicP.h>
82 # define FOUR_BYTE_TYPE unsigned int
84 # define FOUR_BYTE_TYPE unsigned long
86 # define FOUR_BYTE_TYPE unsigned short
88 #error What kind of strange-ass system are we running on?
91 #define LISP_DEVICE_TO_X_SCREEN(dev) XDefaultScreenOfDisplay (DEVICE_X_DISPLAY (XDEVICE (dev)))
93 DECLARE_IMAGE_INSTANTIATOR_FORMAT (nothing);
94 DECLARE_IMAGE_INSTANTIATOR_FORMAT (string);
95 DECLARE_IMAGE_INSTANTIATOR_FORMAT (formatted_string);
96 DECLARE_IMAGE_INSTANTIATOR_FORMAT (inherit);
98 DECLARE_IMAGE_INSTANTIATOR_FORMAT (jpeg);
101 DECLARE_IMAGE_INSTANTIATOR_FORMAT (tiff);
104 DECLARE_IMAGE_INSTANTIATOR_FORMAT (png);
107 DECLARE_IMAGE_INSTANTIATOR_FORMAT (gif);
110 DEFINE_DEVICE_IIFORMAT (x, xpm);
112 DEFINE_DEVICE_IIFORMAT (x, xbm);
113 DEFINE_DEVICE_IIFORMAT (x, subwindow);
115 DEFINE_DEVICE_IIFORMAT (x, xface);
118 DEFINE_IMAGE_INSTANTIATOR_FORMAT (cursor_font);
119 Lisp_Object Qcursor_font;
121 DEFINE_IMAGE_INSTANTIATOR_FORMAT (font);
123 DEFINE_IMAGE_INSTANTIATOR_FORMAT (autodetect);
125 DEFINE_DEVICE_IIFORMAT (x, widget);
126 DEFINE_DEVICE_IIFORMAT (x, button);
127 DEFINE_DEVICE_IIFORMAT (x, progress_gauge);
128 DEFINE_DEVICE_IIFORMAT (x, edit_field);
129 DEFINE_DEVICE_IIFORMAT (x, combo_box);
131 static void cursor_font_instantiate (Lisp_Object image_instance,
132 Lisp_Object instantiator,
133 Lisp_Object pointer_fg,
134 Lisp_Object pointer_bg,
141 /************************************************************************/
142 /* image instance methods */
143 /************************************************************************/
145 /************************************************************************/
146 /* convert from a series of RGB triples to an XImage formated for the */
148 /************************************************************************/
150 convert_EImage_to_XImage (Lisp_Object device, int width, int height,
151 unsigned char *pic, unsigned long **pixtbl,
158 int depth, bitmap_pad, bits_per_pixel, byte_cnt, i, j;
160 unsigned char *data, *ip, *dp;
161 quant_table *qtable = 0;
167 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
168 cmap = DEVICE_X_COLORMAP (XDEVICE(device));
169 vis = DEVICE_X_VISUAL (XDEVICE(device));
170 depth = DEVICE_X_DEPTH(XDEVICE(device));
172 if (vis->class == PseudoColor)
174 /* Quantize the image and get a histogram while we're at it.
175 Do this first to save memory */
176 qtable = build_EImage_quantable(pic, width, height, 256);
177 if (qtable == NULL) return NULL;
180 bitmap_pad = ((depth > 16) ? 32 :
184 outimg = XCreateImage (dpy, vis,
185 depth, ZPixmap, 0, 0, width, height,
187 if (!outimg) return NULL;
189 bits_per_pixel = outimg->bits_per_pixel;
190 byte_cnt = bits_per_pixel >> 3;
192 data = (unsigned char *) xmalloc (outimg->bytes_per_line * height);
195 XDestroyImage (outimg);
198 outimg->data = (char *) data;
200 if (vis->class == PseudoColor)
202 unsigned long pixarray[256];
204 /* use our quantize table to allocate the colors */
206 *pixtbl = xnew_array (unsigned long, pixcount);
209 /* ### should implement a sort by popularity to assure proper allocation */
211 for (i = 0; i < qtable->num_active_colors; i++)
216 color.red = qtable->rm[i] ? qtable->rm[i] << 8 : 0;
217 color.green = qtable->gm[i] ? qtable->gm[i] << 8 : 0;
218 color.blue = qtable->bm[i] ? qtable->bm[i] << 8 : 0;
219 color.flags = DoRed | DoGreen | DoBlue;
220 res = allocate_nearest_color (dpy, cmap, vis, &color);
221 if (res > 0 && res < 3)
223 DO_REALLOC(*pixtbl, pixcount, n+1, unsigned long);
224 (*pixtbl)[n] = color.pixel;
227 pixarray[i] = color.pixel;
231 for (i = 0; i < height; i++)
233 dp = data + (i * outimg->bytes_per_line);
234 for (j = 0; j < width; j++)
239 conv.val = pixarray[QUANT_GET_COLOR(qtable,rd,gr,bl)];
241 if (outimg->byte_order == MSBFirst)
242 for (q = 4-byte_cnt; q < 4; q++) *dp++ = conv.cp[q];
244 for (q = 3; q >= 4-byte_cnt; q--) *dp++ = conv.cp[q];
246 if (outimg->byte_order == MSBFirst)
247 for (q = byte_cnt-1; q >= 0; q--) *dp++ = conv.cp[q];
249 for (q = 0; q < byte_cnt; q++) *dp++ = conv.cp[q];
255 unsigned long rshift,gshift,bshift,rbits,gbits,bbits,junk;
256 junk = vis->red_mask;
258 while ((junk & 0x1) == 0)
269 junk = vis->green_mask;
271 while ((junk & 0x1) == 0)
282 junk = vis->blue_mask;
284 while ((junk & 0x1) == 0)
296 for (i = 0; i < height; i++)
298 dp = data + (i * outimg->bytes_per_line);
299 for (j = 0; j < width; j++)
302 rd = *ip++ << (rbits - 8);
304 rd = *ip++ >> (8 - rbits);
306 gr = *ip++ << (gbits - 8);
308 gr = *ip++ >> (8 - gbits);
310 bl = *ip++ << (bbits - 8);
312 bl = *ip++ >> (8 - bbits);
314 conv.val = (rd << rshift) | (gr << gshift) | (bl << bshift);
316 if (outimg->byte_order == MSBFirst)
317 for (q = 4-byte_cnt; q < 4; q++) *dp++ = conv.cp[q];
319 for (q = 3; q >= 4-byte_cnt; q--) *dp++ = conv.cp[q];
321 if (outimg->byte_order == MSBFirst)
322 for (q = byte_cnt-1; q >= 0; q--) *dp++ = conv.cp[q];
324 for (q = 0; q < byte_cnt; q++) *dp++ = conv.cp[q];
335 x_print_image_instance (struct Lisp_Image_Instance *p,
336 Lisp_Object printcharfun,
341 switch (IMAGE_INSTANCE_TYPE (p))
343 case IMAGE_MONO_PIXMAP:
344 case IMAGE_COLOR_PIXMAP:
346 sprintf (buf, " (0x%lx", (unsigned long) IMAGE_INSTANCE_X_PIXMAP (p));
347 write_c_string (buf, printcharfun);
348 if (IMAGE_INSTANCE_X_MASK (p))
350 sprintf (buf, "/0x%lx", (unsigned long) IMAGE_INSTANCE_X_MASK (p));
351 write_c_string (buf, printcharfun);
353 write_c_string (")", printcharfun);
361 x_finalize_image_instance (struct Lisp_Image_Instance *p)
366 if (DEVICE_LIVE_P (XDEVICE (p->device)))
368 Display *dpy = DEVICE_X_DISPLAY (XDEVICE (p->device));
370 if (IMAGE_INSTANCE_TYPE (p) == IMAGE_WIDGET)
372 if (IMAGE_INSTANCE_SUBWINDOW_ID (p))
374 XtUnmanageChild (IMAGE_INSTANCE_X_WIDGET_ID (p));
375 XtDestroyWidget (IMAGE_INSTANCE_X_WIDGET_ID (p));
376 IMAGE_INSTANCE_SUBWINDOW_ID (p) = 0;
379 else if (IMAGE_INSTANCE_TYPE (p) == IMAGE_SUBWINDOW)
381 if (IMAGE_INSTANCE_SUBWINDOW_ID (p))
382 XDestroyWindow (dpy, IMAGE_INSTANCE_X_SUBWINDOW_ID (p));
383 IMAGE_INSTANCE_SUBWINDOW_ID (p) = 0;
387 if (IMAGE_INSTANCE_X_PIXMAP (p))
388 XFreePixmap (dpy, IMAGE_INSTANCE_X_PIXMAP (p));
389 if (IMAGE_INSTANCE_X_MASK (p) &&
390 IMAGE_INSTANCE_X_MASK (p) != IMAGE_INSTANCE_X_PIXMAP (p))
391 XFreePixmap (dpy, IMAGE_INSTANCE_X_MASK (p));
392 IMAGE_INSTANCE_X_PIXMAP (p) = 0;
393 IMAGE_INSTANCE_X_MASK (p) = 0;
395 if (IMAGE_INSTANCE_X_CURSOR (p))
397 XFreeCursor (dpy, IMAGE_INSTANCE_X_CURSOR (p));
398 IMAGE_INSTANCE_X_CURSOR (p) = 0;
401 if (IMAGE_INSTANCE_X_NPIXELS (p) != 0)
404 IMAGE_INSTANCE_X_COLORMAP (p),
405 IMAGE_INSTANCE_X_PIXELS (p),
406 IMAGE_INSTANCE_X_NPIXELS (p), 0);
407 IMAGE_INSTANCE_X_NPIXELS (p) = 0;
411 if (IMAGE_INSTANCE_X_PIXELS (p))
413 xfree (IMAGE_INSTANCE_X_PIXELS (p));
414 IMAGE_INSTANCE_X_PIXELS (p) = 0;
422 x_image_instance_equal (struct Lisp_Image_Instance *p1,
423 struct Lisp_Image_Instance *p2, int depth)
425 switch (IMAGE_INSTANCE_TYPE (p1))
427 case IMAGE_MONO_PIXMAP:
428 case IMAGE_COLOR_PIXMAP:
430 if (IMAGE_INSTANCE_X_COLORMAP (p1) != IMAGE_INSTANCE_X_COLORMAP (p2) ||
431 IMAGE_INSTANCE_X_NPIXELS (p1) != IMAGE_INSTANCE_X_NPIXELS (p2))
442 x_image_instance_hash (struct Lisp_Image_Instance *p, int depth)
444 switch (IMAGE_INSTANCE_TYPE (p))
446 case IMAGE_MONO_PIXMAP:
447 case IMAGE_COLOR_PIXMAP:
449 return IMAGE_INSTANCE_X_NPIXELS (p);
455 /* Set all the slots in an image instance structure to reasonable
456 default values. This is used somewhere within an instantiate
457 method. It is assumed that the device slot within the image
458 instance is already set -- this is the case when instantiate
459 methods are called. */
462 x_initialize_pixmap_image_instance (struct Lisp_Image_Instance *ii,
463 enum image_instance_type type)
465 ii->data = xnew_and_zero (struct x_image_instance_data);
466 IMAGE_INSTANCE_TYPE (ii) = type;
467 IMAGE_INSTANCE_PIXMAP_FILENAME (ii) = Qnil;
468 IMAGE_INSTANCE_PIXMAP_MASK_FILENAME (ii) = Qnil;
469 IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii) = Qnil;
470 IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii) = Qnil;
471 IMAGE_INSTANCE_PIXMAP_FG (ii) = Qnil;
472 IMAGE_INSTANCE_PIXMAP_BG (ii) = Qnil;
476 /************************************************************************/
477 /* pixmap file functions */
478 /************************************************************************/
480 /* Where bitmaps are; initialized from resource database */
481 Lisp_Object Vx_bitmap_file_path;
484 #define BITMAPDIR "/usr/include/X11/bitmaps"
487 #define USE_XBMLANGPATH
489 /* Given a pixmap filename, look through all of the "standard" places
490 where the file might be located. Return a full pathname if found;
491 otherwise, return Qnil. */
494 x_locate_pixmap_file (Lisp_Object name)
496 /* This function can GC if IN_REDISPLAY is false */
499 /* Check non-absolute pathnames with a directory component relative to
500 the search path; that's the way Xt does it. */
501 /* #### Unix-specific */
502 if (XSTRING_BYTE (name, 0) == '/' ||
503 (XSTRING_BYTE (name, 0) == '.' &&
504 (XSTRING_BYTE (name, 1) == '/' ||
505 (XSTRING_BYTE (name, 1) == '.' &&
506 (XSTRING_BYTE (name, 2) == '/')))))
508 if (!NILP (Ffile_readable_p (name)))
514 if (NILP (Vdefault_x_device))
515 /* This may occur during initialization. */
518 /* We only check the bitmapFilePath resource on the original X device. */
519 display = DEVICE_X_DISPLAY (XDEVICE (Vdefault_x_device));
521 #ifdef USE_XBMLANGPATH
523 char *path = egetenv ("XBMLANGPATH");
524 SubstitutionRec subs[1];
526 subs[0].substitution = (char *) XSTRING_DATA (name);
527 /* #### Motif uses a big hairy default if $XBMLANGPATH isn't set.
528 We don't. If you want it used, set it. */
530 (path = XtResolvePathname (display, "bitmaps", 0, 0, path,
531 subs, XtNumber (subs), 0)))
533 name = build_string (path);
540 if (NILP (Vx_bitmap_file_path))
544 if (XrmGetResource (XtDatabase (display),
545 "bitmapFilePath", "BitmapFilePath", &type, &value)
546 && !strcmp (type, "String"))
547 Vx_bitmap_file_path = decode_env_path (0, (char *) value.addr);
548 Vx_bitmap_file_path = nconc2 (Vx_bitmap_file_path,
549 (decode_path (BITMAPDIR)));
554 if (locate_file (Vx_bitmap_file_path, name, Qnil, &found, R_OK) < 0)
556 Lisp_Object temp = list1 (Vdata_directory);
560 locate_file (temp, name, Qnil, &found, R_OK);
569 locate_pixmap_file (Lisp_Object name)
571 return x_locate_pixmap_file (name);
576 write_lisp_string_to_temp_file (Lisp_Object string, char *filename_out)
578 Lisp_Object instream, outstream;
579 Lstream *istr, *ostr;
580 char tempbuf[1024]; /* some random amount */
583 static Extbyte_dynarr *conversion_out_dynarr;
584 Bytecount bstart, bend;
585 struct gcpro gcpro1, gcpro2;
587 Lisp_Object conv_out_stream;
592 /* This function can GC */
593 if (!conversion_out_dynarr)
594 conversion_out_dynarr = Dynarr_new (Extbyte);
596 Dynarr_reset (conversion_out_dynarr);
598 /* Create the temporary file ... */
599 sprintf (filename_out, "/tmp/emacs%d.XXXXXX", (int) getpid ());
600 mktemp (filename_out);
601 tmpfil = fopen (filename_out, "w");
606 int old_errno = errno;
608 unlink (filename_out);
611 report_file_error ("Creating temp file",
612 list1 (build_string (filename_out)));
615 CHECK_STRING (string);
616 get_string_range_byte (string, Qnil, Qnil, &bstart, &bend,
617 GB_HISTORICAL_STRING_BEHAVIOR);
618 instream = make_lisp_string_input_stream (string, bstart, bend);
619 istr = XLSTREAM (instream);
620 /* setup the out stream */
621 outstream = make_dynarr_output_stream((unsigned_char_dynarr *)conversion_out_dynarr);
622 ostr = XLSTREAM (outstream);
624 /* setup the conversion stream */
625 conv_out_stream = make_encoding_output_stream (ostr, Fget_coding_system(Qbinary));
626 costr = XLSTREAM (conv_out_stream);
627 GCPRO3 (instream, outstream, conv_out_stream);
629 GCPRO2 (instream, outstream);
632 /* Get the data while doing the conversion */
635 int size_in_bytes = Lstream_read (istr, tempbuf, sizeof (tempbuf));
638 /* It does seem the flushes are necessary... */
640 Lstream_write (costr, tempbuf, size_in_bytes);
641 Lstream_flush (costr);
643 Lstream_write (ostr, tempbuf, size_in_bytes);
645 Lstream_flush (ostr);
646 if (fwrite ((unsigned char *)Dynarr_atp(conversion_out_dynarr, 0),
647 Dynarr_length(conversion_out_dynarr), 1, tmpfil) != 1)
652 /* reset the dynarr */
653 Lstream_rewind(ostr);
656 if (fclose (tmpfil) != 0)
658 Lstream_close (istr);
660 Lstream_close (costr);
662 Lstream_close (ostr);
665 Lstream_delete (istr);
666 Lstream_delete (ostr);
668 Lstream_delete (costr);
672 report_file_error ("Writing temp file",
673 list1 (build_string (filename_out)));
678 /************************************************************************/
679 /* cursor functions */
680 /************************************************************************/
682 /* Check that this server supports cursors of size WIDTH * HEIGHT. If
683 not, signal an error. INSTANTIATOR is only used in the error
687 check_pointer_sizes (Screen *xs, unsigned int width, unsigned int height,
688 Lisp_Object instantiator)
690 unsigned int best_width, best_height;
691 if (! XQueryBestCursor (DisplayOfScreen (xs), RootWindowOfScreen (xs),
692 width, height, &best_width, &best_height))
693 /* this means that an X error of some sort occurred (we trap
694 these so they're not fatal). */
695 signal_simple_error ("XQueryBestCursor() failed?", instantiator);
697 if (width > best_width || height > best_height)
698 error_with_frob (instantiator,
699 "pointer too large (%dx%d): "
700 "server requires %dx%d or smaller",
701 width, height, best_width, best_height);
706 generate_cursor_fg_bg (Lisp_Object device, Lisp_Object *foreground,
707 Lisp_Object *background, XColor *xfg, XColor *xbg)
709 if (!NILP (*foreground) && !COLOR_INSTANCEP (*foreground))
711 Fmake_color_instance (*foreground, device,
712 encode_error_behavior_flag (ERROR_ME));
713 if (COLOR_INSTANCEP (*foreground))
714 *xfg = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (*foreground));
718 xfg->red = xfg->green = xfg->blue = 0;
721 if (!NILP (*background) && !COLOR_INSTANCEP (*background))
723 Fmake_color_instance (*background, device,
724 encode_error_behavior_flag (ERROR_ME));
725 if (COLOR_INSTANCEP (*background))
726 *xbg = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (*background));
730 xbg->red = xbg->green = xbg->blue = ~0;
735 maybe_recolor_cursor (Lisp_Object image_instance, Lisp_Object foreground,
736 Lisp_Object background)
738 Lisp_Object device = XIMAGE_INSTANCE_DEVICE (image_instance);
741 generate_cursor_fg_bg (device, &foreground, &background, &xfg, &xbg);
742 if (!NILP (foreground) || !NILP (background))
744 XRecolorCursor (DEVICE_X_DISPLAY (XDEVICE (device)),
745 XIMAGE_INSTANCE_X_CURSOR (image_instance),
747 XIMAGE_INSTANCE_PIXMAP_FG (image_instance) = foreground;
748 XIMAGE_INSTANCE_PIXMAP_BG (image_instance) = background;
753 /************************************************************************/
754 /* color pixmap functions */
755 /************************************************************************/
757 /* Initialize an image instance from an XImage.
759 DEST_MASK specifies the mask of allowed image types.
761 PIXELS and NPIXELS specify an array of pixels that are used in
762 the image. These need to be kept around for the duration of the
763 image. When the image instance is freed, XFreeColors() will
764 automatically be called on all the pixels specified here; thus,
765 you should have allocated the pixels yourself using XAllocColor()
766 or the like. The array passed in is used directly without
767 being copied, so it should be heap data created with xmalloc().
768 It will be freed using xfree() when the image instance is
771 If this fails, signal an error. INSTANTIATOR is only used
772 in the error message.
774 #### This should be able to handle conversion into `pointer'.
775 Use the same code as for `xpm'. */
778 init_image_instance_from_x_image (struct Lisp_Image_Instance *ii,
782 unsigned long *pixels,
784 Lisp_Object instantiator)
786 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
792 if (!DEVICE_X_P (XDEVICE (device)))
793 signal_simple_error ("Not an X device", device);
795 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
796 d = XtWindow(DEVICE_XT_APP_SHELL (XDEVICE (device)));
798 if (!(dest_mask & IMAGE_COLOR_PIXMAP_MASK))
799 incompatible_image_types (instantiator, dest_mask,
800 IMAGE_COLOR_PIXMAP_MASK);
802 pixmap = XCreatePixmap (dpy, d, ximage->width,
803 ximage->height, ximage->depth);
805 signal_simple_error ("Unable to create pixmap", instantiator);
807 gc = XCreateGC (dpy, pixmap, 0, NULL);
810 XFreePixmap (dpy, pixmap);
811 signal_simple_error ("Unable to create GC", instantiator);
814 XPutImage (dpy, pixmap, gc, ximage, 0, 0, 0, 0,
815 ximage->width, ximage->height);
819 x_initialize_pixmap_image_instance (ii, IMAGE_COLOR_PIXMAP);
821 IMAGE_INSTANCE_PIXMAP_FILENAME (ii) =
822 find_keyword_in_vector (instantiator, Q_file);
824 IMAGE_INSTANCE_X_PIXMAP (ii) = pixmap;
825 IMAGE_INSTANCE_X_MASK (ii) = 0;
826 IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = ximage->width;
827 IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = ximage->height;
828 IMAGE_INSTANCE_PIXMAP_DEPTH (ii) = ximage->depth;
829 IMAGE_INSTANCE_X_COLORMAP (ii) = cmap;
830 IMAGE_INSTANCE_X_PIXELS (ii) = pixels;
831 IMAGE_INSTANCE_X_NPIXELS (ii) = npixels;
835 x_init_image_instance_from_eimage (struct Lisp_Image_Instance *ii,
836 int width, int height,
837 unsigned char *eimage,
839 Lisp_Object instantiator,
842 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
843 Colormap cmap = DEVICE_X_COLORMAP (XDEVICE(device));
844 unsigned long *pixtbl = NULL;
848 ximage = convert_EImage_to_XImage (device, width, height, eimage,
852 if (pixtbl) xfree (pixtbl);
853 signal_image_error("EImage to XImage conversion failed", instantiator);
856 /* Now create the pixmap and set up the image instance */
857 init_image_instance_from_x_image (ii, ximage, dest_mask,
858 cmap, pixtbl, npixels,
865 xfree (ximage->data);
868 XDestroyImage (ximage);
872 int read_bitmap_data_from_file (CONST char *filename, unsigned int *width,
873 unsigned int *height, unsigned char **datap,
874 int *x_hot, int *y_hot)
876 return XmuReadBitmapDataFromFile (filename, width, height,
877 datap, x_hot, y_hot);
880 /* Given inline data for a mono pixmap, create and return the
881 corresponding X object. */
884 pixmap_from_xbm_inline (Lisp_Object device, int width, int height,
885 /* Note that data is in ext-format! */
888 return XCreatePixmapFromBitmapData (DEVICE_X_DISPLAY (XDEVICE(device)),
889 XtWindow (DEVICE_XT_APP_SHELL (XDEVICE (device))),
890 (char *) bits, width, height,
894 /* Given inline data for a mono pixmap, initialize the given
895 image instance accordingly. */
898 init_image_instance_from_xbm_inline (struct Lisp_Image_Instance *ii,
899 int width, int height,
900 /* Note that data is in ext-format! */
902 Lisp_Object instantiator,
903 Lisp_Object pointer_fg,
904 Lisp_Object pointer_bg,
907 Lisp_Object mask_filename)
909 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
910 Lisp_Object foreground = find_keyword_in_vector (instantiator, Q_foreground);
911 Lisp_Object background = find_keyword_in_vector (instantiator, Q_background);
915 enum image_instance_type type;
917 if (!DEVICE_X_P (XDEVICE (device)))
918 signal_simple_error ("Not an X device", device);
920 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
921 draw = XtWindow(DEVICE_XT_APP_SHELL (XDEVICE (device)));
922 scr = DefaultScreenOfDisplay (dpy);
924 if ((dest_mask & IMAGE_MONO_PIXMAP_MASK) &&
925 (dest_mask & IMAGE_COLOR_PIXMAP_MASK))
927 if (!NILP (foreground) || !NILP (background))
928 type = IMAGE_COLOR_PIXMAP;
930 type = IMAGE_MONO_PIXMAP;
932 else if (dest_mask & IMAGE_MONO_PIXMAP_MASK)
933 type = IMAGE_MONO_PIXMAP;
934 else if (dest_mask & IMAGE_COLOR_PIXMAP_MASK)
935 type = IMAGE_COLOR_PIXMAP;
936 else if (dest_mask & IMAGE_POINTER_MASK)
937 type = IMAGE_POINTER;
939 incompatible_image_types (instantiator, dest_mask,
940 IMAGE_MONO_PIXMAP_MASK | IMAGE_COLOR_PIXMAP_MASK
941 | IMAGE_POINTER_MASK);
943 x_initialize_pixmap_image_instance (ii, type);
944 IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = width;
945 IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = height;
946 IMAGE_INSTANCE_PIXMAP_FILENAME (ii) =
947 find_keyword_in_vector (instantiator, Q_file);
951 case IMAGE_MONO_PIXMAP:
953 IMAGE_INSTANCE_X_PIXMAP (ii) =
954 pixmap_from_xbm_inline (device, width, height, (Extbyte *) bits);
958 case IMAGE_COLOR_PIXMAP:
960 Dimension d = DEVICE_X_DEPTH (XDEVICE(device));
961 unsigned long fg = BlackPixelOfScreen (scr);
962 unsigned long bg = WhitePixelOfScreen (scr);
964 if (!NILP (foreground) && !COLOR_INSTANCEP (foreground))
966 Fmake_color_instance (foreground, device,
967 encode_error_behavior_flag (ERROR_ME));
969 if (COLOR_INSTANCEP (foreground))
970 fg = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (foreground)).pixel;
972 if (!NILP (background) && !COLOR_INSTANCEP (background))
974 Fmake_color_instance (background, device,
975 encode_error_behavior_flag (ERROR_ME));
977 if (COLOR_INSTANCEP (background))
978 bg = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (background)).pixel;
980 /* We used to duplicate the pixels using XAllocColor(), to protect
981 against their getting freed. Just as easy to just store the
982 color instances here and GC-protect them, so this doesn't
984 IMAGE_INSTANCE_PIXMAP_FG (ii) = foreground;
985 IMAGE_INSTANCE_PIXMAP_BG (ii) = background;
986 IMAGE_INSTANCE_X_PIXMAP (ii) =
987 XCreatePixmapFromBitmapData (dpy, draw,
988 (char *) bits, width, height,
990 IMAGE_INSTANCE_PIXMAP_DEPTH (ii) = d;
996 XColor fg_color, bg_color;
999 check_pointer_sizes (scr, width, height, instantiator);
1002 XCreatePixmapFromBitmapData (dpy, draw,
1003 (char *) bits, width, height,
1006 if (NILP (foreground))
1007 foreground = pointer_fg;
1008 if (NILP (background))
1009 background = pointer_bg;
1010 generate_cursor_fg_bg (device, &foreground, &background,
1011 &fg_color, &bg_color);
1013 IMAGE_INSTANCE_PIXMAP_FG (ii) = foreground;
1014 IMAGE_INSTANCE_PIXMAP_BG (ii) = background;
1015 IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii) =
1016 find_keyword_in_vector (instantiator, Q_hotspot_x);
1017 IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii) =
1018 find_keyword_in_vector (instantiator, Q_hotspot_y);
1019 IMAGE_INSTANCE_X_CURSOR (ii) =
1021 (dpy, source, mask, &fg_color, &bg_color,
1022 !NILP (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii)) ?
1023 XINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii)) : 0,
1024 !NILP (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii)) ?
1025 XINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii)) : 0);
1035 xbm_instantiate_1 (Lisp_Object image_instance, Lisp_Object instantiator,
1036 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1037 int dest_mask, int width, int height,
1038 /* Note that data is in ext-format! */
1041 Lisp_Object mask_data = find_keyword_in_vector (instantiator, Q_mask_data);
1042 Lisp_Object mask_file = find_keyword_in_vector (instantiator, Q_mask_file);
1043 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1045 CONST char *gcc_may_you_rot_in_hell;
1047 if (!NILP (mask_data))
1049 GET_C_STRING_BINARY_DATA_ALLOCA (XCAR (XCDR (XCDR (mask_data))),
1050 gcc_may_you_rot_in_hell);
1052 pixmap_from_xbm_inline (IMAGE_INSTANCE_DEVICE (ii),
1053 XINT (XCAR (mask_data)),
1054 XINT (XCAR (XCDR (mask_data))),
1055 (CONST unsigned char *)
1056 gcc_may_you_rot_in_hell);
1059 init_image_instance_from_xbm_inline (ii, width, height, bits,
1060 instantiator, pointer_fg, pointer_bg,
1061 dest_mask, mask, mask_file);
1064 /* Instantiate method for XBM's. */
1067 x_xbm_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1068 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1069 int dest_mask, Lisp_Object domain)
1071 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1072 CONST char *gcc_go_home;
1074 assert (!NILP (data));
1076 GET_C_STRING_BINARY_DATA_ALLOCA (XCAR (XCDR (XCDR (data))),
1079 xbm_instantiate_1 (image_instance, instantiator, pointer_fg,
1080 pointer_bg, dest_mask, XINT (XCAR (data)),
1081 XINT (XCAR (XCDR (data))), gcc_go_home);
1087 /**********************************************************************
1089 **********************************************************************/
1090 /* xpm 3.2g and better has XpmCreatePixmapFromBuffer()...
1091 There was no version number in xpm.h before 3.3, but this should do.
1093 #if (XpmVersion >= 3) || defined(XpmExactColors)
1094 # define XPM_DOES_BUFFERS
1097 #ifndef XPM_DOES_BUFFERS
1098 Your version of XPM is too old. You cannot compile with it.
1099 Upgrade to version 3.2g or better or compile with --with-xpm=no.
1100 #endif /* !XPM_DOES_BUFFERS */
1102 static XpmColorSymbol *
1103 extract_xpm_color_names (XpmAttributes *xpmattrs, Lisp_Object device,
1105 Lisp_Object color_symbol_alist)
1107 /* This function can GC */
1108 Display *dpy = DEVICE_X_DISPLAY (XDEVICE(device));
1109 Colormap cmap = DEVICE_X_COLORMAP (XDEVICE(device));
1112 Lisp_Object results = Qnil;
1114 XpmColorSymbol *symbols;
1115 struct gcpro gcpro1, gcpro2;
1117 GCPRO2 (results, device);
1119 /* We built up results to be (("name" . #<color>) ...) so that if an
1120 error happens we don't lose any malloc()ed data, or more importantly,
1121 leave any pixels allocated in the server. */
1123 LIST_LOOP (rest, color_symbol_alist)
1125 Lisp_Object cons = XCAR (rest);
1126 Lisp_Object name = XCAR (cons);
1127 Lisp_Object value = XCDR (cons);
1130 if (STRINGP (value))
1132 Fmake_color_instance
1133 (value, device, encode_error_behavior_flag (ERROR_ME_NOT));
1136 assert (COLOR_SPECIFIERP (value));
1137 value = Fspecifier_instance (value, domain, Qnil, Qnil);
1141 results = noseeum_cons (noseeum_cons (name, value), results);
1144 UNGCPRO; /* no more evaluation */
1146 if (i == 0) return 0;
1148 symbols = xnew_array (XpmColorSymbol, i);
1149 xpmattrs->valuemask |= XpmColorSymbols;
1150 xpmattrs->colorsymbols = symbols;
1151 xpmattrs->numsymbols = i;
1155 Lisp_Object cons = XCAR (results);
1156 color = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (XCDR (cons)));
1157 /* Duplicate the pixel value so that we still have a lock on it if
1158 the pixel we were passed is later freed. */
1159 if (! XAllocColor (dpy, cmap, &color))
1160 abort (); /* it must be allocable since we're just duplicating it */
1162 symbols [i].name = (char *) XSTRING_DATA (XCAR (cons));
1163 symbols [i].pixel = color.pixel;
1164 symbols [i].value = 0;
1165 free_cons (XCONS (cons));
1167 results = XCDR (results);
1168 free_cons (XCONS (cons));
1174 xpm_free (XpmAttributes *xpmattrs)
1176 /* Could conceivably lose if XpmXXX returned an error without first
1177 initializing this structure, if we didn't know that initializing it
1178 to all zeros was ok (and also that it's ok to call XpmFreeAttributes()
1179 multiple times, since it zeros slots as it frees them...) */
1180 XpmFreeAttributes (xpmattrs);
1184 x_xpm_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1185 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1186 int dest_mask, Lisp_Object domain)
1188 /* This function can GC */
1189 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1190 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
1191 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1199 XpmAttributes xpmattrs;
1201 XpmColorSymbol *color_symbols;
1202 Lisp_Object color_symbol_alist = find_keyword_in_vector (instantiator,
1204 enum image_instance_type type;
1208 if (!DEVICE_X_P (XDEVICE (device)))
1209 signal_simple_error ("Not an X device", device);
1211 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
1212 xs = DefaultScreenOfDisplay (dpy);
1214 if (dest_mask & IMAGE_COLOR_PIXMAP_MASK)
1215 type = IMAGE_COLOR_PIXMAP;
1216 else if (dest_mask & IMAGE_MONO_PIXMAP_MASK)
1217 type = IMAGE_MONO_PIXMAP;
1218 else if (dest_mask & IMAGE_POINTER_MASK)
1219 type = IMAGE_POINTER;
1221 incompatible_image_types (instantiator, dest_mask,
1222 IMAGE_MONO_PIXMAP_MASK | IMAGE_COLOR_PIXMAP_MASK
1223 | IMAGE_POINTER_MASK);
1224 force_mono = (type != IMAGE_COLOR_PIXMAP);
1227 /* Although I haven't found it documented yet, it appears that pointers are
1228 always colored via the default window colormap... Sigh. */
1229 if (type == IMAGE_POINTER)
1231 cmap = DefaultColormap(dpy, DefaultScreen(dpy));
1232 depth = DefaultDepthOfScreen (xs);
1233 visual = DefaultVisualOfScreen (xs);
1237 cmap = DEVICE_X_COLORMAP (XDEVICE(device));
1238 depth = DEVICE_X_DEPTH (XDEVICE(device));
1239 visual = DEVICE_X_VISUAL (XDEVICE(device));
1242 cmap = DEVICE_X_COLORMAP (XDEVICE(device));
1243 depth = DEVICE_X_DEPTH (XDEVICE(device));
1244 visual = DEVICE_X_VISUAL (XDEVICE(device));
1247 x_initialize_pixmap_image_instance (ii, type);
1249 assert (!NILP (data));
1253 xzero (xpmattrs); /* want XpmInitAttributes() */
1254 xpmattrs.valuemask = XpmReturnPixels;
1257 /* Without this, we get a 1-bit version of the color image, which
1258 isn't quite right. With this, we get the mono image, which might
1259 be very different looking. */
1260 xpmattrs.valuemask |= XpmColorKey;
1261 xpmattrs.color_key = XPM_MONO;
1263 xpmattrs.valuemask |= XpmDepth;
1267 xpmattrs.closeness = 65535;
1268 xpmattrs.valuemask |= XpmCloseness;
1269 xpmattrs.depth = depth;
1270 xpmattrs.valuemask |= XpmDepth;
1271 xpmattrs.visual = visual;
1272 xpmattrs.valuemask |= XpmVisual;
1273 xpmattrs.colormap = cmap;
1274 xpmattrs.valuemask |= XpmColormap;
1277 color_symbols = extract_xpm_color_names (&xpmattrs, device, domain,
1278 color_symbol_alist);
1280 result = XpmCreatePixmapFromBuffer (dpy,
1281 XtWindow(DEVICE_XT_APP_SHELL (XDEVICE(device))),
1282 (char *) XSTRING_DATA (data),
1283 &pixmap, &mask, &xpmattrs);
1287 xfree (color_symbols);
1288 xpmattrs.colorsymbols = 0; /* in case XpmFreeAttr is too smart... */
1289 xpmattrs.numsymbols = 0;
1296 case XpmFileInvalid:
1298 xpm_free (&xpmattrs);
1299 signal_image_error ("invalid XPM data", data);
1301 case XpmColorFailed:
1304 xpm_free (&xpmattrs);
1307 /* second time; blow out. */
1308 signal_double_file_error ("Reading pixmap data",
1309 "color allocation failed",
1314 if (! (dest_mask & IMAGE_MONO_PIXMAP_MASK))
1316 /* second time; blow out. */
1317 signal_double_file_error ("Reading pixmap data",
1318 "color allocation failed",
1322 IMAGE_INSTANCE_TYPE (ii) = IMAGE_MONO_PIXMAP;
1328 xpm_free (&xpmattrs);
1329 signal_double_file_error ("Parsing pixmap data",
1330 "out of memory", data);
1334 xpm_free (&xpmattrs);
1335 signal_double_file_error_2 ("Parsing pixmap data",
1336 "unknown error code",
1337 make_int (result), data);
1342 h = xpmattrs.height;
1345 int npixels = xpmattrs.npixels;
1350 pixels = xnew_array (Pixel, npixels);
1351 memcpy (pixels, xpmattrs.pixels, npixels * sizeof (Pixel));
1356 IMAGE_INSTANCE_X_PIXMAP (ii) = pixmap;
1357 IMAGE_INSTANCE_X_MASK (ii) = mask;
1358 IMAGE_INSTANCE_X_COLORMAP (ii) = cmap;
1359 IMAGE_INSTANCE_X_PIXELS (ii) = pixels;
1360 IMAGE_INSTANCE_X_NPIXELS (ii) = npixels;
1361 IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = w;
1362 IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = h;
1363 IMAGE_INSTANCE_PIXMAP_FILENAME (ii) =
1364 find_keyword_in_vector (instantiator, Q_file);
1369 case IMAGE_MONO_PIXMAP:
1372 case IMAGE_COLOR_PIXMAP:
1374 IMAGE_INSTANCE_PIXMAP_DEPTH (ii) = depth;
1380 int npixels = xpmattrs.npixels;
1381 Pixel *pixels = xpmattrs.pixels;
1384 int xhot = 0, yhot = 0;
1386 if (xpmattrs.valuemask & XpmHotspot)
1388 xhot = xpmattrs.x_hotspot;
1389 XSETINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii), xpmattrs.x_hotspot);
1391 if (xpmattrs.valuemask & XpmHotspot)
1393 yhot = xpmattrs.y_hotspot;
1394 XSETINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii), xpmattrs.y_hotspot);
1396 check_pointer_sizes (xs, w, h, instantiator);
1398 /* If the loaded pixmap has colors allocated (meaning it came from an
1399 XPM file), then use those as the default colors for the cursor we
1400 create. Otherwise, default to pointer_fg and pointer_bg.
1404 /* With an XBM file, it's obvious which bit is foreground
1405 and which is background, or rather, it's implicit: in
1406 an XBM file, a 1 bit is foreground, and a 0 bit is
1409 XCreatePixmapCursor() assumes this property of the
1410 pixmap it is called with as well; the `foreground'
1411 color argument is used for the 1 bits.
1413 With an XPM file, it's tricker, since the elements of
1414 the pixmap don't represent FG and BG, but are actual
1415 pixel values. So we need to figure out which of those
1416 pixels is the foreground color and which is the
1417 background. We do it by comparing RGB and assuming
1418 that the darker color is the foreground. This works
1419 with the result of xbmtopbm|ppmtoxpm, at least.
1421 It might be nice if there was some way to tag the
1422 colors in the XPM file with whether they are the
1423 foreground - perhaps with logical color names somehow?
1425 Once we have decided which color is the foreground, we
1426 need to ensure that that color corresponds to a `1' bit
1427 in the Pixmap. The XPM library wrote into the (1-bit)
1428 pixmap with XPutPixel, which will ignore all but the
1429 least significant bit.
1431 This means that a 1 bit in the image corresponds to
1432 `fg' only if `fg.pixel' is odd.
1434 (This also means that the image will be all the same
1435 color if both `fg' and `bg' are odd or even, but we can
1436 safely assume that that won't happen if the XPM file is
1439 The desired result is that the image use `1' to
1440 represent the foreground color, and `0' to represent
1441 the background color. So, we may need to invert the
1442 image to accomplish this; we invert if fg is
1443 odd. (Remember that WhitePixel and BlackPixel are not
1444 necessarily 1 and 0 respectively, though I think it
1445 might be safe to assume that one of them is always 1
1446 and the other is always 0. We also pretty much need to
1447 assume that one is even and the other is odd.)
1450 fg.pixel = pixels[0]; /* pick a pixel at random. */
1451 bg.pixel = fg.pixel;
1452 for (i = 1; i < npixels; i++) /* Look for an "other" pixel value.*/
1454 bg.pixel = pixels[i];
1455 if (fg.pixel != bg.pixel)
1459 /* If (fg.pixel == bg.pixel) then probably something has
1460 gone wrong, but I don't think signalling an error would
1463 XQueryColor (dpy, cmap, &fg);
1464 XQueryColor (dpy, cmap, &bg);
1466 /* If the foreground is lighter than the background, swap them.
1467 (This occurs semi-randomly, depending on the ordering of the
1468 color list in the XPM file.)
1471 unsigned short fg_total = ((fg.red / 3) + (fg.green / 3)
1473 unsigned short bg_total = ((bg.red / 3) + (bg.green / 3)
1475 if (fg_total > bg_total)
1484 /* If the fg pixel corresponds to a `0' in the bitmap, invert it.
1485 (This occurs (only?) on servers with Black=0, White=1.)
1487 if ((fg.pixel & 1) == 0)
1491 gcv.function = GXxor;
1493 gc = XCreateGC (dpy, pixmap, (GCFunction | GCForeground),
1495 XFillRectangle (dpy, pixmap, gc, 0, 0, w, h);
1501 generate_cursor_fg_bg (device, &pointer_fg, &pointer_bg,
1503 IMAGE_INSTANCE_PIXMAP_FG (ii) = pointer_fg;
1504 IMAGE_INSTANCE_PIXMAP_BG (ii) = pointer_bg;
1507 IMAGE_INSTANCE_X_CURSOR (ii) =
1509 (dpy, pixmap, mask, &fg, &bg, xhot, yhot);
1518 xpm_free (&xpmattrs); /* after we've read pixels and hotspot */
1521 #endif /* HAVE_XPM */
1526 /**********************************************************************
1528 **********************************************************************/
1530 /* This is about to get redefined! */
1533 /* We have to define SYSV32 so that compface.h includes string.h
1534 instead of strings.h. */
1539 #include <compface.h>
1543 /* JMP_BUF cannot be used here because if it doesn't get defined
1544 to jmp_buf we end up with a conflicting type error with the
1545 definition in compface.h */
1546 extern jmp_buf comp_env;
1550 x_xface_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1551 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1552 int dest_mask, Lisp_Object domain)
1554 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1556 char *p, *bits, *bp;
1557 CONST char * volatile emsg = 0;
1558 CONST char * volatile dstring;
1560 assert (!NILP (data));
1562 GET_C_STRING_BINARY_DATA_ALLOCA (data, dstring);
1564 if ((p = strchr (dstring, ':')))
1569 /* Must use setjmp not SETJMP because we used jmp_buf above not JMP_BUF */
1570 if (!(stattis = setjmp (comp_env)))
1572 UnCompAll ((char *) dstring);
1579 emsg = "uncompface: internal error";
1582 emsg = "uncompface: insufficient or invalid data";
1585 emsg = "uncompface: excess data ignored";
1590 signal_simple_error_2 (emsg, data, Qimage);
1592 bp = bits = (char *) alloca (PIXELS / 8);
1594 /* the compface library exports char F[], which uses a single byte per
1595 pixel to represent a 48x48 bitmap. Yuck. */
1596 for (i = 0, p = F; i < (PIXELS / 8); ++i)
1599 /* reverse the bit order of each byte... */
1600 for (b = n = 0; b < 8; ++b)
1607 xbm_instantiate_1 (image_instance, instantiator, pointer_fg,
1608 pointer_bg, dest_mask, 48, 48, bits);
1611 #endif /* HAVE_XFACE */
1614 /**********************************************************************
1616 **********************************************************************/
1619 autodetect_validate (Lisp_Object instantiator)
1621 data_must_be_present (instantiator);
1625 autodetect_normalize (Lisp_Object instantiator,
1626 Lisp_Object console_type)
1628 Lisp_Object file = find_keyword_in_vector (instantiator, Q_data);
1629 Lisp_Object filename = Qnil;
1630 Lisp_Object data = Qnil;
1631 struct gcpro gcpro1, gcpro2, gcpro3;
1632 Lisp_Object alist = Qnil;
1634 GCPRO3 (filename, data, alist);
1636 if (NILP (file)) /* no conversion necessary */
1637 RETURN_UNGCPRO (instantiator);
1639 alist = tagged_vector_to_alist (instantiator);
1641 filename = locate_pixmap_file (file);
1642 if (!NILP (filename))
1645 /* #### Apparently some versions of XpmReadFileToData, which is
1646 called by pixmap_to_lisp_data, don't return an error value
1647 if the given file is not a valid XPM file. Instead, they
1648 just seg fault. It is definitely caused by passing a
1649 bitmap. To try and avoid this we check for bitmaps first. */
1651 data = bitmap_to_lisp_data (filename, &xhot, &yhot, 1);
1655 alist = remassq_no_quit (Q_data, alist);
1656 alist = Fcons (Fcons (Q_file, filename),
1657 Fcons (Fcons (Q_data, data), alist));
1659 alist = Fcons (Fcons (Q_hotspot_x, make_int (xhot)),
1662 alist = Fcons (Fcons (Q_hotspot_y, make_int (yhot)),
1665 alist = xbm_mask_file_munging (alist, filename, Qnil, console_type);
1668 Lisp_Object result = alist_to_tagged_vector (Qxbm, alist);
1670 RETURN_UNGCPRO (result);
1675 data = pixmap_to_lisp_data (filename, 1);
1679 alist = remassq_no_quit (Q_data, alist);
1680 alist = Fcons (Fcons (Q_file, filename),
1681 Fcons (Fcons (Q_data, data), alist));
1682 alist = Fcons (Fcons (Q_color_symbols,
1683 evaluate_xpm_color_symbols ()),
1686 Lisp_Object result = alist_to_tagged_vector (Qxpm, alist);
1688 RETURN_UNGCPRO (result);
1694 /* If we couldn't convert it, just put it back as it is.
1695 We might try to further frob it later as a cursor-font
1696 specification. (We can't do that now because we don't know
1697 what dest-types it's going to be instantiated into.) */
1699 Lisp_Object result = alist_to_tagged_vector (Qautodetect, alist);
1701 RETURN_UNGCPRO (result);
1706 autodetect_possible_dest_types (void)
1709 IMAGE_MONO_PIXMAP_MASK |
1710 IMAGE_COLOR_PIXMAP_MASK |
1711 IMAGE_POINTER_MASK |
1716 autodetect_instantiate (Lisp_Object image_instance,
1717 Lisp_Object instantiator,
1718 Lisp_Object pointer_fg,
1719 Lisp_Object pointer_bg,
1720 int dest_mask, Lisp_Object domain)
1722 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1723 struct gcpro gcpro1, gcpro2, gcpro3;
1724 Lisp_Object alist = Qnil;
1725 Lisp_Object result = Qnil;
1726 int is_cursor_font = 0;
1728 GCPRO3 (data, alist, result);
1730 alist = tagged_vector_to_alist (instantiator);
1731 if (dest_mask & IMAGE_POINTER_MASK)
1733 CONST char *name_ext;
1734 GET_C_STRING_FILENAME_DATA_ALLOCA (data, name_ext);
1735 if (XmuCursorNameToIndex (name_ext) != -1)
1737 result = alist_to_tagged_vector (Qcursor_font, alist);
1742 if (!is_cursor_font)
1743 result = alist_to_tagged_vector (Qstring, alist);
1747 cursor_font_instantiate (image_instance, result, pointer_fg,
1748 pointer_bg, dest_mask, domain);
1750 string_instantiate (image_instance, result, pointer_fg,
1751 pointer_bg, dest_mask, domain);
1757 /**********************************************************************
1759 **********************************************************************/
1762 font_validate (Lisp_Object instantiator)
1764 data_must_be_present (instantiator);
1767 /* XmuCvtStringToCursor is bogus in the following ways:
1769 - When it can't convert the given string to a real cursor, it will
1770 sometimes return a "success" value, after triggering a BadPixmap
1771 error. It then gives you a cursor that will itself generate BadCursor
1772 errors. So we install this error handler to catch/notice the X error
1773 and take that as meaning "couldn't convert."
1775 - When you tell it to find a cursor file that doesn't exist, it prints
1776 an error message on stderr. You can't make it not do that.
1778 - Also, using Xmu means we can't properly hack Lisp_Image_Instance
1779 objects, or XPM files, or $XBMLANGPATH.
1782 /* Duplicate the behavior of XmuCvtStringToCursor() to bypass its bogusness. */
1784 static int XLoadFont_got_error;
1787 XLoadFont_error_handler (Display *dpy, XErrorEvent *xerror)
1789 XLoadFont_got_error = 1;
1794 safe_XLoadFont (Display *dpy, char *name)
1797 int (*old_handler) (Display *, XErrorEvent *);
1798 XLoadFont_got_error = 0;
1800 old_handler = XSetErrorHandler (XLoadFont_error_handler);
1801 font = XLoadFont (dpy, name);
1803 XSetErrorHandler (old_handler);
1804 if (XLoadFont_got_error) return 0;
1809 font_possible_dest_types (void)
1811 return IMAGE_POINTER_MASK;
1815 font_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1816 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1817 int dest_mask, Lisp_Object domain)
1819 /* This function can GC */
1820 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1821 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1822 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
1826 char source_name[MAXPATHLEN], mask_name[MAXPATHLEN], dummy;
1827 int source_char, mask_char;
1829 Lisp_Object foreground, background;
1831 if (!DEVICE_X_P (XDEVICE (device)))
1832 signal_simple_error ("Not an X device", device);
1834 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
1836 if (!STRINGP (data) ||
1837 strncmp ("FONT ", (char *) XSTRING_DATA (data), 5))
1838 signal_simple_error ("Invalid font-glyph instantiator",
1841 if (!(dest_mask & IMAGE_POINTER_MASK))
1842 incompatible_image_types (instantiator, dest_mask, IMAGE_POINTER_MASK);
1844 foreground = find_keyword_in_vector (instantiator, Q_foreground);
1845 if (NILP (foreground))
1846 foreground = pointer_fg;
1847 background = find_keyword_in_vector (instantiator, Q_background);
1848 if (NILP (background))
1849 background = pointer_bg;
1851 generate_cursor_fg_bg (device, &foreground, &background, &fg, &bg);
1853 count = sscanf ((char *) XSTRING_DATA (data),
1854 "FONT %s %d %s %d %c",
1855 source_name, &source_char,
1856 mask_name, &mask_char, &dummy);
1857 /* Allow "%s %d %d" as well... */
1858 if (count == 3 && (1 == sscanf (mask_name, "%d %c", &mask_char, &dummy)))
1859 count = 4, mask_name[0] = 0;
1861 if (count != 2 && count != 4)
1862 signal_simple_error ("invalid cursor specification", data);
1863 source = safe_XLoadFont (dpy, source_name);
1865 signal_simple_error_2 ("couldn't load font",
1866 build_string (source_name),
1870 else if (!mask_name[0])
1874 mask = safe_XLoadFont (dpy, mask_name);
1877 Fsignal (Qerror, list3 (build_string ("couldn't load font"),
1878 build_string (mask_name), data));
1883 /* #### call XQueryTextExtents() and check_pointer_sizes() here. */
1885 x_initialize_pixmap_image_instance (ii, IMAGE_POINTER);
1886 IMAGE_INSTANCE_X_CURSOR (ii) =
1887 XCreateGlyphCursor (dpy, source, mask, source_char, mask_char,
1889 XIMAGE_INSTANCE_PIXMAP_FG (image_instance) = foreground;
1890 XIMAGE_INSTANCE_PIXMAP_BG (image_instance) = background;
1891 XUnloadFont (dpy, source);
1892 if (mask && mask != source) XUnloadFont (dpy, mask);
1896 /**********************************************************************
1898 **********************************************************************/
1901 cursor_font_validate (Lisp_Object instantiator)
1903 data_must_be_present (instantiator);
1907 cursor_font_possible_dest_types (void)
1909 return IMAGE_POINTER_MASK;
1913 cursor_font_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1914 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1915 int dest_mask, Lisp_Object domain)
1917 /* This function can GC */
1918 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1919 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1920 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
1923 CONST char *name_ext;
1924 Lisp_Object foreground, background;
1926 if (!DEVICE_X_P (XDEVICE (device)))
1927 signal_simple_error ("Not an X device", device);
1929 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
1931 if (!(dest_mask & IMAGE_POINTER_MASK))
1932 incompatible_image_types (instantiator, dest_mask, IMAGE_POINTER_MASK);
1934 GET_C_STRING_FILENAME_DATA_ALLOCA (data, name_ext);
1935 if ((i = XmuCursorNameToIndex (name_ext)) == -1)
1936 signal_simple_error ("Unrecognized cursor-font name", data);
1938 x_initialize_pixmap_image_instance (ii, IMAGE_POINTER);
1939 IMAGE_INSTANCE_X_CURSOR (ii) = XCreateFontCursor (dpy, i);
1940 foreground = find_keyword_in_vector (instantiator, Q_foreground);
1941 if (NILP (foreground))
1942 foreground = pointer_fg;
1943 background = find_keyword_in_vector (instantiator, Q_background);
1944 if (NILP (background))
1945 background = pointer_bg;
1946 maybe_recolor_cursor (image_instance, foreground, background);
1950 x_colorize_image_instance (Lisp_Object image_instance,
1951 Lisp_Object foreground, Lisp_Object background)
1953 struct Lisp_Image_Instance *p;
1955 p = XIMAGE_INSTANCE (image_instance);
1957 switch (IMAGE_INSTANCE_TYPE (p))
1959 case IMAGE_MONO_PIXMAP:
1960 IMAGE_INSTANCE_TYPE (p) = IMAGE_COLOR_PIXMAP;
1961 /* Make sure there aren't two pointers to the same mask, causing
1962 it to get freed twice. */
1963 IMAGE_INSTANCE_X_MASK (p) = 0;
1971 Display *dpy = DEVICE_X_DISPLAY (XDEVICE (IMAGE_INSTANCE_DEVICE (p)));
1972 Drawable draw = XtWindow(DEVICE_XT_APP_SHELL (XDEVICE (IMAGE_INSTANCE_DEVICE (p))));
1973 Dimension d = DEVICE_X_DEPTH (XDEVICE (IMAGE_INSTANCE_DEVICE (p)));
1974 Pixmap new = XCreatePixmap (dpy, draw,
1975 IMAGE_INSTANCE_PIXMAP_WIDTH (p),
1976 IMAGE_INSTANCE_PIXMAP_HEIGHT (p), d);
1980 color = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (foreground));
1981 gcv.foreground = color.pixel;
1982 color = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (background));
1983 gcv.background = color.pixel;
1984 gc = XCreateGC (dpy, new, GCBackground|GCForeground, &gcv);
1985 XCopyPlane (dpy, IMAGE_INSTANCE_X_PIXMAP (p), new, gc, 0, 0,
1986 IMAGE_INSTANCE_PIXMAP_WIDTH (p),
1987 IMAGE_INSTANCE_PIXMAP_HEIGHT (p),
1990 IMAGE_INSTANCE_X_PIXMAP (p) = new;
1991 IMAGE_INSTANCE_PIXMAP_DEPTH (p) = d;
1992 IMAGE_INSTANCE_PIXMAP_FG (p) = foreground;
1993 IMAGE_INSTANCE_PIXMAP_BG (p) = background;
1999 /************************************************************************/
2000 /* subwindow and widget support */
2001 /************************************************************************/
2003 /* unmap the image if it is a widget. This is used by redisplay via
2004 redisplay_unmap_subwindows */
2006 x_unmap_subwindow (struct Lisp_Image_Instance *p)
2008 if (IMAGE_INSTANCE_TYPE (p) == IMAGE_SUBWINDOW)
2011 (DisplayOfScreen (IMAGE_INSTANCE_X_SUBWINDOW_SCREEN (p)),
2012 IMAGE_INSTANCE_X_SUBWINDOW_ID (p));
2014 else /* must be a widget */
2016 XtUnmapWidget (IMAGE_INSTANCE_X_WIDGET_ID (p));
2020 /* map the subwindow. This is used by redisplay via
2021 redisplay_output_subwindow */
2023 x_map_subwindow (struct Lisp_Image_Instance *p, int x, int y)
2025 if (IMAGE_INSTANCE_TYPE (p) == IMAGE_SUBWINDOW)
2027 Window subwindow = IMAGE_INSTANCE_X_SUBWINDOW_ID (p);
2028 Screen* screen = IMAGE_INSTANCE_X_SUBWINDOW_SCREEN (p);
2029 XMapWindow (DisplayOfScreen (screen), subwindow);
2030 XMoveWindow (DisplayOfScreen (screen), subwindow, x, y);
2032 else /* must be a widget */
2034 XtMoveWidget (IMAGE_INSTANCE_X_WIDGET_ID (p),
2035 x + IMAGE_INSTANCE_X_WIDGET_XOFFSET (p),
2036 y + IMAGE_INSTANCE_X_WIDGET_YOFFSET (p));
2037 XtMapWidget (IMAGE_INSTANCE_X_WIDGET_ID (p));
2041 /* when you click on a widget you may activate another widget this
2042 needs to be checked and all appropriate widgets updated */
2044 x_update_subwindow (struct Lisp_Image_Instance *p)
2046 if (IMAGE_INSTANCE_TYPE (p) == IMAGE_WIDGET)
2048 widget_value* wv = xmalloc_widget_value ();
2049 button_item_to_widget_value (IMAGE_INSTANCE_WIDGET_SINGLE_ITEM (p),
2051 lw_modify_all_widgets (IMAGE_INSTANCE_X_WIDGET_LWID (p),
2056 /* instantiate and x type subwindow */
2058 x_subwindow_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2059 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2060 int dest_mask, Lisp_Object domain)
2062 /* This function can GC */
2063 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2064 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
2065 Lisp_Object frame = FW_FRAME (domain);
2066 struct frame* f = XFRAME (frame);
2070 XSetWindowAttributes xswa;
2072 unsigned int w = IMAGE_INSTANCE_SUBWINDOW_WIDTH (ii),
2073 h = IMAGE_INSTANCE_SUBWINDOW_HEIGHT (ii);
2075 if (!DEVICE_X_P (XDEVICE (device)))
2076 signal_simple_error ("Not an X device", device);
2078 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
2079 xs = DefaultScreenOfDisplay (dpy);
2081 IMAGE_INSTANCE_TYPE (ii) = IMAGE_SUBWINDOW;
2083 pw = XtWindow (FRAME_X_TEXT_WIDGET (f));
2085 ii->data = xnew_and_zero (struct x_subwindow_data);
2087 IMAGE_INSTANCE_X_SUBWINDOW_PARENT (ii) = pw;
2088 IMAGE_INSTANCE_X_SUBWINDOW_SCREEN (ii) = xs;
2090 xswa.backing_store = Always;
2091 valueMask |= CWBackingStore;
2092 xswa.colormap = DefaultColormapOfScreen (xs);
2093 valueMask |= CWColormap;
2095 win = XCreateWindow (dpy, pw, 0, 0, w, h, 0, CopyFromParent,
2096 InputOutput, CopyFromParent, valueMask,
2099 IMAGE_INSTANCE_SUBWINDOW_ID (ii) = (void*)win;
2103 /* #### Should this function exist? If there's any doubt I'm not implementing it --andyp */
2104 DEFUN ("change-subwindow-property", Fchange_subwindow_property, 3, 3, 0, /*
2105 For the given SUBWINDOW, set PROPERTY to DATA, which is a string.
2106 Subwindows are not currently implemented.
2108 (subwindow, property, data))
2111 struct Lisp_Subwindow *sw;
2114 CHECK_SUBWINDOW (subwindow);
2115 CHECK_STRING (property);
2116 CHECK_STRING (data);
2118 sw = XSUBWINDOW (subwindow);
2119 dpy = DisplayOfScreen (LISP_DEVICE_TO_X_SCREEN
2120 (FRAME_DEVICE (XFRAME (sw->frame))));
2122 property_atom = XInternAtom (dpy, (char *) XSTRING_DATA (property), False);
2123 XChangeProperty (dpy, sw->subwindow, property_atom, XA_STRING, 8,
2125 XSTRING_DATA (data),
2126 XSTRING_LENGTH (data));
2133 x_resize_subwindow (struct Lisp_Image_Instance* ii, int w, int h)
2135 if (IMAGE_INSTANCE_TYPE (ii) == IMAGE_SUBWINDOW)
2137 XResizeWindow (DisplayOfScreen (IMAGE_INSTANCE_X_SUBWINDOW_SCREEN (ii)),
2138 IMAGE_INSTANCE_X_SUBWINDOW_ID (ii),
2141 else /* must be a widget */
2144 XtSetArg (al [0], XtNwidth, (Dimension)w);
2145 XtSetArg (al [1], XtNheight, (Dimension)h);
2146 XtSetValues (IMAGE_INSTANCE_X_WIDGET_ID (ii), al, 2);
2150 /************************************************************************/
2152 /************************************************************************/
2155 x_widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2156 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2157 int dest_mask, Lisp_Object domain,
2158 CONST char* type, widget_value* wv)
2160 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2161 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii), pixel;
2162 struct device* d = XDEVICE (device);
2163 Lisp_Object frame = FW_FRAME (domain);
2164 struct frame* f = XFRAME (frame);
2165 XColor fcolor, bcolor;
2170 int id = new_lwlib_id ();
2171 #ifdef LWLIB_USES_MOTIF
2172 XmFontList fontList;
2175 if (!DEVICE_X_P (d))
2176 signal_simple_error ("Not an mswindows device", device);
2178 /* have to set the type this late in case there is no device
2179 instantiation for a widget. But we can go ahead and do it without
2180 checking because there is always a generic instantiator. */
2181 IMAGE_INSTANCE_TYPE (ii) = IMAGE_WIDGET;
2183 if (!NILP (IMAGE_INSTANCE_WIDGET_TEXT (ii)))
2184 GET_C_STRING_OS_DATA_ALLOCA (IMAGE_INSTANCE_WIDGET_TEXT (ii), nm);
2186 ii->data = xnew_and_zero (struct x_subwindow_data);
2188 /* copy any args we were given */
2190 lw_add_value_args_to_args (wv, al, &ac);
2192 /* add our own arguments */
2193 pixel = FACE_FOREGROUND
2194 (IMAGE_INSTANCE_WIDGET_FACE (ii),
2195 IMAGE_INSTANCE_SUBWINDOW_FRAME (ii));
2196 fcolor = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (pixel));
2197 pixel = FACE_BACKGROUND
2198 (IMAGE_INSTANCE_WIDGET_FACE (ii),
2199 IMAGE_INSTANCE_SUBWINDOW_FRAME (ii));
2200 bcolor = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (pixel));
2202 XtSetArg (al [ac], XtNbackground, bcolor.pixel); ac++;
2203 XtSetArg (al [ac], XtNforeground, fcolor.pixel); ac++;
2204 #ifdef LWLIB_USES_MOTIF
2205 fontList = XmFontListCreate
2206 ((void*)FONT_INSTANCE_X_FONT
2207 (XFONT_INSTANCE (widget_face_font_info
2208 (domain, IMAGE_INSTANCE_WIDGET_FACE (ii),
2209 0, 0))), XmSTRING_DEFAULT_CHARSET);
2210 XtSetArg (al [ac], XmNfontList, fontList ); ac++;
2212 XtSetArg (al [ac], XtNfont, (void*)FONT_INSTANCE_X_FONT
2213 (XFONT_INSTANCE (widget_face_font_info
2215 IMAGE_INSTANCE_WIDGET_FACE (ii),
2222 wid = lw_create_widget (type, wv->name, id, wv, FRAME_X_CONTAINER_WIDGET (f),
2223 False, 0, popup_selection_callback, 0);
2225 IMAGE_INSTANCE_X_WIDGET_LWID (ii) = id;
2226 #ifdef LWLIB_USES_MOTIF
2227 XmFontListFree (fontList);
2229 /* because the EmacsManager is the widgets parent we have to
2230 offset the redisplay of the widget by the amount the text
2231 widget is inside the manager. */
2233 XtSetArg (al [ac], XtNwidth,
2234 (Dimension)IMAGE_INSTANCE_SUBWINDOW_WIDTH (ii)); ac++;
2235 XtSetArg (al [ac], XtNheight,
2236 (Dimension)IMAGE_INSTANCE_SUBWINDOW_HEIGHT (ii)); ac++;
2237 XtSetValues (wid, al, ac);
2238 /* finally get offsets in the frame */
2240 XtSetArg (al [ac], XtNx, &IMAGE_INSTANCE_X_WIDGET_XOFFSET (ii)); ac++;
2241 XtSetArg (al [ac], XtNy, &IMAGE_INSTANCE_X_WIDGET_YOFFSET (ii)); ac++;
2242 XtGetValues (FRAME_X_TEXT_WIDGET (f), al, ac);
2244 IMAGE_INSTANCE_SUBWINDOW_ID (ii) = (void*)wid;
2246 free_widget_value (wv);
2250 x_widget_set_property (Lisp_Object image_instance, Lisp_Object prop,
2253 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2255 if (EQ (prop, Q_text))
2258 widget_value* wv = lw_get_all_values (IMAGE_INSTANCE_X_WIDGET_LWID (ii));
2260 GET_C_STRING_OS_DATA_ALLOCA (val, str);
2262 lw_modify_all_widgets (IMAGE_INSTANCE_X_WIDGET_LWID (ii), wv, False);
2268 /* get properties of a control */
2270 x_widget_property (Lisp_Object image_instance, Lisp_Object prop)
2272 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2273 /* get the text from a control */
2274 if (EQ (prop, Q_text))
2276 widget_value* wv = lw_get_all_values (IMAGE_INSTANCE_X_WIDGET_LWID (ii));
2277 return build_ext_string (wv->value, FORMAT_OS);
2282 /* Instantiate a button widget. Unfortunately instantiated widgets are
2283 particular to a frame since they need to have a parent. It's not
2284 like images where you just select the image into the context you
2285 want to display it in and BitBlt it. So images instances can have a
2286 many-to-one relationship with things you see, whereas widgets can
2287 only be one-to-one (i.e. per frame) */
2289 x_button_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2290 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2291 int dest_mask, Lisp_Object domain)
2293 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2294 Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM (ii);
2295 Lisp_Object glyph = find_keyword_in_vector (instantiator, Q_image);
2296 widget_value* wv = xmalloc_widget_value ();
2298 button_item_to_widget_value (gui, wv, 1, 1);
2302 if (!IMAGE_INSTANCEP (glyph))
2303 glyph = glyph_image_instance (glyph, domain, ERROR_ME, 1);
2306 x_widget_instantiate (image_instance, instantiator, pointer_fg,
2307 pointer_bg, dest_mask, domain, "button", wv);
2309 /* add the image if one was given */
2310 if (!NILP (glyph) && IMAGE_INSTANCEP (glyph))
2314 #ifdef LWLIB_USES_MOTIF
2315 XtSetArg (al [ac], XmNlabelType, XmPIXMAP); ac++;
2316 XtSetArg (al [ac], XmNlabelPixmap, XIMAGE_INSTANCE_X_PIXMAP (glyph));ac++;
2318 XtSetArg (al [ac], XtNpixmap, XIMAGE_INSTANCE_X_PIXMAP (glyph)); ac++;
2320 XtSetValues (IMAGE_INSTANCE_X_WIDGET_ID (ii), al, ac);
2324 /* get properties of a button */
2326 x_button_property (Lisp_Object image_instance, Lisp_Object prop)
2328 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2329 /* check the state of a button */
2330 if (EQ (prop, Q_selected))
2332 widget_value* wv = lw_get_all_values (IMAGE_INSTANCE_X_WIDGET_LWID (ii));
2342 /* instantiate a progress gauge */
2344 x_progress_gauge_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2345 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2346 int dest_mask, Lisp_Object domain)
2348 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2349 Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM (ii);
2350 widget_value* wv = xmalloc_widget_value ();
2352 button_item_to_widget_value (gui, wv, 1, 1);
2354 x_widget_instantiate (image_instance, instantiator, pointer_fg,
2355 pointer_bg, dest_mask, domain, "progress", wv);
2358 /* set the properties of a progres guage */
2360 x_progress_gauge_set_property (Lisp_Object image_instance, Lisp_Object prop,
2363 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2365 if (EQ (prop, Q_percent))
2369 XtSetArg (al[0], XtNvalue, XINT (val));
2370 XtSetValues (IMAGE_INSTANCE_X_WIDGET_ID (ii), al, 1);
2376 /* instantiate an edit control */
2378 x_edit_field_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2379 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2380 int dest_mask, Lisp_Object domain)
2382 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2383 Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM (ii);
2384 widget_value* wv = xmalloc_widget_value ();
2386 button_item_to_widget_value (gui, wv, 1, 1);
2388 x_widget_instantiate (image_instance, instantiator, pointer_fg,
2389 pointer_bg, dest_mask, domain, "text-field", wv);
2392 /* instantiate a combo control */
2394 x_combo_box_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2395 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2396 int dest_mask, Lisp_Object domain)
2398 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2400 Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM (ii);
2401 widget_value* wv = xmalloc_widget_value ();
2403 button_item_to_widget_value (gui, wv, 1, 1);
2405 x_widget_instantiate (image_instance, instantiator, pointer_fg,
2406 pointer_bg, dest_mask, domain, "combo-box", wv);
2407 /* add items to the combo box */
2408 LIST_LOOP (rest, Fplist_get (IMAGE_INSTANCE_WIDGET_PROPS (ii), Q_items, Qnil))
2413 GET_C_STRING_OS_DATA_ALLOCA (XCAR (rest), str);
2414 xmstr = XmStringCreate (str, XmSTRING_DEFAULT_CHARSET);
2415 XmListAddItem (IMAGE_INSTANCE_X_WIDGET_ID (ii), xmstr, 0);
2416 XmStringFree (xmstr);
2422 /************************************************************************/
2423 /* initialization */
2424 /************************************************************************/
2427 syms_of_glyphs_x (void)
2430 DEFSUBR (Fchange_subwindow_property);
2435 console_type_create_glyphs_x (void)
2439 CONSOLE_HAS_METHOD (x, print_image_instance);
2440 CONSOLE_HAS_METHOD (x, finalize_image_instance);
2441 CONSOLE_HAS_METHOD (x, image_instance_equal);
2442 CONSOLE_HAS_METHOD (x, image_instance_hash);
2443 CONSOLE_HAS_METHOD (x, colorize_image_instance);
2444 CONSOLE_HAS_METHOD (x, init_image_instance_from_eimage);
2445 CONSOLE_HAS_METHOD (x, locate_pixmap_file);
2446 CONSOLE_HAS_METHOD (x, unmap_subwindow);
2447 CONSOLE_HAS_METHOD (x, map_subwindow);
2448 CONSOLE_HAS_METHOD (x, resize_subwindow);
2449 CONSOLE_HAS_METHOD (x, update_subwindow);
2453 image_instantiator_format_create_glyphs_x (void)
2455 IIFORMAT_VALID_CONSOLE (x, nothing);
2456 IIFORMAT_VALID_CONSOLE (x, string);
2457 IIFORMAT_VALID_CONSOLE (x, formatted_string);
2458 IIFORMAT_VALID_CONSOLE (x, inherit);
2460 INITIALIZE_DEVICE_IIFORMAT (x, xpm);
2461 IIFORMAT_HAS_DEVMETHOD (x, xpm, instantiate);
2464 IIFORMAT_VALID_CONSOLE (x, jpeg);
2467 IIFORMAT_VALID_CONSOLE (x, tiff);
2470 IIFORMAT_VALID_CONSOLE (x, png);
2473 IIFORMAT_VALID_CONSOLE (x, gif);
2475 INITIALIZE_DEVICE_IIFORMAT (x, xbm);
2476 IIFORMAT_HAS_DEVMETHOD (x, xbm, instantiate);
2478 INITIALIZE_DEVICE_IIFORMAT (x, subwindow);
2479 IIFORMAT_HAS_DEVMETHOD (x, subwindow, instantiate);
2480 #ifdef LWLIB_USES_MOTIF
2482 INITIALIZE_DEVICE_IIFORMAT (x, button);
2483 IIFORMAT_HAS_DEVMETHOD (x, button, property);
2484 IIFORMAT_HAS_DEVMETHOD (x, button, instantiate);
2486 INITIALIZE_DEVICE_IIFORMAT (x, widget);
2487 IIFORMAT_HAS_DEVMETHOD (x, widget, property);
2488 IIFORMAT_HAS_DEVMETHOD (x, widget, set_property);
2489 /* progress gauge */
2490 INITIALIZE_DEVICE_IIFORMAT (x, progress_gauge);
2491 IIFORMAT_HAS_DEVMETHOD (x, progress_gauge, set_property);
2492 IIFORMAT_HAS_DEVMETHOD (x, progress_gauge, instantiate);
2494 INITIALIZE_DEVICE_IIFORMAT (x, edit_field);
2495 IIFORMAT_HAS_DEVMETHOD (x, edit_field, instantiate);
2496 #if 0 /* XmVERSION > 1*/
2498 INITIALIZE_DEVICE_IIFORMAT (x, combo_box);
2499 IIFORMAT_HAS_DEVMETHOD (x, combo_box, instantiate);
2502 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (cursor_font, "cursor-font");
2503 IIFORMAT_VALID_CONSOLE (x, cursor_font);
2505 IIFORMAT_HAS_METHOD (cursor_font, validate);
2506 IIFORMAT_HAS_METHOD (cursor_font, possible_dest_types);
2507 IIFORMAT_HAS_METHOD (cursor_font, instantiate);
2509 IIFORMAT_VALID_KEYWORD (cursor_font, Q_data, check_valid_string);
2510 IIFORMAT_VALID_KEYWORD (cursor_font, Q_foreground, check_valid_string);
2511 IIFORMAT_VALID_KEYWORD (cursor_font, Q_background, check_valid_string);
2513 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (font, "font");
2515 IIFORMAT_HAS_METHOD (font, validate);
2516 IIFORMAT_HAS_METHOD (font, possible_dest_types);
2517 IIFORMAT_HAS_METHOD (font, instantiate);
2518 IIFORMAT_VALID_CONSOLE (x, font);
2520 IIFORMAT_VALID_KEYWORD (font, Q_data, check_valid_string);
2521 IIFORMAT_VALID_KEYWORD (font, Q_foreground, check_valid_string);
2522 IIFORMAT_VALID_KEYWORD (font, Q_background, check_valid_string);
2525 INITIALIZE_DEVICE_IIFORMAT (x, xface);
2526 IIFORMAT_HAS_DEVMETHOD (x, xface, instantiate);
2529 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (autodetect,
2532 IIFORMAT_HAS_METHOD (autodetect, validate);
2533 IIFORMAT_HAS_METHOD (autodetect, normalize);
2534 IIFORMAT_HAS_METHOD (autodetect, possible_dest_types);
2535 IIFORMAT_HAS_METHOD (autodetect, instantiate);
2536 IIFORMAT_VALID_CONSOLE (x, autodetect);
2538 IIFORMAT_VALID_KEYWORD (autodetect, Q_data, check_valid_string);
2542 vars_of_glyphs_x (void)
2544 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path /*
2545 A list of the directories in which X bitmap files may be found.
2546 If nil, this is initialized from the "*bitmapFilePath" resource.
2547 This is used by the `make-image-instance' function (however, note that if
2548 the environment variable XBMLANGPATH is set, it is consulted first).
2550 Vx_bitmap_file_path = Qnil;
2554 complex_vars_of_glyphs_x (void)
2556 #define BUILD_GLYPH_INST(variable, name) \
2557 Fadd_spec_to_specifier \
2558 (GLYPH_IMAGE (XGLYPH (variable)), \
2559 vector3 (Qxbm, Q_data, \
2560 list3 (make_int (name##_width), \
2561 make_int (name##_height), \
2562 make_ext_string (name##_bits, \
2563 sizeof (name##_bits), \
2567 BUILD_GLYPH_INST (Vtruncation_glyph, truncator);
2568 BUILD_GLYPH_INST (Vcontinuation_glyph, continuer);
2569 BUILD_GLYPH_INST (Vxemacs_logo, xemacs);
2570 BUILD_GLYPH_INST (Vhscroll_glyph, hscroll);
2572 #undef BUILD_GLYPH_INST