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];
235 /* use our quantize table to allocate the colors */
237 *pixtbl = xnew_array (unsigned long, pixcount);
240 /* #### should implement a sort by popularity to assure proper allocation */
242 for (i = 0; i < qtable->num_active_colors; i++)
247 color.red = qtable->rm[i] ? qtable->rm[i] << 8 : 0;
248 color.green = qtable->gm[i] ? qtable->gm[i] << 8 : 0;
249 color.blue = qtable->bm[i] ? qtable->bm[i] << 8 : 0;
250 color.flags = DoRed | DoGreen | DoBlue;
251 res = allocate_nearest_color (dpy, cmap, vis, &color);
252 if (res > 0 && res < 3)
254 DO_REALLOC(*pixtbl, pixcount, n+1, unsigned long);
255 (*pixtbl)[n] = color.pixel;
258 pixarray[i] = color.pixel;
262 for (i = 0; i < height; i++)
264 dp = data + (i * outimg->bytes_per_line);
265 for (j = 0; j < width; j++)
270 conv.val = pixarray[QUANT_GET_COLOR(qtable,rd,gr,bl)];
271 #ifdef WORDS_BIGENDIAN
272 if (outimg->byte_order == MSBFirst)
273 for (q = 4-byte_cnt; q < 4; q++) *dp++ = conv.cp[q];
275 for (q = 3; q >= 4-byte_cnt; q--) *dp++ = conv.cp[q];
277 if (outimg->byte_order == MSBFirst)
278 for (q = byte_cnt-1; q >= 0; q--) *dp++ = conv.cp[q];
280 for (q = 0; q < byte_cnt; q++) *dp++ = conv.cp[q];
286 unsigned long rshift,gshift,bshift,rbits,gbits,bbits,junk;
287 junk = vis->red_mask;
289 while ((junk & 0x1) == 0)
300 junk = vis->green_mask;
302 while ((junk & 0x1) == 0)
313 junk = vis->blue_mask;
315 while ((junk & 0x1) == 0)
327 for (i = 0; i < height; i++)
329 dp = data + (i * outimg->bytes_per_line);
330 for (j = 0; j < width; j++)
333 rd = *ip++ << (rbits - 8);
335 rd = *ip++ >> (8 - rbits);
337 gr = *ip++ << (gbits - 8);
339 gr = *ip++ >> (8 - gbits);
341 bl = *ip++ << (bbits - 8);
343 bl = *ip++ >> (8 - bbits);
345 conv.val = (rd << rshift) | (gr << gshift) | (bl << bshift);
346 #ifdef WORDS_BIGENDIAN
347 if (outimg->byte_order == MSBFirst)
348 for (q = 4-byte_cnt; q < 4; q++) *dp++ = conv.cp[q];
350 for (q = 3; q >= 4-byte_cnt; q--) *dp++ = conv.cp[q];
352 if (outimg->byte_order == MSBFirst)
353 for (q = byte_cnt-1; q >= 0; q--) *dp++ = conv.cp[q];
355 for (q = 0; q < byte_cnt; q++) *dp++ = conv.cp[q];
366 x_print_image_instance (Lisp_Image_Instance *p,
367 Lisp_Object printcharfun,
372 switch (IMAGE_INSTANCE_TYPE (p))
374 case IMAGE_MONO_PIXMAP:
375 case IMAGE_COLOR_PIXMAP:
377 sprintf (buf, " (0x%lx", (unsigned long) IMAGE_INSTANCE_X_PIXMAP (p));
378 write_c_string (buf, printcharfun);
379 if (IMAGE_INSTANCE_X_MASK (p))
381 sprintf (buf, "/0x%lx", (unsigned long) IMAGE_INSTANCE_X_MASK (p));
382 write_c_string (buf, printcharfun);
384 write_c_string (")", printcharfun);
392 extern int debug_widget_instances;
396 x_finalize_image_instance (Lisp_Image_Instance *p)
401 if (DEVICE_LIVE_P (XDEVICE (IMAGE_INSTANCE_DEVICE (p))))
403 Display *dpy = DEVICE_X_DISPLAY
404 (XDEVICE (IMAGE_INSTANCE_DEVICE (p)));
408 else if (IMAGE_INSTANCE_TYPE (p) == IMAGE_WIDGET)
410 if (IMAGE_INSTANCE_SUBWINDOW_ID (p))
413 debug_widget_instances--;
414 stderr_out ("widget destroyed, %d left\n", debug_widget_instances);
416 lw_destroy_widget (IMAGE_INSTANCE_X_WIDGET_ID (p));
417 lw_destroy_widget (IMAGE_INSTANCE_X_CLIPWIDGET (p));
419 /* We can release the callbacks again. */
420 ungcpro_popup_callbacks (IMAGE_INSTANCE_X_WIDGET_LWID (p));
422 IMAGE_INSTANCE_X_WIDGET_ID (p) = 0;
423 IMAGE_INSTANCE_X_CLIPWIDGET (p) = 0;
427 else if (IMAGE_INSTANCE_TYPE (p) == IMAGE_SUBWINDOW)
429 if (IMAGE_INSTANCE_SUBWINDOW_ID (p))
430 XDestroyWindow (dpy, IMAGE_INSTANCE_X_SUBWINDOW_ID (p));
431 IMAGE_INSTANCE_SUBWINDOW_ID (p) = 0;
436 if (IMAGE_INSTANCE_PIXMAP_TIMEOUT (p))
437 disable_glyph_animated_timeout (IMAGE_INSTANCE_PIXMAP_TIMEOUT (p));
439 if (IMAGE_INSTANCE_X_MASK (p) &&
440 IMAGE_INSTANCE_X_MASK (p) != IMAGE_INSTANCE_X_PIXMAP (p))
441 XFreePixmap (dpy, IMAGE_INSTANCE_X_MASK (p));
442 IMAGE_INSTANCE_PIXMAP_MASK (p) = 0;
444 if (IMAGE_INSTANCE_X_PIXMAP_SLICES (p))
446 for (i = 0; i < IMAGE_INSTANCE_PIXMAP_MAXSLICE (p); i++)
447 if (IMAGE_INSTANCE_X_PIXMAP_SLICE (p,i))
449 XFreePixmap (dpy, IMAGE_INSTANCE_X_PIXMAP_SLICE (p,i));
450 IMAGE_INSTANCE_X_PIXMAP_SLICE (p, i) = 0;
452 xfree (IMAGE_INSTANCE_X_PIXMAP_SLICES (p));
453 IMAGE_INSTANCE_X_PIXMAP_SLICES (p) = 0;
456 if (IMAGE_INSTANCE_X_CURSOR (p))
458 XFreeCursor (dpy, IMAGE_INSTANCE_X_CURSOR (p));
459 IMAGE_INSTANCE_X_CURSOR (p) = 0;
462 if (IMAGE_INSTANCE_X_NPIXELS (p) != 0)
465 IMAGE_INSTANCE_X_COLORMAP (p),
466 IMAGE_INSTANCE_X_PIXELS (p),
467 IMAGE_INSTANCE_X_NPIXELS (p), 0);
468 IMAGE_INSTANCE_X_NPIXELS (p) = 0;
472 /* You can sometimes have pixels without a live device. I forget
473 why, but that's why we free them here if we have a pixmap type
474 image instance. It probably means that we might also get a memory
475 leak with widgets. */
476 if (IMAGE_INSTANCE_TYPE (p) != IMAGE_WIDGET
477 && IMAGE_INSTANCE_TYPE (p) != IMAGE_SUBWINDOW
478 && IMAGE_INSTANCE_X_PIXELS (p))
480 xfree (IMAGE_INSTANCE_X_PIXELS (p));
481 IMAGE_INSTANCE_X_PIXELS (p) = 0;
489 x_image_instance_equal (Lisp_Image_Instance *p1,
490 Lisp_Image_Instance *p2, int depth)
492 switch (IMAGE_INSTANCE_TYPE (p1))
494 case IMAGE_MONO_PIXMAP:
495 case IMAGE_COLOR_PIXMAP:
497 if (IMAGE_INSTANCE_X_COLORMAP (p1) != IMAGE_INSTANCE_X_COLORMAP (p2) ||
498 IMAGE_INSTANCE_X_NPIXELS (p1) != IMAGE_INSTANCE_X_NPIXELS (p2))
509 x_image_instance_hash (Lisp_Image_Instance *p, int depth)
511 switch (IMAGE_INSTANCE_TYPE (p))
513 case IMAGE_MONO_PIXMAP:
514 case IMAGE_COLOR_PIXMAP:
516 return IMAGE_INSTANCE_X_NPIXELS (p);
522 /* Set all the slots in an image instance structure to reasonable
523 default values. This is used somewhere within an instantiate
524 method. It is assumed that the device slot within the image
525 instance is already set -- this is the case when instantiate
526 methods are called. */
529 x_initialize_pixmap_image_instance (Lisp_Image_Instance *ii,
531 enum image_instance_type type)
533 ii->data = xnew_and_zero (struct x_image_instance_data);
534 IMAGE_INSTANCE_PIXMAP_MAXSLICE (ii) = slices;
535 IMAGE_INSTANCE_X_PIXMAP_SLICES (ii) =
536 xnew_array_and_zero (Pixmap, slices);
537 IMAGE_INSTANCE_TYPE (ii) = type;
538 IMAGE_INSTANCE_PIXMAP_FILENAME (ii) = Qnil;
539 IMAGE_INSTANCE_PIXMAP_MASK_FILENAME (ii) = Qnil;
540 IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii) = Qnil;
541 IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii) = Qnil;
542 IMAGE_INSTANCE_PIXMAP_FG (ii) = Qnil;
543 IMAGE_INSTANCE_PIXMAP_BG (ii) = Qnil;
547 /************************************************************************/
548 /* pixmap file functions */
549 /************************************************************************/
551 /* Where bitmaps are; initialized from resource database */
552 Lisp_Object Vx_bitmap_file_path;
555 #define BITMAPDIR "/usr/include/X11/bitmaps"
558 #define USE_XBMLANGPATH
560 /* Given a pixmap filename, look through all of the "standard" places
561 where the file might be located. Return a full pathname if found;
562 otherwise, return Qnil. */
565 x_locate_pixmap_file (Lisp_Object name)
567 /* This function can GC if IN_REDISPLAY is false */
570 /* Check non-absolute pathnames with a directory component relative to
571 the search path; that's the way Xt does it. */
572 /* #### Unix-specific */
573 if (XSTRING_BYTE (name, 0) == '/' ||
574 (XSTRING_BYTE (name, 0) == '.' &&
575 (XSTRING_BYTE (name, 1) == '/' ||
576 (XSTRING_BYTE (name, 1) == '.' &&
577 (XSTRING_BYTE (name, 2) == '/')))))
579 if (!NILP (Ffile_readable_p (name)))
580 return Fexpand_file_name (name, Qnil);
585 if (NILP (Vdefault_x_device))
586 /* This may occur during initialization. */
589 /* We only check the bitmapFilePath resource on the original X device. */
590 display = DEVICE_X_DISPLAY (XDEVICE (Vdefault_x_device));
592 #ifdef USE_XBMLANGPATH
594 char *path = egetenv ("XBMLANGPATH");
595 SubstitutionRec subs[1];
597 subs[0].substitution = (char *) XSTRING_DATA (name);
598 /* #### Motif uses a big hairy default if $XBMLANGPATH isn't set.
599 We don't. If you want it used, set it. */
601 (path = XtResolvePathname (display, "bitmaps", 0, 0, path,
602 subs, XtNumber (subs), 0)))
604 name = build_string (path);
611 if (NILP (Vx_bitmap_file_path))
615 if (XrmGetResource (XtDatabase (display),
616 "bitmapFilePath", "BitmapFilePath", &type, &value)
617 && !strcmp (type, "String"))
618 Vx_bitmap_file_path = decode_env_path (0, (char *) value.addr);
619 Vx_bitmap_file_path = nconc2 (Vx_bitmap_file_path,
620 (decode_path (BITMAPDIR)));
625 if (locate_file (Vx_bitmap_file_path, name, Qnil, &found, R_OK) < 0)
627 Lisp_Object temp = list1 (Vdata_directory);
631 locate_file (temp, name, Qnil, &found, R_OK);
640 locate_pixmap_file (Lisp_Object name)
642 return x_locate_pixmap_file (name);
647 write_lisp_string_to_temp_file (Lisp_Object string, char *filename_out)
649 Lisp_Object instream, outstream;
650 Lstream *istr, *ostr;
651 char tempbuf[1024]; /* some random amount */
654 static Extbyte_dynarr *conversion_out_dynarr;
655 Bytecount bstart, bend;
656 struct gcpro gcpro1, gcpro2;
658 Lisp_Object conv_out_stream;
663 /* This function can GC */
664 if (!conversion_out_dynarr)
665 conversion_out_dynarr = Dynarr_new (Extbyte);
667 Dynarr_reset (conversion_out_dynarr);
669 /* Create the temporary file ... */
670 sprintf (filename_out, "/tmp/emacs%d.XXXXXX", (int) getpid ());
671 mktemp (filename_out);
672 tmpfil = fopen (filename_out, "w");
677 int old_errno = errno;
679 unlink (filename_out);
682 report_file_error ("Creating temp file",
683 list1 (build_string (filename_out)));
686 CHECK_STRING (string);
687 get_string_range_byte (string, Qnil, Qnil, &bstart, &bend,
688 GB_HISTORICAL_STRING_BEHAVIOR);
689 instream = make_lisp_string_input_stream (string, bstart, bend);
690 istr = XLSTREAM (instream);
691 /* setup the out stream */
692 outstream = make_dynarr_output_stream((unsigned_char_dynarr *)conversion_out_dynarr);
693 ostr = XLSTREAM (outstream);
695 /* setup the conversion stream */
696 conv_out_stream = make_encoding_output_stream (ostr, Fget_coding_system(Qbinary));
697 costr = XLSTREAM (conv_out_stream);
698 GCPRO3 (instream, outstream, conv_out_stream);
700 GCPRO2 (instream, outstream);
703 /* Get the data while doing the conversion */
706 ssize_t size_in_bytes = Lstream_read (istr, tempbuf, sizeof (tempbuf));
709 /* It does seem the flushes are necessary... */
711 Lstream_write (costr, tempbuf, size_in_bytes);
712 Lstream_flush (costr);
714 Lstream_write (ostr, tempbuf, size_in_bytes);
716 Lstream_flush (ostr);
717 if (fwrite ((unsigned char *)Dynarr_atp(conversion_out_dynarr, 0),
718 Dynarr_length(conversion_out_dynarr), 1, tmpfil) != 1)
723 /* reset the dynarr */
724 Lstream_rewind(ostr);
727 if (fclose (tmpfil) != 0)
729 Lstream_close (istr);
731 Lstream_close (costr);
733 Lstream_close (ostr);
736 Lstream_delete (istr);
737 Lstream_delete (ostr);
739 Lstream_delete (costr);
743 report_file_error ("Writing temp file",
744 list1 (build_string (filename_out)));
749 /************************************************************************/
750 /* cursor functions */
751 /************************************************************************/
753 /* Check that this server supports cursors of size WIDTH * HEIGHT. If
754 not, signal an error. INSTANTIATOR is only used in the error
758 check_pointer_sizes (Screen *xs, unsigned int width, unsigned int height,
759 Lisp_Object instantiator)
761 unsigned int best_width, best_height;
762 if (! XQueryBestCursor (DisplayOfScreen (xs), RootWindowOfScreen (xs),
763 width, height, &best_width, &best_height))
764 /* this means that an X error of some sort occurred (we trap
765 these so they're not fatal). */
766 signal_simple_error ("XQueryBestCursor() failed?", instantiator);
768 if (width > best_width || height > best_height)
769 error_with_frob (instantiator,
770 "pointer too large (%dx%d): "
771 "server requires %dx%d or smaller",
772 width, height, best_width, best_height);
777 generate_cursor_fg_bg (Lisp_Object device, Lisp_Object *foreground,
778 Lisp_Object *background, XColor *xfg, XColor *xbg)
780 if (!NILP (*foreground) && !COLOR_INSTANCEP (*foreground))
782 Fmake_color_instance (*foreground, device,
783 encode_error_behavior_flag (ERROR_ME));
784 if (COLOR_INSTANCEP (*foreground))
785 *xfg = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (*foreground));
789 xfg->red = xfg->green = xfg->blue = 0;
792 if (!NILP (*background) && !COLOR_INSTANCEP (*background))
794 Fmake_color_instance (*background, device,
795 encode_error_behavior_flag (ERROR_ME));
796 if (COLOR_INSTANCEP (*background))
797 *xbg = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (*background));
801 xbg->red = xbg->green = xbg->blue = ~0;
806 maybe_recolor_cursor (Lisp_Object image_instance, Lisp_Object foreground,
807 Lisp_Object background)
809 Lisp_Object device = XIMAGE_INSTANCE_DEVICE (image_instance);
812 generate_cursor_fg_bg (device, &foreground, &background, &xfg, &xbg);
813 if (!NILP (foreground) || !NILP (background))
815 XRecolorCursor (DEVICE_X_DISPLAY (XDEVICE (device)),
816 XIMAGE_INSTANCE_X_CURSOR (image_instance),
818 XIMAGE_INSTANCE_PIXMAP_FG (image_instance) = foreground;
819 XIMAGE_INSTANCE_PIXMAP_BG (image_instance) = background;
824 /************************************************************************/
825 /* color pixmap functions */
826 /************************************************************************/
828 /* Initialize an image instance from an XImage.
830 DEST_MASK specifies the mask of allowed image types.
832 PIXELS and NPIXELS specify an array of pixels that are used in
833 the image. These need to be kept around for the duration of the
834 image. When the image instance is freed, XFreeColors() will
835 automatically be called on all the pixels specified here; thus,
836 you should have allocated the pixels yourself using XAllocColor()
837 or the like. The array passed in is used directly without
838 being copied, so it should be heap data created with xmalloc().
839 It will be freed using xfree() when the image instance is
842 If this fails, signal an error. INSTANTIATOR is only used
843 in the error message.
845 #### This should be able to handle conversion into `pointer'.
846 Use the same code as for `xpm'. */
849 init_image_instance_from_x_image (Lisp_Image_Instance *ii,
853 unsigned long *pixels,
856 Lisp_Object instantiator)
858 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
864 if (!DEVICE_X_P (XDEVICE (device)))
865 signal_simple_error ("Not an X device", device);
867 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
868 d = XtWindow(DEVICE_XT_APP_SHELL (XDEVICE (device)));
870 if (!(dest_mask & IMAGE_COLOR_PIXMAP_MASK))
871 incompatible_image_types (instantiator, dest_mask,
872 IMAGE_COLOR_PIXMAP_MASK);
874 pixmap = XCreatePixmap (dpy, d, ximage->width,
875 ximage->height, ximage->depth);
877 signal_simple_error ("Unable to create pixmap", instantiator);
879 gc = XCreateGC (dpy, pixmap, 0, NULL);
882 XFreePixmap (dpy, pixmap);
883 signal_simple_error ("Unable to create GC", instantiator);
886 XPutImage (dpy, pixmap, gc, ximage, 0, 0, 0, 0,
887 ximage->width, ximage->height);
891 x_initialize_pixmap_image_instance (ii, slices, IMAGE_COLOR_PIXMAP);
893 IMAGE_INSTANCE_PIXMAP_FILENAME (ii) =
894 find_keyword_in_vector (instantiator, Q_file);
896 /* Fixup a set of pixmaps. */
897 IMAGE_INSTANCE_X_PIXMAP (ii) = pixmap;
899 IMAGE_INSTANCE_PIXMAP_MASK (ii) = 0;
900 IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = ximage->width;
901 IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = ximage->height;
902 IMAGE_INSTANCE_PIXMAP_DEPTH (ii) = ximage->depth;
903 IMAGE_INSTANCE_X_COLORMAP (ii) = cmap;
904 IMAGE_INSTANCE_X_PIXELS (ii) = pixels;
905 IMAGE_INSTANCE_X_NPIXELS (ii) = npixels;
909 image_instance_add_x_image (Lisp_Image_Instance *ii,
912 Lisp_Object instantiator)
914 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
920 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
921 d = XtWindow(DEVICE_XT_APP_SHELL (XDEVICE (device)));
923 pixmap = XCreatePixmap (dpy, d, ximage->width,
924 ximage->height, ximage->depth);
926 signal_simple_error ("Unable to create pixmap", instantiator);
928 gc = XCreateGC (dpy, pixmap, 0, NULL);
931 XFreePixmap (dpy, pixmap);
932 signal_simple_error ("Unable to create GC", instantiator);
935 XPutImage (dpy, pixmap, gc, ximage, 0, 0, 0, 0,
936 ximage->width, ximage->height);
940 IMAGE_INSTANCE_X_PIXMAP_SLICE (ii, slice) = pixmap;
944 x_init_image_instance_from_eimage (Lisp_Image_Instance *ii,
945 int width, int height,
947 unsigned char *eimage,
949 Lisp_Object instantiator,
952 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
953 Colormap cmap = DEVICE_X_COLORMAP (XDEVICE(device));
954 unsigned long *pixtbl = NULL;
959 for (slice = 0; slice < slices; slice++)
961 ximage = convert_EImage_to_XImage (device, width, height,
962 eimage + (width * height * 3 * slice),
966 if (pixtbl) xfree (pixtbl);
967 signal_image_error("EImage to XImage conversion failed", instantiator);
970 /* Now create the pixmap and set up the image instance */
972 init_image_instance_from_x_image (ii, ximage, dest_mask,
973 cmap, pixtbl, npixels, slices,
976 image_instance_add_x_image (ii, ximage, slice, instantiator);
982 xfree (ximage->data);
985 XDestroyImage (ximage);
991 int read_bitmap_data_from_file (const char *filename, unsigned int *width,
992 unsigned int *height, unsigned char **datap,
993 int *x_hot, int *y_hot)
995 return XmuReadBitmapDataFromFile (filename, width, height,
996 datap, x_hot, y_hot);
999 /* Given inline data for a mono pixmap, create and return the
1000 corresponding X object. */
1003 pixmap_from_xbm_inline (Lisp_Object device, int width, int height,
1004 /* Note that data is in ext-format! */
1007 return XCreatePixmapFromBitmapData
1008 (DEVICE_X_DISPLAY (XDEVICE (device)),
1009 XtWindow (DEVICE_XT_APP_SHELL (XDEVICE (device))),
1010 (char *) bits, width, height,
1014 /* Given inline data for a mono pixmap, initialize the given
1015 image instance accordingly. */
1018 init_image_instance_from_xbm_inline (Lisp_Image_Instance *ii,
1019 int width, int height,
1020 /* Note that data is in ext-format! */
1022 Lisp_Object instantiator,
1023 Lisp_Object pointer_fg,
1024 Lisp_Object pointer_bg,
1027 Lisp_Object mask_filename)
1029 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
1030 Lisp_Object foreground = find_keyword_in_vector (instantiator, Q_foreground);
1031 Lisp_Object background = find_keyword_in_vector (instantiator, Q_background);
1035 enum image_instance_type type;
1037 if (!DEVICE_X_P (XDEVICE (device)))
1038 signal_simple_error ("Not an X device", device);
1040 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
1041 draw = XtWindow(DEVICE_XT_APP_SHELL (XDEVICE (device)));
1042 scr = DefaultScreenOfDisplay (dpy);
1044 if ((dest_mask & IMAGE_MONO_PIXMAP_MASK) &&
1045 (dest_mask & IMAGE_COLOR_PIXMAP_MASK))
1047 if (!NILP (foreground) || !NILP (background))
1048 type = IMAGE_COLOR_PIXMAP;
1050 type = IMAGE_MONO_PIXMAP;
1052 else if (dest_mask & IMAGE_MONO_PIXMAP_MASK)
1053 type = IMAGE_MONO_PIXMAP;
1054 else if (dest_mask & IMAGE_COLOR_PIXMAP_MASK)
1055 type = IMAGE_COLOR_PIXMAP;
1056 else if (dest_mask & IMAGE_POINTER_MASK)
1057 type = IMAGE_POINTER;
1059 incompatible_image_types (instantiator, dest_mask,
1060 IMAGE_MONO_PIXMAP_MASK | IMAGE_COLOR_PIXMAP_MASK
1061 | IMAGE_POINTER_MASK);
1063 x_initialize_pixmap_image_instance (ii, 1, type);
1064 IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = width;
1065 IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = height;
1066 IMAGE_INSTANCE_PIXMAP_FILENAME (ii) =
1067 find_keyword_in_vector (instantiator, Q_file);
1071 case IMAGE_MONO_PIXMAP:
1073 IMAGE_INSTANCE_X_PIXMAP (ii) =
1074 pixmap_from_xbm_inline (device, width, height, (Extbyte *) bits);
1078 case IMAGE_COLOR_PIXMAP:
1080 Dimension d = DEVICE_X_DEPTH (XDEVICE(device));
1081 unsigned long fg = BlackPixelOfScreen (scr);
1082 unsigned long bg = WhitePixelOfScreen (scr);
1084 if (!NILP (foreground) && !COLOR_INSTANCEP (foreground))
1086 Fmake_color_instance (foreground, device,
1087 encode_error_behavior_flag (ERROR_ME));
1089 if (COLOR_INSTANCEP (foreground))
1090 fg = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (foreground)).pixel;
1092 if (!NILP (background) && !COLOR_INSTANCEP (background))
1094 Fmake_color_instance (background, device,
1095 encode_error_behavior_flag (ERROR_ME));
1097 if (COLOR_INSTANCEP (background))
1098 bg = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (background)).pixel;
1100 /* We used to duplicate the pixels using XAllocColor(), to protect
1101 against their getting freed. Just as easy to just store the
1102 color instances here and GC-protect them, so this doesn't
1104 IMAGE_INSTANCE_PIXMAP_FG (ii) = foreground;
1105 IMAGE_INSTANCE_PIXMAP_BG (ii) = background;
1106 IMAGE_INSTANCE_X_PIXMAP (ii) =
1107 XCreatePixmapFromBitmapData (dpy, draw,
1108 (char *) bits, width, height,
1110 IMAGE_INSTANCE_PIXMAP_DEPTH (ii) = d;
1116 XColor fg_color, bg_color;
1119 check_pointer_sizes (scr, width, height, instantiator);
1122 XCreatePixmapFromBitmapData (dpy, draw,
1123 (char *) bits, width, height,
1126 if (NILP (foreground))
1127 foreground = pointer_fg;
1128 if (NILP (background))
1129 background = pointer_bg;
1130 generate_cursor_fg_bg (device, &foreground, &background,
1131 &fg_color, &bg_color);
1133 IMAGE_INSTANCE_PIXMAP_FG (ii) = foreground;
1134 IMAGE_INSTANCE_PIXMAP_BG (ii) = background;
1135 IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii) =
1136 find_keyword_in_vector (instantiator, Q_hotspot_x);
1137 IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii) =
1138 find_keyword_in_vector (instantiator, Q_hotspot_y);
1139 IMAGE_INSTANCE_X_CURSOR (ii) =
1141 (dpy, source, mask, &fg_color, &bg_color,
1142 !NILP (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii)) ?
1143 XINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii)) : 0,
1144 !NILP (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii)) ?
1145 XINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii)) : 0);
1155 xbm_instantiate_1 (Lisp_Object image_instance, Lisp_Object instantiator,
1156 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1157 int dest_mask, int width, int height,
1158 /* Note that data is in ext-format! */
1161 Lisp_Object mask_data = find_keyword_in_vector (instantiator, Q_mask_data);
1162 Lisp_Object mask_file = find_keyword_in_vector (instantiator, Q_mask_file);
1163 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1166 if (!NILP (mask_data))
1168 const char *ext_data;
1170 LISP_STRING_TO_EXTERNAL (XCAR (XCDR (XCDR (mask_data))), ext_data, Qbinary);
1171 mask = pixmap_from_xbm_inline (IMAGE_INSTANCE_DEVICE (ii),
1172 XINT (XCAR (mask_data)),
1173 XINT (XCAR (XCDR (mask_data))),
1177 init_image_instance_from_xbm_inline (ii, width, height, bits,
1178 instantiator, pointer_fg, pointer_bg,
1179 dest_mask, mask, mask_file);
1182 /* Instantiate method for XBM's. */
1185 x_xbm_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1186 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1187 int dest_mask, Lisp_Object domain)
1189 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1190 const char *ext_data;
1192 assert (!NILP (data));
1194 LISP_STRING_TO_EXTERNAL (XCAR (XCDR (XCDR (data))), ext_data, Qbinary);
1196 xbm_instantiate_1 (image_instance, instantiator, pointer_fg,
1197 pointer_bg, dest_mask, XINT (XCAR (data)),
1198 XINT (XCAR (XCDR (data))), ext_data);
1204 /**********************************************************************
1206 **********************************************************************/
1207 /* xpm 3.2g and better has XpmCreatePixmapFromBuffer()...
1208 There was no version number in xpm.h before 3.3, but this should do.
1210 #if (XpmVersion >= 3) || defined(XpmExactColors)
1211 # define XPM_DOES_BUFFERS
1214 #ifndef XPM_DOES_BUFFERS
1215 Your version of XPM is too old. You cannot compile with it.
1216 Upgrade to version 3.2g or better or compile with --with-xpm=no.
1217 #endif /* !XPM_DOES_BUFFERS */
1219 static XpmColorSymbol *
1220 extract_xpm_color_names (XpmAttributes *xpmattrs, Lisp_Object device,
1222 Lisp_Object color_symbol_alist)
1224 /* This function can GC */
1225 Display *dpy = DEVICE_X_DISPLAY (XDEVICE(device));
1226 Colormap cmap = DEVICE_X_COLORMAP (XDEVICE(device));
1229 Lisp_Object results = Qnil;
1231 XpmColorSymbol *symbols;
1232 struct gcpro gcpro1, gcpro2;
1234 GCPRO2 (results, device);
1236 /* We built up results to be (("name" . #<color>) ...) so that if an
1237 error happens we don't lose any malloc()ed data, or more importantly,
1238 leave any pixels allocated in the server. */
1240 LIST_LOOP (rest, color_symbol_alist)
1242 Lisp_Object cons = XCAR (rest);
1243 Lisp_Object name = XCAR (cons);
1244 Lisp_Object value = XCDR (cons);
1247 if (STRINGP (value))
1249 Fmake_color_instance
1250 (value, device, encode_error_behavior_flag (ERROR_ME_NOT));
1253 assert (COLOR_SPECIFIERP (value));
1254 value = Fspecifier_instance (value, domain, Qnil, Qnil);
1258 results = noseeum_cons (noseeum_cons (name, value), results);
1261 UNGCPRO; /* no more evaluation */
1263 if (i == 0) return 0;
1265 symbols = xnew_array (XpmColorSymbol, i);
1266 xpmattrs->valuemask |= XpmColorSymbols;
1267 xpmattrs->colorsymbols = symbols;
1268 xpmattrs->numsymbols = i;
1272 Lisp_Object cons = XCAR (results);
1273 color = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (XCDR (cons)));
1274 /* Duplicate the pixel value so that we still have a lock on it if
1275 the pixel we were passed is later freed. */
1276 if (! XAllocColor (dpy, cmap, &color))
1277 abort (); /* it must be allocable since we're just duplicating it */
1279 symbols [i].name = (char *) XSTRING_DATA (XCAR (cons));
1280 symbols [i].pixel = color.pixel;
1281 symbols [i].value = 0;
1282 free_cons (XCONS (cons));
1284 results = XCDR (results);
1285 free_cons (XCONS (cons));
1291 xpm_free (XpmAttributes *xpmattrs)
1293 /* Could conceivably lose if XpmXXX returned an error without first
1294 initializing this structure, if we didn't know that initializing it
1295 to all zeros was ok (and also that it's ok to call XpmFreeAttributes()
1296 multiple times, since it zeros slots as it frees them...) */
1297 XpmFreeAttributes (xpmattrs);
1301 x_xpm_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1302 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1303 int dest_mask, Lisp_Object domain)
1305 /* This function can GC */
1306 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1307 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
1308 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1316 XpmAttributes xpmattrs;
1318 XpmColorSymbol *color_symbols;
1319 Lisp_Object color_symbol_alist = find_keyword_in_vector (instantiator,
1321 enum image_instance_type type;
1325 if (!DEVICE_X_P (XDEVICE (device)))
1326 signal_simple_error ("Not an X device", device);
1328 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
1329 xs = DefaultScreenOfDisplay (dpy);
1331 if (dest_mask & IMAGE_COLOR_PIXMAP_MASK)
1332 type = IMAGE_COLOR_PIXMAP;
1333 else if (dest_mask & IMAGE_MONO_PIXMAP_MASK)
1334 type = IMAGE_MONO_PIXMAP;
1335 else if (dest_mask & IMAGE_POINTER_MASK)
1336 type = IMAGE_POINTER;
1338 incompatible_image_types (instantiator, dest_mask,
1339 IMAGE_MONO_PIXMAP_MASK | IMAGE_COLOR_PIXMAP_MASK
1340 | IMAGE_POINTER_MASK);
1341 force_mono = (type != IMAGE_COLOR_PIXMAP);
1344 /* Although I haven't found it documented yet, it appears that pointers are
1345 always colored via the default window colormap... Sigh. */
1346 if (type == IMAGE_POINTER)
1348 cmap = DefaultColormap(dpy, DefaultScreen(dpy));
1349 depth = DefaultDepthOfScreen (xs);
1350 visual = DefaultVisualOfScreen (xs);
1354 cmap = DEVICE_X_COLORMAP (XDEVICE(device));
1355 depth = DEVICE_X_DEPTH (XDEVICE(device));
1356 visual = DEVICE_X_VISUAL (XDEVICE(device));
1359 cmap = DEVICE_X_COLORMAP (XDEVICE(device));
1360 depth = DEVICE_X_DEPTH (XDEVICE(device));
1361 visual = DEVICE_X_VISUAL (XDEVICE(device));
1364 x_initialize_pixmap_image_instance (ii, 1, type);
1366 assert (!NILP (data));
1370 xzero (xpmattrs); /* want XpmInitAttributes() */
1371 xpmattrs.valuemask = XpmReturnPixels;
1374 /* Without this, we get a 1-bit version of the color image, which
1375 isn't quite right. With this, we get the mono image, which might
1376 be very different looking. */
1377 xpmattrs.valuemask |= XpmColorKey;
1378 xpmattrs.color_key = XPM_MONO;
1380 xpmattrs.valuemask |= XpmDepth;
1384 xpmattrs.closeness = 65535;
1385 xpmattrs.valuemask |= XpmCloseness;
1386 xpmattrs.depth = depth;
1387 xpmattrs.valuemask |= XpmDepth;
1388 xpmattrs.visual = visual;
1389 xpmattrs.valuemask |= XpmVisual;
1390 xpmattrs.colormap = cmap;
1391 xpmattrs.valuemask |= XpmColormap;
1394 color_symbols = extract_xpm_color_names (&xpmattrs, device, domain,
1395 color_symbol_alist);
1397 result = XpmCreatePixmapFromBuffer (dpy,
1398 XtWindow(DEVICE_XT_APP_SHELL (XDEVICE(device))),
1399 (char *) XSTRING_DATA (data),
1400 &pixmap, &mask, &xpmattrs);
1404 xfree (color_symbols);
1405 xpmattrs.colorsymbols = 0; /* in case XpmFreeAttr is too smart... */
1406 xpmattrs.numsymbols = 0;
1413 case XpmFileInvalid:
1415 xpm_free (&xpmattrs);
1416 signal_image_error ("invalid XPM data", data);
1418 case XpmColorFailed:
1421 xpm_free (&xpmattrs);
1424 /* second time; blow out. */
1425 signal_double_file_error ("Reading pixmap data",
1426 "color allocation failed",
1431 if (! (dest_mask & IMAGE_MONO_PIXMAP_MASK))
1433 /* second time; blow out. */
1434 signal_double_file_error ("Reading pixmap data",
1435 "color allocation failed",
1439 IMAGE_INSTANCE_TYPE (ii) = IMAGE_MONO_PIXMAP;
1445 xpm_free (&xpmattrs);
1446 signal_double_file_error ("Parsing pixmap data",
1447 "out of memory", data);
1451 xpm_free (&xpmattrs);
1452 signal_double_file_error_2 ("Parsing pixmap data",
1453 "unknown error code",
1454 make_int (result), data);
1459 h = xpmattrs.height;
1462 int npixels = xpmattrs.npixels;
1467 pixels = xnew_array (Pixel, npixels);
1468 memcpy (pixels, xpmattrs.pixels, npixels * sizeof (Pixel));
1473 IMAGE_INSTANCE_X_PIXMAP (ii) = pixmap;
1474 IMAGE_INSTANCE_PIXMAP_MASK (ii) = (void*)mask;
1475 IMAGE_INSTANCE_X_COLORMAP (ii) = cmap;
1476 IMAGE_INSTANCE_X_PIXELS (ii) = pixels;
1477 IMAGE_INSTANCE_X_NPIXELS (ii) = npixels;
1478 IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = w;
1479 IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = h;
1480 IMAGE_INSTANCE_PIXMAP_FILENAME (ii) =
1481 find_keyword_in_vector (instantiator, Q_file);
1486 case IMAGE_MONO_PIXMAP:
1489 case IMAGE_COLOR_PIXMAP:
1491 IMAGE_INSTANCE_PIXMAP_DEPTH (ii) = depth;
1497 int npixels = xpmattrs.npixels;
1498 Pixel *pixels = xpmattrs.pixels;
1501 int xhot = 0, yhot = 0;
1503 if (xpmattrs.valuemask & XpmHotspot)
1505 xhot = xpmattrs.x_hotspot;
1506 XSETINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii), xpmattrs.x_hotspot);
1508 if (xpmattrs.valuemask & XpmHotspot)
1510 yhot = xpmattrs.y_hotspot;
1511 XSETINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii), xpmattrs.y_hotspot);
1513 check_pointer_sizes (xs, w, h, instantiator);
1515 /* If the loaded pixmap has colors allocated (meaning it came from an
1516 XPM file), then use those as the default colors for the cursor we
1517 create. Otherwise, default to pointer_fg and pointer_bg.
1521 /* With an XBM file, it's obvious which bit is foreground
1522 and which is background, or rather, it's implicit: in
1523 an XBM file, a 1 bit is foreground, and a 0 bit is
1526 XCreatePixmapCursor() assumes this property of the
1527 pixmap it is called with as well; the `foreground'
1528 color argument is used for the 1 bits.
1530 With an XPM file, it's tricker, since the elements of
1531 the pixmap don't represent FG and BG, but are actual
1532 pixel values. So we need to figure out which of those
1533 pixels is the foreground color and which is the
1534 background. We do it by comparing RGB and assuming
1535 that the darker color is the foreground. This works
1536 with the result of xbmtopbm|ppmtoxpm, at least.
1538 It might be nice if there was some way to tag the
1539 colors in the XPM file with whether they are the
1540 foreground - perhaps with logical color names somehow?
1542 Once we have decided which color is the foreground, we
1543 need to ensure that that color corresponds to a `1' bit
1544 in the Pixmap. The XPM library wrote into the (1-bit)
1545 pixmap with XPutPixel, which will ignore all but the
1546 least significant bit.
1548 This means that a 1 bit in the image corresponds to
1549 `fg' only if `fg.pixel' is odd.
1551 (This also means that the image will be all the same
1552 color if both `fg' and `bg' are odd or even, but we can
1553 safely assume that that won't happen if the XPM file is
1556 The desired result is that the image use `1' to
1557 represent the foreground color, and `0' to represent
1558 the background color. So, we may need to invert the
1559 image to accomplish this; we invert if fg is
1560 odd. (Remember that WhitePixel and BlackPixel are not
1561 necessarily 1 and 0 respectively, though I think it
1562 might be safe to assume that one of them is always 1
1563 and the other is always 0. We also pretty much need to
1564 assume that one is even and the other is odd.)
1567 fg.pixel = pixels[0]; /* pick a pixel at random. */
1568 bg.pixel = fg.pixel;
1569 for (i = 1; i < npixels; i++) /* Look for an "other" pixel value.*/
1571 bg.pixel = pixels[i];
1572 if (fg.pixel != bg.pixel)
1576 /* If (fg.pixel == bg.pixel) then probably something has
1577 gone wrong, but I don't think signalling an error would
1580 XQueryColor (dpy, cmap, &fg);
1581 XQueryColor (dpy, cmap, &bg);
1583 /* If the foreground is lighter than the background, swap them.
1584 (This occurs semi-randomly, depending on the ordering of the
1585 color list in the XPM file.)
1588 unsigned short fg_total = ((fg.red / 3) + (fg.green / 3)
1590 unsigned short bg_total = ((bg.red / 3) + (bg.green / 3)
1592 if (fg_total > bg_total)
1601 /* If the fg pixel corresponds to a `0' in the bitmap, invert it.
1602 (This occurs (only?) on servers with Black=0, White=1.)
1604 if ((fg.pixel & 1) == 0)
1608 gcv.function = GXxor;
1610 gc = XCreateGC (dpy, pixmap, (GCFunction | GCForeground),
1612 XFillRectangle (dpy, pixmap, gc, 0, 0, w, h);
1618 generate_cursor_fg_bg (device, &pointer_fg, &pointer_bg,
1620 IMAGE_INSTANCE_PIXMAP_FG (ii) = pointer_fg;
1621 IMAGE_INSTANCE_PIXMAP_BG (ii) = pointer_bg;
1624 IMAGE_INSTANCE_X_CURSOR (ii) =
1626 (dpy, pixmap, mask, &fg, &bg, xhot, yhot);
1635 xpm_free (&xpmattrs); /* after we've read pixels and hotspot */
1638 #endif /* HAVE_XPM */
1643 /**********************************************************************
1645 **********************************************************************/
1647 /* This is about to get redefined! */
1650 /* We have to define SYSV32 so that compface.h includes string.h
1651 instead of strings.h. */
1656 #include <compface.h>
1660 /* JMP_BUF cannot be used here because if it doesn't get defined
1661 to jmp_buf we end up with a conflicting type error with the
1662 definition in compface.h */
1663 extern jmp_buf comp_env;
1667 x_xface_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1668 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1669 int dest_mask, Lisp_Object domain)
1671 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1675 const char * volatile emsg = 0;
1676 const char * volatile dstring;
1678 assert (!NILP (data));
1680 LISP_STRING_TO_EXTERNAL (data, dstring, Qbinary);
1682 if ((p = strchr (dstring, ':')))
1687 /* Must use setjmp not SETJMP because we used jmp_buf above not JMP_BUF */
1688 if (!(stattis = setjmp (comp_env)))
1690 UnCompAll ((char *) dstring);
1697 emsg = "uncompface: internal error";
1700 emsg = "uncompface: insufficient or invalid data";
1703 emsg = "uncompface: excess data ignored";
1708 signal_simple_error_2 (emsg, data, Qimage);
1710 bp = bits = (char *) alloca (PIXELS / 8);
1712 /* the compface library exports char F[], which uses a single byte per
1713 pixel to represent a 48x48 bitmap. Yuck. */
1714 for (i = 0, p = F; i < (PIXELS / 8); ++i)
1717 /* reverse the bit order of each byte... */
1718 for (b = n = 0; b < 8; ++b)
1725 xbm_instantiate_1 (image_instance, instantiator, pointer_fg,
1726 pointer_bg, dest_mask, 48, 48, bits);
1729 #endif /* HAVE_XFACE */
1732 /**********************************************************************
1734 **********************************************************************/
1737 autodetect_validate (Lisp_Object instantiator)
1739 data_must_be_present (instantiator);
1743 autodetect_normalize (Lisp_Object instantiator,
1744 Lisp_Object console_type,
1745 Lisp_Object dest_mask)
1747 Lisp_Object file = find_keyword_in_vector (instantiator, Q_data);
1748 Lisp_Object filename = Qnil;
1749 Lisp_Object data = Qnil;
1750 struct gcpro gcpro1, gcpro2, gcpro3;
1751 Lisp_Object alist = Qnil;
1753 GCPRO3 (filename, data, alist);
1755 if (NILP (file)) /* no conversion necessary */
1756 RETURN_UNGCPRO (instantiator);
1758 alist = tagged_vector_to_alist (instantiator);
1760 filename = locate_pixmap_file (file);
1761 if (!NILP (filename))
1764 /* #### Apparently some versions of XpmReadFileToData, which is
1765 called by pixmap_to_lisp_data, don't return an error value
1766 if the given file is not a valid XPM file. Instead, they
1767 just seg fault. It is definitely caused by passing a
1768 bitmap. To try and avoid this we check for bitmaps first. */
1770 data = bitmap_to_lisp_data (filename, &xhot, &yhot, 1);
1774 alist = remassq_no_quit (Q_data, alist);
1775 alist = Fcons (Fcons (Q_file, filename),
1776 Fcons (Fcons (Q_data, data), alist));
1778 alist = Fcons (Fcons (Q_hotspot_x, make_int (xhot)),
1781 alist = Fcons (Fcons (Q_hotspot_y, make_int (yhot)),
1784 alist = xbm_mask_file_munging (alist, filename, Qnil, console_type);
1787 Lisp_Object result = alist_to_tagged_vector (Qxbm, alist);
1789 RETURN_UNGCPRO (result);
1794 data = pixmap_to_lisp_data (filename, 1);
1798 alist = remassq_no_quit (Q_data, alist);
1799 alist = Fcons (Fcons (Q_file, filename),
1800 Fcons (Fcons (Q_data, data), alist));
1801 alist = Fcons (Fcons (Q_color_symbols,
1802 evaluate_xpm_color_symbols ()),
1805 Lisp_Object result = alist_to_tagged_vector (Qxpm, alist);
1807 RETURN_UNGCPRO (result);
1813 /* If we couldn't convert it, just put it back as it is.
1814 We might try to further frob it later as a cursor-font
1815 specification. (We can't do that now because we don't know
1816 what dest-types it's going to be instantiated into.) */
1818 Lisp_Object result = alist_to_tagged_vector (Qautodetect, alist);
1820 RETURN_UNGCPRO (result);
1825 autodetect_possible_dest_types (void)
1828 IMAGE_MONO_PIXMAP_MASK |
1829 IMAGE_COLOR_PIXMAP_MASK |
1830 IMAGE_POINTER_MASK |
1835 autodetect_instantiate (Lisp_Object image_instance,
1836 Lisp_Object instantiator,
1837 Lisp_Object pointer_fg,
1838 Lisp_Object pointer_bg,
1839 int dest_mask, Lisp_Object domain)
1841 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1842 struct gcpro gcpro1, gcpro2, gcpro3;
1843 Lisp_Object alist = Qnil;
1844 Lisp_Object result = Qnil;
1845 int is_cursor_font = 0;
1847 GCPRO3 (data, alist, result);
1849 alist = tagged_vector_to_alist (instantiator);
1850 if (dest_mask & IMAGE_POINTER_MASK)
1852 const char *name_ext;
1853 LISP_STRING_TO_EXTERNAL (data, name_ext, Qfile_name);
1854 if (XmuCursorNameToIndex (name_ext) != -1)
1856 result = alist_to_tagged_vector (Qcursor_font, alist);
1861 if (!is_cursor_font)
1862 result = alist_to_tagged_vector (Qstring, alist);
1866 cursor_font_instantiate (image_instance, result, pointer_fg,
1867 pointer_bg, dest_mask, domain);
1869 string_instantiate (image_instance, result, pointer_fg,
1870 pointer_bg, dest_mask, domain);
1876 /**********************************************************************
1878 **********************************************************************/
1881 font_validate (Lisp_Object instantiator)
1883 data_must_be_present (instantiator);
1886 /* XmuCvtStringToCursor is bogus in the following ways:
1888 - When it can't convert the given string to a real cursor, it will
1889 sometimes return a "success" value, after triggering a BadPixmap
1890 error. It then gives you a cursor that will itself generate BadCursor
1891 errors. So we install this error handler to catch/notice the X error
1892 and take that as meaning "couldn't convert."
1894 - When you tell it to find a cursor file that doesn't exist, it prints
1895 an error message on stderr. You can't make it not do that.
1897 - Also, using Xmu means we can't properly hack Lisp_Image_Instance
1898 objects, or XPM files, or $XBMLANGPATH.
1901 /* Duplicate the behavior of XmuCvtStringToCursor() to bypass its bogusness. */
1903 static int XLoadFont_got_error;
1906 XLoadFont_error_handler (Display *dpy, XErrorEvent *xerror)
1908 XLoadFont_got_error = 1;
1913 safe_XLoadFont (Display *dpy, char *name)
1916 int (*old_handler) (Display *, XErrorEvent *);
1917 XLoadFont_got_error = 0;
1919 old_handler = XSetErrorHandler (XLoadFont_error_handler);
1920 font = XLoadFont (dpy, name);
1922 XSetErrorHandler (old_handler);
1923 if (XLoadFont_got_error) return 0;
1928 font_possible_dest_types (void)
1930 return IMAGE_POINTER_MASK;
1934 font_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1935 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1936 int dest_mask, Lisp_Object domain)
1938 /* This function can GC */
1939 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1940 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1941 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
1945 char source_name[MAXPATHLEN], mask_name[MAXPATHLEN], dummy;
1946 int source_char, mask_char;
1948 Lisp_Object foreground, background;
1950 if (!DEVICE_X_P (XDEVICE (device)))
1951 signal_simple_error ("Not an X device", device);
1953 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
1955 if (!STRINGP (data) ||
1956 strncmp ("FONT ", (char *) XSTRING_DATA (data), 5))
1957 signal_simple_error ("Invalid font-glyph instantiator",
1960 if (!(dest_mask & IMAGE_POINTER_MASK))
1961 incompatible_image_types (instantiator, dest_mask, IMAGE_POINTER_MASK);
1963 foreground = find_keyword_in_vector (instantiator, Q_foreground);
1964 if (NILP (foreground))
1965 foreground = pointer_fg;
1966 background = find_keyword_in_vector (instantiator, Q_background);
1967 if (NILP (background))
1968 background = pointer_bg;
1970 generate_cursor_fg_bg (device, &foreground, &background, &fg, &bg);
1972 count = sscanf ((char *) XSTRING_DATA (data),
1973 "FONT %s %d %s %d %c",
1974 source_name, &source_char,
1975 mask_name, &mask_char, &dummy);
1976 /* Allow "%s %d %d" as well... */
1977 if (count == 3 && (1 == sscanf (mask_name, "%d %c", &mask_char, &dummy)))
1978 count = 4, mask_name[0] = 0;
1980 if (count != 2 && count != 4)
1981 signal_simple_error ("invalid cursor specification", data);
1982 source = safe_XLoadFont (dpy, source_name);
1984 signal_simple_error_2 ("couldn't load font",
1985 build_string (source_name),
1989 else if (!mask_name[0])
1993 mask = safe_XLoadFont (dpy, mask_name);
1996 Fsignal (Qerror, list3 (build_string ("couldn't load font"),
1997 build_string (mask_name), data));
2002 /* #### call XQueryTextExtents() and check_pointer_sizes() here. */
2004 x_initialize_pixmap_image_instance (ii, 1, IMAGE_POINTER);
2005 IMAGE_INSTANCE_X_CURSOR (ii) =
2006 XCreateGlyphCursor (dpy, source, mask, source_char, mask_char,
2008 XIMAGE_INSTANCE_PIXMAP_FG (image_instance) = foreground;
2009 XIMAGE_INSTANCE_PIXMAP_BG (image_instance) = background;
2010 XUnloadFont (dpy, source);
2011 if (mask && mask != source) XUnloadFont (dpy, mask);
2015 /**********************************************************************
2017 **********************************************************************/
2020 cursor_font_validate (Lisp_Object instantiator)
2022 data_must_be_present (instantiator);
2026 cursor_font_possible_dest_types (void)
2028 return IMAGE_POINTER_MASK;
2032 cursor_font_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2033 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2034 int dest_mask, Lisp_Object domain)
2036 /* This function can GC */
2037 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
2038 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2039 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
2042 const char *name_ext;
2043 Lisp_Object foreground, background;
2045 if (!DEVICE_X_P (XDEVICE (device)))
2046 signal_simple_error ("Not an X device", device);
2048 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
2050 if (!(dest_mask & IMAGE_POINTER_MASK))
2051 incompatible_image_types (instantiator, dest_mask, IMAGE_POINTER_MASK);
2053 LISP_STRING_TO_EXTERNAL (data, name_ext, Qfile_name);
2054 if ((i = XmuCursorNameToIndex (name_ext)) == -1)
2055 signal_simple_error ("Unrecognized cursor-font name", data);
2057 x_initialize_pixmap_image_instance (ii, 1, IMAGE_POINTER);
2058 IMAGE_INSTANCE_X_CURSOR (ii) = XCreateFontCursor (dpy, i);
2059 foreground = find_keyword_in_vector (instantiator, Q_foreground);
2060 if (NILP (foreground))
2061 foreground = pointer_fg;
2062 background = find_keyword_in_vector (instantiator, Q_background);
2063 if (NILP (background))
2064 background = pointer_bg;
2065 maybe_recolor_cursor (image_instance, foreground, background);
2069 x_colorize_image_instance (Lisp_Object image_instance,
2070 Lisp_Object foreground, Lisp_Object background)
2072 Lisp_Image_Instance *p;
2074 p = XIMAGE_INSTANCE (image_instance);
2076 switch (IMAGE_INSTANCE_TYPE (p))
2078 case IMAGE_MONO_PIXMAP:
2079 IMAGE_INSTANCE_TYPE (p) = IMAGE_COLOR_PIXMAP;
2080 /* Make sure there aren't two pointers to the same mask, causing
2081 it to get freed twice. */
2082 IMAGE_INSTANCE_PIXMAP_MASK (p) = 0;
2090 Display *dpy = DEVICE_X_DISPLAY (XDEVICE (IMAGE_INSTANCE_DEVICE (p)));
2091 Drawable draw = XtWindow(DEVICE_XT_APP_SHELL (XDEVICE (IMAGE_INSTANCE_DEVICE (p))));
2092 Dimension d = DEVICE_X_DEPTH (XDEVICE (IMAGE_INSTANCE_DEVICE (p)));
2093 Pixmap new = XCreatePixmap (dpy, draw,
2094 IMAGE_INSTANCE_PIXMAP_WIDTH (p),
2095 IMAGE_INSTANCE_PIXMAP_HEIGHT (p), d);
2099 color = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (foreground));
2100 gcv.foreground = color.pixel;
2101 color = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (background));
2102 gcv.background = color.pixel;
2103 gc = XCreateGC (dpy, new, GCBackground|GCForeground, &gcv);
2104 XCopyPlane (dpy, IMAGE_INSTANCE_X_PIXMAP (p), new, gc, 0, 0,
2105 IMAGE_INSTANCE_PIXMAP_WIDTH (p),
2106 IMAGE_INSTANCE_PIXMAP_HEIGHT (p),
2109 IMAGE_INSTANCE_X_PIXMAP (p) = new;
2110 IMAGE_INSTANCE_PIXMAP_DEPTH (p) = d;
2111 IMAGE_INSTANCE_PIXMAP_FG (p) = foreground;
2112 IMAGE_INSTANCE_PIXMAP_BG (p) = background;
2118 /************************************************************************/
2119 /* subwindow and widget support */
2120 /************************************************************************/
2122 /* unmap the image if it is a widget. This is used by redisplay via
2123 redisplay_unmap_subwindows */
2125 x_unmap_subwindow (Lisp_Image_Instance *p)
2127 if (IMAGE_INSTANCE_TYPE (p) == IMAGE_SUBWINDOW)
2130 (IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY (p),
2131 IMAGE_INSTANCE_X_CLIPWINDOW (p));
2133 else /* must be a widget */
2135 /* Since we are being unmapped we want the enclosing frame to
2136 get focus. The losing with simple scrolling but is the safest
2138 emacs_Xt_handle_widget_losing_focus
2139 ( XFRAME (IMAGE_INSTANCE_FRAME (p)),
2140 IMAGE_INSTANCE_X_WIDGET_ID (p));
2141 XtUnmapWidget (IMAGE_INSTANCE_X_CLIPWIDGET (p));
2145 /* map the subwindow. This is used by redisplay via
2146 redisplay_output_subwindow */
2148 x_map_subwindow (Lisp_Image_Instance *p, int x, int y,
2149 struct display_glyph_area* dga)
2151 assert (dga->width > 0 && dga->height > 0);
2152 if (IMAGE_INSTANCE_TYPE (p) == IMAGE_SUBWINDOW)
2154 Window subwindow = IMAGE_INSTANCE_X_SUBWINDOW_ID (p);
2155 XMoveResizeWindow (IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY (p),
2156 IMAGE_INSTANCE_X_CLIPWINDOW (p),
2157 x, y, dga->width, dga->height);
2158 XMoveWindow (IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY (p),
2159 subwindow, -dga->xoffset, -dga->yoffset);
2160 if (!IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (p))
2161 XMapWindow (IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY (p),
2162 IMAGE_INSTANCE_X_CLIPWINDOW (p));
2164 else /* must be a widget */
2166 XtConfigureWidget (IMAGE_INSTANCE_X_CLIPWIDGET (p),
2167 x + IMAGE_INSTANCE_X_WIDGET_XOFFSET (p),
2168 y + IMAGE_INSTANCE_X_WIDGET_YOFFSET (p),
2169 dga->width, dga->height, 0);
2170 XtMoveWidget (IMAGE_INSTANCE_X_WIDGET_ID (p),
2171 -dga->xoffset, -dga->yoffset);
2172 if (!IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (p))
2173 XtMapWidget (IMAGE_INSTANCE_X_CLIPWIDGET (p));
2177 /* when you click on a widget you may activate another widget this
2178 needs to be checked and all appropriate widgets updated */
2180 x_redisplay_subwindow (Lisp_Image_Instance *p)
2182 /* Update the subwindow size if necessary. */
2183 if (IMAGE_INSTANCE_SIZE_CHANGED (p))
2185 XResizeWindow (IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY (p),
2186 IMAGE_INSTANCE_X_SUBWINDOW_ID (p),
2187 IMAGE_INSTANCE_WIDTH (p),
2188 IMAGE_INSTANCE_HEIGHT (p));
2192 /* Update all attributes that have changed. Lwlib actually does most
2195 x_redisplay_widget (Lisp_Image_Instance *p)
2197 /* This function can GC if IN_REDISPLAY is false. */
2199 widget_value* wv = 0;
2201 /* First get the items if they have changed since this is a
2202 structural change. As such it will nuke all added values so we
2203 need to update most other things after the items have changed.*/
2204 if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (p))
2206 Lisp_Object image_instance;
2208 XSETIMAGE_INSTANCE (image_instance, p);
2209 wv = gui_items_to_widget_values
2210 (image_instance, IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (p),
2211 /* #### this is not right; we need to keep track of which widgets
2212 want accelerators and which don't */ 0);
2213 wv->change = STRUCTURAL_CHANGE;
2217 /* Assume the lotus position, breath deeply and chant to
2218 yourself lwlibsux, lwlibsux ... lw_get_all_values returns a
2219 reference to the real values rather than a copy thus any
2220 changes we make to the values we get back will look like they
2221 have already been applied. If we rebuild the widget tree then
2222 we may lose properties. */
2223 wv = copy_widget_value_tree (lw_get_all_values
2224 (IMAGE_INSTANCE_X_WIDGET_LWID (p)),
2228 /* Possibly update the colors and font */
2229 if (IMAGE_INSTANCE_WIDGET_FACE_CHANGED (p)
2231 XFRAME (IMAGE_INSTANCE_FRAME (p))->faces_changed
2233 IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (p))
2235 update_widget_face (wv, p, IMAGE_INSTANCE_FRAME (p));
2238 /* Possibly update the text. */
2239 if (IMAGE_INSTANCE_TEXT_CHANGED (p))
2242 Lisp_Object val = IMAGE_INSTANCE_WIDGET_TEXT (p);
2243 LISP_STRING_TO_EXTERNAL (val, str, Qnative);
2247 /* Possibly update the size. */
2248 if (IMAGE_INSTANCE_SIZE_CHANGED (p)
2250 IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (p)
2252 IMAGE_INSTANCE_TEXT_CHANGED (p))
2254 assert (IMAGE_INSTANCE_X_WIDGET_ID (p) &&
2255 IMAGE_INSTANCE_X_CLIPWIDGET (p)) ;
2257 if (IMAGE_INSTANCE_X_WIDGET_ID (p)->core.being_destroyed
2258 || !XtIsManaged(IMAGE_INSTANCE_X_WIDGET_ID (p)))
2261 XSETIMAGE_INSTANCE (sw, p);
2262 signal_simple_error ("XEmacs bug: subwindow is deleted", sw);
2265 lw_add_widget_value_arg (wv, XtNwidth,
2266 (Dimension)IMAGE_INSTANCE_WIDTH (p));
2267 lw_add_widget_value_arg (wv, XtNheight,
2268 (Dimension)IMAGE_INSTANCE_HEIGHT (p));
2271 /* Adjust offsets within the frame. */
2272 if (XFRAME (IMAGE_INSTANCE_FRAME (p))->size_changed)
2275 XtSetArg (al [0], XtNx, &IMAGE_INSTANCE_X_WIDGET_XOFFSET (p));
2276 XtSetArg (al [1], XtNy, &IMAGE_INSTANCE_X_WIDGET_YOFFSET (p));
2277 XtGetValues (FRAME_X_TEXT_WIDGET
2278 (XFRAME (IMAGE_INSTANCE_FRAME (p))), al, 2);
2281 /* now modify the widget */
2282 lw_modify_all_widgets (IMAGE_INSTANCE_X_WIDGET_LWID (p),
2284 free_widget_value_tree (wv);
2288 /* instantiate and x type subwindow */
2290 x_subwindow_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2291 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2292 int dest_mask, Lisp_Object domain)
2294 /* This function can GC */
2295 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2296 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
2297 Lisp_Object frame = DOMAIN_FRAME (domain);
2298 struct frame* f = XFRAME (frame);
2302 XSetWindowAttributes xswa;
2304 unsigned int w = IMAGE_INSTANCE_WIDTH (ii),
2305 h = IMAGE_INSTANCE_HEIGHT (ii);
2307 if (!DEVICE_X_P (XDEVICE (device)))
2308 signal_simple_error ("Not an X device", device);
2310 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
2311 xs = DefaultScreenOfDisplay (dpy);
2313 IMAGE_INSTANCE_TYPE (ii) = IMAGE_SUBWINDOW;
2315 pw = XtWindow (FRAME_X_TEXT_WIDGET (f));
2317 ii->data = xnew_and_zero (struct x_subwindow_data);
2319 IMAGE_INSTANCE_X_SUBWINDOW_PARENT (ii) = pw;
2320 IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY (ii) = DisplayOfScreen (xs);
2322 xswa.backing_store = Always;
2323 valueMask |= CWBackingStore;
2324 xswa.colormap = DefaultColormapOfScreen (xs);
2325 valueMask |= CWColormap;
2327 /* Create a window for clipping */
2328 IMAGE_INSTANCE_X_CLIPWINDOW (ii) =
2329 XCreateWindow (dpy, pw, 0, 0, w, h, 0, CopyFromParent,
2330 InputOutput, CopyFromParent, valueMask,
2333 /* Now put the subwindow inside the clip window. */
2334 win = XCreateWindow (dpy, IMAGE_INSTANCE_X_CLIPWINDOW (ii),
2335 0, 0, w, h, 0, CopyFromParent,
2336 InputOutput, CopyFromParent, valueMask,
2339 IMAGE_INSTANCE_SUBWINDOW_ID (ii) = (void*)win;
2343 /* #### Should this function exist? If there's any doubt I'm not implementing it --andyp */
2344 DEFUN ("change-subwindow-property", Fchange_subwindow_property, 3, 3, 0, /*
2345 For the given SUBWINDOW, set PROPERTY to DATA, which is a string.
2346 Subwindows are not currently implemented.
2348 (subwindow, property, data))
2354 CHECK_SUBWINDOW (subwindow);
2355 CHECK_STRING (property);
2356 CHECK_STRING (data);
2358 sw = XSUBWINDOW (subwindow);
2359 dpy = DisplayOfScreen (LISP_DEVICE_TO_X_SCREEN
2360 (FRAME_DEVICE (XFRAME (sw->frame))));
2362 property_atom = XInternAtom (dpy, (char *) XSTRING_DATA (property), False);
2363 XChangeProperty (dpy, sw->subwindow, property_atom, XA_STRING, 8,
2365 XSTRING_DATA (data),
2366 XSTRING_LENGTH (data));
2375 /************************************************************************/
2377 /************************************************************************/
2380 update_widget_face (widget_value* wv, Lisp_Image_Instance *ii,
2383 #ifdef LWLIB_WIDGETS_MOTIF
2384 XmFontList fontList;
2386 /* Update the foreground. */
2387 Lisp_Object pixel = FACE_FOREGROUND
2388 (IMAGE_INSTANCE_WIDGET_FACE (ii),
2390 XColor fcolor = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (pixel)), bcolor;
2391 lw_add_widget_value_arg (wv, XtNforeground, fcolor.pixel);
2393 /* Update the background. */
2394 pixel = FACE_BACKGROUND (IMAGE_INSTANCE_WIDGET_FACE (ii),
2396 bcolor = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (pixel));
2397 lw_add_widget_value_arg (wv, XtNbackground, bcolor.pixel);
2399 #ifdef LWLIB_WIDGETS_MOTIF
2400 fontList = XmFontListCreate
2401 (FONT_INSTANCE_X_FONT
2402 (XFONT_INSTANCE (query_string_font
2403 (IMAGE_INSTANCE_WIDGET_TEXT (ii),
2404 IMAGE_INSTANCE_WIDGET_FACE (ii),
2405 domain))), XmSTRING_DEFAULT_CHARSET);
2406 lw_add_widget_value_arg (wv, XmNfontList, (XtArgVal)fontList);
2408 lw_add_widget_value_arg
2409 (wv, XtNfont, (XtArgVal)FONT_INSTANCE_X_FONT
2410 (XFONT_INSTANCE (query_string_font
2411 (IMAGE_INSTANCE_WIDGET_TEXT (ii),
2412 IMAGE_INSTANCE_WIDGET_FACE (ii),
2414 wv->change = VISIBLE_CHANGE;
2415 /* #### Megahack - but its just getting too complicated to do this
2416 in the right place. */
2417 if (EQ (IMAGE_INSTANCE_WIDGET_TYPE (ii), Qtab_control))
2418 update_tab_widget_face (wv, ii, domain);
2422 update_tab_widget_face (widget_value* wv, Lisp_Image_Instance *ii,
2427 widget_value* val = wv->contents, *cur;
2429 /* Give each child label the correct foreground color. */
2430 Lisp_Object pixel = FACE_FOREGROUND
2431 (IMAGE_INSTANCE_WIDGET_FACE (ii),
2433 XColor fcolor = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (pixel));
2434 lw_add_widget_value_arg (val, XtNtabForeground, fcolor.pixel);
2435 wv->change = VISIBLE_CHANGE;
2436 val->change = VISIBLE_CHANGE;
2438 for (cur = val->next; cur; cur = cur->next)
2440 cur->change = VISIBLE_CHANGE;
2443 lw_copy_widget_value_args (val, cur);
2450 x_widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2451 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2452 int dest_mask, Lisp_Object domain,
2453 const char* type, widget_value* wv)
2455 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2456 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii), pixel;
2457 struct device* d = XDEVICE (device);
2458 Lisp_Object frame = DOMAIN_FRAME (domain);
2459 struct frame* f = XFRAME (frame);
2464 int id = new_lwlib_id ();
2465 widget_value* clip_wv;
2466 XColor fcolor, bcolor;
2468 if (!DEVICE_X_P (d))
2469 signal_simple_error ("Not an X device", device);
2471 /* have to set the type this late in case there is no device
2472 instantiation for a widget. But we can go ahead and do it without
2473 checking because there is always a generic instantiator. */
2474 IMAGE_INSTANCE_TYPE (ii) = IMAGE_WIDGET;
2476 if (!NILP (IMAGE_INSTANCE_WIDGET_TEXT (ii)))
2477 LISP_STRING_TO_EXTERNAL (IMAGE_INSTANCE_WIDGET_TEXT (ii), nm, Qnative);
2479 ii->data = xnew_and_zero (struct x_subwindow_data);
2481 /* Create a clip window to contain the subwidget. Incredibly the
2482 XEmacs manager seems to be the most appropriate widget for
2483 this. Nothing else is simple enough and yet does what is
2485 clip_wv = xmalloc_widget_value ();
2487 lw_add_widget_value_arg (clip_wv, XtNresize, False);
2488 lw_add_widget_value_arg (clip_wv, XtNwidth,
2489 (Dimension)IMAGE_INSTANCE_WIDTH (ii));
2490 lw_add_widget_value_arg (clip_wv, XtNheight,
2491 (Dimension)IMAGE_INSTANCE_HEIGHT (ii));
2492 clip_wv->enabled = True;
2494 clip_wv->name = xstrdup ("clip-window");
2495 clip_wv->value = xstrdup ("clip-window");
2497 IMAGE_INSTANCE_X_CLIPWIDGET (ii)
2498 = lw_create_widget ("clip-window", "clip-window", new_lwlib_id (),
2499 clip_wv, FRAME_X_CONTAINER_WIDGET (f),
2502 free_widget_value_tree (clip_wv);
2504 /* copy any args we were given */
2506 lw_add_value_args_to_args (wv, al, &ac);
2508 /* Fixup the colors. We have to do this *before* the widget gets
2509 created so that Motif will fix up the shadow colors
2510 correctly. Once the widget is created Motif won't do this
2512 pixel = FACE_FOREGROUND
2513 (IMAGE_INSTANCE_WIDGET_FACE (ii),
2514 IMAGE_INSTANCE_FRAME (ii));
2515 fcolor = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (pixel));
2517 pixel = FACE_BACKGROUND
2518 (IMAGE_INSTANCE_WIDGET_FACE (ii),
2519 IMAGE_INSTANCE_FRAME (ii));
2520 bcolor = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (pixel));
2522 lw_add_widget_value_arg (wv, XtNbackground, bcolor.pixel);
2523 lw_add_widget_value_arg (wv, XtNforeground, fcolor.pixel);
2524 /* we cannot allow widgets to resize themselves */
2525 lw_add_widget_value_arg (wv, XtNresize, False);
2526 lw_add_widget_value_arg (wv, XtNwidth,
2527 (Dimension)IMAGE_INSTANCE_WIDTH (ii));
2528 lw_add_widget_value_arg (wv, XtNheight,
2529 (Dimension)IMAGE_INSTANCE_HEIGHT (ii));
2530 /* update the font. */
2531 update_widget_face (wv, ii, domain);
2533 wid = lw_create_widget (type, wv->name, id, wv, IMAGE_INSTANCE_X_CLIPWIDGET (ii),
2534 False, 0, popup_selection_callback, 0);
2536 IMAGE_INSTANCE_SUBWINDOW_ID (ii) = (void*)wid;
2537 IMAGE_INSTANCE_X_WIDGET_LWID (ii) = id;
2538 /* because the EmacsManager is the widgets parent we have to
2539 offset the redisplay of the widget by the amount the text
2540 widget is inside the manager. */
2542 XtSetArg (al [ac], XtNx, &IMAGE_INSTANCE_X_WIDGET_XOFFSET (ii)); ac++;
2543 XtSetArg (al [ac], XtNy, &IMAGE_INSTANCE_X_WIDGET_YOFFSET (ii)); ac++;
2544 XtGetValues (FRAME_X_TEXT_WIDGET (f), al, ac);
2546 XtSetMappedWhenManaged (wid, TRUE);
2548 free_widget_value_tree (wv);
2549 /* A kludgy but simple way to make sure the callback for a widget
2550 doesn't get deleted. */
2551 gcpro_popup_callbacks (id);
2554 /* get properties of a control */
2556 x_widget_property (Lisp_Object image_instance, Lisp_Object prop)
2558 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2559 /* get the text from a control */
2560 if (EQ (prop, Q_text))
2562 widget_value* wv = lw_get_all_values (IMAGE_INSTANCE_X_WIDGET_LWID (ii));
2563 return build_ext_string (wv->value, Qnative);
2568 /* Instantiate a layout control for putting other widgets in. */
2570 x_native_layout_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2571 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2572 int dest_mask, Lisp_Object domain)
2574 x_widget_instantiate (image_instance, instantiator, pointer_fg,
2575 pointer_bg, dest_mask, domain, "layout", 0);
2578 /* Instantiate a button widget. Unfortunately instantiated widgets are
2579 particular to a frame since they need to have a parent. It's not
2580 like images where you just select the image into the context you
2581 want to display it in and BitBlt it. So images instances can have a
2582 many-to-one relationship with things you see, whereas widgets can
2583 only be one-to-one (i.e. per frame) */
2585 x_button_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2586 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2587 int dest_mask, Lisp_Object domain)
2589 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2590 Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM (ii);
2591 Lisp_Object glyph = find_keyword_in_vector (instantiator, Q_image);
2592 widget_value* wv = gui_items_to_widget_values (image_instance, gui, 1);
2596 if (!IMAGE_INSTANCEP (glyph))
2597 glyph = glyph_image_instance (glyph, domain, ERROR_ME, 1);
2600 x_widget_instantiate (image_instance, instantiator, pointer_fg,
2601 pointer_bg, dest_mask, domain, "button", wv);
2603 /* add the image if one was given */
2604 if (!NILP (glyph) && IMAGE_INSTANCEP (glyph)
2605 && IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (glyph)))
2609 #ifdef LWLIB_WIDGETS_MOTIF
2610 XtSetArg (al [ac], XmNlabelType, XmPIXMAP); ac++;
2611 XtSetArg (al [ac], XmNlabelPixmap, XIMAGE_INSTANCE_X_PIXMAP (glyph));ac++;
2613 XtSetArg (al [ac], XtNpixmap, XIMAGE_INSTANCE_X_PIXMAP (glyph)); ac++;
2615 XtSetValues (IMAGE_INSTANCE_X_WIDGET_ID (ii), al, ac);
2619 /* Update a button's clicked state.
2621 #### This is overkill, but it works. Right now this causes all
2622 button instances to flash for some reason buried deep in lwlib. In
2623 theory this should be the Right Thing to do since lwlib should only
2624 merge in changed values - and if nothing has changed then nothing
2625 should get done. This may be because of the args stuff,
2626 i.e. although the arg contents may be the same the args look
2627 different and so are re-applied to the widget. */
2629 x_button_redisplay (Lisp_Object image_instance)
2631 /* This function can GC if IN_REDISPLAY is false. */
2632 Lisp_Image_Instance *p = XIMAGE_INSTANCE (image_instance);
2634 gui_items_to_widget_values (image_instance,
2635 IMAGE_INSTANCE_WIDGET_ITEMS (p), 1);
2637 /* now modify the widget */
2638 lw_modify_all_widgets (IMAGE_INSTANCE_X_WIDGET_LWID (p),
2640 free_widget_value_tree (wv);
2643 /* get properties of a button */
2645 x_button_property (Lisp_Object image_instance, Lisp_Object prop)
2647 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2648 /* check the state of a button */
2649 if (EQ (prop, Q_selected))
2651 widget_value* wv = lw_get_all_values (IMAGE_INSTANCE_X_WIDGET_LWID (ii));
2661 /* instantiate a progress gauge */
2663 x_progress_gauge_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2664 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2665 int dest_mask, Lisp_Object domain)
2667 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2668 Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM (ii);
2669 widget_value* wv = gui_items_to_widget_values (image_instance, gui, 0);
2671 x_widget_instantiate (image_instance, instantiator, pointer_fg,
2672 pointer_bg, dest_mask, domain, "progress", wv);
2675 /* set the properties of a progress gauge */
2677 x_progress_gauge_redisplay (Lisp_Object image_instance)
2679 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2681 if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii))
2685 #ifdef ERROR_CHECK_GLYPHS
2686 assert (GUI_ITEMP (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii)));
2688 val = XGUI_ITEM (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii))->value;
2689 XtSetArg (al[0], XtNvalue, XINT (val));
2690 XtSetValues (IMAGE_INSTANCE_X_WIDGET_ID (ii), al, 1);
2694 /* instantiate an edit control */
2696 x_edit_field_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2697 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2698 int dest_mask, Lisp_Object domain)
2700 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2701 Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM (ii);
2702 widget_value* wv = gui_items_to_widget_values (image_instance, gui, 0);
2704 x_widget_instantiate (image_instance, instantiator, pointer_fg,
2705 pointer_bg, dest_mask, domain, "text-field", wv);
2708 #if defined (LWLIB_WIDGETS_MOTIF) && XmVERSION > 1
2709 /* instantiate a combo control */
2711 x_combo_box_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2712 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2713 int dest_mask, Lisp_Object domain)
2715 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2716 widget_value * wv = 0;
2717 /* This is not done generically because of sizing problems under
2719 widget_instantiate (image_instance, instantiator, pointer_fg,
2720 pointer_bg, dest_mask, domain);
2722 wv = gui_items_to_widget_values (image_instance,
2723 IMAGE_INSTANCE_WIDGET_ITEMS (ii), 0);
2725 x_widget_instantiate (image_instance, instantiator, pointer_fg,
2726 pointer_bg, dest_mask, domain, "combo-box", wv);
2731 x_tab_control_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2732 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2733 int dest_mask, Lisp_Object domain)
2735 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2737 gui_items_to_widget_values (image_instance,
2738 IMAGE_INSTANCE_WIDGET_ITEMS (ii), 0);
2739 update_tab_widget_face (wv, ii,
2740 IMAGE_INSTANCE_FRAME (ii));
2741 x_widget_instantiate (image_instance, instantiator, pointer_fg,
2742 pointer_bg, dest_mask, domain, "tab-control", wv);
2745 /* Set the properties of a tab control */
2747 x_tab_control_redisplay (Lisp_Object image_instance)
2749 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2751 if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii)
2753 IMAGE_INSTANCE_WIDGET_ACTION_OCCURRED (ii))
2755 /* If only the order has changed then simply select the first
2756 one of the pending set. This stops horrendous rebuilding -
2757 and hence flicker - of the tabs each time you click on
2759 if (tab_control_order_only_changed (image_instance))
2761 Lisp_Object rest, selected =
2762 gui_item_list_find_selected
2763 (NILP (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii)) ?
2764 XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)) :
2765 XCDR (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii)));
2767 LIST_LOOP (rest, XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)))
2769 if (gui_item_equal_sans_selected (XCAR (rest), selected, 0))
2771 /* There may be an encapsulated way of doing this,
2772 but I couldn't find it. */
2773 Lisp_Object old_selected =gui_item_list_find_selected
2774 (XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)));
2777 unsigned int num_children, i;
2780 LISP_STRING_TO_EXTERNAL (XGUI_ITEM (XCAR (rest))->name,
2782 /* The name may contain a `.' which confuses
2783 XtNameToWidget, so we do it ourselves. */
2784 children = XtCompositeChildren (IMAGE_INSTANCE_X_WIDGET_ID (ii),
2786 for (i = 0; i < num_children; i++)
2788 if (!strcmp (XtName (children [i]), name))
2790 XtSetArg (al [0], XtNtopWidget, children [i]);
2791 XtSetValues (IMAGE_INSTANCE_X_WIDGET_ID (ii), al, 1);
2795 /* Pick up the new selected item. */
2796 XGUI_ITEM (old_selected)->selected =
2797 XGUI_ITEM (XCAR (rest))->selected;
2798 XGUI_ITEM (XCAR (rest))->selected =
2799 XGUI_ITEM (selected)->selected;
2800 /* We're not actually changing the items anymore. */
2801 IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii) = 0;
2802 IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii) = Qnil;
2808 /* Possibly update the face. */
2809 if (IMAGE_INSTANCE_WIDGET_FACE_CHANGED (ii)
2811 XFRAME (IMAGE_INSTANCE_FRAME (ii))->faces_changed
2813 IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii))
2815 /* See previous comments on the brokeness of lwlib.
2817 #### There's actually not much point in doing this here
2818 since, colors will have been set appropriately by
2819 x_redisplay_widget. */
2820 widget_value* wv =copy_widget_value_tree
2822 (IMAGE_INSTANCE_X_WIDGET_LWID (ii)),
2825 update_tab_widget_face (wv, ii,
2826 IMAGE_INSTANCE_FRAME (ii));
2828 lw_modify_all_widgets (IMAGE_INSTANCE_X_WIDGET_LWID (ii), wv, True);
2829 free_widget_value_tree (wv);
2833 /* instantiate a static control possible for putting other things in */
2835 x_label_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2836 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2837 int dest_mask, Lisp_Object domain)
2839 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2840 Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM (ii);
2841 widget_value* wv = gui_items_to_widget_values (image_instance, gui, 0);
2843 x_widget_instantiate (image_instance, instantiator, pointer_fg,
2844 pointer_bg, dest_mask, domain, "button", wv);
2846 #endif /* HAVE_WIDGETS */
2849 /************************************************************************/
2850 /* initialization */
2851 /************************************************************************/
2854 syms_of_glyphs_x (void)
2857 DEFSUBR (Fchange_subwindow_property);
2862 console_type_create_glyphs_x (void)
2866 CONSOLE_HAS_METHOD (x, print_image_instance);
2867 CONSOLE_HAS_METHOD (x, finalize_image_instance);
2868 CONSOLE_HAS_METHOD (x, image_instance_equal);
2869 CONSOLE_HAS_METHOD (x, image_instance_hash);
2870 CONSOLE_HAS_METHOD (x, colorize_image_instance);
2871 CONSOLE_HAS_METHOD (x, init_image_instance_from_eimage);
2872 CONSOLE_HAS_METHOD (x, locate_pixmap_file);
2873 CONSOLE_HAS_METHOD (x, unmap_subwindow);
2874 CONSOLE_HAS_METHOD (x, map_subwindow);
2875 CONSOLE_HAS_METHOD (x, redisplay_widget);
2876 CONSOLE_HAS_METHOD (x, redisplay_subwindow);
2880 image_instantiator_format_create_glyphs_x (void)
2882 IIFORMAT_VALID_CONSOLE (x, nothing);
2883 IIFORMAT_VALID_CONSOLE (x, string);
2885 IIFORMAT_VALID_CONSOLE (x, layout);
2887 IIFORMAT_VALID_CONSOLE (x, formatted_string);
2888 IIFORMAT_VALID_CONSOLE (x, inherit);
2890 INITIALIZE_DEVICE_IIFORMAT (x, xpm);
2891 IIFORMAT_HAS_DEVMETHOD (x, xpm, instantiate);
2894 IIFORMAT_VALID_CONSOLE (x, jpeg);
2897 IIFORMAT_VALID_CONSOLE (x, tiff);
2900 IIFORMAT_VALID_CONSOLE (x, png);
2903 IIFORMAT_VALID_CONSOLE (x, gif);
2905 INITIALIZE_DEVICE_IIFORMAT (x, xbm);
2906 IIFORMAT_HAS_DEVMETHOD (x, xbm, instantiate);
2908 INITIALIZE_DEVICE_IIFORMAT (x, subwindow);
2909 IIFORMAT_HAS_DEVMETHOD (x, subwindow, instantiate);
2912 INITIALIZE_DEVICE_IIFORMAT (x, native_layout);
2913 IIFORMAT_HAS_DEVMETHOD (x, native_layout, instantiate);
2915 INITIALIZE_DEVICE_IIFORMAT (x, button);
2916 IIFORMAT_HAS_DEVMETHOD (x, button, property);
2917 IIFORMAT_HAS_DEVMETHOD (x, button, instantiate);
2918 IIFORMAT_HAS_DEVMETHOD (x, button, redisplay);
2919 /* general widget methods. */
2920 INITIALIZE_DEVICE_IIFORMAT (x, widget);
2921 IIFORMAT_HAS_DEVMETHOD (x, widget, property);
2922 /* progress gauge */
2923 INITIALIZE_DEVICE_IIFORMAT (x, progress_gauge);
2924 IIFORMAT_HAS_DEVMETHOD (x, progress_gauge, redisplay);
2925 IIFORMAT_HAS_DEVMETHOD (x, progress_gauge, instantiate);
2927 INITIALIZE_DEVICE_IIFORMAT (x, edit_field);
2928 IIFORMAT_HAS_DEVMETHOD (x, edit_field, instantiate);
2929 #if defined (LWLIB_WIDGETS_MOTIF) && XmVERSION > 1
2931 INITIALIZE_DEVICE_IIFORMAT (x, combo_box);
2932 IIFORMAT_HAS_DEVMETHOD (x, combo_box, instantiate);
2933 IIFORMAT_HAS_SHARED_DEVMETHOD (x, combo_box, redisplay, tab_control);
2935 /* tab control widget */
2936 INITIALIZE_DEVICE_IIFORMAT (x, tab_control);
2937 IIFORMAT_HAS_DEVMETHOD (x, tab_control, instantiate);
2938 IIFORMAT_HAS_DEVMETHOD (x, tab_control, redisplay);
2940 INITIALIZE_DEVICE_IIFORMAT (x, label);
2941 IIFORMAT_HAS_DEVMETHOD (x, label, instantiate);
2943 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (cursor_font, "cursor-font");
2944 IIFORMAT_VALID_CONSOLE (x, cursor_font);
2946 IIFORMAT_HAS_METHOD (cursor_font, validate);
2947 IIFORMAT_HAS_METHOD (cursor_font, possible_dest_types);
2948 IIFORMAT_HAS_METHOD (cursor_font, instantiate);
2950 IIFORMAT_VALID_KEYWORD (cursor_font, Q_data, check_valid_string);
2951 IIFORMAT_VALID_KEYWORD (cursor_font, Q_foreground, check_valid_string);
2952 IIFORMAT_VALID_KEYWORD (cursor_font, Q_background, check_valid_string);
2954 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (font, "font");
2956 IIFORMAT_HAS_METHOD (font, validate);
2957 IIFORMAT_HAS_METHOD (font, possible_dest_types);
2958 IIFORMAT_HAS_METHOD (font, instantiate);
2959 IIFORMAT_VALID_CONSOLE (x, font);
2961 IIFORMAT_VALID_KEYWORD (font, Q_data, check_valid_string);
2962 IIFORMAT_VALID_KEYWORD (font, Q_foreground, check_valid_string);
2963 IIFORMAT_VALID_KEYWORD (font, Q_background, check_valid_string);
2966 INITIALIZE_DEVICE_IIFORMAT (x, xface);
2967 IIFORMAT_HAS_DEVMETHOD (x, xface, instantiate);
2970 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (autodetect,
2973 IIFORMAT_HAS_METHOD (autodetect, validate);
2974 IIFORMAT_HAS_METHOD (autodetect, normalize);
2975 IIFORMAT_HAS_METHOD (autodetect, possible_dest_types);
2976 /* #### autodetect is flawed IMO:
2977 1. It makes the assumption that you can detect whether the user
2978 wanted a cursor or a string based on the data, since the data is a
2979 string you have to prioritise cursors. Instead we will force users
2980 to pick the appropriate image type, this is what we do under
2982 2. It doesn't fit with the new domain model - you cannot tell which
2983 domain it needs to be instantiated in until you've actually
2984 instantiated it, which mucks up caching.
2985 3. It only copes with cursors and strings which seems bogus. */
2986 IIFORMAT_HAS_SHARED_METHOD (autodetect, governing_domain, subwindow);
2987 IIFORMAT_HAS_METHOD (autodetect, instantiate);
2988 IIFORMAT_VALID_CONSOLE (x, autodetect);
2990 IIFORMAT_VALID_KEYWORD (autodetect, Q_data, check_valid_string);
2994 vars_of_glyphs_x (void)
2996 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path /*
2997 A list of the directories in which X bitmap files may be found.
2998 If nil, this is initialized from the "*bitmapFilePath" resource.
2999 This is used by the `make-image-instance' function (however, note that if
3000 the environment variable XBMLANGPATH is set, it is consulted first).
3002 Vx_bitmap_file_path = Qnil;
3006 complex_vars_of_glyphs_x (void)
3008 #define BUILD_GLYPH_INST(variable, name) \
3009 Fadd_spec_to_specifier \
3010 (GLYPH_IMAGE (XGLYPH (variable)), \
3011 vector3 (Qxbm, Q_data, \
3012 list3 (make_int (name##_width), \
3013 make_int (name##_height), \
3014 make_ext_string ((Extbyte *) name##_bits, \
3015 sizeof (name##_bits), \
3019 BUILD_GLYPH_INST (Vtruncation_glyph, truncator);
3020 BUILD_GLYPH_INST (Vcontinuation_glyph, continuer);
3021 BUILD_GLYPH_INST (Vxemacs_logo, xemacs);
3022 BUILD_GLYPH_INST (Vhscroll_glyph, hscroll);
3024 #undef BUILD_GLYPH_INST