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);
163 /************************************************************************/
164 /* image instance methods */
165 /************************************************************************/
167 /************************************************************************/
168 /* convert from a series of RGB triples to an XImage formated for the */
170 /************************************************************************/
172 convert_EImage_to_XImage (Lisp_Object device, int width, int height,
173 unsigned char *pic, unsigned long **pixtbl,
180 int depth, bitmap_pad, bits_per_pixel, byte_cnt, i, j;
182 unsigned char *data, *ip, *dp;
183 quant_table *qtable = 0;
189 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
190 cmap = DEVICE_X_COLORMAP (XDEVICE(device));
191 vis = DEVICE_X_VISUAL (XDEVICE(device));
192 depth = DEVICE_X_DEPTH(XDEVICE(device));
194 if (vis->class == GrayScale || vis->class == StaticColor ||
195 vis->class == StaticGray)
197 /* #### Implement me!!! */
201 if (vis->class == PseudoColor)
203 /* Quantize the image and get a histogram while we're at it.
204 Do this first to save memory */
205 qtable = build_EImage_quantable(pic, width, height, 256);
206 if (qtable == NULL) return NULL;
209 bitmap_pad = ((depth > 16) ? 32 :
213 outimg = XCreateImage (dpy, vis,
214 depth, ZPixmap, 0, 0, width, height,
216 if (!outimg) return NULL;
218 bits_per_pixel = outimg->bits_per_pixel;
219 byte_cnt = bits_per_pixel >> 3;
221 data = (unsigned char *) xmalloc (outimg->bytes_per_line * height);
224 XDestroyImage (outimg);
227 outimg->data = (char *) data;
229 if (vis->class == PseudoColor)
231 unsigned long pixarray[256];
233 /* use our quantize table to allocate the colors */
235 *pixtbl = xnew_array (unsigned long, pixcount);
238 /* #### should implement a sort by popularity to assure proper allocation */
240 for (i = 0; i < qtable->num_active_colors; i++)
245 color.red = qtable->rm[i] ? qtable->rm[i] << 8 : 0;
246 color.green = qtable->gm[i] ? qtable->gm[i] << 8 : 0;
247 color.blue = qtable->bm[i] ? qtable->bm[i] << 8 : 0;
248 color.flags = DoRed | DoGreen | DoBlue;
249 res = allocate_nearest_color (dpy, cmap, vis, &color);
250 if (res > 0 && res < 3)
252 DO_REALLOC(*pixtbl, pixcount, n+1, unsigned long);
253 (*pixtbl)[n] = color.pixel;
256 pixarray[i] = color.pixel;
260 for (i = 0; i < height; i++)
262 dp = data + (i * outimg->bytes_per_line);
263 for (j = 0; j < width; j++)
268 conv.val = pixarray[QUANT_GET_COLOR(qtable,rd,gr,bl)];
269 #ifdef WORDS_BIGENDIAN
270 if (outimg->byte_order == MSBFirst)
271 for (q = 4-byte_cnt; q < 4; q++) *dp++ = conv.cp[q];
273 for (q = 3; q >= 4-byte_cnt; q--) *dp++ = conv.cp[q];
275 if (outimg->byte_order == MSBFirst)
276 for (q = byte_cnt-1; q >= 0; q--) *dp++ = conv.cp[q];
278 for (q = 0; q < byte_cnt; q++) *dp++ = conv.cp[q];
284 unsigned long rshift,gshift,bshift,rbits,gbits,bbits,junk;
285 junk = vis->red_mask;
287 while ((junk & 0x1) == 0)
298 junk = vis->green_mask;
300 while ((junk & 0x1) == 0)
311 junk = vis->blue_mask;
313 while ((junk & 0x1) == 0)
325 for (i = 0; i < height; i++)
327 dp = data + (i * outimg->bytes_per_line);
328 for (j = 0; j < width; j++)
331 rd = *ip++ << (rbits - 8);
333 rd = *ip++ >> (8 - rbits);
335 gr = *ip++ << (gbits - 8);
337 gr = *ip++ >> (8 - gbits);
339 bl = *ip++ << (bbits - 8);
341 bl = *ip++ >> (8 - bbits);
343 conv.val = (rd << rshift) | (gr << gshift) | (bl << bshift);
344 #ifdef WORDS_BIGENDIAN
345 if (outimg->byte_order == MSBFirst)
346 for (q = 4-byte_cnt; q < 4; q++) *dp++ = conv.cp[q];
348 for (q = 3; q >= 4-byte_cnt; q--) *dp++ = conv.cp[q];
350 if (outimg->byte_order == MSBFirst)
351 for (q = byte_cnt-1; q >= 0; q--) *dp++ = conv.cp[q];
353 for (q = 0; q < byte_cnt; q++) *dp++ = conv.cp[q];
364 x_print_image_instance (Lisp_Image_Instance *p,
365 Lisp_Object printcharfun,
370 switch (IMAGE_INSTANCE_TYPE (p))
372 case IMAGE_MONO_PIXMAP:
373 case IMAGE_COLOR_PIXMAP:
375 sprintf (buf, " (0x%lx", (unsigned long) IMAGE_INSTANCE_X_PIXMAP (p));
376 write_c_string (buf, printcharfun);
377 if (IMAGE_INSTANCE_X_MASK (p))
379 sprintf (buf, "/0x%lx", (unsigned long) IMAGE_INSTANCE_X_MASK (p));
380 write_c_string (buf, printcharfun);
382 write_c_string (")", printcharfun);
390 extern int debug_widget_instances;
394 x_finalize_image_instance (Lisp_Image_Instance *p)
399 if (DEVICE_LIVE_P (XDEVICE (IMAGE_INSTANCE_DEVICE (p))))
401 Display *dpy = DEVICE_X_DISPLAY
402 (XDEVICE (IMAGE_INSTANCE_DEVICE (p)));
406 else if (IMAGE_INSTANCE_TYPE (p) == IMAGE_WIDGET)
408 if (IMAGE_INSTANCE_SUBWINDOW_ID (p))
411 debug_widget_instances--;
412 stderr_out ("widget destroyed, %d left\n", debug_widget_instances);
414 lw_destroy_widget (IMAGE_INSTANCE_X_WIDGET_ID (p));
415 lw_destroy_widget (IMAGE_INSTANCE_X_CLIPWIDGET (p));
417 /* We can release the callbacks again. */
418 ungcpro_popup_callbacks (IMAGE_INSTANCE_X_WIDGET_LWID (p));
420 IMAGE_INSTANCE_X_WIDGET_ID (p) = 0;
421 IMAGE_INSTANCE_X_CLIPWIDGET (p) = 0;
425 else if (IMAGE_INSTANCE_TYPE (p) == IMAGE_SUBWINDOW)
427 if (IMAGE_INSTANCE_SUBWINDOW_ID (p))
428 XDestroyWindow (dpy, IMAGE_INSTANCE_X_SUBWINDOW_ID (p));
429 IMAGE_INSTANCE_SUBWINDOW_ID (p) = 0;
434 if (IMAGE_INSTANCE_PIXMAP_TIMEOUT (p))
435 disable_glyph_animated_timeout (IMAGE_INSTANCE_PIXMAP_TIMEOUT (p));
437 if (IMAGE_INSTANCE_X_MASK (p) &&
438 IMAGE_INSTANCE_X_MASK (p) != IMAGE_INSTANCE_X_PIXMAP (p))
439 XFreePixmap (dpy, IMAGE_INSTANCE_X_MASK (p));
440 IMAGE_INSTANCE_PIXMAP_MASK (p) = 0;
442 if (IMAGE_INSTANCE_X_PIXMAP_SLICES (p))
444 for (i = 0; i < IMAGE_INSTANCE_PIXMAP_MAXSLICE (p); i++)
445 if (IMAGE_INSTANCE_X_PIXMAP_SLICE (p,i))
447 XFreePixmap (dpy, IMAGE_INSTANCE_X_PIXMAP_SLICE (p,i));
448 IMAGE_INSTANCE_X_PIXMAP_SLICE (p, i) = 0;
450 xfree (IMAGE_INSTANCE_X_PIXMAP_SLICES (p));
451 IMAGE_INSTANCE_X_PIXMAP_SLICES (p) = 0;
454 if (IMAGE_INSTANCE_X_CURSOR (p))
456 XFreeCursor (dpy, IMAGE_INSTANCE_X_CURSOR (p));
457 IMAGE_INSTANCE_X_CURSOR (p) = 0;
460 if (IMAGE_INSTANCE_X_NPIXELS (p) != 0)
463 IMAGE_INSTANCE_X_COLORMAP (p),
464 IMAGE_INSTANCE_X_PIXELS (p),
465 IMAGE_INSTANCE_X_NPIXELS (p), 0);
466 IMAGE_INSTANCE_X_NPIXELS (p) = 0;
470 /* You can sometimes have pixels without a live device. I forget
471 why, but that's why we free them here if we have a pixmap type
472 image instance. It probably means that we might also get a memory
473 leak with widgets. */
474 if (IMAGE_INSTANCE_TYPE (p) != IMAGE_WIDGET
475 && IMAGE_INSTANCE_TYPE (p) != IMAGE_SUBWINDOW
476 && IMAGE_INSTANCE_X_PIXELS (p))
478 xfree (IMAGE_INSTANCE_X_PIXELS (p));
479 IMAGE_INSTANCE_X_PIXELS (p) = 0;
487 x_image_instance_equal (Lisp_Image_Instance *p1,
488 Lisp_Image_Instance *p2, int depth)
490 switch (IMAGE_INSTANCE_TYPE (p1))
492 case IMAGE_MONO_PIXMAP:
493 case IMAGE_COLOR_PIXMAP:
495 if (IMAGE_INSTANCE_X_COLORMAP (p1) != IMAGE_INSTANCE_X_COLORMAP (p2) ||
496 IMAGE_INSTANCE_X_NPIXELS (p1) != IMAGE_INSTANCE_X_NPIXELS (p2))
507 x_image_instance_hash (Lisp_Image_Instance *p, int depth)
509 switch (IMAGE_INSTANCE_TYPE (p))
511 case IMAGE_MONO_PIXMAP:
512 case IMAGE_COLOR_PIXMAP:
514 return IMAGE_INSTANCE_X_NPIXELS (p);
520 /* Set all the slots in an image instance structure to reasonable
521 default values. This is used somewhere within an instantiate
522 method. It is assumed that the device slot within the image
523 instance is already set -- this is the case when instantiate
524 methods are called. */
527 x_initialize_pixmap_image_instance (Lisp_Image_Instance *ii,
529 enum image_instance_type type)
531 ii->data = xnew_and_zero (struct x_image_instance_data);
532 IMAGE_INSTANCE_PIXMAP_MAXSLICE (ii) = slices;
533 IMAGE_INSTANCE_X_PIXMAP_SLICES (ii) =
534 xnew_array_and_zero (Pixmap, slices);
535 IMAGE_INSTANCE_TYPE (ii) = type;
536 IMAGE_INSTANCE_PIXMAP_FILENAME (ii) = Qnil;
537 IMAGE_INSTANCE_PIXMAP_MASK_FILENAME (ii) = Qnil;
538 IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii) = Qnil;
539 IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii) = Qnil;
540 IMAGE_INSTANCE_PIXMAP_FG (ii) = Qnil;
541 IMAGE_INSTANCE_PIXMAP_BG (ii) = Qnil;
545 /************************************************************************/
546 /* pixmap file functions */
547 /************************************************************************/
549 /* Where bitmaps are; initialized from resource database */
550 Lisp_Object Vx_bitmap_file_path;
553 #define BITMAPDIR "/usr/include/X11/bitmaps"
556 #define USE_XBMLANGPATH
558 /* Given a pixmap filename, look through all of the "standard" places
559 where the file might be located. Return a full pathname if found;
560 otherwise, return Qnil. */
563 x_locate_pixmap_file (Lisp_Object name)
565 /* This function can GC if IN_REDISPLAY is false */
568 /* Check non-absolute pathnames with a directory component relative to
569 the search path; that's the way Xt does it. */
570 /* #### Unix-specific */
571 if (XSTRING_BYTE (name, 0) == '/' ||
572 (XSTRING_BYTE (name, 0) == '.' &&
573 (XSTRING_BYTE (name, 1) == '/' ||
574 (XSTRING_BYTE (name, 1) == '.' &&
575 (XSTRING_BYTE (name, 2) == '/')))))
577 if (!NILP (Ffile_readable_p (name)))
578 return Fexpand_file_name (name, Qnil);
583 if (NILP (Vdefault_x_device))
584 /* This may occur during initialization. */
587 /* We only check the bitmapFilePath resource on the original X device. */
588 display = DEVICE_X_DISPLAY (XDEVICE (Vdefault_x_device));
590 #ifdef USE_XBMLANGPATH
592 char *path = egetenv ("XBMLANGPATH");
593 SubstitutionRec subs[1];
595 subs[0].substitution = (char *) XSTRING_DATA (name);
596 /* #### Motif uses a big hairy default if $XBMLANGPATH isn't set.
597 We don't. If you want it used, set it. */
599 (path = XtResolvePathname (display, "bitmaps", 0, 0, path,
600 subs, XtNumber (subs), 0)))
602 name = build_string (path);
609 if (NILP (Vx_bitmap_file_path))
613 if (XrmGetResource (XtDatabase (display),
614 "bitmapFilePath", "BitmapFilePath", &type, &value)
615 && !strcmp (type, "String"))
616 Vx_bitmap_file_path = decode_env_path (0, (char *) value.addr);
617 Vx_bitmap_file_path = nconc2 (Vx_bitmap_file_path,
618 (decode_path (BITMAPDIR)));
623 if (locate_file (Vx_bitmap_file_path, name, Qnil, &found, R_OK) < 0)
625 Lisp_Object temp = list1 (Vdata_directory);
629 locate_file (temp, name, Qnil, &found, R_OK);
638 locate_pixmap_file (Lisp_Object name)
640 return x_locate_pixmap_file (name);
645 write_lisp_string_to_temp_file (Lisp_Object string, char *filename_out)
647 Lisp_Object instream, outstream;
648 Lstream *istr, *ostr;
649 char tempbuf[1024]; /* some random amount */
652 static Extbyte_dynarr *conversion_out_dynarr;
653 Bytecount bstart, bend;
654 struct gcpro gcpro1, gcpro2;
656 Lisp_Object conv_out_stream;
661 /* This function can GC */
662 if (!conversion_out_dynarr)
663 conversion_out_dynarr = Dynarr_new (Extbyte);
665 Dynarr_reset (conversion_out_dynarr);
667 /* Create the temporary file ... */
668 sprintf (filename_out, "/tmp/emacs%d.XXXXXX", (int) getpid ());
669 mktemp (filename_out);
670 tmpfil = fopen (filename_out, "w");
675 int old_errno = errno;
677 unlink (filename_out);
680 report_file_error ("Creating temp file",
681 list1 (build_string (filename_out)));
684 CHECK_STRING (string);
685 get_string_range_byte (string, Qnil, Qnil, &bstart, &bend,
686 GB_HISTORICAL_STRING_BEHAVIOR);
687 instream = make_lisp_string_input_stream (string, bstart, bend);
688 istr = XLSTREAM (instream);
689 /* setup the out stream */
690 outstream = make_dynarr_output_stream((unsigned_char_dynarr *)conversion_out_dynarr);
691 ostr = XLSTREAM (outstream);
693 /* setup the conversion stream */
694 conv_out_stream = make_encoding_output_stream (ostr, Fget_coding_system(Qbinary));
695 costr = XLSTREAM (conv_out_stream);
696 GCPRO3 (instream, outstream, conv_out_stream);
698 GCPRO2 (instream, outstream);
701 /* Get the data while doing the conversion */
704 ssize_t size_in_bytes = Lstream_read (istr, tempbuf, sizeof (tempbuf));
707 /* It does seem the flushes are necessary... */
709 Lstream_write (costr, tempbuf, size_in_bytes);
710 Lstream_flush (costr);
712 Lstream_write (ostr, tempbuf, size_in_bytes);
714 Lstream_flush (ostr);
715 if (fwrite ((unsigned char *)Dynarr_atp(conversion_out_dynarr, 0),
716 Dynarr_length(conversion_out_dynarr), 1, tmpfil) != 1)
721 /* reset the dynarr */
722 Lstream_rewind(ostr);
725 if (fclose (tmpfil) != 0)
727 Lstream_close (istr);
729 Lstream_close (costr);
731 Lstream_close (ostr);
734 Lstream_delete (istr);
735 Lstream_delete (ostr);
737 Lstream_delete (costr);
741 report_file_error ("Writing temp file",
742 list1 (build_string (filename_out)));
747 /************************************************************************/
748 /* cursor functions */
749 /************************************************************************/
751 /* Check that this server supports cursors of size WIDTH * HEIGHT. If
752 not, signal an error. INSTANTIATOR is only used in the error
756 check_pointer_sizes (Screen *xs, unsigned int width, unsigned int height,
757 Lisp_Object instantiator)
759 unsigned int best_width, best_height;
760 if (! XQueryBestCursor (DisplayOfScreen (xs), RootWindowOfScreen (xs),
761 width, height, &best_width, &best_height))
762 /* this means that an X error of some sort occurred (we trap
763 these so they're not fatal). */
764 signal_simple_error ("XQueryBestCursor() failed?", instantiator);
766 if (width > best_width || height > best_height)
767 error_with_frob (instantiator,
768 "pointer too large (%dx%d): "
769 "server requires %dx%d or smaller",
770 width, height, best_width, best_height);
775 generate_cursor_fg_bg (Lisp_Object device, Lisp_Object *foreground,
776 Lisp_Object *background, XColor *xfg, XColor *xbg)
778 if (!NILP (*foreground) && !COLOR_INSTANCEP (*foreground))
780 Fmake_color_instance (*foreground, device,
781 encode_error_behavior_flag (ERROR_ME));
782 if (COLOR_INSTANCEP (*foreground))
783 *xfg = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (*foreground));
787 xfg->red = xfg->green = xfg->blue = 0;
790 if (!NILP (*background) && !COLOR_INSTANCEP (*background))
792 Fmake_color_instance (*background, device,
793 encode_error_behavior_flag (ERROR_ME));
794 if (COLOR_INSTANCEP (*background))
795 *xbg = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (*background));
799 xbg->red = xbg->green = xbg->blue = ~0;
804 maybe_recolor_cursor (Lisp_Object image_instance, Lisp_Object foreground,
805 Lisp_Object background)
807 Lisp_Object device = XIMAGE_INSTANCE_DEVICE (image_instance);
810 generate_cursor_fg_bg (device, &foreground, &background, &xfg, &xbg);
811 if (!NILP (foreground) || !NILP (background))
813 XRecolorCursor (DEVICE_X_DISPLAY (XDEVICE (device)),
814 XIMAGE_INSTANCE_X_CURSOR (image_instance),
816 XIMAGE_INSTANCE_PIXMAP_FG (image_instance) = foreground;
817 XIMAGE_INSTANCE_PIXMAP_BG (image_instance) = background;
822 /************************************************************************/
823 /* color pixmap functions */
824 /************************************************************************/
826 /* Initialize an image instance from an XImage.
828 DEST_MASK specifies the mask of allowed image types.
830 PIXELS and NPIXELS specify an array of pixels that are used in
831 the image. These need to be kept around for the duration of the
832 image. When the image instance is freed, XFreeColors() will
833 automatically be called on all the pixels specified here; thus,
834 you should have allocated the pixels yourself using XAllocColor()
835 or the like. The array passed in is used directly without
836 being copied, so it should be heap data created with xmalloc().
837 It will be freed using xfree() when the image instance is
840 If this fails, signal an error. INSTANTIATOR is only used
841 in the error message.
843 #### This should be able to handle conversion into `pointer'.
844 Use the same code as for `xpm'. */
847 init_image_instance_from_x_image (Lisp_Image_Instance *ii,
851 unsigned long *pixels,
854 Lisp_Object instantiator)
856 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
862 if (!DEVICE_X_P (XDEVICE (device)))
863 signal_simple_error ("Not an X device", device);
865 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
866 d = XtWindow(DEVICE_XT_APP_SHELL (XDEVICE (device)));
868 if (!(dest_mask & IMAGE_COLOR_PIXMAP_MASK))
869 incompatible_image_types (instantiator, dest_mask,
870 IMAGE_COLOR_PIXMAP_MASK);
872 pixmap = XCreatePixmap (dpy, d, ximage->width,
873 ximage->height, ximage->depth);
875 signal_simple_error ("Unable to create pixmap", instantiator);
877 gc = XCreateGC (dpy, pixmap, 0, NULL);
880 XFreePixmap (dpy, pixmap);
881 signal_simple_error ("Unable to create GC", instantiator);
884 XPutImage (dpy, pixmap, gc, ximage, 0, 0, 0, 0,
885 ximage->width, ximage->height);
889 x_initialize_pixmap_image_instance (ii, slices, IMAGE_COLOR_PIXMAP);
891 IMAGE_INSTANCE_PIXMAP_FILENAME (ii) =
892 find_keyword_in_vector (instantiator, Q_file);
894 /* Fixup a set of pixmaps. */
895 IMAGE_INSTANCE_X_PIXMAP (ii) = pixmap;
897 IMAGE_INSTANCE_PIXMAP_MASK (ii) = 0;
898 IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = ximage->width;
899 IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = ximage->height;
900 IMAGE_INSTANCE_PIXMAP_DEPTH (ii) = ximage->depth;
901 IMAGE_INSTANCE_X_COLORMAP (ii) = cmap;
902 IMAGE_INSTANCE_X_PIXELS (ii) = pixels;
903 IMAGE_INSTANCE_X_NPIXELS (ii) = npixels;
907 image_instance_add_x_image (Lisp_Image_Instance *ii,
910 Lisp_Object instantiator)
912 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
918 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
919 d = XtWindow(DEVICE_XT_APP_SHELL (XDEVICE (device)));
921 pixmap = XCreatePixmap (dpy, d, ximage->width,
922 ximage->height, ximage->depth);
924 signal_simple_error ("Unable to create pixmap", instantiator);
926 gc = XCreateGC (dpy, pixmap, 0, NULL);
929 XFreePixmap (dpy, pixmap);
930 signal_simple_error ("Unable to create GC", instantiator);
933 XPutImage (dpy, pixmap, gc, ximage, 0, 0, 0, 0,
934 ximage->width, ximage->height);
938 IMAGE_INSTANCE_X_PIXMAP_SLICE (ii, slice) = pixmap;
942 x_init_image_instance_from_eimage (Lisp_Image_Instance *ii,
943 int width, int height,
945 unsigned char *eimage,
947 Lisp_Object instantiator,
950 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
951 Colormap cmap = DEVICE_X_COLORMAP (XDEVICE(device));
952 unsigned long *pixtbl = NULL;
957 for (slice = 0; slice < slices; slice++)
959 ximage = convert_EImage_to_XImage (device, width, height,
960 eimage + (width * height * 3 * slice),
964 if (pixtbl) xfree (pixtbl);
965 signal_image_error("EImage to XImage conversion failed", instantiator);
968 /* Now create the pixmap and set up the image instance */
970 init_image_instance_from_x_image (ii, ximage, dest_mask,
971 cmap, pixtbl, npixels, slices,
974 image_instance_add_x_image (ii, ximage, slice, instantiator);
980 xfree (ximage->data);
983 XDestroyImage (ximage);
989 int read_bitmap_data_from_file (const char *filename, unsigned int *width,
990 unsigned int *height, unsigned char **datap,
991 int *x_hot, int *y_hot)
993 return XmuReadBitmapDataFromFile (filename, width, height,
994 datap, x_hot, y_hot);
997 /* Given inline data for a mono pixmap, create and return the
998 corresponding X object. */
1001 pixmap_from_xbm_inline (Lisp_Object device, int width, int height,
1002 /* Note that data is in ext-format! */
1005 return XCreatePixmapFromBitmapData
1006 (DEVICE_X_DISPLAY (XDEVICE (device)),
1007 XtWindow (DEVICE_XT_APP_SHELL (XDEVICE (device))),
1008 (char *) bits, width, height,
1012 /* Given inline data for a mono pixmap, initialize the given
1013 image instance accordingly. */
1016 init_image_instance_from_xbm_inline (Lisp_Image_Instance *ii,
1017 int width, int height,
1018 /* Note that data is in ext-format! */
1020 Lisp_Object instantiator,
1021 Lisp_Object pointer_fg,
1022 Lisp_Object pointer_bg,
1025 Lisp_Object mask_filename)
1027 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
1028 Lisp_Object foreground = find_keyword_in_vector (instantiator, Q_foreground);
1029 Lisp_Object background = find_keyword_in_vector (instantiator, Q_background);
1033 enum image_instance_type type;
1035 if (!DEVICE_X_P (XDEVICE (device)))
1036 signal_simple_error ("Not an X device", device);
1038 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
1039 draw = XtWindow(DEVICE_XT_APP_SHELL (XDEVICE (device)));
1040 scr = DefaultScreenOfDisplay (dpy);
1042 if ((dest_mask & IMAGE_MONO_PIXMAP_MASK) &&
1043 (dest_mask & IMAGE_COLOR_PIXMAP_MASK))
1045 if (!NILP (foreground) || !NILP (background))
1046 type = IMAGE_COLOR_PIXMAP;
1048 type = IMAGE_MONO_PIXMAP;
1050 else if (dest_mask & IMAGE_MONO_PIXMAP_MASK)
1051 type = IMAGE_MONO_PIXMAP;
1052 else if (dest_mask & IMAGE_COLOR_PIXMAP_MASK)
1053 type = IMAGE_COLOR_PIXMAP;
1054 else if (dest_mask & IMAGE_POINTER_MASK)
1055 type = IMAGE_POINTER;
1057 incompatible_image_types (instantiator, dest_mask,
1058 IMAGE_MONO_PIXMAP_MASK | IMAGE_COLOR_PIXMAP_MASK
1059 | IMAGE_POINTER_MASK);
1061 x_initialize_pixmap_image_instance (ii, 1, type);
1062 IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = width;
1063 IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = height;
1064 IMAGE_INSTANCE_PIXMAP_FILENAME (ii) =
1065 find_keyword_in_vector (instantiator, Q_file);
1069 case IMAGE_MONO_PIXMAP:
1071 IMAGE_INSTANCE_X_PIXMAP (ii) =
1072 pixmap_from_xbm_inline (device, width, height, (Extbyte *) bits);
1076 case IMAGE_COLOR_PIXMAP:
1078 Dimension d = DEVICE_X_DEPTH (XDEVICE(device));
1079 unsigned long fg = BlackPixelOfScreen (scr);
1080 unsigned long bg = WhitePixelOfScreen (scr);
1082 if (!NILP (foreground) && !COLOR_INSTANCEP (foreground))
1084 Fmake_color_instance (foreground, device,
1085 encode_error_behavior_flag (ERROR_ME));
1087 if (COLOR_INSTANCEP (foreground))
1088 fg = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (foreground)).pixel;
1090 if (!NILP (background) && !COLOR_INSTANCEP (background))
1092 Fmake_color_instance (background, device,
1093 encode_error_behavior_flag (ERROR_ME));
1095 if (COLOR_INSTANCEP (background))
1096 bg = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (background)).pixel;
1098 /* We used to duplicate the pixels using XAllocColor(), to protect
1099 against their getting freed. Just as easy to just store the
1100 color instances here and GC-protect them, so this doesn't
1102 IMAGE_INSTANCE_PIXMAP_FG (ii) = foreground;
1103 IMAGE_INSTANCE_PIXMAP_BG (ii) = background;
1104 IMAGE_INSTANCE_X_PIXMAP (ii) =
1105 XCreatePixmapFromBitmapData (dpy, draw,
1106 (char *) bits, width, height,
1108 IMAGE_INSTANCE_PIXMAP_DEPTH (ii) = d;
1114 XColor fg_color, bg_color;
1117 check_pointer_sizes (scr, width, height, instantiator);
1120 XCreatePixmapFromBitmapData (dpy, draw,
1121 (char *) bits, width, height,
1124 if (NILP (foreground))
1125 foreground = pointer_fg;
1126 if (NILP (background))
1127 background = pointer_bg;
1128 generate_cursor_fg_bg (device, &foreground, &background,
1129 &fg_color, &bg_color);
1131 IMAGE_INSTANCE_PIXMAP_FG (ii) = foreground;
1132 IMAGE_INSTANCE_PIXMAP_BG (ii) = background;
1133 IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii) =
1134 find_keyword_in_vector (instantiator, Q_hotspot_x);
1135 IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii) =
1136 find_keyword_in_vector (instantiator, Q_hotspot_y);
1137 IMAGE_INSTANCE_X_CURSOR (ii) =
1139 (dpy, source, mask, &fg_color, &bg_color,
1140 !NILP (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii)) ?
1141 XINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii)) : 0,
1142 !NILP (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii)) ?
1143 XINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii)) : 0);
1153 xbm_instantiate_1 (Lisp_Object image_instance, Lisp_Object instantiator,
1154 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1155 int dest_mask, int width, int height,
1156 /* Note that data is in ext-format! */
1159 Lisp_Object mask_data = find_keyword_in_vector (instantiator, Q_mask_data);
1160 Lisp_Object mask_file = find_keyword_in_vector (instantiator, Q_mask_file);
1161 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1164 if (!NILP (mask_data))
1166 const char *ext_data;
1168 LISP_STRING_TO_EXTERNAL (XCAR (XCDR (XCDR (mask_data))), ext_data, Qbinary);
1169 mask = pixmap_from_xbm_inline (IMAGE_INSTANCE_DEVICE (ii),
1170 XINT (XCAR (mask_data)),
1171 XINT (XCAR (XCDR (mask_data))),
1175 init_image_instance_from_xbm_inline (ii, width, height, bits,
1176 instantiator, pointer_fg, pointer_bg,
1177 dest_mask, mask, mask_file);
1180 /* Instantiate method for XBM's. */
1183 x_xbm_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1184 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1185 int dest_mask, Lisp_Object domain)
1187 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1188 const char *ext_data;
1190 assert (!NILP (data));
1192 LISP_STRING_TO_EXTERNAL (XCAR (XCDR (XCDR (data))), ext_data, Qbinary);
1194 xbm_instantiate_1 (image_instance, instantiator, pointer_fg,
1195 pointer_bg, dest_mask, XINT (XCAR (data)),
1196 XINT (XCAR (XCDR (data))), ext_data);
1202 /**********************************************************************
1204 **********************************************************************/
1205 /* xpm 3.2g and better has XpmCreatePixmapFromBuffer()...
1206 There was no version number in xpm.h before 3.3, but this should do.
1208 #if (XpmVersion >= 3) || defined(XpmExactColors)
1209 # define XPM_DOES_BUFFERS
1212 #ifndef XPM_DOES_BUFFERS
1213 Your version of XPM is too old. You cannot compile with it.
1214 Upgrade to version 3.2g or better or compile with --with-xpm=no.
1215 #endif /* !XPM_DOES_BUFFERS */
1217 static XpmColorSymbol *
1218 extract_xpm_color_names (XpmAttributes *xpmattrs, Lisp_Object device,
1220 Lisp_Object color_symbol_alist)
1222 /* This function can GC */
1223 Display *dpy = DEVICE_X_DISPLAY (XDEVICE(device));
1224 Colormap cmap = DEVICE_X_COLORMAP (XDEVICE(device));
1227 Lisp_Object results = Qnil;
1229 XpmColorSymbol *symbols;
1230 struct gcpro gcpro1, gcpro2;
1232 GCPRO2 (results, device);
1234 /* We built up results to be (("name" . #<color>) ...) so that if an
1235 error happens we don't lose any malloc()ed data, or more importantly,
1236 leave any pixels allocated in the server. */
1238 LIST_LOOP (rest, color_symbol_alist)
1240 Lisp_Object cons = XCAR (rest);
1241 Lisp_Object name = XCAR (cons);
1242 Lisp_Object value = XCDR (cons);
1245 if (STRINGP (value))
1247 Fmake_color_instance
1248 (value, device, encode_error_behavior_flag (ERROR_ME_NOT));
1251 assert (COLOR_SPECIFIERP (value));
1252 value = Fspecifier_instance (value, domain, Qnil, Qnil);
1256 results = noseeum_cons (noseeum_cons (name, value), results);
1259 UNGCPRO; /* no more evaluation */
1261 if (i == 0) return 0;
1263 symbols = xnew_array (XpmColorSymbol, i);
1264 xpmattrs->valuemask |= XpmColorSymbols;
1265 xpmattrs->colorsymbols = symbols;
1266 xpmattrs->numsymbols = i;
1270 Lisp_Object cons = XCAR (results);
1271 color = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (XCDR (cons)));
1272 /* Duplicate the pixel value so that we still have a lock on it if
1273 the pixel we were passed is later freed. */
1274 if (! XAllocColor (dpy, cmap, &color))
1275 abort (); /* it must be allocable since we're just duplicating it */
1277 symbols [i].name = (char *) XSTRING_DATA (XCAR (cons));
1278 symbols [i].pixel = color.pixel;
1279 symbols [i].value = 0;
1280 free_cons (XCONS (cons));
1282 results = XCDR (results);
1283 free_cons (XCONS (cons));
1289 xpm_free (XpmAttributes *xpmattrs)
1291 /* Could conceivably lose if XpmXXX returned an error without first
1292 initializing this structure, if we didn't know that initializing it
1293 to all zeros was ok (and also that it's ok to call XpmFreeAttributes()
1294 multiple times, since it zeros slots as it frees them...) */
1295 XpmFreeAttributes (xpmattrs);
1299 x_xpm_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1300 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1301 int dest_mask, Lisp_Object domain)
1303 /* This function can GC */
1304 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1305 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
1306 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1314 XpmAttributes xpmattrs;
1316 XpmColorSymbol *color_symbols;
1317 Lisp_Object color_symbol_alist = find_keyword_in_vector (instantiator,
1319 enum image_instance_type type;
1323 if (!DEVICE_X_P (XDEVICE (device)))
1324 signal_simple_error ("Not an X device", device);
1326 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
1327 xs = DefaultScreenOfDisplay (dpy);
1329 if (dest_mask & IMAGE_COLOR_PIXMAP_MASK)
1330 type = IMAGE_COLOR_PIXMAP;
1331 else if (dest_mask & IMAGE_MONO_PIXMAP_MASK)
1332 type = IMAGE_MONO_PIXMAP;
1333 else if (dest_mask & IMAGE_POINTER_MASK)
1334 type = IMAGE_POINTER;
1336 incompatible_image_types (instantiator, dest_mask,
1337 IMAGE_MONO_PIXMAP_MASK | IMAGE_COLOR_PIXMAP_MASK
1338 | IMAGE_POINTER_MASK);
1339 force_mono = (type != IMAGE_COLOR_PIXMAP);
1342 /* Although I haven't found it documented yet, it appears that pointers are
1343 always colored via the default window colormap... Sigh. */
1344 if (type == IMAGE_POINTER)
1346 cmap = DefaultColormap(dpy, DefaultScreen(dpy));
1347 depth = DefaultDepthOfScreen (xs);
1348 visual = DefaultVisualOfScreen (xs);
1352 cmap = DEVICE_X_COLORMAP (XDEVICE(device));
1353 depth = DEVICE_X_DEPTH (XDEVICE(device));
1354 visual = DEVICE_X_VISUAL (XDEVICE(device));
1357 cmap = DEVICE_X_COLORMAP (XDEVICE(device));
1358 depth = DEVICE_X_DEPTH (XDEVICE(device));
1359 visual = DEVICE_X_VISUAL (XDEVICE(device));
1362 x_initialize_pixmap_image_instance (ii, 1, type);
1364 assert (!NILP (data));
1368 xzero (xpmattrs); /* want XpmInitAttributes() */
1369 xpmattrs.valuemask = XpmReturnPixels;
1372 /* Without this, we get a 1-bit version of the color image, which
1373 isn't quite right. With this, we get the mono image, which might
1374 be very different looking. */
1375 xpmattrs.valuemask |= XpmColorKey;
1376 xpmattrs.color_key = XPM_MONO;
1378 xpmattrs.valuemask |= XpmDepth;
1382 xpmattrs.closeness = 65535;
1383 xpmattrs.valuemask |= XpmCloseness;
1384 xpmattrs.depth = depth;
1385 xpmattrs.valuemask |= XpmDepth;
1386 xpmattrs.visual = visual;
1387 xpmattrs.valuemask |= XpmVisual;
1388 xpmattrs.colormap = cmap;
1389 xpmattrs.valuemask |= XpmColormap;
1392 color_symbols = extract_xpm_color_names (&xpmattrs, device, domain,
1393 color_symbol_alist);
1395 result = XpmCreatePixmapFromBuffer (dpy,
1396 XtWindow(DEVICE_XT_APP_SHELL (XDEVICE(device))),
1397 (char *) XSTRING_DATA (data),
1398 &pixmap, &mask, &xpmattrs);
1402 xfree (color_symbols);
1403 xpmattrs.colorsymbols = 0; /* in case XpmFreeAttr is too smart... */
1404 xpmattrs.numsymbols = 0;
1411 case XpmFileInvalid:
1413 xpm_free (&xpmattrs);
1414 signal_image_error ("invalid XPM data", data);
1416 case XpmColorFailed:
1419 xpm_free (&xpmattrs);
1422 /* second time; blow out. */
1423 signal_double_file_error ("Reading pixmap data",
1424 "color allocation failed",
1429 if (! (dest_mask & IMAGE_MONO_PIXMAP_MASK))
1431 /* second time; blow out. */
1432 signal_double_file_error ("Reading pixmap data",
1433 "color allocation failed",
1437 IMAGE_INSTANCE_TYPE (ii) = IMAGE_MONO_PIXMAP;
1443 xpm_free (&xpmattrs);
1444 signal_double_file_error ("Parsing pixmap data",
1445 "out of memory", data);
1449 xpm_free (&xpmattrs);
1450 signal_double_file_error_2 ("Parsing pixmap data",
1451 "unknown error code",
1452 make_int (result), data);
1457 h = xpmattrs.height;
1460 int npixels = xpmattrs.npixels;
1465 pixels = xnew_array (Pixel, npixels);
1466 memcpy (pixels, xpmattrs.pixels, npixels * sizeof (Pixel));
1471 IMAGE_INSTANCE_X_PIXMAP (ii) = pixmap;
1472 IMAGE_INSTANCE_PIXMAP_MASK (ii) = (void*)mask;
1473 IMAGE_INSTANCE_X_COLORMAP (ii) = cmap;
1474 IMAGE_INSTANCE_X_PIXELS (ii) = pixels;
1475 IMAGE_INSTANCE_X_NPIXELS (ii) = npixels;
1476 IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = w;
1477 IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = h;
1478 IMAGE_INSTANCE_PIXMAP_FILENAME (ii) =
1479 find_keyword_in_vector (instantiator, Q_file);
1484 case IMAGE_MONO_PIXMAP:
1487 case IMAGE_COLOR_PIXMAP:
1489 IMAGE_INSTANCE_PIXMAP_DEPTH (ii) = depth;
1495 int npixels = xpmattrs.npixels;
1496 Pixel *pixels = xpmattrs.pixels;
1499 int xhot = 0, yhot = 0;
1501 if (xpmattrs.valuemask & XpmHotspot)
1503 xhot = xpmattrs.x_hotspot;
1504 XSETINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii), xpmattrs.x_hotspot);
1506 if (xpmattrs.valuemask & XpmHotspot)
1508 yhot = xpmattrs.y_hotspot;
1509 XSETINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii), xpmattrs.y_hotspot);
1511 check_pointer_sizes (xs, w, h, instantiator);
1513 /* If the loaded pixmap has colors allocated (meaning it came from an
1514 XPM file), then use those as the default colors for the cursor we
1515 create. Otherwise, default to pointer_fg and pointer_bg.
1519 /* With an XBM file, it's obvious which bit is foreground
1520 and which is background, or rather, it's implicit: in
1521 an XBM file, a 1 bit is foreground, and a 0 bit is
1524 XCreatePixmapCursor() assumes this property of the
1525 pixmap it is called with as well; the `foreground'
1526 color argument is used for the 1 bits.
1528 With an XPM file, it's tricker, since the elements of
1529 the pixmap don't represent FG and BG, but are actual
1530 pixel values. So we need to figure out which of those
1531 pixels is the foreground color and which is the
1532 background. We do it by comparing RGB and assuming
1533 that the darker color is the foreground. This works
1534 with the result of xbmtopbm|ppmtoxpm, at least.
1536 It might be nice if there was some way to tag the
1537 colors in the XPM file with whether they are the
1538 foreground - perhaps with logical color names somehow?
1540 Once we have decided which color is the foreground, we
1541 need to ensure that that color corresponds to a `1' bit
1542 in the Pixmap. The XPM library wrote into the (1-bit)
1543 pixmap with XPutPixel, which will ignore all but the
1544 least significant bit.
1546 This means that a 1 bit in the image corresponds to
1547 `fg' only if `fg.pixel' is odd.
1549 (This also means that the image will be all the same
1550 color if both `fg' and `bg' are odd or even, but we can
1551 safely assume that that won't happen if the XPM file is
1554 The desired result is that the image use `1' to
1555 represent the foreground color, and `0' to represent
1556 the background color. So, we may need to invert the
1557 image to accomplish this; we invert if fg is
1558 odd. (Remember that WhitePixel and BlackPixel are not
1559 necessarily 1 and 0 respectively, though I think it
1560 might be safe to assume that one of them is always 1
1561 and the other is always 0. We also pretty much need to
1562 assume that one is even and the other is odd.)
1565 fg.pixel = pixels[0]; /* pick a pixel at random. */
1566 bg.pixel = fg.pixel;
1567 for (i = 1; i < npixels; i++) /* Look for an "other" pixel value.*/
1569 bg.pixel = pixels[i];
1570 if (fg.pixel != bg.pixel)
1574 /* If (fg.pixel == bg.pixel) then probably something has
1575 gone wrong, but I don't think signalling an error would
1578 XQueryColor (dpy, cmap, &fg);
1579 XQueryColor (dpy, cmap, &bg);
1581 /* If the foreground is lighter than the background, swap them.
1582 (This occurs semi-randomly, depending on the ordering of the
1583 color list in the XPM file.)
1586 unsigned short fg_total = ((fg.red / 3) + (fg.green / 3)
1588 unsigned short bg_total = ((bg.red / 3) + (bg.green / 3)
1590 if (fg_total > bg_total)
1599 /* If the fg pixel corresponds to a `0' in the bitmap, invert it.
1600 (This occurs (only?) on servers with Black=0, White=1.)
1602 if ((fg.pixel & 1) == 0)
1606 gcv.function = GXxor;
1608 gc = XCreateGC (dpy, pixmap, (GCFunction | GCForeground),
1610 XFillRectangle (dpy, pixmap, gc, 0, 0, w, h);
1616 generate_cursor_fg_bg (device, &pointer_fg, &pointer_bg,
1618 IMAGE_INSTANCE_PIXMAP_FG (ii) = pointer_fg;
1619 IMAGE_INSTANCE_PIXMAP_BG (ii) = pointer_bg;
1622 IMAGE_INSTANCE_X_CURSOR (ii) =
1624 (dpy, pixmap, mask, &fg, &bg, xhot, yhot);
1633 xpm_free (&xpmattrs); /* after we've read pixels and hotspot */
1636 #endif /* HAVE_XPM */
1641 /**********************************************************************
1643 **********************************************************************/
1645 /* This is about to get redefined! */
1648 /* We have to define SYSV32 so that compface.h includes string.h
1649 instead of strings.h. */
1654 #include <compface.h>
1658 /* JMP_BUF cannot be used here because if it doesn't get defined
1659 to jmp_buf we end up with a conflicting type error with the
1660 definition in compface.h */
1661 extern jmp_buf comp_env;
1665 x_xface_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1666 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1667 int dest_mask, Lisp_Object domain)
1669 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1673 const char * volatile emsg = 0;
1674 const char * volatile dstring;
1676 assert (!NILP (data));
1678 LISP_STRING_TO_EXTERNAL (data, dstring, Qbinary);
1680 if ((p = strchr (dstring, ':')))
1685 /* Must use setjmp not SETJMP because we used jmp_buf above not JMP_BUF */
1686 if (!(stattis = setjmp (comp_env)))
1688 UnCompAll ((char *) dstring);
1695 emsg = "uncompface: internal error";
1698 emsg = "uncompface: insufficient or invalid data";
1701 emsg = "uncompface: excess data ignored";
1706 signal_simple_error_2 (emsg, data, Qimage);
1708 bp = bits = (char *) alloca (PIXELS / 8);
1710 /* the compface library exports char F[], which uses a single byte per
1711 pixel to represent a 48x48 bitmap. Yuck. */
1712 for (i = 0, p = F; i < (PIXELS / 8); ++i)
1715 /* reverse the bit order of each byte... */
1716 for (b = n = 0; b < 8; ++b)
1723 xbm_instantiate_1 (image_instance, instantiator, pointer_fg,
1724 pointer_bg, dest_mask, 48, 48, bits);
1727 #endif /* HAVE_XFACE */
1730 /**********************************************************************
1732 **********************************************************************/
1735 autodetect_validate (Lisp_Object instantiator)
1737 data_must_be_present (instantiator);
1741 autodetect_normalize (Lisp_Object instantiator,
1742 Lisp_Object console_type,
1743 Lisp_Object dest_mask)
1745 Lisp_Object file = find_keyword_in_vector (instantiator, Q_data);
1746 Lisp_Object filename = Qnil;
1747 Lisp_Object data = Qnil;
1748 struct gcpro gcpro1, gcpro2, gcpro3;
1749 Lisp_Object alist = Qnil;
1751 GCPRO3 (filename, data, alist);
1753 if (NILP (file)) /* no conversion necessary */
1754 RETURN_UNGCPRO (instantiator);
1756 alist = tagged_vector_to_alist (instantiator);
1758 filename = locate_pixmap_file (file);
1759 if (!NILP (filename))
1762 /* #### Apparently some versions of XpmReadFileToData, which is
1763 called by pixmap_to_lisp_data, don't return an error value
1764 if the given file is not a valid XPM file. Instead, they
1765 just seg fault. It is definitely caused by passing a
1766 bitmap. To try and avoid this we check for bitmaps first. */
1768 data = bitmap_to_lisp_data (filename, &xhot, &yhot, 1);
1772 alist = remassq_no_quit (Q_data, alist);
1773 alist = Fcons (Fcons (Q_file, filename),
1774 Fcons (Fcons (Q_data, data), alist));
1776 alist = Fcons (Fcons (Q_hotspot_x, make_int (xhot)),
1779 alist = Fcons (Fcons (Q_hotspot_y, make_int (yhot)),
1782 alist = xbm_mask_file_munging (alist, filename, Qnil, console_type);
1785 Lisp_Object result = alist_to_tagged_vector (Qxbm, alist);
1787 RETURN_UNGCPRO (result);
1792 data = pixmap_to_lisp_data (filename, 1);
1796 alist = remassq_no_quit (Q_data, alist);
1797 alist = Fcons (Fcons (Q_file, filename),
1798 Fcons (Fcons (Q_data, data), alist));
1799 alist = Fcons (Fcons (Q_color_symbols,
1800 evaluate_xpm_color_symbols ()),
1803 Lisp_Object result = alist_to_tagged_vector (Qxpm, alist);
1805 RETURN_UNGCPRO (result);
1811 /* If we couldn't convert it, just put it back as it is.
1812 We might try to further frob it later as a cursor-font
1813 specification. (We can't do that now because we don't know
1814 what dest-types it's going to be instantiated into.) */
1816 Lisp_Object result = alist_to_tagged_vector (Qautodetect, alist);
1818 RETURN_UNGCPRO (result);
1823 autodetect_possible_dest_types (void)
1826 IMAGE_MONO_PIXMAP_MASK |
1827 IMAGE_COLOR_PIXMAP_MASK |
1828 IMAGE_POINTER_MASK |
1833 autodetect_instantiate (Lisp_Object image_instance,
1834 Lisp_Object instantiator,
1835 Lisp_Object pointer_fg,
1836 Lisp_Object pointer_bg,
1837 int dest_mask, Lisp_Object domain)
1839 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1840 struct gcpro gcpro1, gcpro2, gcpro3;
1841 Lisp_Object alist = Qnil;
1842 Lisp_Object result = Qnil;
1843 int is_cursor_font = 0;
1845 GCPRO3 (data, alist, result);
1847 alist = tagged_vector_to_alist (instantiator);
1848 if (dest_mask & IMAGE_POINTER_MASK)
1850 const char *name_ext;
1851 LISP_STRING_TO_EXTERNAL (data, name_ext, Qfile_name);
1852 if (XmuCursorNameToIndex (name_ext) != -1)
1854 result = alist_to_tagged_vector (Qcursor_font, alist);
1859 if (!is_cursor_font)
1860 result = alist_to_tagged_vector (Qstring, alist);
1864 cursor_font_instantiate (image_instance, result, pointer_fg,
1865 pointer_bg, dest_mask, domain);
1867 string_instantiate (image_instance, result, pointer_fg,
1868 pointer_bg, dest_mask, domain);
1874 /**********************************************************************
1876 **********************************************************************/
1879 font_validate (Lisp_Object instantiator)
1881 data_must_be_present (instantiator);
1884 /* XmuCvtStringToCursor is bogus in the following ways:
1886 - When it can't convert the given string to a real cursor, it will
1887 sometimes return a "success" value, after triggering a BadPixmap
1888 error. It then gives you a cursor that will itself generate BadCursor
1889 errors. So we install this error handler to catch/notice the X error
1890 and take that as meaning "couldn't convert."
1892 - When you tell it to find a cursor file that doesn't exist, it prints
1893 an error message on stderr. You can't make it not do that.
1895 - Also, using Xmu means we can't properly hack Lisp_Image_Instance
1896 objects, or XPM files, or $XBMLANGPATH.
1899 /* Duplicate the behavior of XmuCvtStringToCursor() to bypass its bogusness. */
1901 static int XLoadFont_got_error;
1904 XLoadFont_error_handler (Display *dpy, XErrorEvent *xerror)
1906 XLoadFont_got_error = 1;
1911 safe_XLoadFont (Display *dpy, char *name)
1914 int (*old_handler) (Display *, XErrorEvent *);
1915 XLoadFont_got_error = 0;
1917 old_handler = XSetErrorHandler (XLoadFont_error_handler);
1918 font = XLoadFont (dpy, name);
1920 XSetErrorHandler (old_handler);
1921 if (XLoadFont_got_error) return 0;
1926 font_possible_dest_types (void)
1928 return IMAGE_POINTER_MASK;
1932 font_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1933 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1934 int dest_mask, Lisp_Object domain)
1936 /* This function can GC */
1937 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1938 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1939 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
1943 char source_name[MAXPATHLEN], mask_name[MAXPATHLEN], dummy;
1944 int source_char, mask_char;
1946 Lisp_Object foreground, background;
1948 if (!DEVICE_X_P (XDEVICE (device)))
1949 signal_simple_error ("Not an X device", device);
1951 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
1953 if (!STRINGP (data) ||
1954 strncmp ("FONT ", (char *) XSTRING_DATA (data), 5))
1955 signal_simple_error ("Invalid font-glyph instantiator",
1958 if (!(dest_mask & IMAGE_POINTER_MASK))
1959 incompatible_image_types (instantiator, dest_mask, IMAGE_POINTER_MASK);
1961 foreground = find_keyword_in_vector (instantiator, Q_foreground);
1962 if (NILP (foreground))
1963 foreground = pointer_fg;
1964 background = find_keyword_in_vector (instantiator, Q_background);
1965 if (NILP (background))
1966 background = pointer_bg;
1968 generate_cursor_fg_bg (device, &foreground, &background, &fg, &bg);
1970 count = sscanf ((char *) XSTRING_DATA (data),
1971 "FONT %s %d %s %d %c",
1972 source_name, &source_char,
1973 mask_name, &mask_char, &dummy);
1974 /* Allow "%s %d %d" as well... */
1975 if (count == 3 && (1 == sscanf (mask_name, "%d %c", &mask_char, &dummy)))
1976 count = 4, mask_name[0] = 0;
1978 if (count != 2 && count != 4)
1979 signal_simple_error ("invalid cursor specification", data);
1980 source = safe_XLoadFont (dpy, source_name);
1982 signal_simple_error_2 ("couldn't load font",
1983 build_string (source_name),
1987 else if (!mask_name[0])
1991 mask = safe_XLoadFont (dpy, mask_name);
1994 Fsignal (Qerror, list3 (build_string ("couldn't load font"),
1995 build_string (mask_name), data));
2000 /* #### call XQueryTextExtents() and check_pointer_sizes() here. */
2002 x_initialize_pixmap_image_instance (ii, 1, IMAGE_POINTER);
2003 IMAGE_INSTANCE_X_CURSOR (ii) =
2004 XCreateGlyphCursor (dpy, source, mask, source_char, mask_char,
2006 XIMAGE_INSTANCE_PIXMAP_FG (image_instance) = foreground;
2007 XIMAGE_INSTANCE_PIXMAP_BG (image_instance) = background;
2008 XUnloadFont (dpy, source);
2009 if (mask && mask != source) XUnloadFont (dpy, mask);
2013 /**********************************************************************
2015 **********************************************************************/
2018 cursor_font_validate (Lisp_Object instantiator)
2020 data_must_be_present (instantiator);
2024 cursor_font_possible_dest_types (void)
2026 return IMAGE_POINTER_MASK;
2030 cursor_font_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2031 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2032 int dest_mask, Lisp_Object domain)
2034 /* This function can GC */
2035 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
2036 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2037 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
2040 const char *name_ext;
2041 Lisp_Object foreground, background;
2043 if (!DEVICE_X_P (XDEVICE (device)))
2044 signal_simple_error ("Not an X device", device);
2046 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
2048 if (!(dest_mask & IMAGE_POINTER_MASK))
2049 incompatible_image_types (instantiator, dest_mask, IMAGE_POINTER_MASK);
2051 LISP_STRING_TO_EXTERNAL (data, name_ext, Qfile_name);
2052 if ((i = XmuCursorNameToIndex (name_ext)) == -1)
2053 signal_simple_error ("Unrecognized cursor-font name", data);
2055 x_initialize_pixmap_image_instance (ii, 1, IMAGE_POINTER);
2056 IMAGE_INSTANCE_X_CURSOR (ii) = XCreateFontCursor (dpy, i);
2057 foreground = find_keyword_in_vector (instantiator, Q_foreground);
2058 if (NILP (foreground))
2059 foreground = pointer_fg;
2060 background = find_keyword_in_vector (instantiator, Q_background);
2061 if (NILP (background))
2062 background = pointer_bg;
2063 maybe_recolor_cursor (image_instance, foreground, background);
2067 x_colorize_image_instance (Lisp_Object image_instance,
2068 Lisp_Object foreground, Lisp_Object background)
2070 Lisp_Image_Instance *p;
2072 p = XIMAGE_INSTANCE (image_instance);
2074 switch (IMAGE_INSTANCE_TYPE (p))
2076 case IMAGE_MONO_PIXMAP:
2077 IMAGE_INSTANCE_TYPE (p) = IMAGE_COLOR_PIXMAP;
2078 /* Make sure there aren't two pointers to the same mask, causing
2079 it to get freed twice. */
2080 IMAGE_INSTANCE_PIXMAP_MASK (p) = 0;
2088 Display *dpy = DEVICE_X_DISPLAY (XDEVICE (IMAGE_INSTANCE_DEVICE (p)));
2089 Drawable draw = XtWindow(DEVICE_XT_APP_SHELL (XDEVICE (IMAGE_INSTANCE_DEVICE (p))));
2090 Dimension d = DEVICE_X_DEPTH (XDEVICE (IMAGE_INSTANCE_DEVICE (p)));
2091 Pixmap new = XCreatePixmap (dpy, draw,
2092 IMAGE_INSTANCE_PIXMAP_WIDTH (p),
2093 IMAGE_INSTANCE_PIXMAP_HEIGHT (p), d);
2097 color = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (foreground));
2098 gcv.foreground = color.pixel;
2099 color = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (background));
2100 gcv.background = color.pixel;
2101 gc = XCreateGC (dpy, new, GCBackground|GCForeground, &gcv);
2102 XCopyPlane (dpy, IMAGE_INSTANCE_X_PIXMAP (p), new, gc, 0, 0,
2103 IMAGE_INSTANCE_PIXMAP_WIDTH (p),
2104 IMAGE_INSTANCE_PIXMAP_HEIGHT (p),
2107 IMAGE_INSTANCE_X_PIXMAP (p) = new;
2108 IMAGE_INSTANCE_PIXMAP_DEPTH (p) = d;
2109 IMAGE_INSTANCE_PIXMAP_FG (p) = foreground;
2110 IMAGE_INSTANCE_PIXMAP_BG (p) = background;
2116 /************************************************************************/
2117 /* subwindow and widget support */
2118 /************************************************************************/
2120 /* unmap the image if it is a widget. This is used by redisplay via
2121 redisplay_unmap_subwindows */
2123 x_unmap_subwindow (Lisp_Image_Instance *p)
2125 if (IMAGE_INSTANCE_TYPE (p) == IMAGE_SUBWINDOW)
2128 (IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY (p),
2129 IMAGE_INSTANCE_X_CLIPWINDOW (p));
2131 else /* must be a widget */
2133 XtUnmapWidget (IMAGE_INSTANCE_X_CLIPWIDGET (p));
2137 /* map the subwindow. This is used by redisplay via
2138 redisplay_output_subwindow */
2140 x_map_subwindow (Lisp_Image_Instance *p, int x, int y,
2141 struct display_glyph_area* dga)
2143 assert (dga->width > 0 && dga->height > 0);
2144 if (IMAGE_INSTANCE_TYPE (p) == IMAGE_SUBWINDOW)
2146 Window subwindow = IMAGE_INSTANCE_X_SUBWINDOW_ID (p);
2147 XMoveResizeWindow (IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY (p),
2148 IMAGE_INSTANCE_X_CLIPWINDOW (p),
2149 x, y, dga->width, dga->height);
2150 XMoveWindow (IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY (p),
2151 subwindow, -dga->xoffset, -dga->yoffset);
2152 if (!IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (p))
2153 XMapWindow (IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY (p),
2154 IMAGE_INSTANCE_X_CLIPWINDOW (p));
2156 else /* must be a widget */
2158 XtConfigureWidget (IMAGE_INSTANCE_X_CLIPWIDGET (p),
2159 x + IMAGE_INSTANCE_X_WIDGET_XOFFSET (p),
2160 y + IMAGE_INSTANCE_X_WIDGET_YOFFSET (p),
2161 dga->width, dga->height, 0);
2162 XtMoveWidget (IMAGE_INSTANCE_X_WIDGET_ID (p),
2163 -dga->xoffset, -dga->yoffset);
2164 if (!IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (p))
2165 XtMapWidget (IMAGE_INSTANCE_X_CLIPWIDGET (p));
2169 /* when you click on a widget you may activate another widget this
2170 needs to be checked and all appropriate widgets updated */
2172 x_redisplay_subwindow (Lisp_Image_Instance *p)
2174 /* Update the subwindow size if necessary. */
2175 if (IMAGE_INSTANCE_SIZE_CHANGED (p))
2177 XResizeWindow (IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY (p),
2178 IMAGE_INSTANCE_X_SUBWINDOW_ID (p),
2179 IMAGE_INSTANCE_WIDTH (p),
2180 IMAGE_INSTANCE_HEIGHT (p));
2184 /* Update all attributes that have changed. Lwlib actually does most
2187 x_redisplay_widget (Lisp_Image_Instance *p)
2189 /* This function can GC if IN_REDISPLAY is false. */
2191 widget_value* wv = 0;
2193 /* First get the items if they have changed since this is a
2194 structural change. As such it will nuke all added values so we
2195 need to update most other things after the items have changed.*/
2196 if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (p))
2198 Lisp_Object image_instance;
2200 XSETIMAGE_INSTANCE (image_instance, p);
2201 wv = gui_items_to_widget_values
2202 (image_instance, IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (p),
2203 /* #### this is not right; we need to keep track of which widgets
2204 want accelerators and which don't */ 0);
2205 wv->change = STRUCTURAL_CHANGE;
2209 /* Assume the lotus position, breath deeply and chant to
2210 yourself lwlibsux, lwlibsux ... lw_get_all_values returns a
2211 reference to the real values rather than a copy thus any
2212 changes we make to the values we get back will look like they
2213 have already been applied. If we rebuild the widget tree then
2214 we may lose properties. */
2215 wv = copy_widget_value_tree (lw_get_all_values
2216 (IMAGE_INSTANCE_X_WIDGET_LWID (p)),
2220 /* Possibly update the colors and font */
2221 if (IMAGE_INSTANCE_WIDGET_FACE_CHANGED (p)
2223 XFRAME (IMAGE_INSTANCE_FRAME (p))->faces_changed
2225 IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (p))
2227 update_widget_face (wv, p, IMAGE_INSTANCE_FRAME (p));
2230 /* Possibly update the text. */
2231 if (IMAGE_INSTANCE_TEXT_CHANGED (p))
2234 Lisp_Object val = IMAGE_INSTANCE_WIDGET_TEXT (p);
2235 LISP_STRING_TO_EXTERNAL (val, str, Qnative);
2239 /* Possibly update the size. */
2240 if (IMAGE_INSTANCE_SIZE_CHANGED (p)
2242 IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (p)
2244 IMAGE_INSTANCE_TEXT_CHANGED (p))
2246 assert (IMAGE_INSTANCE_X_WIDGET_ID (p) &&
2247 IMAGE_INSTANCE_X_CLIPWIDGET (p)) ;
2249 if (IMAGE_INSTANCE_X_WIDGET_ID (p)->core.being_destroyed
2250 || !XtIsManaged(IMAGE_INSTANCE_X_WIDGET_ID (p)))
2253 XSETIMAGE_INSTANCE (sw, p);
2254 signal_simple_error ("XEmacs bug: subwindow is deleted", sw);
2257 lw_add_widget_value_arg (wv, XtNwidth,
2258 (Dimension)IMAGE_INSTANCE_WIDTH (p));
2259 lw_add_widget_value_arg (wv, XtNheight,
2260 (Dimension)IMAGE_INSTANCE_HEIGHT (p));
2263 /* Adjust offsets within the frame. */
2264 if (XFRAME (IMAGE_INSTANCE_FRAME (p))->frame_changed)
2267 XtSetArg (al [0], XtNx, &IMAGE_INSTANCE_X_WIDGET_XOFFSET (p));
2268 XtSetArg (al [1], XtNy, &IMAGE_INSTANCE_X_WIDGET_YOFFSET (p));
2269 XtGetValues (FRAME_X_TEXT_WIDGET
2270 (XFRAME (IMAGE_INSTANCE_FRAME (p))), al, 2);
2273 /* now modify the widget */
2274 lw_modify_all_widgets (IMAGE_INSTANCE_X_WIDGET_LWID (p),
2276 free_widget_value_tree (wv);
2280 /* instantiate and x type subwindow */
2282 x_subwindow_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2283 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2284 int dest_mask, Lisp_Object domain)
2286 /* This function can GC */
2287 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2288 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
2289 Lisp_Object frame = DOMAIN_FRAME (domain);
2290 struct frame* f = XFRAME (frame);
2294 XSetWindowAttributes xswa;
2296 unsigned int w = IMAGE_INSTANCE_WIDTH (ii),
2297 h = IMAGE_INSTANCE_HEIGHT (ii);
2299 if (!DEVICE_X_P (XDEVICE (device)))
2300 signal_simple_error ("Not an X device", device);
2302 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
2303 xs = DefaultScreenOfDisplay (dpy);
2305 IMAGE_INSTANCE_TYPE (ii) = IMAGE_SUBWINDOW;
2307 pw = XtWindow (FRAME_X_TEXT_WIDGET (f));
2309 ii->data = xnew_and_zero (struct x_subwindow_data);
2311 IMAGE_INSTANCE_X_SUBWINDOW_PARENT (ii) = pw;
2312 IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY (ii) = DisplayOfScreen (xs);
2314 xswa.backing_store = Always;
2315 valueMask |= CWBackingStore;
2316 xswa.colormap = DefaultColormapOfScreen (xs);
2317 valueMask |= CWColormap;
2319 /* Create a window for clipping */
2320 IMAGE_INSTANCE_X_CLIPWINDOW (ii) =
2321 XCreateWindow (dpy, pw, 0, 0, w, h, 0, CopyFromParent,
2322 InputOutput, CopyFromParent, valueMask,
2325 /* Now put the subwindow inside the clip window. */
2326 win = XCreateWindow (dpy, IMAGE_INSTANCE_X_CLIPWINDOW (ii),
2327 0, 0, w, h, 0, CopyFromParent,
2328 InputOutput, CopyFromParent, valueMask,
2331 IMAGE_INSTANCE_SUBWINDOW_ID (ii) = (void*)win;
2335 /* #### Should this function exist? If there's any doubt I'm not implementing it --andyp */
2336 DEFUN ("change-subwindow-property", Fchange_subwindow_property, 3, 3, 0, /*
2337 For the given SUBWINDOW, set PROPERTY to DATA, which is a string.
2338 Subwindows are not currently implemented.
2340 (subwindow, property, data))
2346 CHECK_SUBWINDOW (subwindow);
2347 CHECK_STRING (property);
2348 CHECK_STRING (data);
2350 sw = XSUBWINDOW (subwindow);
2351 dpy = DisplayOfScreen (LISP_DEVICE_TO_X_SCREEN
2352 (FRAME_DEVICE (XFRAME (sw->frame))));
2354 property_atom = XInternAtom (dpy, (char *) XSTRING_DATA (property), False);
2355 XChangeProperty (dpy, sw->subwindow, property_atom, XA_STRING, 8,
2357 XSTRING_DATA (data),
2358 XSTRING_LENGTH (data));
2367 /************************************************************************/
2369 /************************************************************************/
2372 update_widget_face (widget_value* wv, Lisp_Image_Instance *ii,
2375 #ifdef LWLIB_WIDGETS_MOTIF
2376 XmFontList fontList;
2378 /* Update the foreground. */
2379 Lisp_Object pixel = FACE_FOREGROUND
2380 (IMAGE_INSTANCE_WIDGET_FACE (ii),
2382 XColor fcolor = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (pixel)), bcolor;
2383 lw_add_widget_value_arg (wv, XtNforeground, fcolor.pixel);
2385 /* Update the background. */
2386 pixel = FACE_BACKGROUND (IMAGE_INSTANCE_WIDGET_FACE (ii),
2388 bcolor = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (pixel));
2389 lw_add_widget_value_arg (wv, XtNbackground, bcolor.pixel);
2391 #ifdef LWLIB_WIDGETS_MOTIF
2392 fontList = XmFontListCreate
2393 (FONT_INSTANCE_X_FONT
2394 (XFONT_INSTANCE (query_string_font
2395 (IMAGE_INSTANCE_WIDGET_TEXT (ii),
2396 IMAGE_INSTANCE_WIDGET_FACE (ii),
2397 domain))), XmSTRING_DEFAULT_CHARSET);
2398 lw_add_widget_value_arg (wv, XmNfontList, (XtArgVal)fontList);
2400 lw_add_widget_value_arg
2401 (wv, XtNfont, (XtArgVal)FONT_INSTANCE_X_FONT
2402 (XFONT_INSTANCE (query_string_font
2403 (IMAGE_INSTANCE_WIDGET_TEXT (ii),
2404 IMAGE_INSTANCE_WIDGET_FACE (ii),
2406 wv->change = VISIBLE_CHANGE;
2407 /* #### Megahack - but its just getting too complicated to do this
2408 in the right place. */
2409 if (EQ (IMAGE_INSTANCE_WIDGET_TYPE (ii), Qtab_control))
2410 update_tab_widget_face (wv, ii, domain);
2414 update_tab_widget_face (widget_value* wv, Lisp_Image_Instance *ii,
2419 widget_value* val = wv->contents, *cur;
2421 /* Give each child label the correct foreground color. */
2422 Lisp_Object pixel = FACE_FOREGROUND
2423 (IMAGE_INSTANCE_WIDGET_FACE (ii),
2425 XColor fcolor = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (pixel));
2426 lw_add_widget_value_arg (val, XtNtabForeground, fcolor.pixel);
2427 wv->change = VISIBLE_CHANGE;
2428 val->change = VISIBLE_CHANGE;
2430 for (cur = val->next; cur; cur = cur->next)
2432 cur->change = VISIBLE_CHANGE;
2435 lw_copy_widget_value_args (val, cur);
2442 x_widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2443 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2444 int dest_mask, Lisp_Object domain,
2445 const char* type, widget_value* wv)
2447 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2448 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii), pixel;
2449 struct device* d = XDEVICE (device);
2450 Lisp_Object frame = DOMAIN_FRAME (domain);
2451 struct frame* f = XFRAME (frame);
2456 int id = new_lwlib_id ();
2457 widget_value* clip_wv;
2458 XColor fcolor, bcolor;
2460 if (!DEVICE_X_P (d))
2461 signal_simple_error ("Not an X device", device);
2463 /* have to set the type this late in case there is no device
2464 instantiation for a widget. But we can go ahead and do it without
2465 checking because there is always a generic instantiator. */
2466 IMAGE_INSTANCE_TYPE (ii) = IMAGE_WIDGET;
2468 if (!NILP (IMAGE_INSTANCE_WIDGET_TEXT (ii)))
2469 LISP_STRING_TO_EXTERNAL (IMAGE_INSTANCE_WIDGET_TEXT (ii), nm, Qnative);
2471 ii->data = xnew_and_zero (struct x_subwindow_data);
2473 /* Create a clip window to contain the subwidget. Incredibly the
2474 XEmacs manager seems to be the most appropriate widget for
2475 this. Nothing else is simple enough and yet does what is
2477 clip_wv = xmalloc_widget_value ();
2479 lw_add_widget_value_arg (clip_wv, XtNresize, False);
2480 lw_add_widget_value_arg (clip_wv, XtNwidth,
2481 (Dimension)IMAGE_INSTANCE_WIDTH (ii));
2482 lw_add_widget_value_arg (clip_wv, XtNheight,
2483 (Dimension)IMAGE_INSTANCE_HEIGHT (ii));
2484 clip_wv->enabled = True;
2486 clip_wv->name = xstrdup ("clip-window");
2487 clip_wv->value = xstrdup ("clip-window");
2489 IMAGE_INSTANCE_X_CLIPWIDGET (ii)
2490 = lw_create_widget ("clip-window", "clip-window", new_lwlib_id (),
2491 clip_wv, FRAME_X_CONTAINER_WIDGET (f),
2494 free_widget_value_tree (clip_wv);
2496 /* copy any args we were given */
2498 lw_add_value_args_to_args (wv, al, &ac);
2500 /* Fixup the colors. We have to do this *before* the widget gets
2501 created so that Motif will fix up the shadow colors
2502 correctly. Once the widget is created Motif won't do this
2504 pixel = FACE_FOREGROUND
2505 (IMAGE_INSTANCE_WIDGET_FACE (ii),
2506 IMAGE_INSTANCE_FRAME (ii));
2507 fcolor = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (pixel));
2509 pixel = FACE_BACKGROUND
2510 (IMAGE_INSTANCE_WIDGET_FACE (ii),
2511 IMAGE_INSTANCE_FRAME (ii));
2512 bcolor = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (pixel));
2514 lw_add_widget_value_arg (wv, XtNbackground, bcolor.pixel);
2515 lw_add_widget_value_arg (wv, XtNforeground, fcolor.pixel);
2516 /* we cannot allow widgets to resize themselves */
2517 lw_add_widget_value_arg (wv, XtNresize, False);
2518 lw_add_widget_value_arg (wv, XtNwidth,
2519 (Dimension)IMAGE_INSTANCE_WIDTH (ii));
2520 lw_add_widget_value_arg (wv, XtNheight,
2521 (Dimension)IMAGE_INSTANCE_HEIGHT (ii));
2522 /* update the font. */
2523 update_widget_face (wv, ii, domain);
2525 wid = lw_create_widget (type, wv->name, id, wv, IMAGE_INSTANCE_X_CLIPWIDGET (ii),
2526 False, 0, popup_selection_callback, 0);
2528 IMAGE_INSTANCE_SUBWINDOW_ID (ii) = (void*)wid;
2529 IMAGE_INSTANCE_X_WIDGET_LWID (ii) = id;
2530 /* because the EmacsManager is the widgets parent we have to
2531 offset the redisplay of the widget by the amount the text
2532 widget is inside the manager. */
2534 XtSetArg (al [ac], XtNx, &IMAGE_INSTANCE_X_WIDGET_XOFFSET (ii)); ac++;
2535 XtSetArg (al [ac], XtNy, &IMAGE_INSTANCE_X_WIDGET_YOFFSET (ii)); ac++;
2536 XtGetValues (FRAME_X_TEXT_WIDGET (f), al, ac);
2538 XtSetMappedWhenManaged (wid, TRUE);
2540 free_widget_value_tree (wv);
2541 /* A kludgy but simple way to make sure the callback for a widget
2542 doesn't get deleted. */
2543 gcpro_popup_callbacks (id);
2546 /* get properties of a control */
2548 x_widget_property (Lisp_Object image_instance, Lisp_Object prop)
2550 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2551 /* get the text from a control */
2552 if (EQ (prop, Q_text))
2554 widget_value* wv = lw_get_all_values (IMAGE_INSTANCE_X_WIDGET_LWID (ii));
2555 return build_ext_string (wv->value, Qnative);
2560 /* Instantiate a layout control for putting other widgets in. */
2562 x_native_layout_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2563 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2564 int dest_mask, Lisp_Object domain)
2566 x_widget_instantiate (image_instance, instantiator, pointer_fg,
2567 pointer_bg, dest_mask, domain, "layout", 0);
2570 /* Instantiate a button widget. Unfortunately instantiated widgets are
2571 particular to a frame since they need to have a parent. It's not
2572 like images where you just select the image into the context you
2573 want to display it in and BitBlt it. So images instances can have a
2574 many-to-one relationship with things you see, whereas widgets can
2575 only be one-to-one (i.e. per frame) */
2577 x_button_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2578 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2579 int dest_mask, Lisp_Object domain)
2581 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2582 Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM (ii);
2583 Lisp_Object glyph = find_keyword_in_vector (instantiator, Q_image);
2584 widget_value* wv = gui_items_to_widget_values (image_instance, gui, 1);
2588 if (!IMAGE_INSTANCEP (glyph))
2589 glyph = glyph_image_instance (glyph, domain, ERROR_ME, 1);
2592 x_widget_instantiate (image_instance, instantiator, pointer_fg,
2593 pointer_bg, dest_mask, domain, "button", wv);
2595 /* add the image if one was given */
2596 if (!NILP (glyph) && IMAGE_INSTANCEP (glyph)
2597 && IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (glyph)))
2601 #ifdef LWLIB_WIDGETS_MOTIF
2602 XtSetArg (al [ac], XmNlabelType, XmPIXMAP); ac++;
2603 XtSetArg (al [ac], XmNlabelPixmap, XIMAGE_INSTANCE_X_PIXMAP (glyph));ac++;
2605 XtSetArg (al [ac], XtNpixmap, XIMAGE_INSTANCE_X_PIXMAP (glyph)); ac++;
2607 XtSetValues (IMAGE_INSTANCE_X_WIDGET_ID (ii), al, ac);
2611 /* Update a button's clicked state.
2613 #### This is overkill, but it works. Right now this causes all
2614 button instances to flash for some reason buried deep in lwlib. In
2615 theory this should be the Right Thing to do since lwlib should only
2616 merge in changed values - and if nothing has changed then nothing
2617 should get done. This may be because of the args stuff,
2618 i.e. although the arg contents may be the same the args look
2619 different and so are re-applied to the widget. */
2621 x_button_redisplay (Lisp_Object image_instance)
2623 /* This function can GC if IN_REDISPLAY is false. */
2624 Lisp_Image_Instance *p = XIMAGE_INSTANCE (image_instance);
2626 gui_items_to_widget_values (image_instance,
2627 IMAGE_INSTANCE_WIDGET_ITEMS (p), 1);
2629 /* now modify the widget */
2630 lw_modify_all_widgets (IMAGE_INSTANCE_X_WIDGET_LWID (p),
2632 free_widget_value_tree (wv);
2635 /* get properties of a button */
2637 x_button_property (Lisp_Object image_instance, Lisp_Object prop)
2639 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2640 /* check the state of a button */
2641 if (EQ (prop, Q_selected))
2643 widget_value* wv = lw_get_all_values (IMAGE_INSTANCE_X_WIDGET_LWID (ii));
2653 /* instantiate a progress gauge */
2655 x_progress_gauge_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2656 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2657 int dest_mask, Lisp_Object domain)
2659 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2660 Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM (ii);
2661 widget_value* wv = gui_items_to_widget_values (image_instance, gui, 0);
2663 x_widget_instantiate (image_instance, instantiator, pointer_fg,
2664 pointer_bg, dest_mask, domain, "progress", wv);
2667 /* set the properties of a progress gauge */
2669 x_progress_gauge_redisplay (Lisp_Object image_instance)
2671 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2673 if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii))
2677 #ifdef ERROR_CHECK_GLYPHS
2678 assert (GUI_ITEMP (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii)));
2680 val = XGUI_ITEM (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii))->value;
2681 XtSetArg (al[0], XtNvalue, XINT (val));
2682 XtSetValues (IMAGE_INSTANCE_X_WIDGET_ID (ii), al, 1);
2686 /* instantiate an edit control */
2688 x_edit_field_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2689 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2690 int dest_mask, Lisp_Object domain)
2692 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2693 Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM (ii);
2694 widget_value* wv = gui_items_to_widget_values (image_instance, gui, 0);
2696 x_widget_instantiate (image_instance, instantiator, pointer_fg,
2697 pointer_bg, dest_mask, domain, "text-field", wv);
2700 #if defined (LWLIB_WIDGETS_MOTIF) && XmVERSION > 1
2701 /* instantiate a combo control */
2703 x_combo_box_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2704 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2705 int dest_mask, Lisp_Object domain)
2707 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2708 widget_value * wv = 0;
2709 /* This is not done generically because of sizing problems under
2711 widget_instantiate (image_instance, instantiator, pointer_fg,
2712 pointer_bg, dest_mask, domain);
2714 wv = gui_items_to_widget_values (image_instance,
2715 IMAGE_INSTANCE_WIDGET_ITEMS (ii), 0);
2717 x_widget_instantiate (image_instance, instantiator, pointer_fg,
2718 pointer_bg, dest_mask, domain, "combo-box", wv);
2723 x_tab_control_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2724 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2725 int dest_mask, Lisp_Object domain)
2727 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2729 gui_items_to_widget_values (image_instance,
2730 IMAGE_INSTANCE_WIDGET_ITEMS (ii), 0);
2731 update_tab_widget_face (wv, ii,
2732 IMAGE_INSTANCE_FRAME (ii));
2733 x_widget_instantiate (image_instance, instantiator, pointer_fg,
2734 pointer_bg, dest_mask, domain, "tab-control", wv);
2737 /* Set the properties of a tab control */
2739 x_tab_control_redisplay (Lisp_Object image_instance)
2741 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2743 if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii)
2745 IMAGE_INSTANCE_WIDGET_ACTION_OCCURRED (ii))
2747 /* If only the order has changed then simply select the first
2748 one of the pending set. This stops horrendous rebuilding -
2749 and hence flicker - of the tabs each time you click on
2751 if (tab_control_order_only_changed (image_instance))
2753 Lisp_Object rest, selected =
2754 gui_item_list_find_selected
2755 (NILP (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii)) ?
2756 XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)) :
2757 XCDR (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii)));
2759 LIST_LOOP (rest, XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)))
2761 if (gui_item_equal_sans_selected (XCAR (rest), selected, 0))
2763 /* There may be an encapsulated way of doing this,
2764 but I couldn't find it. */
2765 Lisp_Object old_selected =gui_item_list_find_selected
2766 (XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)));
2769 unsigned int num_children, i;
2772 LISP_STRING_TO_EXTERNAL (XGUI_ITEM (XCAR (rest))->name,
2774 /* The name may contain a `.' which confuses
2775 XtNameToWidget, so we do it ourselves. */
2776 children = XtCompositeChildren (IMAGE_INSTANCE_X_WIDGET_ID (ii),
2778 for (i = 0; i < num_children; i++)
2780 if (!strcmp (XtName (children [i]), name))
2782 XtSetArg (al [0], XtNtopWidget, children [i]);
2783 XtSetValues (IMAGE_INSTANCE_X_WIDGET_ID (ii), al, 1);
2787 /* Pick up the new selected item. */
2788 XGUI_ITEM (old_selected)->selected =
2789 XGUI_ITEM (XCAR (rest))->selected;
2790 XGUI_ITEM (XCAR (rest))->selected =
2791 XGUI_ITEM (selected)->selected;
2792 /* We're not actually changing the items anymore. */
2793 IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii) = 0;
2794 IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii) = Qnil;
2800 /* Possibly update the face. */
2801 if (IMAGE_INSTANCE_WIDGET_FACE_CHANGED (ii)
2803 XFRAME (IMAGE_INSTANCE_FRAME (ii))->faces_changed
2805 IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii))
2807 /* See previous comments on the brokeness of lwlib.
2809 #### There's actually not much point in doing this here
2810 since, colors will have been set appropriately by
2811 x_redisplay_widget. */
2812 widget_value* wv =copy_widget_value_tree
2814 (IMAGE_INSTANCE_X_WIDGET_LWID (ii)),
2817 update_tab_widget_face (wv, ii,
2818 IMAGE_INSTANCE_FRAME (ii));
2820 lw_modify_all_widgets (IMAGE_INSTANCE_X_WIDGET_LWID (ii), wv, True);
2821 free_widget_value_tree (wv);
2825 /* instantiate a static control possible for putting other things in */
2827 x_label_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2828 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2829 int dest_mask, Lisp_Object domain)
2831 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2832 Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM (ii);
2833 widget_value* wv = gui_items_to_widget_values (image_instance, gui, 0);
2835 x_widget_instantiate (image_instance, instantiator, pointer_fg,
2836 pointer_bg, dest_mask, domain, "button", wv);
2838 #endif /* HAVE_WIDGETS */
2841 /************************************************************************/
2842 /* initialization */
2843 /************************************************************************/
2846 syms_of_glyphs_x (void)
2849 DEFSUBR (Fchange_subwindow_property);
2854 console_type_create_glyphs_x (void)
2858 CONSOLE_HAS_METHOD (x, print_image_instance);
2859 CONSOLE_HAS_METHOD (x, finalize_image_instance);
2860 CONSOLE_HAS_METHOD (x, image_instance_equal);
2861 CONSOLE_HAS_METHOD (x, image_instance_hash);
2862 CONSOLE_HAS_METHOD (x, colorize_image_instance);
2863 CONSOLE_HAS_METHOD (x, init_image_instance_from_eimage);
2864 CONSOLE_HAS_METHOD (x, locate_pixmap_file);
2865 CONSOLE_HAS_METHOD (x, unmap_subwindow);
2866 CONSOLE_HAS_METHOD (x, map_subwindow);
2867 CONSOLE_HAS_METHOD (x, redisplay_widget);
2868 CONSOLE_HAS_METHOD (x, redisplay_subwindow);
2872 image_instantiator_format_create_glyphs_x (void)
2874 IIFORMAT_VALID_CONSOLE (x, nothing);
2875 IIFORMAT_VALID_CONSOLE (x, string);
2877 IIFORMAT_VALID_CONSOLE (x, layout);
2879 IIFORMAT_VALID_CONSOLE (x, formatted_string);
2880 IIFORMAT_VALID_CONSOLE (x, inherit);
2882 INITIALIZE_DEVICE_IIFORMAT (x, xpm);
2883 IIFORMAT_HAS_DEVMETHOD (x, xpm, instantiate);
2886 IIFORMAT_VALID_CONSOLE (x, jpeg);
2889 IIFORMAT_VALID_CONSOLE (x, tiff);
2892 IIFORMAT_VALID_CONSOLE (x, png);
2895 IIFORMAT_VALID_CONSOLE (x, gif);
2897 INITIALIZE_DEVICE_IIFORMAT (x, xbm);
2898 IIFORMAT_HAS_DEVMETHOD (x, xbm, instantiate);
2900 INITIALIZE_DEVICE_IIFORMAT (x, subwindow);
2901 IIFORMAT_HAS_DEVMETHOD (x, subwindow, instantiate);
2904 INITIALIZE_DEVICE_IIFORMAT (x, native_layout);
2905 IIFORMAT_HAS_DEVMETHOD (x, native_layout, instantiate);
2907 INITIALIZE_DEVICE_IIFORMAT (x, button);
2908 IIFORMAT_HAS_DEVMETHOD (x, button, property);
2909 IIFORMAT_HAS_DEVMETHOD (x, button, instantiate);
2910 IIFORMAT_HAS_DEVMETHOD (x, button, redisplay);
2911 /* general widget methods. */
2912 INITIALIZE_DEVICE_IIFORMAT (x, widget);
2913 IIFORMAT_HAS_DEVMETHOD (x, widget, property);
2914 /* progress gauge */
2915 INITIALIZE_DEVICE_IIFORMAT (x, progress_gauge);
2916 IIFORMAT_HAS_DEVMETHOD (x, progress_gauge, redisplay);
2917 IIFORMAT_HAS_DEVMETHOD (x, progress_gauge, instantiate);
2919 INITIALIZE_DEVICE_IIFORMAT (x, edit_field);
2920 IIFORMAT_HAS_DEVMETHOD (x, edit_field, instantiate);
2921 #if defined (LWLIB_WIDGETS_MOTIF) && XmVERSION > 1
2923 INITIALIZE_DEVICE_IIFORMAT (x, combo_box);
2924 IIFORMAT_HAS_DEVMETHOD (x, combo_box, instantiate);
2925 IIFORMAT_HAS_SHARED_DEVMETHOD (x, combo_box, redisplay, tab_control);
2927 /* tab control widget */
2928 INITIALIZE_DEVICE_IIFORMAT (x, tab_control);
2929 IIFORMAT_HAS_DEVMETHOD (x, tab_control, instantiate);
2930 IIFORMAT_HAS_DEVMETHOD (x, tab_control, redisplay);
2932 INITIALIZE_DEVICE_IIFORMAT (x, label);
2933 IIFORMAT_HAS_DEVMETHOD (x, label, instantiate);
2935 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (cursor_font, "cursor-font");
2936 IIFORMAT_VALID_CONSOLE (x, cursor_font);
2938 IIFORMAT_HAS_METHOD (cursor_font, validate);
2939 IIFORMAT_HAS_METHOD (cursor_font, possible_dest_types);
2940 IIFORMAT_HAS_METHOD (cursor_font, instantiate);
2942 IIFORMAT_VALID_KEYWORD (cursor_font, Q_data, check_valid_string);
2943 IIFORMAT_VALID_KEYWORD (cursor_font, Q_foreground, check_valid_string);
2944 IIFORMAT_VALID_KEYWORD (cursor_font, Q_background, check_valid_string);
2946 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (font, "font");
2948 IIFORMAT_HAS_METHOD (font, validate);
2949 IIFORMAT_HAS_METHOD (font, possible_dest_types);
2950 IIFORMAT_HAS_METHOD (font, instantiate);
2951 IIFORMAT_VALID_CONSOLE (x, font);
2953 IIFORMAT_VALID_KEYWORD (font, Q_data, check_valid_string);
2954 IIFORMAT_VALID_KEYWORD (font, Q_foreground, check_valid_string);
2955 IIFORMAT_VALID_KEYWORD (font, Q_background, check_valid_string);
2958 INITIALIZE_DEVICE_IIFORMAT (x, xface);
2959 IIFORMAT_HAS_DEVMETHOD (x, xface, instantiate);
2962 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (autodetect,
2965 IIFORMAT_HAS_METHOD (autodetect, validate);
2966 IIFORMAT_HAS_METHOD (autodetect, normalize);
2967 IIFORMAT_HAS_METHOD (autodetect, possible_dest_types);
2968 /* #### autodetect is flawed IMO:
2969 1. It makes the assumption that you can detect whether the user
2970 wanted a cursor or a string based on the data, since the data is a
2971 string you have to prioritise cursors. Instead we will force users
2972 to pick the appropriate image type, this is what we do under
2974 2. It doesn't fit with the new domain model - you cannot tell which
2975 domain it needs to be instantiated in until you've actually
2976 instantiated it, which mucks up caching.
2977 3. It only copes with cursors and strings which seems bogus. */
2978 IIFORMAT_HAS_SHARED_METHOD (autodetect, governing_domain, subwindow);
2979 IIFORMAT_HAS_METHOD (autodetect, instantiate);
2980 IIFORMAT_VALID_CONSOLE (x, autodetect);
2982 IIFORMAT_VALID_KEYWORD (autodetect, Q_data, check_valid_string);
2986 vars_of_glyphs_x (void)
2988 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path /*
2989 A list of the directories in which X bitmap files may be found.
2990 If nil, this is initialized from the "*bitmapFilePath" resource.
2991 This is used by the `make-image-instance' function (however, note that if
2992 the environment variable XBMLANGPATH is set, it is consulted first).
2994 Vx_bitmap_file_path = Qnil;
2998 complex_vars_of_glyphs_x (void)
3000 #define BUILD_GLYPH_INST(variable, name) \
3001 Fadd_spec_to_specifier \
3002 (GLYPH_IMAGE (XGLYPH (variable)), \
3003 vector3 (Qxbm, Q_data, \
3004 list3 (make_int (name##_width), \
3005 make_int (name##_height), \
3006 make_ext_string ((Extbyte *) name##_bits, \
3007 sizeof (name##_bits), \
3011 BUILD_GLYPH_INST (Vtruncation_glyph, truncator);
3012 BUILD_GLYPH_INST (Vcontinuation_glyph, continuer);
3013 BUILD_GLYPH_INST (Vxemacs_logo, xemacs);
3014 BUILD_GLYPH_INST (Vhscroll_glyph, hscroll);
3016 #undef BUILD_GLYPH_INST