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
20 You should have received a copy of the GNU General Public License
21 along with XEmacs; see the file COPYING. If not, write to
22 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23 Boston, MA 02111-1307, USA. */
25 /* Synched up with: Not in FSF. */
27 /* 7-8-00 This file is more or less Mule-ized in my Mule workspace. */
29 /* Original author: Jamie Zawinski for 19.8
30 font-truename stuff added by Jamie Zawinski for 19.10
31 subwindow support added by Chuck Thompson
32 additional XPM support added by Chuck Thompson
33 initial X-Face support added by Stig
34 rewritten/restructured by Ben Wing for 19.12/19.13
35 GIF/JPEG support added by Ben Wing for 19.14
36 PNG support added by Bill Perry for 19.14
37 Improved GIF/JPEG support added by Bill Perry for 19.14
38 Cleanup/simplification of error handling by Ben Wing for 19.14
39 Pointer/icon overhaul, more restructuring by Ben Wing for 19.14
40 GIF support changed to external GIFlib 3.1 by Jareth Hein for 21.0
41 Many changes for color work and optimizations by Jareth Hein for 21.0
42 Switch of GIF/JPEG/PNG to new EImage intermediate code by Jareth Hein for 21.0
43 TIFF code by Jareth Hein for 21.0
44 GIF/JPEG/PNG/TIFF code moved to new glyph-eimage.c by Andy Piper for 21.0
45 Subwindow and Widget support by Andy Piper for 21.2
48 Support the GrayScale, StaticColor and StaticGray visual classes.
49 Convert images.el to C and stick it in here?
55 #include "console-x.h"
57 #include "objects-x.h"
78 #include "file-coding.h"
81 #ifdef LWLIB_WIDGETS_MOTIF
84 #include <X11/IntrinsicP.h>
87 # define FOUR_BYTE_TYPE unsigned int
89 # define FOUR_BYTE_TYPE unsigned long
91 # define FOUR_BYTE_TYPE unsigned short
93 #error What kind of strange-ass system are we running on?
96 #define LISP_DEVICE_TO_X_SCREEN(dev) XDefaultScreenOfDisplay (DEVICE_X_DISPLAY (XDEVICE (dev)))
98 DECLARE_IMAGE_INSTANTIATOR_FORMAT (nothing);
99 DECLARE_IMAGE_INSTANTIATOR_FORMAT (string);
100 DECLARE_IMAGE_INSTANTIATOR_FORMAT (formatted_string);
101 DECLARE_IMAGE_INSTANTIATOR_FORMAT (inherit);
103 DECLARE_IMAGE_INSTANTIATOR_FORMAT (jpeg);
106 DECLARE_IMAGE_INSTANTIATOR_FORMAT (tiff);
109 DECLARE_IMAGE_INSTANTIATOR_FORMAT (png);
112 DECLARE_IMAGE_INSTANTIATOR_FORMAT (gif);
115 DEFINE_DEVICE_IIFORMAT (x, xpm);
117 DEFINE_DEVICE_IIFORMAT (x, xbm);
118 DEFINE_DEVICE_IIFORMAT (x, subwindow);
120 DEFINE_DEVICE_IIFORMAT (x, xface);
123 DEFINE_IMAGE_INSTANTIATOR_FORMAT (cursor_font);
124 Lisp_Object Qcursor_font;
126 DEFINE_IMAGE_INSTANTIATOR_FORMAT (font);
128 DEFINE_IMAGE_INSTANTIATOR_FORMAT (autodetect);
131 DECLARE_IMAGE_INSTANTIATOR_FORMAT (layout);
132 DEFINE_DEVICE_IIFORMAT (x, widget);
133 DEFINE_DEVICE_IIFORMAT (x, native_layout);
134 DEFINE_DEVICE_IIFORMAT (x, button);
135 DEFINE_DEVICE_IIFORMAT (x, progress_gauge);
136 DEFINE_DEVICE_IIFORMAT (x, edit_field);
137 #if defined (LWLIB_WIDGETS_MOTIF) && XmVERSION > 1
138 DEFINE_DEVICE_IIFORMAT (x, combo_box);
140 DEFINE_DEVICE_IIFORMAT (x, tab_control);
141 DEFINE_DEVICE_IIFORMAT (x, label);
144 static void cursor_font_instantiate (Lisp_Object image_instance,
145 Lisp_Object instantiator,
146 Lisp_Object pointer_fg,
147 Lisp_Object pointer_bg,
153 update_widget_face (widget_value* wv,
154 Lisp_Image_Instance* ii, Lisp_Object domain);
156 update_tab_widget_face (widget_value* wv,
157 Lisp_Image_Instance* ii, Lisp_Object domain);
160 emacs_Xt_handle_widget_losing_focus (struct frame* f, Widget losing_widget);
165 /************************************************************************/
166 /* image instance methods */
167 /************************************************************************/
169 /************************************************************************/
170 /* convert from a series of RGB triples to an XImage formated for the */
172 /************************************************************************/
174 convert_EImage_to_XImage (Lisp_Object device, int width, int height,
175 unsigned char *pic, unsigned long **pixtbl,
182 int depth, bitmap_pad, bits_per_pixel, byte_cnt, i, j;
184 unsigned char *data, *ip, *dp;
185 quant_table *qtable = 0;
191 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
192 cmap = DEVICE_X_COLORMAP (XDEVICE(device));
193 vis = DEVICE_X_VISUAL (XDEVICE(device));
194 depth = DEVICE_X_DEPTH(XDEVICE(device));
196 if (vis->class == GrayScale || vis->class == StaticColor ||
197 vis->class == StaticGray)
199 /* #### Implement me!!! */
203 if (vis->class == PseudoColor)
205 /* Quantize the image and get a histogram while we're at it.
206 Do this first to save memory */
207 qtable = build_EImage_quantable(pic, width, height, 256);
208 if (qtable == NULL) return NULL;
211 bitmap_pad = ((depth > 16) ? 32 :
215 outimg = XCreateImage (dpy, vis,
216 depth, ZPixmap, 0, 0, width, height,
218 if (!outimg) return NULL;
220 bits_per_pixel = outimg->bits_per_pixel;
221 byte_cnt = bits_per_pixel >> 3;
223 data = (unsigned char *) xmalloc (outimg->bytes_per_line * height);
226 XDestroyImage (outimg);
229 outimg->data = (char *) data;
231 if (vis->class == PseudoColor)
233 unsigned long pixarray[256];
236 /* use our quantize table to allocate the colors */
238 *pixtbl = xnew_array (unsigned long, pixcount);
241 /* #### should implement a sort by popularity to assure proper allocation */
243 for (i = 0; i < qtable->num_active_colors; i++)
248 color.red = qtable->rm[i] ? qtable->rm[i] << 8 : 0;
249 color.green = qtable->gm[i] ? qtable->gm[i] << 8 : 0;
250 color.blue = qtable->bm[i] ? qtable->bm[i] << 8 : 0;
251 color.flags = DoRed | DoGreen | DoBlue;
252 res = allocate_nearest_color (dpy, cmap, vis, &color);
253 if (res > 0 && res < 3)
255 DO_REALLOC(*pixtbl, pixcount, n+1, unsigned long);
256 (*pixtbl)[n] = color.pixel;
259 pixarray[i] = color.pixel;
263 for (i = 0; i < height; i++)
265 dp = data + (i * outimg->bytes_per_line);
266 for (j = 0; j < width; j++)
271 conv.val = pixarray[QUANT_GET_COLOR(qtable,rd,gr,bl)];
272 #ifdef WORDS_BIGENDIAN
273 if (outimg->byte_order == MSBFirst)
274 for (q = 4-byte_cnt; q < 4; q++) *dp++ = conv.cp[q];
276 for (q = 3; q >= 4-byte_cnt; q--) *dp++ = conv.cp[q];
278 if (outimg->byte_order == MSBFirst)
279 for (q = byte_cnt-1; q >= 0; q--) *dp++ = conv.cp[q];
281 for (q = 0; q < byte_cnt; q++) *dp++ = conv.cp[q];
287 unsigned long rshift,gshift,bshift,rbits,gbits,bbits,junk;
288 junk = vis->red_mask;
290 while ((junk & 0x1) == 0)
301 junk = vis->green_mask;
303 while ((junk & 0x1) == 0)
314 junk = vis->blue_mask;
316 while ((junk & 0x1) == 0)
328 for (i = 0; i < height; i++)
330 dp = data + (i * outimg->bytes_per_line);
331 for (j = 0; j < width; j++)
334 rd = *ip++ << (rbits - 8);
336 rd = *ip++ >> (8 - rbits);
338 gr = *ip++ << (gbits - 8);
340 gr = *ip++ >> (8 - gbits);
342 bl = *ip++ << (bbits - 8);
344 bl = *ip++ >> (8 - bbits);
346 conv.val = (rd << rshift) | (gr << gshift) | (bl << bshift);
347 #ifdef WORDS_BIGENDIAN
348 if (outimg->byte_order == MSBFirst)
349 for (q = 4-byte_cnt; q < 4; q++) *dp++ = conv.cp[q];
351 for (q = 3; q >= 4-byte_cnt; q--) *dp++ = conv.cp[q];
353 if (outimg->byte_order == MSBFirst)
354 for (q = byte_cnt-1; q >= 0; q--) *dp++ = conv.cp[q];
356 for (q = 0; q < byte_cnt; q++) *dp++ = conv.cp[q];
367 x_print_image_instance (Lisp_Image_Instance *p,
368 Lisp_Object printcharfun,
373 switch (IMAGE_INSTANCE_TYPE (p))
375 case IMAGE_MONO_PIXMAP:
376 case IMAGE_COLOR_PIXMAP:
378 sprintf (buf, " (0x%lx", (unsigned long) IMAGE_INSTANCE_X_PIXMAP (p));
379 write_c_string (buf, printcharfun);
380 if (IMAGE_INSTANCE_X_MASK (p))
382 sprintf (buf, "/0x%lx", (unsigned long) IMAGE_INSTANCE_X_MASK (p));
383 write_c_string (buf, printcharfun);
385 write_c_string (")", printcharfun);
393 extern int debug_widget_instances;
397 x_finalize_image_instance (Lisp_Image_Instance *p)
402 if (DEVICE_LIVE_P (XDEVICE (IMAGE_INSTANCE_DEVICE (p))))
404 Display *dpy = DEVICE_X_DISPLAY
405 (XDEVICE (IMAGE_INSTANCE_DEVICE (p)));
409 else if (IMAGE_INSTANCE_TYPE (p) == IMAGE_WIDGET)
411 if (IMAGE_INSTANCE_SUBWINDOW_ID (p))
414 debug_widget_instances--;
415 stderr_out ("widget destroyed, %d left\n", debug_widget_instances);
417 lw_destroy_widget (IMAGE_INSTANCE_X_WIDGET_ID (p));
418 lw_destroy_widget (IMAGE_INSTANCE_X_CLIPWIDGET (p));
420 /* We can release the callbacks again. */
421 ungcpro_popup_callbacks (IMAGE_INSTANCE_X_WIDGET_LWID (p));
423 IMAGE_INSTANCE_X_WIDGET_ID (p) = 0;
424 IMAGE_INSTANCE_X_CLIPWIDGET (p) = 0;
428 else if (IMAGE_INSTANCE_TYPE (p) == IMAGE_SUBWINDOW)
430 if (IMAGE_INSTANCE_SUBWINDOW_ID (p))
431 XDestroyWindow (dpy, IMAGE_INSTANCE_X_SUBWINDOW_ID (p));
432 IMAGE_INSTANCE_SUBWINDOW_ID (p) = 0;
437 if (IMAGE_INSTANCE_PIXMAP_TIMEOUT (p))
438 disable_glyph_animated_timeout (IMAGE_INSTANCE_PIXMAP_TIMEOUT (p));
440 if (IMAGE_INSTANCE_X_MASK (p) &&
441 IMAGE_INSTANCE_X_MASK (p) != IMAGE_INSTANCE_X_PIXMAP (p))
442 XFreePixmap (dpy, IMAGE_INSTANCE_X_MASK (p));
443 IMAGE_INSTANCE_PIXMAP_MASK (p) = 0;
445 if (IMAGE_INSTANCE_X_PIXMAP_SLICES (p))
447 for (i = 0; i < IMAGE_INSTANCE_PIXMAP_MAXSLICE (p); i++)
448 if (IMAGE_INSTANCE_X_PIXMAP_SLICE (p,i))
450 XFreePixmap (dpy, IMAGE_INSTANCE_X_PIXMAP_SLICE (p,i));
451 IMAGE_INSTANCE_X_PIXMAP_SLICE (p, i) = 0;
453 xfree (IMAGE_INSTANCE_X_PIXMAP_SLICES (p));
454 IMAGE_INSTANCE_X_PIXMAP_SLICES (p) = 0;
457 if (IMAGE_INSTANCE_X_CURSOR (p))
459 XFreeCursor (dpy, IMAGE_INSTANCE_X_CURSOR (p));
460 IMAGE_INSTANCE_X_CURSOR (p) = 0;
463 if (IMAGE_INSTANCE_X_NPIXELS (p) != 0)
466 IMAGE_INSTANCE_X_COLORMAP (p),
467 IMAGE_INSTANCE_X_PIXELS (p),
468 IMAGE_INSTANCE_X_NPIXELS (p), 0);
469 IMAGE_INSTANCE_X_NPIXELS (p) = 0;
473 /* You can sometimes have pixels without a live device. I forget
474 why, but that's why we free them here if we have a pixmap type
475 image instance. It probably means that we might also get a memory
476 leak with widgets. */
477 if (IMAGE_INSTANCE_TYPE (p) != IMAGE_WIDGET
478 && IMAGE_INSTANCE_TYPE (p) != IMAGE_SUBWINDOW
479 && IMAGE_INSTANCE_X_PIXELS (p))
481 xfree (IMAGE_INSTANCE_X_PIXELS (p));
482 IMAGE_INSTANCE_X_PIXELS (p) = 0;
490 x_image_instance_equal (Lisp_Image_Instance *p1,
491 Lisp_Image_Instance *p2, int depth)
493 switch (IMAGE_INSTANCE_TYPE (p1))
495 case IMAGE_MONO_PIXMAP:
496 case IMAGE_COLOR_PIXMAP:
498 if (IMAGE_INSTANCE_X_COLORMAP (p1) != IMAGE_INSTANCE_X_COLORMAP (p2) ||
499 IMAGE_INSTANCE_X_NPIXELS (p1) != IMAGE_INSTANCE_X_NPIXELS (p2))
510 x_image_instance_hash (Lisp_Image_Instance *p, int depth)
512 switch (IMAGE_INSTANCE_TYPE (p))
514 case IMAGE_MONO_PIXMAP:
515 case IMAGE_COLOR_PIXMAP:
517 return IMAGE_INSTANCE_X_NPIXELS (p);
523 /* Set all the slots in an image instance structure to reasonable
524 default values. This is used somewhere within an instantiate
525 method. It is assumed that the device slot within the image
526 instance is already set -- this is the case when instantiate
527 methods are called. */
530 x_initialize_pixmap_image_instance (Lisp_Image_Instance *ii,
532 enum image_instance_type type)
534 ii->data = xnew_and_zero (struct x_image_instance_data);
535 IMAGE_INSTANCE_PIXMAP_MAXSLICE (ii) = slices;
536 IMAGE_INSTANCE_X_PIXMAP_SLICES (ii) =
537 xnew_array_and_zero (Pixmap, slices);
538 IMAGE_INSTANCE_TYPE (ii) = type;
539 IMAGE_INSTANCE_PIXMAP_FILENAME (ii) = Qnil;
540 IMAGE_INSTANCE_PIXMAP_MASK_FILENAME (ii) = Qnil;
541 IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii) = Qnil;
542 IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii) = Qnil;
543 IMAGE_INSTANCE_PIXMAP_FG (ii) = Qnil;
544 IMAGE_INSTANCE_PIXMAP_BG (ii) = Qnil;
548 /************************************************************************/
549 /* pixmap file functions */
550 /************************************************************************/
552 /* Where bitmaps are; initialized from resource database */
553 Lisp_Object Vx_bitmap_file_path;
556 #define BITMAPDIR "/usr/include/X11/bitmaps"
559 #define USE_XBMLANGPATH
561 /* Given a pixmap filename, look through all of the "standard" places
562 where the file might be located. Return a full pathname if found;
563 otherwise, return Qnil. */
566 x_locate_pixmap_file (Lisp_Object name)
568 /* This function can GC if IN_REDISPLAY is false */
571 /* Check non-absolute pathnames with a directory component relative to
572 the search path; that's the way Xt does it. */
573 /* #### Unix-specific */
574 if (XSTRING_BYTE (name, 0) == '/' ||
575 (XSTRING_BYTE (name, 0) == '.' &&
576 (XSTRING_BYTE (name, 1) == '/' ||
577 (XSTRING_BYTE (name, 1) == '.' &&
578 (XSTRING_BYTE (name, 2) == '/')))))
580 if (!NILP (Ffile_readable_p (name)))
581 return Fexpand_file_name (name, Qnil);
586 if (NILP (Vdefault_x_device))
587 /* This may occur during initialization. */
590 /* We only check the bitmapFilePath resource on the original X device. */
591 display = DEVICE_X_DISPLAY (XDEVICE (Vdefault_x_device));
593 #ifdef USE_XBMLANGPATH
595 char *path = egetenv ("XBMLANGPATH");
596 SubstitutionRec subs[1];
598 subs[0].substitution = (char *) XSTRING_DATA (name);
599 /* #### Motif uses a big hairy default if $XBMLANGPATH isn't set.
600 We don't. If you want it used, set it. */
602 (path = XtResolvePathname (display, "bitmaps", 0, 0, path,
603 subs, XtNumber (subs), 0)))
605 name = build_string (path);
612 if (NILP (Vx_bitmap_file_path))
616 if (XrmGetResource (XtDatabase (display),
617 "bitmapFilePath", "BitmapFilePath", &type, &value)
618 && !strcmp (type, "String"))
619 Vx_bitmap_file_path = decode_env_path (0, (char *) value.addr);
620 Vx_bitmap_file_path = nconc2 (Vx_bitmap_file_path,
621 (decode_path (BITMAPDIR)));
626 if (locate_file (Vx_bitmap_file_path, name, Qnil, &found, R_OK) < 0)
628 Lisp_Object temp = list1 (Vdata_directory);
632 locate_file (temp, name, Qnil, &found, R_OK);
641 locate_pixmap_file (Lisp_Object name)
643 return x_locate_pixmap_file (name);
648 write_lisp_string_to_temp_file (Lisp_Object string, char *filename_out)
650 Lisp_Object instream, outstream;
651 Lstream *istr, *ostr;
652 char tempbuf[1024]; /* some random amount */
655 static Extbyte_dynarr *conversion_out_dynarr;
656 Bytecount bstart, bend;
657 struct gcpro gcpro1, gcpro2;
659 Lisp_Object conv_out_stream;
664 /* This function can GC */
665 if (!conversion_out_dynarr)
666 conversion_out_dynarr = Dynarr_new (Extbyte);
668 Dynarr_reset (conversion_out_dynarr);
670 /* Create the temporary file ... */
671 sprintf (filename_out, "/tmp/emacs%d.XXXXXX", (int) getpid ());
672 mktemp (filename_out);
673 tmpfil = fopen (filename_out, "w");
678 int old_errno = errno;
680 unlink (filename_out);
683 report_file_error ("Creating temp file",
684 list1 (build_string (filename_out)));
687 CHECK_STRING (string);
688 get_string_range_byte (string, Qnil, Qnil, &bstart, &bend,
689 GB_HISTORICAL_STRING_BEHAVIOR);
690 instream = make_lisp_string_input_stream (string, bstart, bend);
691 istr = XLSTREAM (instream);
692 /* setup the out stream */
693 outstream = make_dynarr_output_stream((unsigned_char_dynarr *)conversion_out_dynarr);
694 ostr = XLSTREAM (outstream);
696 /* setup the conversion stream */
697 conv_out_stream = make_encoding_output_stream (ostr, Fget_coding_system(Qbinary));
698 costr = XLSTREAM (conv_out_stream);
699 GCPRO3 (instream, outstream, conv_out_stream);
701 GCPRO2 (instream, outstream);
704 /* Get the data while doing the conversion */
707 Lstream_data_count size_in_bytes = Lstream_read (istr, tempbuf, sizeof (tempbuf));
710 /* It does seem the flushes are necessary... */
712 Lstream_write (costr, tempbuf, size_in_bytes);
713 Lstream_flush (costr);
715 Lstream_write (ostr, tempbuf, size_in_bytes);
717 Lstream_flush (ostr);
718 if (fwrite ((unsigned char *)Dynarr_atp(conversion_out_dynarr, 0),
719 Dynarr_length(conversion_out_dynarr), 1, tmpfil) != 1)
724 /* reset the dynarr */
725 Lstream_rewind(ostr);
728 if (fclose (tmpfil) != 0)
730 Lstream_close (istr);
732 Lstream_close (costr);
734 Lstream_close (ostr);
737 Lstream_delete (istr);
738 Lstream_delete (ostr);
740 Lstream_delete (costr);
744 report_file_error ("Writing temp file",
745 list1 (build_string (filename_out)));
750 /************************************************************************/
751 /* cursor functions */
752 /************************************************************************/
754 /* Check that this server supports cursors of size WIDTH * HEIGHT. If
755 not, signal an error. INSTANTIATOR is only used in the error
759 check_pointer_sizes (Screen *xs, unsigned int width, unsigned int height,
760 Lisp_Object instantiator)
762 unsigned int best_width, best_height;
763 if (! XQueryBestCursor (DisplayOfScreen (xs), RootWindowOfScreen (xs),
764 width, height, &best_width, &best_height))
765 /* this means that an X error of some sort occurred (we trap
766 these so they're not fatal). */
767 signal_simple_error ("XQueryBestCursor() failed?", instantiator);
769 if (width > best_width || height > best_height)
770 error_with_frob (instantiator,
771 "pointer too large (%dx%d): "
772 "server requires %dx%d or smaller",
773 width, height, best_width, best_height);
778 generate_cursor_fg_bg (Lisp_Object device, Lisp_Object *foreground,
779 Lisp_Object *background, XColor *xfg, XColor *xbg)
781 if (!NILP (*foreground) && !COLOR_INSTANCEP (*foreground))
783 Fmake_color_instance (*foreground, device,
784 encode_error_behavior_flag (ERROR_ME));
785 if (COLOR_INSTANCEP (*foreground))
786 *xfg = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (*foreground));
790 xfg->red = xfg->green = xfg->blue = 0;
793 if (!NILP (*background) && !COLOR_INSTANCEP (*background))
795 Fmake_color_instance (*background, device,
796 encode_error_behavior_flag (ERROR_ME));
797 if (COLOR_INSTANCEP (*background))
798 *xbg = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (*background));
802 xbg->red = xbg->green = xbg->blue = USHRT_MAX;
807 maybe_recolor_cursor (Lisp_Object image_instance, Lisp_Object foreground,
808 Lisp_Object background)
810 Lisp_Object device = XIMAGE_INSTANCE_DEVICE (image_instance);
813 generate_cursor_fg_bg (device, &foreground, &background, &xfg, &xbg);
814 if (!NILP (foreground) || !NILP (background))
816 XRecolorCursor (DEVICE_X_DISPLAY (XDEVICE (device)),
817 XIMAGE_INSTANCE_X_CURSOR (image_instance),
819 XIMAGE_INSTANCE_PIXMAP_FG (image_instance) = foreground;
820 XIMAGE_INSTANCE_PIXMAP_BG (image_instance) = background;
825 /************************************************************************/
826 /* color pixmap functions */
827 /************************************************************************/
829 /* Initialize an image instance from an XImage.
831 DEST_MASK specifies the mask of allowed image types.
833 PIXELS and NPIXELS specify an array of pixels that are used in
834 the image. These need to be kept around for the duration of the
835 image. When the image instance is freed, XFreeColors() will
836 automatically be called on all the pixels specified here; thus,
837 you should have allocated the pixels yourself using XAllocColor()
838 or the like. The array passed in is used directly without
839 being copied, so it should be heap data created with xmalloc().
840 It will be freed using xfree() when the image instance is
843 If this fails, signal an error. INSTANTIATOR is only used
844 in the error message.
846 #### This should be able to handle conversion into `pointer'.
847 Use the same code as for `xpm'. */
850 init_image_instance_from_x_image (Lisp_Image_Instance *ii,
854 unsigned long *pixels,
857 Lisp_Object instantiator)
859 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
865 if (!DEVICE_X_P (XDEVICE (device)))
866 signal_simple_error ("Not an X device", device);
868 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
869 d = XtWindow(DEVICE_XT_APP_SHELL (XDEVICE (device)));
871 if (!(dest_mask & IMAGE_COLOR_PIXMAP_MASK))
872 incompatible_image_types (instantiator, dest_mask,
873 IMAGE_COLOR_PIXMAP_MASK);
875 pixmap = XCreatePixmap (dpy, d, ximage->width,
876 ximage->height, ximage->depth);
878 signal_simple_error ("Unable to create pixmap", instantiator);
880 gc = XCreateGC (dpy, pixmap, 0, NULL);
883 XFreePixmap (dpy, pixmap);
884 signal_simple_error ("Unable to create GC", instantiator);
887 XPutImage (dpy, pixmap, gc, ximage, 0, 0, 0, 0,
888 ximage->width, ximage->height);
892 x_initialize_pixmap_image_instance (ii, slices, IMAGE_COLOR_PIXMAP);
894 IMAGE_INSTANCE_PIXMAP_FILENAME (ii) =
895 find_keyword_in_vector (instantiator, Q_file);
897 /* Fixup a set of pixmaps. */
898 IMAGE_INSTANCE_X_PIXMAP (ii) = pixmap;
900 IMAGE_INSTANCE_PIXMAP_MASK (ii) = 0;
901 IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = ximage->width;
902 IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = ximage->height;
903 IMAGE_INSTANCE_PIXMAP_DEPTH (ii) = ximage->depth;
904 IMAGE_INSTANCE_X_COLORMAP (ii) = cmap;
905 IMAGE_INSTANCE_X_PIXELS (ii) = pixels;
906 IMAGE_INSTANCE_X_NPIXELS (ii) = npixels;
910 image_instance_add_x_image (Lisp_Image_Instance *ii,
913 Lisp_Object instantiator)
915 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
921 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
922 d = XtWindow(DEVICE_XT_APP_SHELL (XDEVICE (device)));
924 pixmap = XCreatePixmap (dpy, d, ximage->width,
925 ximage->height, ximage->depth);
927 signal_simple_error ("Unable to create pixmap", instantiator);
929 gc = XCreateGC (dpy, pixmap, 0, NULL);
932 XFreePixmap (dpy, pixmap);
933 signal_simple_error ("Unable to create GC", instantiator);
936 XPutImage (dpy, pixmap, gc, ximage, 0, 0, 0, 0,
937 ximage->width, ximage->height);
941 IMAGE_INSTANCE_X_PIXMAP_SLICE (ii, slice) = pixmap;
945 x_init_image_instance_from_eimage (Lisp_Image_Instance *ii,
946 int width, int height,
948 unsigned char *eimage,
950 Lisp_Object instantiator,
953 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
954 Colormap cmap = DEVICE_X_COLORMAP (XDEVICE(device));
955 unsigned long *pixtbl = NULL;
960 for (slice = 0; slice < slices; slice++)
962 ximage = convert_EImage_to_XImage (device, width, height,
963 eimage + (width * height * 3 * slice),
967 if (pixtbl) xfree (pixtbl);
968 signal_image_error("EImage to XImage conversion failed", instantiator);
971 /* Now create the pixmap and set up the image instance */
973 init_image_instance_from_x_image (ii, ximage, dest_mask,
974 cmap, pixtbl, npixels, slices,
977 image_instance_add_x_image (ii, ximage, slice, instantiator);
983 xfree (ximage->data);
986 XDestroyImage (ximage);
992 int read_bitmap_data_from_file (const char *filename, unsigned int *width,
993 unsigned int *height, unsigned char **datap,
994 int *x_hot, int *y_hot)
996 return XmuReadBitmapDataFromFile (filename, width, height,
997 datap, x_hot, y_hot);
1000 /* Given inline data for a mono pixmap, create and return the
1001 corresponding X object. */
1004 pixmap_from_xbm_inline (Lisp_Object device, int width, int height,
1005 /* Note that data is in ext-format! */
1008 return XCreatePixmapFromBitmapData
1009 (DEVICE_X_DISPLAY (XDEVICE (device)),
1010 XtWindow (DEVICE_XT_APP_SHELL (XDEVICE (device))),
1011 (char *) bits, width, height,
1015 /* Given inline data for a mono pixmap, initialize the given
1016 image instance accordingly. */
1019 init_image_instance_from_xbm_inline (Lisp_Image_Instance *ii,
1020 int width, int height,
1021 /* Note that data is in ext-format! */
1023 Lisp_Object instantiator,
1024 Lisp_Object pointer_fg,
1025 Lisp_Object pointer_bg,
1028 Lisp_Object mask_filename)
1030 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
1031 Lisp_Object foreground = find_keyword_in_vector (instantiator, Q_foreground);
1032 Lisp_Object background = find_keyword_in_vector (instantiator, Q_background);
1036 enum image_instance_type type;
1038 if (!DEVICE_X_P (XDEVICE (device)))
1039 signal_simple_error ("Not an X device", device);
1041 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
1042 draw = XtWindow(DEVICE_XT_APP_SHELL (XDEVICE (device)));
1043 scr = DefaultScreenOfDisplay (dpy);
1045 if ((dest_mask & IMAGE_MONO_PIXMAP_MASK) &&
1046 (dest_mask & IMAGE_COLOR_PIXMAP_MASK))
1048 if (!NILP (foreground) || !NILP (background))
1049 type = IMAGE_COLOR_PIXMAP;
1051 type = IMAGE_MONO_PIXMAP;
1053 else if (dest_mask & IMAGE_MONO_PIXMAP_MASK)
1054 type = IMAGE_MONO_PIXMAP;
1055 else if (dest_mask & IMAGE_COLOR_PIXMAP_MASK)
1056 type = IMAGE_COLOR_PIXMAP;
1057 else if (dest_mask & IMAGE_POINTER_MASK)
1058 type = IMAGE_POINTER;
1060 incompatible_image_types (instantiator, dest_mask,
1061 IMAGE_MONO_PIXMAP_MASK | IMAGE_COLOR_PIXMAP_MASK
1062 | IMAGE_POINTER_MASK);
1064 x_initialize_pixmap_image_instance (ii, 1, type);
1065 IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = width;
1066 IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = height;
1067 IMAGE_INSTANCE_PIXMAP_FILENAME (ii) =
1068 find_keyword_in_vector (instantiator, Q_file);
1072 case IMAGE_MONO_PIXMAP:
1074 IMAGE_INSTANCE_X_PIXMAP (ii) =
1075 pixmap_from_xbm_inline (device, width, height, (Extbyte *) bits);
1079 case IMAGE_COLOR_PIXMAP:
1081 Dimension d = DEVICE_X_DEPTH (XDEVICE(device));
1082 unsigned long fg = BlackPixelOfScreen (scr);
1083 unsigned long bg = WhitePixelOfScreen (scr);
1085 if (!NILP (foreground) && !COLOR_INSTANCEP (foreground))
1087 Fmake_color_instance (foreground, device,
1088 encode_error_behavior_flag (ERROR_ME));
1090 if (COLOR_INSTANCEP (foreground))
1091 fg = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (foreground)).pixel;
1093 if (!NILP (background) && !COLOR_INSTANCEP (background))
1095 Fmake_color_instance (background, device,
1096 encode_error_behavior_flag (ERROR_ME));
1098 if (COLOR_INSTANCEP (background))
1099 bg = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (background)).pixel;
1101 /* We used to duplicate the pixels using XAllocColor(), to protect
1102 against their getting freed. Just as easy to just store the
1103 color instances here and GC-protect them, so this doesn't
1105 IMAGE_INSTANCE_PIXMAP_FG (ii) = foreground;
1106 IMAGE_INSTANCE_PIXMAP_BG (ii) = background;
1107 IMAGE_INSTANCE_X_PIXMAP (ii) =
1108 XCreatePixmapFromBitmapData (dpy, draw,
1109 (char *) bits, width, height,
1111 IMAGE_INSTANCE_PIXMAP_DEPTH (ii) = d;
1117 XColor fg_color, bg_color;
1120 check_pointer_sizes (scr, width, height, instantiator);
1123 XCreatePixmapFromBitmapData (dpy, draw,
1124 (char *) bits, width, height,
1127 if (NILP (foreground))
1128 foreground = pointer_fg;
1129 if (NILP (background))
1130 background = pointer_bg;
1131 generate_cursor_fg_bg (device, &foreground, &background,
1132 &fg_color, &bg_color);
1134 IMAGE_INSTANCE_PIXMAP_FG (ii) = foreground;
1135 IMAGE_INSTANCE_PIXMAP_BG (ii) = background;
1136 IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii) =
1137 find_keyword_in_vector (instantiator, Q_hotspot_x);
1138 IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii) =
1139 find_keyword_in_vector (instantiator, Q_hotspot_y);
1140 IMAGE_INSTANCE_X_CURSOR (ii) =
1142 (dpy, source, mask, &fg_color, &bg_color,
1143 !NILP (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii)) ?
1144 XINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii)) : 0,
1145 !NILP (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii)) ?
1146 XINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii)) : 0);
1156 xbm_instantiate_1 (Lisp_Object image_instance, Lisp_Object instantiator,
1157 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1158 int dest_mask, int width, int height,
1159 /* Note that data is in ext-format! */
1162 Lisp_Object mask_data = find_keyword_in_vector (instantiator, Q_mask_data);
1163 Lisp_Object mask_file = find_keyword_in_vector (instantiator, Q_mask_file);
1164 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1167 if (!NILP (mask_data))
1169 const char *ext_data;
1171 LISP_STRING_TO_EXTERNAL (XCAR (XCDR (XCDR (mask_data))), ext_data, Qbinary);
1172 mask = pixmap_from_xbm_inline (IMAGE_INSTANCE_DEVICE (ii),
1173 XINT (XCAR (mask_data)),
1174 XINT (XCAR (XCDR (mask_data))),
1178 init_image_instance_from_xbm_inline (ii, width, height, bits,
1179 instantiator, pointer_fg, pointer_bg,
1180 dest_mask, mask, mask_file);
1183 /* Instantiate method for XBM's. */
1186 x_xbm_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1187 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1188 int dest_mask, Lisp_Object domain)
1190 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1191 const char *ext_data;
1193 assert (!NILP (data));
1195 LISP_STRING_TO_EXTERNAL (XCAR (XCDR (XCDR (data))), ext_data, Qbinary);
1197 xbm_instantiate_1 (image_instance, instantiator, pointer_fg,
1198 pointer_bg, dest_mask, XINT (XCAR (data)),
1199 XINT (XCAR (XCDR (data))), ext_data);
1205 /**********************************************************************
1207 **********************************************************************/
1208 /* xpm 3.2g and better has XpmCreatePixmapFromBuffer()...
1209 There was no version number in xpm.h before 3.3, but this should do.
1211 #if (XpmVersion >= 3) || defined(XpmExactColors)
1212 # define XPM_DOES_BUFFERS
1215 #ifndef XPM_DOES_BUFFERS
1216 Your version of XPM is too old. You cannot compile with it.
1217 Upgrade to version 3.2g or better or compile with --with-xpm=no.
1218 #endif /* !XPM_DOES_BUFFERS */
1220 static XpmColorSymbol *
1221 extract_xpm_color_names (XpmAttributes *xpmattrs, Lisp_Object device,
1223 Lisp_Object color_symbol_alist)
1225 /* This function can GC */
1226 Display *dpy = DEVICE_X_DISPLAY (XDEVICE(device));
1227 Colormap cmap = DEVICE_X_COLORMAP (XDEVICE(device));
1230 Lisp_Object results = Qnil;
1232 XpmColorSymbol *symbols;
1233 struct gcpro gcpro1, gcpro2;
1235 GCPRO2 (results, device);
1237 /* We built up results to be (("name" . #<color>) ...) so that if an
1238 error happens we don't lose any malloc()ed data, or more importantly,
1239 leave any pixels allocated in the server. */
1241 LIST_LOOP (rest, color_symbol_alist)
1243 Lisp_Object cons = XCAR (rest);
1244 Lisp_Object name = XCAR (cons);
1245 Lisp_Object value = XCDR (cons);
1248 if (STRINGP (value))
1250 Fmake_color_instance
1251 (value, device, encode_error_behavior_flag (ERROR_ME_NOT));
1254 assert (COLOR_SPECIFIERP (value));
1255 value = Fspecifier_instance (value, domain, Qnil, Qnil);
1259 results = noseeum_cons (noseeum_cons (name, value), results);
1262 UNGCPRO; /* no more evaluation */
1264 if (i == 0) return 0;
1266 symbols = xnew_array (XpmColorSymbol, i);
1267 xpmattrs->valuemask |= XpmColorSymbols;
1268 xpmattrs->colorsymbols = symbols;
1269 xpmattrs->numsymbols = i;
1273 Lisp_Object cons = XCAR (results);
1274 color = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (XCDR (cons)));
1275 /* Duplicate the pixel value so that we still have a lock on it if
1276 the pixel we were passed is later freed. */
1277 if (! XAllocColor (dpy, cmap, &color))
1278 abort (); /* it must be allocable since we're just duplicating it */
1280 symbols [i].name = (char *) XSTRING_DATA (XCAR (cons));
1281 symbols [i].pixel = color.pixel;
1282 symbols [i].value = 0;
1283 free_cons (XCONS (cons));
1285 results = XCDR (results);
1286 free_cons (XCONS (cons));
1292 xpm_free (XpmAttributes *xpmattrs)
1294 /* Could conceivably lose if XpmXXX returned an error without first
1295 initializing this structure, if we didn't know that initializing it
1296 to all zeros was ok (and also that it's ok to call XpmFreeAttributes()
1297 multiple times, since it zeros slots as it frees them...) */
1298 XpmFreeAttributes (xpmattrs);
1302 x_xpm_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1303 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1304 int dest_mask, Lisp_Object domain)
1306 /* This function can GC */
1307 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1308 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
1309 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1317 XpmAttributes xpmattrs;
1319 XpmColorSymbol *color_symbols;
1320 Lisp_Object color_symbol_alist = find_keyword_in_vector (instantiator,
1322 enum image_instance_type type;
1326 if (!DEVICE_X_P (XDEVICE (device)))
1327 signal_simple_error ("Not an X device", device);
1329 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
1330 xs = DefaultScreenOfDisplay (dpy);
1332 if (dest_mask & IMAGE_COLOR_PIXMAP_MASK)
1333 type = IMAGE_COLOR_PIXMAP;
1334 else if (dest_mask & IMAGE_MONO_PIXMAP_MASK)
1335 type = IMAGE_MONO_PIXMAP;
1336 else if (dest_mask & IMAGE_POINTER_MASK)
1337 type = IMAGE_POINTER;
1339 incompatible_image_types (instantiator, dest_mask,
1340 IMAGE_MONO_PIXMAP_MASK | IMAGE_COLOR_PIXMAP_MASK
1341 | IMAGE_POINTER_MASK);
1342 force_mono = (type != IMAGE_COLOR_PIXMAP);
1345 /* Although I haven't found it documented yet, it appears that pointers are
1346 always colored via the default window colormap... Sigh. */
1347 if (type == IMAGE_POINTER)
1349 cmap = DefaultColormap(dpy, DefaultScreen(dpy));
1350 depth = DefaultDepthOfScreen (xs);
1351 visual = DefaultVisualOfScreen (xs);
1355 cmap = DEVICE_X_COLORMAP (XDEVICE(device));
1356 depth = DEVICE_X_DEPTH (XDEVICE(device));
1357 visual = DEVICE_X_VISUAL (XDEVICE(device));
1360 cmap = DEVICE_X_COLORMAP (XDEVICE(device));
1361 depth = DEVICE_X_DEPTH (XDEVICE(device));
1362 visual = DEVICE_X_VISUAL (XDEVICE(device));
1365 x_initialize_pixmap_image_instance (ii, 1, type);
1367 assert (!NILP (data));
1371 xzero (xpmattrs); /* want XpmInitAttributes() */
1372 xpmattrs.valuemask = XpmReturnPixels;
1375 /* Without this, we get a 1-bit version of the color image, which
1376 isn't quite right. With this, we get the mono image, which might
1377 be very different looking. */
1378 xpmattrs.valuemask |= XpmColorKey;
1379 xpmattrs.color_key = XPM_MONO;
1381 xpmattrs.valuemask |= XpmDepth;
1385 xpmattrs.closeness = 65535;
1386 xpmattrs.valuemask |= XpmCloseness;
1387 xpmattrs.depth = depth;
1388 xpmattrs.valuemask |= XpmDepth;
1389 xpmattrs.visual = visual;
1390 xpmattrs.valuemask |= XpmVisual;
1391 xpmattrs.colormap = cmap;
1392 xpmattrs.valuemask |= XpmColormap;
1395 color_symbols = extract_xpm_color_names (&xpmattrs, device, domain,
1396 color_symbol_alist);
1398 result = XpmCreatePixmapFromBuffer (dpy,
1399 XtWindow(DEVICE_XT_APP_SHELL (XDEVICE(device))),
1400 (char *) XSTRING_DATA (data),
1401 &pixmap, &mask, &xpmattrs);
1405 xfree (color_symbols);
1406 xpmattrs.colorsymbols = 0; /* in case XpmFreeAttr is too smart... */
1407 xpmattrs.numsymbols = 0;
1414 case XpmFileInvalid:
1416 xpm_free (&xpmattrs);
1417 signal_image_error ("invalid XPM data", data);
1419 case XpmColorFailed:
1422 xpm_free (&xpmattrs);
1425 /* second time; blow out. */
1426 signal_double_file_error ("Reading pixmap data",
1427 "color allocation failed",
1432 if (! (dest_mask & IMAGE_MONO_PIXMAP_MASK))
1434 /* second time; blow out. */
1435 signal_double_file_error ("Reading pixmap data",
1436 "color allocation failed",
1440 IMAGE_INSTANCE_TYPE (ii) = IMAGE_MONO_PIXMAP;
1446 xpm_free (&xpmattrs);
1447 signal_double_file_error ("Parsing pixmap data",
1448 "out of memory", data);
1452 xpm_free (&xpmattrs);
1453 signal_double_file_error_2 ("Parsing pixmap data",
1454 "unknown error code",
1455 make_int (result), data);
1460 h = xpmattrs.height;
1463 int npixels = xpmattrs.npixels;
1468 pixels = xnew_array (Pixel, npixels);
1469 memcpy (pixels, xpmattrs.pixels, npixels * sizeof (Pixel));
1474 IMAGE_INSTANCE_X_PIXMAP (ii) = pixmap;
1475 IMAGE_INSTANCE_PIXMAP_MASK (ii) = (void*)mask;
1476 IMAGE_INSTANCE_X_COLORMAP (ii) = cmap;
1477 IMAGE_INSTANCE_X_PIXELS (ii) = pixels;
1478 IMAGE_INSTANCE_X_NPIXELS (ii) = npixels;
1479 IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = w;
1480 IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = h;
1481 IMAGE_INSTANCE_PIXMAP_FILENAME (ii) =
1482 find_keyword_in_vector (instantiator, Q_file);
1487 case IMAGE_MONO_PIXMAP:
1490 case IMAGE_COLOR_PIXMAP:
1492 IMAGE_INSTANCE_PIXMAP_DEPTH (ii) = depth;
1498 int npixels = xpmattrs.npixels;
1499 Pixel *pixels = xpmattrs.pixels;
1502 int xhot = 0, yhot = 0;
1504 if (xpmattrs.valuemask & XpmHotspot)
1506 xhot = xpmattrs.x_hotspot;
1507 XSETINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii), xpmattrs.x_hotspot);
1509 if (xpmattrs.valuemask & XpmHotspot)
1511 yhot = xpmattrs.y_hotspot;
1512 XSETINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii), xpmattrs.y_hotspot);
1514 check_pointer_sizes (xs, w, h, instantiator);
1516 /* If the loaded pixmap has colors allocated (meaning it came from an
1517 XPM file), then use those as the default colors for the cursor we
1518 create. Otherwise, default to pointer_fg and pointer_bg.
1522 /* With an XBM file, it's obvious which bit is foreground
1523 and which is background, or rather, it's implicit: in
1524 an XBM file, a 1 bit is foreground, and a 0 bit is
1527 XCreatePixmapCursor() assumes this property of the
1528 pixmap it is called with as well; the `foreground'
1529 color argument is used for the 1 bits.
1531 With an XPM file, it's tricker, since the elements of
1532 the pixmap don't represent FG and BG, but are actual
1533 pixel values. So we need to figure out which of those
1534 pixels is the foreground color and which is the
1535 background. We do it by comparing RGB and assuming
1536 that the darker color is the foreground. This works
1537 with the result of xbmtopbm|ppmtoxpm, at least.
1539 It might be nice if there was some way to tag the
1540 colors in the XPM file with whether they are the
1541 foreground - perhaps with logical color names somehow?
1543 Once we have decided which color is the foreground, we
1544 need to ensure that that color corresponds to a `1' bit
1545 in the Pixmap. The XPM library wrote into the (1-bit)
1546 pixmap with XPutPixel, which will ignore all but the
1547 least significant bit.
1549 This means that a 1 bit in the image corresponds to
1550 `fg' only if `fg.pixel' is odd.
1552 (This also means that the image will be all the same
1553 color if both `fg' and `bg' are odd or even, but we can
1554 safely assume that that won't happen if the XPM file is
1557 The desired result is that the image use `1' to
1558 represent the foreground color, and `0' to represent
1559 the background color. So, we may need to invert the
1560 image to accomplish this; we invert if fg is
1561 odd. (Remember that WhitePixel and BlackPixel are not
1562 necessarily 1 and 0 respectively, though I think it
1563 might be safe to assume that one of them is always 1
1564 and the other is always 0. We also pretty much need to
1565 assume that one is even and the other is odd.)
1568 fg.pixel = pixels[0]; /* pick a pixel at random. */
1569 bg.pixel = fg.pixel;
1570 for (i = 1; i < npixels; i++) /* Look for an "other" pixel value.*/
1572 bg.pixel = pixels[i];
1573 if (fg.pixel != bg.pixel)
1577 /* If (fg.pixel == bg.pixel) then probably something has
1578 gone wrong, but I don't think signalling an error would
1581 XQueryColor (dpy, cmap, &fg);
1582 XQueryColor (dpy, cmap, &bg);
1584 /* If the foreground is lighter than the background, swap them.
1585 (This occurs semi-randomly, depending on the ordering of the
1586 color list in the XPM file.)
1589 unsigned short fg_total = ((fg.red / 3) + (fg.green / 3)
1591 unsigned short bg_total = ((bg.red / 3) + (bg.green / 3)
1593 if (fg_total > bg_total)
1602 /* If the fg pixel corresponds to a `0' in the bitmap, invert it.
1603 (This occurs (only?) on servers with Black=0, White=1.)
1605 if ((fg.pixel & 1) == 0)
1609 gcv.function = GXxor;
1611 gc = XCreateGC (dpy, pixmap, (GCFunction | GCForeground),
1613 XFillRectangle (dpy, pixmap, gc, 0, 0, w, h);
1619 generate_cursor_fg_bg (device, &pointer_fg, &pointer_bg,
1621 IMAGE_INSTANCE_PIXMAP_FG (ii) = pointer_fg;
1622 IMAGE_INSTANCE_PIXMAP_BG (ii) = pointer_bg;
1625 IMAGE_INSTANCE_X_CURSOR (ii) =
1627 (dpy, pixmap, mask, &fg, &bg, xhot, yhot);
1636 xpm_free (&xpmattrs); /* after we've read pixels and hotspot */
1639 #endif /* HAVE_XPM */
1644 /**********************************************************************
1646 **********************************************************************/
1648 /* This is about to get redefined! */
1651 /* We have to define SYSV32 so that compface.h includes string.h
1652 instead of strings.h. */
1657 #include <compface.h>
1661 /* JMP_BUF cannot be used here because if it doesn't get defined
1662 to jmp_buf we end up with a conflicting type error with the
1663 definition in compface.h */
1664 extern jmp_buf comp_env;
1668 x_xface_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1669 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1670 int dest_mask, Lisp_Object domain)
1672 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1676 const char * volatile emsg = 0;
1677 const char * volatile dstring;
1679 assert (!NILP (data));
1681 LISP_STRING_TO_EXTERNAL (data, dstring, Qbinary);
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,
1746 Lisp_Object dest_mask)
1748 Lisp_Object file = find_keyword_in_vector (instantiator, Q_data);
1749 Lisp_Object filename = Qnil;
1750 Lisp_Object data = Qnil;
1751 struct gcpro gcpro1, gcpro2, gcpro3;
1752 Lisp_Object alist = Qnil;
1754 GCPRO3 (filename, data, alist);
1756 if (NILP (file)) /* no conversion necessary */
1757 RETURN_UNGCPRO (instantiator);
1759 alist = tagged_vector_to_alist (instantiator);
1761 filename = locate_pixmap_file (file);
1762 if (!NILP (filename))
1765 /* #### Apparently some versions of XpmReadFileToData, which is
1766 called by pixmap_to_lisp_data, don't return an error value
1767 if the given file is not a valid XPM file. Instead, they
1768 just seg fault. It is definitely caused by passing a
1769 bitmap. To try and avoid this we check for bitmaps first. */
1771 data = bitmap_to_lisp_data (filename, &xhot, &yhot, 1);
1775 alist = remassq_no_quit (Q_data, alist);
1776 alist = Fcons (Fcons (Q_file, filename),
1777 Fcons (Fcons (Q_data, data), alist));
1779 alist = Fcons (Fcons (Q_hotspot_x, make_int (xhot)),
1782 alist = Fcons (Fcons (Q_hotspot_y, make_int (yhot)),
1785 alist = xbm_mask_file_munging (alist, filename, Qnil, console_type);
1788 Lisp_Object result = alist_to_tagged_vector (Qxbm, alist);
1790 RETURN_UNGCPRO (result);
1795 data = pixmap_to_lisp_data (filename, 1);
1799 alist = remassq_no_quit (Q_data, alist);
1800 alist = Fcons (Fcons (Q_file, filename),
1801 Fcons (Fcons (Q_data, data), alist));
1802 alist = Fcons (Fcons (Q_color_symbols,
1803 evaluate_xpm_color_symbols ()),
1806 Lisp_Object result = alist_to_tagged_vector (Qxpm, alist);
1808 RETURN_UNGCPRO (result);
1814 /* If we couldn't convert it, just put it back as it is.
1815 We might try to further frob it later as a cursor-font
1816 specification. (We can't do that now because we don't know
1817 what dest-types it's going to be instantiated into.) */
1819 Lisp_Object result = alist_to_tagged_vector (Qautodetect, alist);
1821 RETURN_UNGCPRO (result);
1826 autodetect_possible_dest_types (void)
1829 IMAGE_MONO_PIXMAP_MASK |
1830 IMAGE_COLOR_PIXMAP_MASK |
1831 IMAGE_POINTER_MASK |
1836 autodetect_instantiate (Lisp_Object image_instance,
1837 Lisp_Object instantiator,
1838 Lisp_Object pointer_fg,
1839 Lisp_Object pointer_bg,
1840 int dest_mask, Lisp_Object domain)
1842 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1843 struct gcpro gcpro1, gcpro2, gcpro3;
1844 Lisp_Object alist = Qnil;
1845 Lisp_Object result = Qnil;
1846 int is_cursor_font = 0;
1848 GCPRO3 (data, alist, result);
1850 alist = tagged_vector_to_alist (instantiator);
1851 if (dest_mask & IMAGE_POINTER_MASK)
1853 const char *name_ext;
1854 LISP_STRING_TO_EXTERNAL (data, name_ext, Qfile_name);
1855 if (XmuCursorNameToIndex (name_ext) != -1)
1857 result = alist_to_tagged_vector (Qcursor_font, alist);
1862 if (!is_cursor_font)
1863 result = alist_to_tagged_vector (Qstring, alist);
1867 cursor_font_instantiate (image_instance, result, pointer_fg,
1868 pointer_bg, dest_mask, domain);
1870 string_instantiate (image_instance, result, pointer_fg,
1871 pointer_bg, dest_mask, domain);
1877 /**********************************************************************
1879 **********************************************************************/
1882 font_validate (Lisp_Object instantiator)
1884 data_must_be_present (instantiator);
1887 /* XmuCvtStringToCursor is bogus in the following ways:
1889 - When it can't convert the given string to a real cursor, it will
1890 sometimes return a "success" value, after triggering a BadPixmap
1891 error. It then gives you a cursor that will itself generate BadCursor
1892 errors. So we install this error handler to catch/notice the X error
1893 and take that as meaning "couldn't convert."
1895 - When you tell it to find a cursor file that doesn't exist, it prints
1896 an error message on stderr. You can't make it not do that.
1898 - Also, using Xmu means we can't properly hack Lisp_Image_Instance
1899 objects, or XPM files, or $XBMLANGPATH.
1902 /* Duplicate the behavior of XmuCvtStringToCursor() to bypass its bogusness. */
1904 static int XLoadFont_got_error;
1907 XLoadFont_error_handler (Display *dpy, XErrorEvent *xerror)
1909 XLoadFont_got_error = 1;
1914 safe_XLoadFont (Display *dpy, char *name)
1917 int (*old_handler) (Display *, XErrorEvent *);
1918 XLoadFont_got_error = 0;
1920 old_handler = XSetErrorHandler (XLoadFont_error_handler);
1921 font = XLoadFont (dpy, name);
1923 XSetErrorHandler (old_handler);
1924 if (XLoadFont_got_error) return 0;
1929 font_possible_dest_types (void)
1931 return IMAGE_POINTER_MASK;
1935 font_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1936 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1937 int dest_mask, Lisp_Object domain)
1939 /* This function can GC */
1940 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1941 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1942 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
1946 char source_name[MAXPATHLEN], mask_name[MAXPATHLEN], dummy;
1947 int source_char, mask_char;
1949 Lisp_Object foreground, background;
1951 if (!DEVICE_X_P (XDEVICE (device)))
1952 signal_simple_error ("Not an X device", device);
1954 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
1956 if (!STRINGP (data) ||
1957 strncmp ("FONT ", (char *) XSTRING_DATA (data), 5))
1958 signal_simple_error ("Invalid font-glyph instantiator",
1961 if (!(dest_mask & IMAGE_POINTER_MASK))
1962 incompatible_image_types (instantiator, dest_mask, IMAGE_POINTER_MASK);
1964 foreground = find_keyword_in_vector (instantiator, Q_foreground);
1965 if (NILP (foreground))
1966 foreground = pointer_fg;
1967 background = find_keyword_in_vector (instantiator, Q_background);
1968 if (NILP (background))
1969 background = pointer_bg;
1971 generate_cursor_fg_bg (device, &foreground, &background, &fg, &bg);
1973 count = sscanf ((char *) XSTRING_DATA (data),
1974 "FONT %s %d %s %d %c",
1975 source_name, &source_char,
1976 mask_name, &mask_char, &dummy);
1977 /* Allow "%s %d %d" as well... */
1978 if (count == 3 && (1 == sscanf (mask_name, "%d %c", &mask_char, &dummy)))
1979 count = 4, mask_name[0] = 0;
1981 if (count != 2 && count != 4)
1982 signal_simple_error ("invalid cursor specification", data);
1983 source = safe_XLoadFont (dpy, source_name);
1985 signal_simple_error_2 ("couldn't load font",
1986 build_string (source_name),
1990 else if (!mask_name[0])
1994 mask = safe_XLoadFont (dpy, mask_name);
1997 Fsignal (Qerror, list3 (build_string ("couldn't load font"),
1998 build_string (mask_name), data));
2003 /* #### call XQueryTextExtents() and check_pointer_sizes() here. */
2005 x_initialize_pixmap_image_instance (ii, 1, IMAGE_POINTER);
2006 IMAGE_INSTANCE_X_CURSOR (ii) =
2007 XCreateGlyphCursor (dpy, source, mask, source_char, mask_char,
2009 XIMAGE_INSTANCE_PIXMAP_FG (image_instance) = foreground;
2010 XIMAGE_INSTANCE_PIXMAP_BG (image_instance) = background;
2011 XUnloadFont (dpy, source);
2012 if (mask && mask != source) XUnloadFont (dpy, mask);
2016 /**********************************************************************
2018 **********************************************************************/
2021 cursor_font_validate (Lisp_Object instantiator)
2023 data_must_be_present (instantiator);
2027 cursor_font_possible_dest_types (void)
2029 return IMAGE_POINTER_MASK;
2033 cursor_font_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2034 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2035 int dest_mask, Lisp_Object domain)
2037 /* This function can GC */
2038 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
2039 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2040 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
2043 const char *name_ext;
2044 Lisp_Object foreground, background;
2046 if (!DEVICE_X_P (XDEVICE (device)))
2047 signal_simple_error ("Not an X device", device);
2049 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
2051 if (!(dest_mask & IMAGE_POINTER_MASK))
2052 incompatible_image_types (instantiator, dest_mask, IMAGE_POINTER_MASK);
2054 LISP_STRING_TO_EXTERNAL (data, name_ext, Qfile_name);
2055 if ((i = XmuCursorNameToIndex (name_ext)) == -1)
2056 signal_simple_error ("Unrecognized cursor-font name", data);
2058 x_initialize_pixmap_image_instance (ii, 1, IMAGE_POINTER);
2059 IMAGE_INSTANCE_X_CURSOR (ii) = XCreateFontCursor (dpy, i);
2060 foreground = find_keyword_in_vector (instantiator, Q_foreground);
2061 if (NILP (foreground))
2062 foreground = pointer_fg;
2063 background = find_keyword_in_vector (instantiator, Q_background);
2064 if (NILP (background))
2065 background = pointer_bg;
2066 maybe_recolor_cursor (image_instance, foreground, background);
2070 x_colorize_image_instance (Lisp_Object image_instance,
2071 Lisp_Object foreground, Lisp_Object background)
2073 Lisp_Image_Instance *p;
2075 p = XIMAGE_INSTANCE (image_instance);
2077 switch (IMAGE_INSTANCE_TYPE (p))
2079 case IMAGE_MONO_PIXMAP:
2080 IMAGE_INSTANCE_TYPE (p) = IMAGE_COLOR_PIXMAP;
2081 /* Make sure there aren't two pointers to the same mask, causing
2082 it to get freed twice. */
2083 IMAGE_INSTANCE_PIXMAP_MASK (p) = 0;
2091 Display *dpy = DEVICE_X_DISPLAY (XDEVICE (IMAGE_INSTANCE_DEVICE (p)));
2092 Drawable draw = XtWindow(DEVICE_XT_APP_SHELL (XDEVICE (IMAGE_INSTANCE_DEVICE (p))));
2093 Dimension d = DEVICE_X_DEPTH (XDEVICE (IMAGE_INSTANCE_DEVICE (p)));
2094 Pixmap new = XCreatePixmap (dpy, draw,
2095 IMAGE_INSTANCE_PIXMAP_WIDTH (p),
2096 IMAGE_INSTANCE_PIXMAP_HEIGHT (p), d);
2100 color = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (foreground));
2101 gcv.foreground = color.pixel;
2102 color = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (background));
2103 gcv.background = color.pixel;
2104 gc = XCreateGC (dpy, new, GCBackground|GCForeground, &gcv);
2105 XCopyPlane (dpy, IMAGE_INSTANCE_X_PIXMAP (p), new, gc, 0, 0,
2106 IMAGE_INSTANCE_PIXMAP_WIDTH (p),
2107 IMAGE_INSTANCE_PIXMAP_HEIGHT (p),
2110 IMAGE_INSTANCE_X_PIXMAP (p) = new;
2111 IMAGE_INSTANCE_PIXMAP_DEPTH (p) = d;
2112 IMAGE_INSTANCE_PIXMAP_FG (p) = foreground;
2113 IMAGE_INSTANCE_PIXMAP_BG (p) = background;
2119 /************************************************************************/
2120 /* subwindow and widget support */
2121 /************************************************************************/
2123 /* unmap the image if it is a widget. This is used by redisplay via
2124 redisplay_unmap_subwindows */
2126 x_unmap_subwindow (Lisp_Image_Instance *p)
2128 if (IMAGE_INSTANCE_TYPE (p) == IMAGE_SUBWINDOW)
2131 (IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY (p),
2132 IMAGE_INSTANCE_X_CLIPWINDOW (p));
2134 else /* must be a widget */
2136 /* Since we are being unmapped we want the enclosing frame to
2137 get focus. The losing with simple scrolling but is the safest
2139 emacs_Xt_handle_widget_losing_focus
2140 ( XFRAME (IMAGE_INSTANCE_FRAME (p)),
2141 IMAGE_INSTANCE_X_WIDGET_ID (p));
2142 XtUnmapWidget (IMAGE_INSTANCE_X_CLIPWIDGET (p));
2146 /* map the subwindow. This is used by redisplay via
2147 redisplay_output_subwindow */
2149 x_map_subwindow (Lisp_Image_Instance *p, int x, int y,
2150 struct display_glyph_area* dga)
2152 assert (dga->width > 0 && dga->height > 0);
2153 if (IMAGE_INSTANCE_TYPE (p) == IMAGE_SUBWINDOW)
2155 Window subwindow = IMAGE_INSTANCE_X_SUBWINDOW_ID (p);
2156 XMoveResizeWindow (IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY (p),
2157 IMAGE_INSTANCE_X_CLIPWINDOW (p),
2158 x, y, dga->width, dga->height);
2159 XMoveWindow (IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY (p),
2160 subwindow, -dga->xoffset, -dga->yoffset);
2161 if (!IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (p))
2162 XMapWindow (IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY (p),
2163 IMAGE_INSTANCE_X_CLIPWINDOW (p));
2165 else /* must be a widget */
2167 XtConfigureWidget (IMAGE_INSTANCE_X_CLIPWIDGET (p),
2168 x + IMAGE_INSTANCE_X_WIDGET_XOFFSET (p),
2169 y + IMAGE_INSTANCE_X_WIDGET_YOFFSET (p),
2170 dga->width, dga->height, 0);
2171 XtMoveWidget (IMAGE_INSTANCE_X_WIDGET_ID (p),
2172 -dga->xoffset, -dga->yoffset);
2173 if (!IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (p))
2174 XtMapWidget (IMAGE_INSTANCE_X_CLIPWIDGET (p));
2178 /* when you click on a widget you may activate another widget this
2179 needs to be checked and all appropriate widgets updated */
2181 x_redisplay_subwindow (Lisp_Image_Instance *p)
2183 /* Update the subwindow size if necessary. */
2184 if (IMAGE_INSTANCE_SIZE_CHANGED (p))
2186 XResizeWindow (IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY (p),
2187 IMAGE_INSTANCE_X_SUBWINDOW_ID (p),
2188 IMAGE_INSTANCE_WIDTH (p),
2189 IMAGE_INSTANCE_HEIGHT (p));
2193 /* Update all attributes that have changed. Lwlib actually does most
2196 x_redisplay_widget (Lisp_Image_Instance *p)
2198 /* This function can GC if IN_REDISPLAY is false. */
2200 widget_value* wv = 0;
2202 /* First get the items if they have changed since this is a
2203 structural change. As such it will nuke all added values so we
2204 need to update most other things after the items have changed.*/
2205 if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (p))
2207 Lisp_Object image_instance;
2209 XSETIMAGE_INSTANCE (image_instance, p);
2210 wv = gui_items_to_widget_values
2211 (image_instance, IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (p),
2212 /* #### this is not right; we need to keep track of which widgets
2213 want accelerators and which don't */ 0);
2214 wv->change = STRUCTURAL_CHANGE;
2218 /* Assume the lotus position, breath deeply and chant to
2219 yourself lwlibsux, lwlibsux ... lw_get_all_values returns a
2220 reference to the real values rather than a copy thus any
2221 changes we make to the values we get back will look like they
2222 have already been applied. If we rebuild the widget tree then
2223 we may lose properties. */
2224 wv = copy_widget_value_tree (lw_get_all_values
2225 (IMAGE_INSTANCE_X_WIDGET_LWID (p)),
2229 /* Possibly update the colors and font */
2230 if (IMAGE_INSTANCE_WIDGET_FACE_CHANGED (p)
2232 /* #### This is not sufficient because it will not cope with widgets
2233 that are not currently visible. Once redisplay has done the
2234 visible ones it will clear this flag so that when new ones
2235 become visible they will not be updated. */
2236 XFRAME (IMAGE_INSTANCE_FRAME (p))->faces_changed
2238 XFRAME (IMAGE_INSTANCE_FRAME (p))->frame_changed
2240 IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (p))
2242 update_widget_face (wv, p, IMAGE_INSTANCE_FRAME (p));
2245 /* Possibly update the text. */
2246 if (IMAGE_INSTANCE_TEXT_CHANGED (p))
2249 Lisp_Object val = IMAGE_INSTANCE_WIDGET_TEXT (p);
2250 LISP_STRING_TO_EXTERNAL (val, str, Qnative);
2254 /* Possibly update the size. */
2255 if (IMAGE_INSTANCE_SIZE_CHANGED (p)
2257 IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (p)
2259 IMAGE_INSTANCE_TEXT_CHANGED (p))
2261 assert (IMAGE_INSTANCE_X_WIDGET_ID (p) &&
2262 IMAGE_INSTANCE_X_CLIPWIDGET (p)) ;
2264 if (IMAGE_INSTANCE_X_WIDGET_ID (p)->core.being_destroyed
2265 || !XtIsManaged(IMAGE_INSTANCE_X_WIDGET_ID (p)))
2268 XSETIMAGE_INSTANCE (sw, p);
2269 signal_simple_error ("XEmacs bug: subwindow is deleted", sw);
2272 lw_add_widget_value_arg (wv, XtNwidth,
2273 (Dimension)IMAGE_INSTANCE_WIDTH (p));
2274 lw_add_widget_value_arg (wv, XtNheight,
2275 (Dimension)IMAGE_INSTANCE_HEIGHT (p));
2278 /* Adjust offsets within the frame. */
2279 if (XFRAME (IMAGE_INSTANCE_FRAME (p))->size_changed)
2282 XtSetArg (al [0], XtNx, &IMAGE_INSTANCE_X_WIDGET_XOFFSET (p));
2283 XtSetArg (al [1], XtNy, &IMAGE_INSTANCE_X_WIDGET_YOFFSET (p));
2284 XtGetValues (FRAME_X_TEXT_WIDGET
2285 (XFRAME (IMAGE_INSTANCE_FRAME (p))), al, 2);
2288 /* now modify the widget */
2289 lw_modify_all_widgets (IMAGE_INSTANCE_X_WIDGET_LWID (p),
2291 free_widget_value_tree (wv);
2295 /* instantiate and x type subwindow */
2297 x_subwindow_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2298 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2299 int dest_mask, Lisp_Object domain)
2301 /* This function can GC */
2302 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2303 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
2304 Lisp_Object frame = DOMAIN_FRAME (domain);
2305 struct frame* f = XFRAME (frame);
2309 XSetWindowAttributes xswa;
2311 unsigned int w = IMAGE_INSTANCE_WIDTH (ii),
2312 h = IMAGE_INSTANCE_HEIGHT (ii);
2314 if (!DEVICE_X_P (XDEVICE (device)))
2315 signal_simple_error ("Not an X device", device);
2317 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
2318 xs = DefaultScreenOfDisplay (dpy);
2320 IMAGE_INSTANCE_TYPE (ii) = IMAGE_SUBWINDOW;
2322 pw = XtWindow (FRAME_X_TEXT_WIDGET (f));
2324 ii->data = xnew_and_zero (struct x_subwindow_data);
2326 IMAGE_INSTANCE_X_SUBWINDOW_PARENT (ii) = pw;
2327 IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY (ii) = DisplayOfScreen (xs);
2329 xswa.backing_store = Always;
2330 valueMask |= CWBackingStore;
2331 xswa.colormap = DefaultColormapOfScreen (xs);
2332 valueMask |= CWColormap;
2334 /* Create a window for clipping */
2335 IMAGE_INSTANCE_X_CLIPWINDOW (ii) =
2336 XCreateWindow (dpy, pw, 0, 0, w, h, 0, CopyFromParent,
2337 InputOutput, CopyFromParent, valueMask,
2340 /* Now put the subwindow inside the clip window. */
2341 win = XCreateWindow (dpy, IMAGE_INSTANCE_X_CLIPWINDOW (ii),
2342 0, 0, w, h, 0, CopyFromParent,
2343 InputOutput, CopyFromParent, valueMask,
2346 IMAGE_INSTANCE_SUBWINDOW_ID (ii) = (void*)win;
2350 /* #### Should this function exist? If there's any doubt I'm not implementing it --andyp */
2351 DEFUN ("change-subwindow-property", Fchange_subwindow_property, 3, 3, 0, /*
2352 For the given SUBWINDOW, set PROPERTY to DATA, which is a string.
2353 Subwindows are not currently implemented.
2355 (subwindow, property, data))
2361 CHECK_SUBWINDOW (subwindow);
2362 CHECK_STRING (property);
2363 CHECK_STRING (data);
2365 sw = XSUBWINDOW (subwindow);
2366 dpy = DisplayOfScreen (LISP_DEVICE_TO_X_SCREEN
2367 (FRAME_DEVICE (XFRAME (sw->frame))));
2369 property_atom = XInternAtom (dpy, (char *) XSTRING_DATA (property), False);
2370 XChangeProperty (dpy, sw->subwindow, property_atom, XA_STRING, 8,
2372 XSTRING_DATA (data),
2373 XSTRING_LENGTH (data));
2382 /************************************************************************/
2384 /************************************************************************/
2387 update_widget_face (widget_value* wv, Lisp_Image_Instance *ii,
2390 #ifdef LWLIB_WIDGETS_MOTIF
2391 XmFontList fontList;
2393 /* Update the foreground. */
2394 Lisp_Object pixel = FACE_FOREGROUND
2395 (IMAGE_INSTANCE_WIDGET_FACE (ii),
2397 XColor fcolor = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (pixel)), bcolor;
2398 lw_add_widget_value_arg (wv, XtNforeground, fcolor.pixel);
2400 /* Update the background. */
2401 pixel = FACE_BACKGROUND (IMAGE_INSTANCE_WIDGET_FACE (ii),
2403 bcolor = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (pixel));
2404 lw_add_widget_value_arg (wv, XtNbackground, bcolor.pixel);
2406 #ifdef LWLIB_WIDGETS_MOTIF
2407 fontList = XmFontListCreate
2408 (FONT_INSTANCE_X_FONT
2409 (XFONT_INSTANCE (query_string_font
2410 (IMAGE_INSTANCE_WIDGET_TEXT (ii),
2411 IMAGE_INSTANCE_WIDGET_FACE (ii),
2412 domain))), XmSTRING_DEFAULT_CHARSET);
2413 lw_add_widget_value_arg (wv, XmNfontList, (XtArgVal)fontList);
2415 lw_add_widget_value_arg
2416 (wv, XtNfont, (XtArgVal)FONT_INSTANCE_X_FONT
2417 (XFONT_INSTANCE (query_string_font
2418 (IMAGE_INSTANCE_WIDGET_TEXT (ii),
2419 IMAGE_INSTANCE_WIDGET_FACE (ii),
2421 wv->change = VISIBLE_CHANGE;
2422 /* #### Megahack - but its just getting too complicated to do this
2423 in the right place. */
2424 if (EQ (IMAGE_INSTANCE_WIDGET_TYPE (ii), Qtab_control))
2425 update_tab_widget_face (wv, ii, domain);
2429 update_tab_widget_face (widget_value* wv, Lisp_Image_Instance *ii,
2434 widget_value* val = wv->contents, *cur;
2436 /* Give each child label the correct foreground color. */
2437 Lisp_Object pixel = FACE_FOREGROUND
2438 (IMAGE_INSTANCE_WIDGET_FACE (ii),
2440 XColor fcolor = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (pixel));
2441 lw_add_widget_value_arg (val, XtNtabForeground, fcolor.pixel);
2442 wv->change = VISIBLE_CHANGE;
2443 val->change = VISIBLE_CHANGE;
2445 for (cur = val->next; cur; cur = cur->next)
2447 cur->change = VISIBLE_CHANGE;
2450 lw_copy_widget_value_args (val, cur);
2457 x_widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2458 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2459 int dest_mask, Lisp_Object domain,
2460 const char* type, widget_value* wv)
2462 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2463 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii), pixel;
2464 struct device* d = XDEVICE (device);
2465 Lisp_Object frame = DOMAIN_FRAME (domain);
2466 struct frame* f = XFRAME (frame);
2471 int id = new_lwlib_id ();
2472 widget_value* clip_wv;
2473 XColor fcolor, bcolor;
2475 if (!DEVICE_X_P (d))
2476 signal_simple_error ("Not an X device", device);
2478 /* have to set the type this late in case there is no device
2479 instantiation for a widget. But we can go ahead and do it without
2480 checking because there is always a generic instantiator. */
2481 IMAGE_INSTANCE_TYPE (ii) = IMAGE_WIDGET;
2483 if (!NILP (IMAGE_INSTANCE_WIDGET_TEXT (ii)))
2484 LISP_STRING_TO_EXTERNAL (IMAGE_INSTANCE_WIDGET_TEXT (ii), nm, Qnative);
2486 ii->data = xnew_and_zero (struct x_subwindow_data);
2488 /* Create a clip window to contain the subwidget. Incredibly the
2489 XEmacs manager seems to be the most appropriate widget for
2490 this. Nothing else is simple enough and yet does what is
2492 clip_wv = xmalloc_widget_value ();
2494 lw_add_widget_value_arg (clip_wv, XtNresize, False);
2495 lw_add_widget_value_arg (clip_wv, XtNwidth,
2496 (Dimension)IMAGE_INSTANCE_WIDTH (ii));
2497 lw_add_widget_value_arg (clip_wv, XtNheight,
2498 (Dimension)IMAGE_INSTANCE_HEIGHT (ii));
2499 clip_wv->enabled = True;
2501 clip_wv->name = xstrdup ("clip-window");
2502 clip_wv->value = xstrdup ("clip-window");
2504 IMAGE_INSTANCE_X_CLIPWIDGET (ii)
2505 = lw_create_widget ("clip-window", "clip-window", new_lwlib_id (),
2506 clip_wv, FRAME_X_CONTAINER_WIDGET (f),
2509 free_widget_value_tree (clip_wv);
2511 /* copy any args we were given */
2513 lw_add_value_args_to_args (wv, al, &ac);
2515 /* Fixup the colors. We have to do this *before* the widget gets
2516 created so that Motif will fix up the shadow colors
2517 correctly. Once the widget is created Motif won't do this
2519 pixel = FACE_FOREGROUND
2520 (IMAGE_INSTANCE_WIDGET_FACE (ii),
2521 IMAGE_INSTANCE_FRAME (ii));
2522 fcolor = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (pixel));
2524 pixel = FACE_BACKGROUND
2525 (IMAGE_INSTANCE_WIDGET_FACE (ii),
2526 IMAGE_INSTANCE_FRAME (ii));
2527 bcolor = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (pixel));
2529 lw_add_widget_value_arg (wv, XtNbackground, bcolor.pixel);
2530 lw_add_widget_value_arg (wv, XtNforeground, fcolor.pixel);
2531 /* we cannot allow widgets to resize themselves */
2532 lw_add_widget_value_arg (wv, XtNresize, False);
2533 lw_add_widget_value_arg (wv, XtNwidth,
2534 (Dimension)IMAGE_INSTANCE_WIDTH (ii));
2535 lw_add_widget_value_arg (wv, XtNheight,
2536 (Dimension)IMAGE_INSTANCE_HEIGHT (ii));
2537 /* update the font. */
2538 update_widget_face (wv, ii, domain);
2540 wid = lw_create_widget (type, wv->name, id, wv, IMAGE_INSTANCE_X_CLIPWIDGET (ii),
2541 False, 0, popup_selection_callback, 0);
2543 IMAGE_INSTANCE_SUBWINDOW_ID (ii) = (void*)wid;
2544 IMAGE_INSTANCE_X_WIDGET_LWID (ii) = id;
2545 /* because the EmacsManager is the widgets parent we have to
2546 offset the redisplay of the widget by the amount the text
2547 widget is inside the manager. */
2549 XtSetArg (al [ac], XtNx, &IMAGE_INSTANCE_X_WIDGET_XOFFSET (ii)); ac++;
2550 XtSetArg (al [ac], XtNy, &IMAGE_INSTANCE_X_WIDGET_YOFFSET (ii)); ac++;
2551 XtGetValues (FRAME_X_TEXT_WIDGET (f), al, ac);
2553 XtSetMappedWhenManaged (wid, TRUE);
2555 free_widget_value_tree (wv);
2556 /* A kludgy but simple way to make sure the callback for a widget
2557 doesn't get deleted. */
2558 gcpro_popup_callbacks (id);
2561 /* get properties of a control */
2563 x_widget_property (Lisp_Object image_instance, Lisp_Object prop)
2565 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2566 /* get the text from a control */
2567 if (EQ (prop, Q_text))
2569 widget_value* wv = lw_get_all_values (IMAGE_INSTANCE_X_WIDGET_LWID (ii));
2570 return build_ext_string (wv->value, Qnative);
2575 /* Instantiate a layout control for putting other widgets in. */
2577 x_native_layout_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2578 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2579 int dest_mask, Lisp_Object domain)
2581 x_widget_instantiate (image_instance, instantiator, pointer_fg,
2582 pointer_bg, dest_mask, domain, "layout", 0);
2585 /* Instantiate a button widget. Unfortunately instantiated widgets are
2586 particular to a frame since they need to have a parent. It's not
2587 like images where you just select the image into the context you
2588 want to display it in and BitBlt it. So images instances can have a
2589 many-to-one relationship with things you see, whereas widgets can
2590 only be one-to-one (i.e. per frame) */
2592 x_button_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2593 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2594 int dest_mask, Lisp_Object domain)
2596 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2597 Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM (ii);
2598 Lisp_Object glyph = find_keyword_in_vector (instantiator, Q_image);
2599 widget_value* wv = gui_items_to_widget_values (image_instance, gui, 1);
2603 if (!IMAGE_INSTANCEP (glyph))
2604 glyph = glyph_image_instance (glyph, domain, ERROR_ME, 1);
2607 x_widget_instantiate (image_instance, instantiator, pointer_fg,
2608 pointer_bg, dest_mask, domain, "button", wv);
2610 /* add the image if one was given */
2611 if (!NILP (glyph) && IMAGE_INSTANCEP (glyph)
2612 && IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (glyph)))
2616 #ifdef LWLIB_WIDGETS_MOTIF
2617 XtSetArg (al [ac], XmNlabelType, XmPIXMAP); ac++;
2618 XtSetArg (al [ac], XmNlabelPixmap, XIMAGE_INSTANCE_X_PIXMAP (glyph));ac++;
2620 XtSetArg (al [ac], XtNpixmap, XIMAGE_INSTANCE_X_PIXMAP (glyph)); ac++;
2622 XtSetValues (IMAGE_INSTANCE_X_WIDGET_ID (ii), al, ac);
2626 /* Update a button's clicked state.
2628 #### This is overkill, but it works. Right now this causes all
2629 button instances to flash for some reason buried deep in lwlib. In
2630 theory this should be the Right Thing to do since lwlib should only
2631 merge in changed values - and if nothing has changed then nothing
2632 should get done. This may be because of the args stuff,
2633 i.e. although the arg contents may be the same the args look
2634 different and so are re-applied to the widget. */
2636 x_button_redisplay (Lisp_Object image_instance)
2638 /* This function can GC if IN_REDISPLAY is false. */
2639 Lisp_Image_Instance *p = XIMAGE_INSTANCE (image_instance);
2641 gui_items_to_widget_values (image_instance,
2642 IMAGE_INSTANCE_WIDGET_ITEMS (p), 1);
2644 /* now modify the widget */
2645 lw_modify_all_widgets (IMAGE_INSTANCE_X_WIDGET_LWID (p),
2647 free_widget_value_tree (wv);
2650 /* get properties of a button */
2652 x_button_property (Lisp_Object image_instance, Lisp_Object prop)
2654 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2655 /* check the state of a button */
2656 if (EQ (prop, Q_selected))
2658 widget_value* wv = lw_get_all_values (IMAGE_INSTANCE_X_WIDGET_LWID (ii));
2668 /* instantiate a progress gauge */
2670 x_progress_gauge_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2671 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2672 int dest_mask, Lisp_Object domain)
2674 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2675 Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM (ii);
2676 widget_value* wv = gui_items_to_widget_values (image_instance, gui, 0);
2678 x_widget_instantiate (image_instance, instantiator, pointer_fg,
2679 pointer_bg, dest_mask, domain, "progress", wv);
2682 /* set the properties of a progress gauge */
2684 x_progress_gauge_redisplay (Lisp_Object image_instance)
2686 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2688 if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii))
2692 #ifdef ERROR_CHECK_GLYPHS
2693 assert (GUI_ITEMP (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii)));
2695 val = XGUI_ITEM (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii))->value;
2696 XtSetArg (al[0], XtNvalue, XINT (val));
2697 XtSetValues (IMAGE_INSTANCE_X_WIDGET_ID (ii), al, 1);
2701 /* instantiate an edit control */
2703 x_edit_field_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2704 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2705 int dest_mask, Lisp_Object domain)
2707 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2708 Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM (ii);
2709 widget_value* wv = gui_items_to_widget_values (image_instance, gui, 0);
2711 x_widget_instantiate (image_instance, instantiator, pointer_fg,
2712 pointer_bg, dest_mask, domain, "text-field", wv);
2715 #if defined (LWLIB_WIDGETS_MOTIF) && XmVERSION > 1
2716 /* instantiate a combo control */
2718 x_combo_box_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2719 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2720 int dest_mask, Lisp_Object domain)
2722 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2723 widget_value * wv = 0;
2724 /* This is not done generically because of sizing problems under
2726 widget_instantiate (image_instance, instantiator, pointer_fg,
2727 pointer_bg, dest_mask, domain);
2729 wv = gui_items_to_widget_values (image_instance,
2730 IMAGE_INSTANCE_WIDGET_ITEMS (ii), 0);
2732 x_widget_instantiate (image_instance, instantiator, pointer_fg,
2733 pointer_bg, dest_mask, domain, "combo-box", wv);
2738 x_tab_control_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2739 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2740 int dest_mask, Lisp_Object domain)
2742 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2744 gui_items_to_widget_values (image_instance,
2745 IMAGE_INSTANCE_WIDGET_ITEMS (ii), 0);
2746 update_tab_widget_face (wv, ii,
2747 IMAGE_INSTANCE_FRAME (ii));
2748 x_widget_instantiate (image_instance, instantiator, pointer_fg,
2749 pointer_bg, dest_mask, domain, "tab-control", wv);
2752 /* Set the properties of a tab control */
2754 x_tab_control_redisplay (Lisp_Object image_instance)
2756 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2758 if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii)
2760 IMAGE_INSTANCE_WIDGET_ACTION_OCCURRED (ii))
2762 /* If only the order has changed then simply select the first
2763 one of the pending set. This stops horrendous rebuilding -
2764 and hence flicker - of the tabs each time you click on
2766 if (tab_control_order_only_changed (image_instance))
2768 Lisp_Object rest, selected =
2769 gui_item_list_find_selected
2770 (NILP (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii)) ?
2771 XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)) :
2772 XCDR (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii)));
2774 LIST_LOOP (rest, XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)))
2776 if (gui_item_equal_sans_selected (XCAR (rest), selected, 0))
2778 /* There may be an encapsulated way of doing this,
2779 but I couldn't find it. */
2780 Lisp_Object old_selected =gui_item_list_find_selected
2781 (XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)));
2784 unsigned int num_children, i;
2787 LISP_STRING_TO_EXTERNAL (XGUI_ITEM (XCAR (rest))->name,
2789 /* The name may contain a `.' which confuses
2790 XtNameToWidget, so we do it ourselves. */
2791 children = XtCompositeChildren (IMAGE_INSTANCE_X_WIDGET_ID (ii),
2793 for (i = 0; i < num_children; i++)
2795 if (!strcmp (XtName (children [i]), name))
2797 XtSetArg (al [0], XtNtopWidget, children [i]);
2798 XtSetArg (al [1], XtNhighlightWidget,
2800 XtSetValues (IMAGE_INSTANCE_X_WIDGET_ID (ii), al, 2);
2804 /* Pick up the new selected item. */
2805 XGUI_ITEM (old_selected)->selected =
2806 XGUI_ITEM (XCAR (rest))->selected;
2807 XGUI_ITEM (XCAR (rest))->selected =
2808 XGUI_ITEM (selected)->selected;
2809 /* We're not actually changing the items anymore. */
2810 IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii) = 0;
2811 IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii) = Qnil;
2817 /* Possibly update the face. */
2818 if (IMAGE_INSTANCE_WIDGET_FACE_CHANGED (ii)
2820 XFRAME (IMAGE_INSTANCE_FRAME (ii))->faces_changed
2822 IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii))
2824 /* See previous comments on the brokeness of lwlib.
2826 #### There's actually not much point in doing this here
2827 since, colors will have been set appropriately by
2828 x_redisplay_widget. */
2829 widget_value* wv =copy_widget_value_tree
2831 (IMAGE_INSTANCE_X_WIDGET_LWID (ii)),
2834 update_tab_widget_face (wv, ii,
2835 IMAGE_INSTANCE_FRAME (ii));
2837 lw_modify_all_widgets (IMAGE_INSTANCE_X_WIDGET_LWID (ii), wv, True);
2838 free_widget_value_tree (wv);
2842 /* instantiate a static control possible for putting other things in */
2844 x_label_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2845 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2846 int dest_mask, Lisp_Object domain)
2848 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2849 Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM (ii);
2850 widget_value* wv = gui_items_to_widget_values (image_instance, gui, 0);
2852 x_widget_instantiate (image_instance, instantiator, pointer_fg,
2853 pointer_bg, dest_mask, domain, "button", wv);
2855 #endif /* HAVE_WIDGETS */
2858 /************************************************************************/
2859 /* initialization */
2860 /************************************************************************/
2863 syms_of_glyphs_x (void)
2866 DEFSUBR (Fchange_subwindow_property);
2871 console_type_create_glyphs_x (void)
2875 CONSOLE_HAS_METHOD (x, print_image_instance);
2876 CONSOLE_HAS_METHOD (x, finalize_image_instance);
2877 CONSOLE_HAS_METHOD (x, image_instance_equal);
2878 CONSOLE_HAS_METHOD (x, image_instance_hash);
2879 CONSOLE_HAS_METHOD (x, colorize_image_instance);
2880 CONSOLE_HAS_METHOD (x, init_image_instance_from_eimage);
2881 CONSOLE_HAS_METHOD (x, locate_pixmap_file);
2882 CONSOLE_HAS_METHOD (x, unmap_subwindow);
2883 CONSOLE_HAS_METHOD (x, map_subwindow);
2884 CONSOLE_HAS_METHOD (x, redisplay_widget);
2885 CONSOLE_HAS_METHOD (x, redisplay_subwindow);
2889 image_instantiator_format_create_glyphs_x (void)
2891 IIFORMAT_VALID_CONSOLE (x, nothing);
2892 IIFORMAT_VALID_CONSOLE (x, string);
2894 IIFORMAT_VALID_CONSOLE (x, layout);
2896 IIFORMAT_VALID_CONSOLE (x, formatted_string);
2897 IIFORMAT_VALID_CONSOLE (x, inherit);
2899 INITIALIZE_DEVICE_IIFORMAT (x, xpm);
2900 IIFORMAT_HAS_DEVMETHOD (x, xpm, instantiate);
2903 IIFORMAT_VALID_CONSOLE (x, jpeg);
2906 IIFORMAT_VALID_CONSOLE (x, tiff);
2909 IIFORMAT_VALID_CONSOLE (x, png);
2912 IIFORMAT_VALID_CONSOLE (x, gif);
2914 INITIALIZE_DEVICE_IIFORMAT (x, xbm);
2915 IIFORMAT_HAS_DEVMETHOD (x, xbm, instantiate);
2917 INITIALIZE_DEVICE_IIFORMAT (x, subwindow);
2918 IIFORMAT_HAS_DEVMETHOD (x, subwindow, instantiate);
2921 INITIALIZE_DEVICE_IIFORMAT (x, native_layout);
2922 IIFORMAT_HAS_DEVMETHOD (x, native_layout, instantiate);
2924 INITIALIZE_DEVICE_IIFORMAT (x, button);
2925 IIFORMAT_HAS_DEVMETHOD (x, button, property);
2926 IIFORMAT_HAS_DEVMETHOD (x, button, instantiate);
2927 IIFORMAT_HAS_DEVMETHOD (x, button, redisplay);
2928 /* general widget methods. */
2929 INITIALIZE_DEVICE_IIFORMAT (x, widget);
2930 IIFORMAT_HAS_DEVMETHOD (x, widget, property);
2931 /* progress gauge */
2932 INITIALIZE_DEVICE_IIFORMAT (x, progress_gauge);
2933 IIFORMAT_HAS_DEVMETHOD (x, progress_gauge, redisplay);
2934 IIFORMAT_HAS_DEVMETHOD (x, progress_gauge, instantiate);
2936 INITIALIZE_DEVICE_IIFORMAT (x, edit_field);
2937 IIFORMAT_HAS_DEVMETHOD (x, edit_field, instantiate);
2938 #if defined (LWLIB_WIDGETS_MOTIF) && XmVERSION > 1
2940 INITIALIZE_DEVICE_IIFORMAT (x, combo_box);
2941 IIFORMAT_HAS_DEVMETHOD (x, combo_box, instantiate);
2942 IIFORMAT_HAS_SHARED_DEVMETHOD (x, combo_box, redisplay, tab_control);
2944 /* tab control widget */
2945 INITIALIZE_DEVICE_IIFORMAT (x, tab_control);
2946 IIFORMAT_HAS_DEVMETHOD (x, tab_control, instantiate);
2947 IIFORMAT_HAS_DEVMETHOD (x, tab_control, redisplay);
2949 INITIALIZE_DEVICE_IIFORMAT (x, label);
2950 IIFORMAT_HAS_DEVMETHOD (x, label, instantiate);
2952 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (cursor_font, "cursor-font");
2953 IIFORMAT_VALID_CONSOLE (x, cursor_font);
2955 IIFORMAT_HAS_METHOD (cursor_font, validate);
2956 IIFORMAT_HAS_METHOD (cursor_font, possible_dest_types);
2957 IIFORMAT_HAS_METHOD (cursor_font, instantiate);
2959 IIFORMAT_VALID_KEYWORD (cursor_font, Q_data, check_valid_string);
2960 IIFORMAT_VALID_KEYWORD (cursor_font, Q_foreground, check_valid_string);
2961 IIFORMAT_VALID_KEYWORD (cursor_font, Q_background, check_valid_string);
2963 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (font, "font");
2965 IIFORMAT_HAS_METHOD (font, validate);
2966 IIFORMAT_HAS_METHOD (font, possible_dest_types);
2967 IIFORMAT_HAS_METHOD (font, instantiate);
2968 IIFORMAT_VALID_CONSOLE (x, font);
2970 IIFORMAT_VALID_KEYWORD (font, Q_data, check_valid_string);
2971 IIFORMAT_VALID_KEYWORD (font, Q_foreground, check_valid_string);
2972 IIFORMAT_VALID_KEYWORD (font, Q_background, check_valid_string);
2975 INITIALIZE_DEVICE_IIFORMAT (x, xface);
2976 IIFORMAT_HAS_DEVMETHOD (x, xface, instantiate);
2979 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (autodetect,
2982 IIFORMAT_HAS_METHOD (autodetect, validate);
2983 IIFORMAT_HAS_METHOD (autodetect, normalize);
2984 IIFORMAT_HAS_METHOD (autodetect, possible_dest_types);
2985 /* #### autodetect is flawed IMO:
2986 1. It makes the assumption that you can detect whether the user
2987 wanted a cursor or a string based on the data, since the data is a
2988 string you have to prioritise cursors. Instead we will force users
2989 to pick the appropriate image type, this is what we do under
2991 2. It doesn't fit with the new domain model - you cannot tell which
2992 domain it needs to be instantiated in until you've actually
2993 instantiated it, which mucks up caching.
2994 3. It only copes with cursors and strings which seems bogus. */
2995 IIFORMAT_HAS_SHARED_METHOD (autodetect, governing_domain, subwindow);
2996 IIFORMAT_HAS_METHOD (autodetect, instantiate);
2997 IIFORMAT_VALID_CONSOLE (x, autodetect);
2999 IIFORMAT_VALID_KEYWORD (autodetect, Q_data, check_valid_string);
3003 vars_of_glyphs_x (void)
3005 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path /*
3006 A list of the directories in which X bitmap files may be found.
3007 If nil, this is initialized from the "*bitmapFilePath" resource.
3008 This is used by the `make-image-instance' function (however, note that if
3009 the environment variable XBMLANGPATH is set, it is consulted first).
3011 Vx_bitmap_file_path = Qnil;
3015 complex_vars_of_glyphs_x (void)
3017 #define BUILD_GLYPH_INST(variable, name) \
3018 Fadd_spec_to_specifier \
3019 (GLYPH_IMAGE (XGLYPH (variable)), \
3020 vector3 (Qxbm, Q_data, \
3021 list3 (make_int (name##_width), \
3022 make_int (name##_height), \
3023 make_ext_string ((Extbyte *) name##_bits, \
3024 sizeof (name##_bits), \
3028 BUILD_GLYPH_INST (Vtruncation_glyph, truncator);
3029 BUILD_GLYPH_INST (Vcontinuation_glyph, continuer);
3030 BUILD_GLYPH_INST (Vxemacs_logo, xemacs);
3031 BUILD_GLYPH_INST (Vhscroll_glyph, hscroll);
3033 #undef BUILD_GLYPH_INST