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 Lstream_data_count 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 = USHRT_MAX;
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 /* #### This is not sufficient because it will not cope with widgets
2232 that are not currently visible. Once redisplay has done the
2233 visible ones it will clear this flag so that when new ones
2234 become visible they will not be updated. */
2235 XFRAME (IMAGE_INSTANCE_FRAME (p))->faces_changed
2237 XFRAME (IMAGE_INSTANCE_FRAME (p))->frame_changed
2239 IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (p))
2241 update_widget_face (wv, p, IMAGE_INSTANCE_FRAME (p));
2244 /* Possibly update the text. */
2245 if (IMAGE_INSTANCE_TEXT_CHANGED (p))
2248 Lisp_Object val = IMAGE_INSTANCE_WIDGET_TEXT (p);
2249 LISP_STRING_TO_EXTERNAL (val, str, Qnative);
2253 /* Possibly update the size. */
2254 if (IMAGE_INSTANCE_SIZE_CHANGED (p)
2256 IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (p)
2258 IMAGE_INSTANCE_TEXT_CHANGED (p))
2260 assert (IMAGE_INSTANCE_X_WIDGET_ID (p) &&
2261 IMAGE_INSTANCE_X_CLIPWIDGET (p)) ;
2263 if (IMAGE_INSTANCE_X_WIDGET_ID (p)->core.being_destroyed
2264 || !XtIsManaged(IMAGE_INSTANCE_X_WIDGET_ID (p)))
2267 XSETIMAGE_INSTANCE (sw, p);
2268 signal_simple_error ("XEmacs bug: subwindow is deleted", sw);
2271 lw_add_widget_value_arg (wv, XtNwidth,
2272 (Dimension)IMAGE_INSTANCE_WIDTH (p));
2273 lw_add_widget_value_arg (wv, XtNheight,
2274 (Dimension)IMAGE_INSTANCE_HEIGHT (p));
2277 /* Adjust offsets within the frame. */
2278 if (XFRAME (IMAGE_INSTANCE_FRAME (p))->size_changed)
2281 XtSetArg (al [0], XtNx, &IMAGE_INSTANCE_X_WIDGET_XOFFSET (p));
2282 XtSetArg (al [1], XtNy, &IMAGE_INSTANCE_X_WIDGET_YOFFSET (p));
2283 XtGetValues (FRAME_X_TEXT_WIDGET
2284 (XFRAME (IMAGE_INSTANCE_FRAME (p))), al, 2);
2287 /* now modify the widget */
2288 lw_modify_all_widgets (IMAGE_INSTANCE_X_WIDGET_LWID (p),
2290 free_widget_value_tree (wv);
2294 /* instantiate and x type subwindow */
2296 x_subwindow_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2297 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2298 int dest_mask, Lisp_Object domain)
2300 /* This function can GC */
2301 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2302 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
2303 Lisp_Object frame = DOMAIN_FRAME (domain);
2304 struct frame* f = XFRAME (frame);
2308 XSetWindowAttributes xswa;
2310 unsigned int w = IMAGE_INSTANCE_WIDTH (ii),
2311 h = IMAGE_INSTANCE_HEIGHT (ii);
2313 if (!DEVICE_X_P (XDEVICE (device)))
2314 signal_simple_error ("Not an X device", device);
2316 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
2317 xs = DefaultScreenOfDisplay (dpy);
2319 IMAGE_INSTANCE_TYPE (ii) = IMAGE_SUBWINDOW;
2321 pw = XtWindow (FRAME_X_TEXT_WIDGET (f));
2323 ii->data = xnew_and_zero (struct x_subwindow_data);
2325 IMAGE_INSTANCE_X_SUBWINDOW_PARENT (ii) = pw;
2326 IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY (ii) = DisplayOfScreen (xs);
2328 xswa.backing_store = Always;
2329 valueMask |= CWBackingStore;
2330 xswa.colormap = DefaultColormapOfScreen (xs);
2331 valueMask |= CWColormap;
2333 /* Create a window for clipping */
2334 IMAGE_INSTANCE_X_CLIPWINDOW (ii) =
2335 XCreateWindow (dpy, pw, 0, 0, w, h, 0, CopyFromParent,
2336 InputOutput, CopyFromParent, valueMask,
2339 /* Now put the subwindow inside the clip window. */
2340 win = XCreateWindow (dpy, IMAGE_INSTANCE_X_CLIPWINDOW (ii),
2341 0, 0, w, h, 0, CopyFromParent,
2342 InputOutput, CopyFromParent, valueMask,
2345 IMAGE_INSTANCE_SUBWINDOW_ID (ii) = (void*)win;
2349 /* #### Should this function exist? If there's any doubt I'm not implementing it --andyp */
2350 DEFUN ("change-subwindow-property", Fchange_subwindow_property, 3, 3, 0, /*
2351 For the given SUBWINDOW, set PROPERTY to DATA, which is a string.
2352 Subwindows are not currently implemented.
2354 (subwindow, property, data))
2360 CHECK_SUBWINDOW (subwindow);
2361 CHECK_STRING (property);
2362 CHECK_STRING (data);
2364 sw = XSUBWINDOW (subwindow);
2365 dpy = DisplayOfScreen (LISP_DEVICE_TO_X_SCREEN
2366 (FRAME_DEVICE (XFRAME (sw->frame))));
2368 property_atom = XInternAtom (dpy, (char *) XSTRING_DATA (property), False);
2369 XChangeProperty (dpy, sw->subwindow, property_atom, XA_STRING, 8,
2371 XSTRING_DATA (data),
2372 XSTRING_LENGTH (data));
2381 /************************************************************************/
2383 /************************************************************************/
2386 update_widget_face (widget_value* wv, Lisp_Image_Instance *ii,
2389 #ifdef LWLIB_WIDGETS_MOTIF
2390 XmFontList fontList;
2392 /* Update the foreground. */
2393 Lisp_Object pixel = FACE_FOREGROUND
2394 (IMAGE_INSTANCE_WIDGET_FACE (ii),
2396 XColor fcolor = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (pixel)), bcolor;
2397 lw_add_widget_value_arg (wv, XtNforeground, fcolor.pixel);
2399 /* Update the background. */
2400 pixel = FACE_BACKGROUND (IMAGE_INSTANCE_WIDGET_FACE (ii),
2402 bcolor = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (pixel));
2403 lw_add_widget_value_arg (wv, XtNbackground, bcolor.pixel);
2405 #ifdef LWLIB_WIDGETS_MOTIF
2406 fontList = XmFontListCreate
2407 (FONT_INSTANCE_X_FONT
2408 (XFONT_INSTANCE (query_string_font
2409 (IMAGE_INSTANCE_WIDGET_TEXT (ii),
2410 IMAGE_INSTANCE_WIDGET_FACE (ii),
2411 domain))), XmSTRING_DEFAULT_CHARSET);
2412 lw_add_widget_value_arg (wv, XmNfontList, (XtArgVal)fontList);
2414 lw_add_widget_value_arg
2415 (wv, XtNfont, (XtArgVal)FONT_INSTANCE_X_FONT
2416 (XFONT_INSTANCE (query_string_font
2417 (IMAGE_INSTANCE_WIDGET_TEXT (ii),
2418 IMAGE_INSTANCE_WIDGET_FACE (ii),
2420 wv->change = VISIBLE_CHANGE;
2421 /* #### Megahack - but its just getting too complicated to do this
2422 in the right place. */
2423 if (EQ (IMAGE_INSTANCE_WIDGET_TYPE (ii), Qtab_control))
2424 update_tab_widget_face (wv, ii, domain);
2428 update_tab_widget_face (widget_value* wv, Lisp_Image_Instance *ii,
2433 widget_value* val = wv->contents, *cur;
2435 /* Give each child label the correct foreground color. */
2436 Lisp_Object pixel = FACE_FOREGROUND
2437 (IMAGE_INSTANCE_WIDGET_FACE (ii),
2439 XColor fcolor = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (pixel));
2440 lw_add_widget_value_arg (val, XtNtabForeground, fcolor.pixel);
2441 wv->change = VISIBLE_CHANGE;
2442 val->change = VISIBLE_CHANGE;
2444 for (cur = val->next; cur; cur = cur->next)
2446 cur->change = VISIBLE_CHANGE;
2449 lw_copy_widget_value_args (val, cur);
2456 x_widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2457 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2458 int dest_mask, Lisp_Object domain,
2459 const char* type, widget_value* wv)
2461 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2462 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii), pixel;
2463 struct device* d = XDEVICE (device);
2464 Lisp_Object frame = DOMAIN_FRAME (domain);
2465 struct frame* f = XFRAME (frame);
2470 int id = new_lwlib_id ();
2471 widget_value* clip_wv;
2472 XColor fcolor, bcolor;
2474 if (!DEVICE_X_P (d))
2475 signal_simple_error ("Not an X device", device);
2477 /* have to set the type this late in case there is no device
2478 instantiation for a widget. But we can go ahead and do it without
2479 checking because there is always a generic instantiator. */
2480 IMAGE_INSTANCE_TYPE (ii) = IMAGE_WIDGET;
2482 if (!NILP (IMAGE_INSTANCE_WIDGET_TEXT (ii)))
2483 LISP_STRING_TO_EXTERNAL (IMAGE_INSTANCE_WIDGET_TEXT (ii), nm, Qnative);
2485 ii->data = xnew_and_zero (struct x_subwindow_data);
2487 /* Create a clip window to contain the subwidget. Incredibly the
2488 XEmacs manager seems to be the most appropriate widget for
2489 this. Nothing else is simple enough and yet does what is
2491 clip_wv = xmalloc_widget_value ();
2493 lw_add_widget_value_arg (clip_wv, XtNresize, False);
2494 lw_add_widget_value_arg (clip_wv, XtNwidth,
2495 (Dimension)IMAGE_INSTANCE_WIDTH (ii));
2496 lw_add_widget_value_arg (clip_wv, XtNheight,
2497 (Dimension)IMAGE_INSTANCE_HEIGHT (ii));
2498 clip_wv->enabled = True;
2500 clip_wv->name = xstrdup ("clip-window");
2501 clip_wv->value = xstrdup ("clip-window");
2503 IMAGE_INSTANCE_X_CLIPWIDGET (ii)
2504 = lw_create_widget ("clip-window", "clip-window", new_lwlib_id (),
2505 clip_wv, FRAME_X_CONTAINER_WIDGET (f),
2508 free_widget_value_tree (clip_wv);
2510 /* copy any args we were given */
2512 lw_add_value_args_to_args (wv, al, &ac);
2514 /* Fixup the colors. We have to do this *before* the widget gets
2515 created so that Motif will fix up the shadow colors
2516 correctly. Once the widget is created Motif won't do this
2518 pixel = FACE_FOREGROUND
2519 (IMAGE_INSTANCE_WIDGET_FACE (ii),
2520 IMAGE_INSTANCE_FRAME (ii));
2521 fcolor = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (pixel));
2523 pixel = FACE_BACKGROUND
2524 (IMAGE_INSTANCE_WIDGET_FACE (ii),
2525 IMAGE_INSTANCE_FRAME (ii));
2526 bcolor = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (pixel));
2528 lw_add_widget_value_arg (wv, XtNbackground, bcolor.pixel);
2529 lw_add_widget_value_arg (wv, XtNforeground, fcolor.pixel);
2530 /* we cannot allow widgets to resize themselves */
2531 lw_add_widget_value_arg (wv, XtNresize, False);
2532 lw_add_widget_value_arg (wv, XtNwidth,
2533 (Dimension)IMAGE_INSTANCE_WIDTH (ii));
2534 lw_add_widget_value_arg (wv, XtNheight,
2535 (Dimension)IMAGE_INSTANCE_HEIGHT (ii));
2536 /* update the font. */
2537 update_widget_face (wv, ii, domain);
2539 wid = lw_create_widget (type, wv->name, id, wv, IMAGE_INSTANCE_X_CLIPWIDGET (ii),
2540 False, 0, popup_selection_callback, 0);
2542 IMAGE_INSTANCE_SUBWINDOW_ID (ii) = (void*)wid;
2543 IMAGE_INSTANCE_X_WIDGET_LWID (ii) = id;
2544 /* because the EmacsManager is the widgets parent we have to
2545 offset the redisplay of the widget by the amount the text
2546 widget is inside the manager. */
2548 XtSetArg (al [ac], XtNx, &IMAGE_INSTANCE_X_WIDGET_XOFFSET (ii)); ac++;
2549 XtSetArg (al [ac], XtNy, &IMAGE_INSTANCE_X_WIDGET_YOFFSET (ii)); ac++;
2550 XtGetValues (FRAME_X_TEXT_WIDGET (f), al, ac);
2552 XtSetMappedWhenManaged (wid, TRUE);
2554 free_widget_value_tree (wv);
2555 /* A kludgy but simple way to make sure the callback for a widget
2556 doesn't get deleted. */
2557 gcpro_popup_callbacks (id);
2560 /* get properties of a control */
2562 x_widget_property (Lisp_Object image_instance, Lisp_Object prop)
2564 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2565 /* get the text from a control */
2566 if (EQ (prop, Q_text))
2568 widget_value* wv = lw_get_all_values (IMAGE_INSTANCE_X_WIDGET_LWID (ii));
2569 return build_ext_string (wv->value, Qnative);
2574 /* Instantiate a layout control for putting other widgets in. */
2576 x_native_layout_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2577 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2578 int dest_mask, Lisp_Object domain)
2580 x_widget_instantiate (image_instance, instantiator, pointer_fg,
2581 pointer_bg, dest_mask, domain, "layout", 0);
2584 /* Instantiate a button widget. Unfortunately instantiated widgets are
2585 particular to a frame since they need to have a parent. It's not
2586 like images where you just select the image into the context you
2587 want to display it in and BitBlt it. So images instances can have a
2588 many-to-one relationship with things you see, whereas widgets can
2589 only be one-to-one (i.e. per frame) */
2591 x_button_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2592 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2593 int dest_mask, Lisp_Object domain)
2595 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2596 Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM (ii);
2597 Lisp_Object glyph = find_keyword_in_vector (instantiator, Q_image);
2598 widget_value* wv = gui_items_to_widget_values (image_instance, gui, 1);
2602 if (!IMAGE_INSTANCEP (glyph))
2603 glyph = glyph_image_instance (glyph, domain, ERROR_ME, 1);
2606 x_widget_instantiate (image_instance, instantiator, pointer_fg,
2607 pointer_bg, dest_mask, domain, "button", wv);
2609 /* add the image if one was given */
2610 if (!NILP (glyph) && IMAGE_INSTANCEP (glyph)
2611 && IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (glyph)))
2615 #ifdef LWLIB_WIDGETS_MOTIF
2616 XtSetArg (al [ac], XmNlabelType, XmPIXMAP); ac++;
2617 XtSetArg (al [ac], XmNlabelPixmap, XIMAGE_INSTANCE_X_PIXMAP (glyph));ac++;
2619 XtSetArg (al [ac], XtNpixmap, XIMAGE_INSTANCE_X_PIXMAP (glyph)); ac++;
2621 XtSetValues (IMAGE_INSTANCE_X_WIDGET_ID (ii), al, ac);
2625 /* Update a button's clicked state.
2627 #### This is overkill, but it works. Right now this causes all
2628 button instances to flash for some reason buried deep in lwlib. In
2629 theory this should be the Right Thing to do since lwlib should only
2630 merge in changed values - and if nothing has changed then nothing
2631 should get done. This may be because of the args stuff,
2632 i.e. although the arg contents may be the same the args look
2633 different and so are re-applied to the widget. */
2635 x_button_redisplay (Lisp_Object image_instance)
2637 /* This function can GC if IN_REDISPLAY is false. */
2638 Lisp_Image_Instance *p = XIMAGE_INSTANCE (image_instance);
2640 gui_items_to_widget_values (image_instance,
2641 IMAGE_INSTANCE_WIDGET_ITEMS (p), 1);
2643 /* now modify the widget */
2644 lw_modify_all_widgets (IMAGE_INSTANCE_X_WIDGET_LWID (p),
2646 free_widget_value_tree (wv);
2649 /* get properties of a button */
2651 x_button_property (Lisp_Object image_instance, Lisp_Object prop)
2653 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2654 /* check the state of a button */
2655 if (EQ (prop, Q_selected))
2657 widget_value* wv = lw_get_all_values (IMAGE_INSTANCE_X_WIDGET_LWID (ii));
2667 /* instantiate a progress gauge */
2669 x_progress_gauge_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2670 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2671 int dest_mask, Lisp_Object domain)
2673 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2674 Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM (ii);
2675 widget_value* wv = gui_items_to_widget_values (image_instance, gui, 0);
2677 x_widget_instantiate (image_instance, instantiator, pointer_fg,
2678 pointer_bg, dest_mask, domain, "progress", wv);
2681 /* set the properties of a progress gauge */
2683 x_progress_gauge_redisplay (Lisp_Object image_instance)
2685 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2687 if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii))
2691 #ifdef ERROR_CHECK_GLYPHS
2692 assert (GUI_ITEMP (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii)));
2694 val = XGUI_ITEM (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii))->value;
2695 XtSetArg (al[0], XtNvalue, XINT (val));
2696 XtSetValues (IMAGE_INSTANCE_X_WIDGET_ID (ii), al, 1);
2700 /* instantiate an edit control */
2702 x_edit_field_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2703 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2704 int dest_mask, Lisp_Object domain)
2706 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2707 Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM (ii);
2708 widget_value* wv = gui_items_to_widget_values (image_instance, gui, 0);
2710 x_widget_instantiate (image_instance, instantiator, pointer_fg,
2711 pointer_bg, dest_mask, domain, "text-field", wv);
2714 #if defined (LWLIB_WIDGETS_MOTIF) && XmVERSION > 1
2715 /* instantiate a combo control */
2717 x_combo_box_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2718 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2719 int dest_mask, Lisp_Object domain)
2721 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2722 widget_value * wv = 0;
2723 /* This is not done generically because of sizing problems under
2725 widget_instantiate (image_instance, instantiator, pointer_fg,
2726 pointer_bg, dest_mask, domain);
2728 wv = gui_items_to_widget_values (image_instance,
2729 IMAGE_INSTANCE_WIDGET_ITEMS (ii), 0);
2731 x_widget_instantiate (image_instance, instantiator, pointer_fg,
2732 pointer_bg, dest_mask, domain, "combo-box", wv);
2737 x_tab_control_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2738 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2739 int dest_mask, Lisp_Object domain)
2741 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2743 gui_items_to_widget_values (image_instance,
2744 IMAGE_INSTANCE_WIDGET_ITEMS (ii), 0);
2745 update_tab_widget_face (wv, ii,
2746 IMAGE_INSTANCE_FRAME (ii));
2747 x_widget_instantiate (image_instance, instantiator, pointer_fg,
2748 pointer_bg, dest_mask, domain, "tab-control", wv);
2751 /* Set the properties of a tab control */
2753 x_tab_control_redisplay (Lisp_Object image_instance)
2755 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2757 if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii)
2759 IMAGE_INSTANCE_WIDGET_ACTION_OCCURRED (ii))
2761 /* If only the order has changed then simply select the first
2762 one of the pending set. This stops horrendous rebuilding -
2763 and hence flicker - of the tabs each time you click on
2765 if (tab_control_order_only_changed (image_instance))
2767 Lisp_Object rest, selected =
2768 gui_item_list_find_selected
2769 (NILP (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii)) ?
2770 XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)) :
2771 XCDR (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii)));
2773 LIST_LOOP (rest, XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)))
2775 if (gui_item_equal_sans_selected (XCAR (rest), selected, 0))
2777 /* There may be an encapsulated way of doing this,
2778 but I couldn't find it. */
2779 Lisp_Object old_selected =gui_item_list_find_selected
2780 (XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)));
2783 unsigned int num_children, i;
2786 LISP_STRING_TO_EXTERNAL (XGUI_ITEM (XCAR (rest))->name,
2788 /* The name may contain a `.' which confuses
2789 XtNameToWidget, so we do it ourselves. */
2790 children = XtCompositeChildren (IMAGE_INSTANCE_X_WIDGET_ID (ii),
2792 for (i = 0; i < num_children; i++)
2794 if (!strcmp (XtName (children [i]), name))
2796 XtSetArg (al [0], XtNtopWidget, children [i]);
2797 XtSetValues (IMAGE_INSTANCE_X_WIDGET_ID (ii), al, 1);
2801 /* Pick up the new selected item. */
2802 XGUI_ITEM (old_selected)->selected =
2803 XGUI_ITEM (XCAR (rest))->selected;
2804 XGUI_ITEM (XCAR (rest))->selected =
2805 XGUI_ITEM (selected)->selected;
2806 /* We're not actually changing the items anymore. */
2807 IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii) = 0;
2808 IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii) = Qnil;
2814 /* Possibly update the face. */
2815 if (IMAGE_INSTANCE_WIDGET_FACE_CHANGED (ii)
2817 XFRAME (IMAGE_INSTANCE_FRAME (ii))->faces_changed
2819 IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii))
2821 /* See previous comments on the brokeness of lwlib.
2823 #### There's actually not much point in doing this here
2824 since, colors will have been set appropriately by
2825 x_redisplay_widget. */
2826 widget_value* wv =copy_widget_value_tree
2828 (IMAGE_INSTANCE_X_WIDGET_LWID (ii)),
2831 update_tab_widget_face (wv, ii,
2832 IMAGE_INSTANCE_FRAME (ii));
2834 lw_modify_all_widgets (IMAGE_INSTANCE_X_WIDGET_LWID (ii), wv, True);
2835 free_widget_value_tree (wv);
2839 /* instantiate a static control possible for putting other things in */
2841 x_label_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2842 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2843 int dest_mask, Lisp_Object domain)
2845 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2846 Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM (ii);
2847 widget_value* wv = gui_items_to_widget_values (image_instance, gui, 0);
2849 x_widget_instantiate (image_instance, instantiator, pointer_fg,
2850 pointer_bg, dest_mask, domain, "button", wv);
2852 #endif /* HAVE_WIDGETS */
2855 /************************************************************************/
2856 /* initialization */
2857 /************************************************************************/
2860 syms_of_glyphs_x (void)
2863 DEFSUBR (Fchange_subwindow_property);
2868 console_type_create_glyphs_x (void)
2872 CONSOLE_HAS_METHOD (x, print_image_instance);
2873 CONSOLE_HAS_METHOD (x, finalize_image_instance);
2874 CONSOLE_HAS_METHOD (x, image_instance_equal);
2875 CONSOLE_HAS_METHOD (x, image_instance_hash);
2876 CONSOLE_HAS_METHOD (x, colorize_image_instance);
2877 CONSOLE_HAS_METHOD (x, init_image_instance_from_eimage);
2878 CONSOLE_HAS_METHOD (x, locate_pixmap_file);
2879 CONSOLE_HAS_METHOD (x, unmap_subwindow);
2880 CONSOLE_HAS_METHOD (x, map_subwindow);
2881 CONSOLE_HAS_METHOD (x, redisplay_widget);
2882 CONSOLE_HAS_METHOD (x, redisplay_subwindow);
2886 image_instantiator_format_create_glyphs_x (void)
2888 IIFORMAT_VALID_CONSOLE (x, nothing);
2889 IIFORMAT_VALID_CONSOLE (x, string);
2891 IIFORMAT_VALID_CONSOLE (x, layout);
2893 IIFORMAT_VALID_CONSOLE (x, formatted_string);
2894 IIFORMAT_VALID_CONSOLE (x, inherit);
2896 INITIALIZE_DEVICE_IIFORMAT (x, xpm);
2897 IIFORMAT_HAS_DEVMETHOD (x, xpm, instantiate);
2900 IIFORMAT_VALID_CONSOLE (x, jpeg);
2903 IIFORMAT_VALID_CONSOLE (x, tiff);
2906 IIFORMAT_VALID_CONSOLE (x, png);
2909 IIFORMAT_VALID_CONSOLE (x, gif);
2911 INITIALIZE_DEVICE_IIFORMAT (x, xbm);
2912 IIFORMAT_HAS_DEVMETHOD (x, xbm, instantiate);
2914 INITIALIZE_DEVICE_IIFORMAT (x, subwindow);
2915 IIFORMAT_HAS_DEVMETHOD (x, subwindow, instantiate);
2918 INITIALIZE_DEVICE_IIFORMAT (x, native_layout);
2919 IIFORMAT_HAS_DEVMETHOD (x, native_layout, instantiate);
2921 INITIALIZE_DEVICE_IIFORMAT (x, button);
2922 IIFORMAT_HAS_DEVMETHOD (x, button, property);
2923 IIFORMAT_HAS_DEVMETHOD (x, button, instantiate);
2924 IIFORMAT_HAS_DEVMETHOD (x, button, redisplay);
2925 /* general widget methods. */
2926 INITIALIZE_DEVICE_IIFORMAT (x, widget);
2927 IIFORMAT_HAS_DEVMETHOD (x, widget, property);
2928 /* progress gauge */
2929 INITIALIZE_DEVICE_IIFORMAT (x, progress_gauge);
2930 IIFORMAT_HAS_DEVMETHOD (x, progress_gauge, redisplay);
2931 IIFORMAT_HAS_DEVMETHOD (x, progress_gauge, instantiate);
2933 INITIALIZE_DEVICE_IIFORMAT (x, edit_field);
2934 IIFORMAT_HAS_DEVMETHOD (x, edit_field, instantiate);
2935 #if defined (LWLIB_WIDGETS_MOTIF) && XmVERSION > 1
2937 INITIALIZE_DEVICE_IIFORMAT (x, combo_box);
2938 IIFORMAT_HAS_DEVMETHOD (x, combo_box, instantiate);
2939 IIFORMAT_HAS_SHARED_DEVMETHOD (x, combo_box, redisplay, tab_control);
2941 /* tab control widget */
2942 INITIALIZE_DEVICE_IIFORMAT (x, tab_control);
2943 IIFORMAT_HAS_DEVMETHOD (x, tab_control, instantiate);
2944 IIFORMAT_HAS_DEVMETHOD (x, tab_control, redisplay);
2946 INITIALIZE_DEVICE_IIFORMAT (x, label);
2947 IIFORMAT_HAS_DEVMETHOD (x, label, instantiate);
2949 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (cursor_font, "cursor-font");
2950 IIFORMAT_VALID_CONSOLE (x, cursor_font);
2952 IIFORMAT_HAS_METHOD (cursor_font, validate);
2953 IIFORMAT_HAS_METHOD (cursor_font, possible_dest_types);
2954 IIFORMAT_HAS_METHOD (cursor_font, instantiate);
2956 IIFORMAT_VALID_KEYWORD (cursor_font, Q_data, check_valid_string);
2957 IIFORMAT_VALID_KEYWORD (cursor_font, Q_foreground, check_valid_string);
2958 IIFORMAT_VALID_KEYWORD (cursor_font, Q_background, check_valid_string);
2960 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (font, "font");
2962 IIFORMAT_HAS_METHOD (font, validate);
2963 IIFORMAT_HAS_METHOD (font, possible_dest_types);
2964 IIFORMAT_HAS_METHOD (font, instantiate);
2965 IIFORMAT_VALID_CONSOLE (x, font);
2967 IIFORMAT_VALID_KEYWORD (font, Q_data, check_valid_string);
2968 IIFORMAT_VALID_KEYWORD (font, Q_foreground, check_valid_string);
2969 IIFORMAT_VALID_KEYWORD (font, Q_background, check_valid_string);
2972 INITIALIZE_DEVICE_IIFORMAT (x, xface);
2973 IIFORMAT_HAS_DEVMETHOD (x, xface, instantiate);
2976 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (autodetect,
2979 IIFORMAT_HAS_METHOD (autodetect, validate);
2980 IIFORMAT_HAS_METHOD (autodetect, normalize);
2981 IIFORMAT_HAS_METHOD (autodetect, possible_dest_types);
2982 /* #### autodetect is flawed IMO:
2983 1. It makes the assumption that you can detect whether the user
2984 wanted a cursor or a string based on the data, since the data is a
2985 string you have to prioritise cursors. Instead we will force users
2986 to pick the appropriate image type, this is what we do under
2988 2. It doesn't fit with the new domain model - you cannot tell which
2989 domain it needs to be instantiated in until you've actually
2990 instantiated it, which mucks up caching.
2991 3. It only copes with cursors and strings which seems bogus. */
2992 IIFORMAT_HAS_SHARED_METHOD (autodetect, governing_domain, subwindow);
2993 IIFORMAT_HAS_METHOD (autodetect, instantiate);
2994 IIFORMAT_VALID_CONSOLE (x, autodetect);
2996 IIFORMAT_VALID_KEYWORD (autodetect, Q_data, check_valid_string);
3000 vars_of_glyphs_x (void)
3002 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path /*
3003 A list of the directories in which X bitmap files may be found.
3004 If nil, this is initialized from the "*bitmapFilePath" resource.
3005 This is used by the `make-image-instance' function (however, note that if
3006 the environment variable XBMLANGPATH is set, it is consulted first).
3008 Vx_bitmap_file_path = Qnil;
3012 complex_vars_of_glyphs_x (void)
3014 #define BUILD_GLYPH_INST(variable, name) \
3015 Fadd_spec_to_specifier \
3016 (GLYPH_IMAGE (XGLYPH (variable)), \
3017 vector3 (Qxbm, Q_data, \
3018 list3 (make_int (name##_width), \
3019 make_int (name##_height), \
3020 make_ext_string ((Extbyte *) name##_bits, \
3021 sizeof (name##_bits), \
3025 BUILD_GLYPH_INST (Vtruncation_glyph, truncator);
3026 BUILD_GLYPH_INST (Vcontinuation_glyph, continuer);
3027 BUILD_GLYPH_INST (Vxemacs_logo, xemacs);
3028 BUILD_GLYPH_INST (Vhscroll_glyph, hscroll);
3030 #undef BUILD_GLYPH_INST