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! */
1003 const Extbyte *bits)
1005 return XCreatePixmapFromBitmapData (DEVICE_X_DISPLAY (XDEVICE(device)),
1006 XtWindow (DEVICE_XT_APP_SHELL (XDEVICE (device))),
1007 (char *) bits, width, height,
1011 /* Given inline data for a mono pixmap, initialize the given
1012 image instance accordingly. */
1015 init_image_instance_from_xbm_inline (Lisp_Image_Instance *ii,
1016 int width, int height,
1017 /* Note that data is in ext-format! */
1019 Lisp_Object instantiator,
1020 Lisp_Object pointer_fg,
1021 Lisp_Object pointer_bg,
1024 Lisp_Object mask_filename)
1026 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
1027 Lisp_Object foreground = find_keyword_in_vector (instantiator, Q_foreground);
1028 Lisp_Object background = find_keyword_in_vector (instantiator, Q_background);
1032 enum image_instance_type type;
1034 if (!DEVICE_X_P (XDEVICE (device)))
1035 signal_simple_error ("Not an X device", device);
1037 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
1038 draw = XtWindow(DEVICE_XT_APP_SHELL (XDEVICE (device)));
1039 scr = DefaultScreenOfDisplay (dpy);
1041 if ((dest_mask & IMAGE_MONO_PIXMAP_MASK) &&
1042 (dest_mask & IMAGE_COLOR_PIXMAP_MASK))
1044 if (!NILP (foreground) || !NILP (background))
1045 type = IMAGE_COLOR_PIXMAP;
1047 type = IMAGE_MONO_PIXMAP;
1049 else if (dest_mask & IMAGE_MONO_PIXMAP_MASK)
1050 type = IMAGE_MONO_PIXMAP;
1051 else if (dest_mask & IMAGE_COLOR_PIXMAP_MASK)
1052 type = IMAGE_COLOR_PIXMAP;
1053 else if (dest_mask & IMAGE_POINTER_MASK)
1054 type = IMAGE_POINTER;
1056 incompatible_image_types (instantiator, dest_mask,
1057 IMAGE_MONO_PIXMAP_MASK | IMAGE_COLOR_PIXMAP_MASK
1058 | IMAGE_POINTER_MASK);
1060 x_initialize_pixmap_image_instance (ii, 1, type);
1061 IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = width;
1062 IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = height;
1063 IMAGE_INSTANCE_PIXMAP_FILENAME (ii) =
1064 find_keyword_in_vector (instantiator, Q_file);
1068 case IMAGE_MONO_PIXMAP:
1070 IMAGE_INSTANCE_X_PIXMAP (ii) =
1071 pixmap_from_xbm_inline (device, width, height, (Extbyte *) bits);
1075 case IMAGE_COLOR_PIXMAP:
1077 Dimension d = DEVICE_X_DEPTH (XDEVICE(device));
1078 unsigned long fg = BlackPixelOfScreen (scr);
1079 unsigned long bg = WhitePixelOfScreen (scr);
1081 if (!NILP (foreground) && !COLOR_INSTANCEP (foreground))
1083 Fmake_color_instance (foreground, device,
1084 encode_error_behavior_flag (ERROR_ME));
1086 if (COLOR_INSTANCEP (foreground))
1087 fg = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (foreground)).pixel;
1089 if (!NILP (background) && !COLOR_INSTANCEP (background))
1091 Fmake_color_instance (background, device,
1092 encode_error_behavior_flag (ERROR_ME));
1094 if (COLOR_INSTANCEP (background))
1095 bg = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (background)).pixel;
1097 /* We used to duplicate the pixels using XAllocColor(), to protect
1098 against their getting freed. Just as easy to just store the
1099 color instances here and GC-protect them, so this doesn't
1101 IMAGE_INSTANCE_PIXMAP_FG (ii) = foreground;
1102 IMAGE_INSTANCE_PIXMAP_BG (ii) = background;
1103 IMAGE_INSTANCE_X_PIXMAP (ii) =
1104 XCreatePixmapFromBitmapData (dpy, draw,
1105 (char *) bits, width, height,
1107 IMAGE_INSTANCE_PIXMAP_DEPTH (ii) = d;
1113 XColor fg_color, bg_color;
1116 check_pointer_sizes (scr, width, height, instantiator);
1119 XCreatePixmapFromBitmapData (dpy, draw,
1120 (char *) bits, width, height,
1123 if (NILP (foreground))
1124 foreground = pointer_fg;
1125 if (NILP (background))
1126 background = pointer_bg;
1127 generate_cursor_fg_bg (device, &foreground, &background,
1128 &fg_color, &bg_color);
1130 IMAGE_INSTANCE_PIXMAP_FG (ii) = foreground;
1131 IMAGE_INSTANCE_PIXMAP_BG (ii) = background;
1132 IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii) =
1133 find_keyword_in_vector (instantiator, Q_hotspot_x);
1134 IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii) =
1135 find_keyword_in_vector (instantiator, Q_hotspot_y);
1136 IMAGE_INSTANCE_X_CURSOR (ii) =
1138 (dpy, source, mask, &fg_color, &bg_color,
1139 !NILP (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii)) ?
1140 XINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii)) : 0,
1141 !NILP (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii)) ?
1142 XINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii)) : 0);
1152 xbm_instantiate_1 (Lisp_Object image_instance, Lisp_Object instantiator,
1153 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1154 int dest_mask, int width, int height,
1155 /* Note that data is in ext-format! */
1158 Lisp_Object mask_data = find_keyword_in_vector (instantiator, Q_mask_data);
1159 Lisp_Object mask_file = find_keyword_in_vector (instantiator, Q_mask_file);
1160 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1163 if (!NILP (mask_data))
1165 const char *ext_data;
1167 LISP_STRING_TO_EXTERNAL (XCAR (XCDR (XCDR (mask_data))), ext_data, Qbinary);
1168 mask = pixmap_from_xbm_inline (IMAGE_INSTANCE_DEVICE (ii),
1169 XINT (XCAR (mask_data)),
1170 XINT (XCAR (XCDR (mask_data))),
1171 (const unsigned char *) ext_data);
1174 init_image_instance_from_xbm_inline (ii, width, height, bits,
1175 instantiator, pointer_fg, pointer_bg,
1176 dest_mask, mask, mask_file);
1179 /* Instantiate method for XBM's. */
1182 x_xbm_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1183 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1184 int dest_mask, Lisp_Object domain)
1186 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1187 const char *ext_data;
1189 assert (!NILP (data));
1191 LISP_STRING_TO_EXTERNAL (XCAR (XCDR (XCDR (data))), ext_data, Qbinary);
1193 xbm_instantiate_1 (image_instance, instantiator, pointer_fg,
1194 pointer_bg, dest_mask, XINT (XCAR (data)),
1195 XINT (XCAR (XCDR (data))), ext_data);
1201 /**********************************************************************
1203 **********************************************************************/
1204 /* xpm 3.2g and better has XpmCreatePixmapFromBuffer()...
1205 There was no version number in xpm.h before 3.3, but this should do.
1207 #if (XpmVersion >= 3) || defined(XpmExactColors)
1208 # define XPM_DOES_BUFFERS
1211 #ifndef XPM_DOES_BUFFERS
1212 Your version of XPM is too old. You cannot compile with it.
1213 Upgrade to version 3.2g or better or compile with --with-xpm=no.
1214 #endif /* !XPM_DOES_BUFFERS */
1216 static XpmColorSymbol *
1217 extract_xpm_color_names (XpmAttributes *xpmattrs, Lisp_Object device,
1219 Lisp_Object color_symbol_alist)
1221 /* This function can GC */
1222 Display *dpy = DEVICE_X_DISPLAY (XDEVICE(device));
1223 Colormap cmap = DEVICE_X_COLORMAP (XDEVICE(device));
1226 Lisp_Object results = Qnil;
1228 XpmColorSymbol *symbols;
1229 struct gcpro gcpro1, gcpro2;
1231 GCPRO2 (results, device);
1233 /* We built up results to be (("name" . #<color>) ...) so that if an
1234 error happens we don't lose any malloc()ed data, or more importantly,
1235 leave any pixels allocated in the server. */
1237 LIST_LOOP (rest, color_symbol_alist)
1239 Lisp_Object cons = XCAR (rest);
1240 Lisp_Object name = XCAR (cons);
1241 Lisp_Object value = XCDR (cons);
1244 if (STRINGP (value))
1246 Fmake_color_instance
1247 (value, device, encode_error_behavior_flag (ERROR_ME_NOT));
1250 assert (COLOR_SPECIFIERP (value));
1251 value = Fspecifier_instance (value, domain, Qnil, Qnil);
1255 results = noseeum_cons (noseeum_cons (name, value), results);
1258 UNGCPRO; /* no more evaluation */
1260 if (i == 0) return 0;
1262 symbols = xnew_array (XpmColorSymbol, i);
1263 xpmattrs->valuemask |= XpmColorSymbols;
1264 xpmattrs->colorsymbols = symbols;
1265 xpmattrs->numsymbols = i;
1269 Lisp_Object cons = XCAR (results);
1270 color = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (XCDR (cons)));
1271 /* Duplicate the pixel value so that we still have a lock on it if
1272 the pixel we were passed is later freed. */
1273 if (! XAllocColor (dpy, cmap, &color))
1274 abort (); /* it must be allocable since we're just duplicating it */
1276 symbols [i].name = (char *) XSTRING_DATA (XCAR (cons));
1277 symbols [i].pixel = color.pixel;
1278 symbols [i].value = 0;
1279 free_cons (XCONS (cons));
1281 results = XCDR (results);
1282 free_cons (XCONS (cons));
1288 xpm_free (XpmAttributes *xpmattrs)
1290 /* Could conceivably lose if XpmXXX returned an error without first
1291 initializing this structure, if we didn't know that initializing it
1292 to all zeros was ok (and also that it's ok to call XpmFreeAttributes()
1293 multiple times, since it zeros slots as it frees them...) */
1294 XpmFreeAttributes (xpmattrs);
1298 x_xpm_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1299 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1300 int dest_mask, Lisp_Object domain)
1302 /* This function can GC */
1303 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1304 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
1305 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1313 XpmAttributes xpmattrs;
1315 XpmColorSymbol *color_symbols;
1316 Lisp_Object color_symbol_alist = find_keyword_in_vector (instantiator,
1318 enum image_instance_type type;
1322 if (!DEVICE_X_P (XDEVICE (device)))
1323 signal_simple_error ("Not an X device", device);
1325 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
1326 xs = DefaultScreenOfDisplay (dpy);
1328 if (dest_mask & IMAGE_COLOR_PIXMAP_MASK)
1329 type = IMAGE_COLOR_PIXMAP;
1330 else if (dest_mask & IMAGE_MONO_PIXMAP_MASK)
1331 type = IMAGE_MONO_PIXMAP;
1332 else if (dest_mask & IMAGE_POINTER_MASK)
1333 type = IMAGE_POINTER;
1335 incompatible_image_types (instantiator, dest_mask,
1336 IMAGE_MONO_PIXMAP_MASK | IMAGE_COLOR_PIXMAP_MASK
1337 | IMAGE_POINTER_MASK);
1338 force_mono = (type != IMAGE_COLOR_PIXMAP);
1341 /* Although I haven't found it documented yet, it appears that pointers are
1342 always colored via the default window colormap... Sigh. */
1343 if (type == IMAGE_POINTER)
1345 cmap = DefaultColormap(dpy, DefaultScreen(dpy));
1346 depth = DefaultDepthOfScreen (xs);
1347 visual = DefaultVisualOfScreen (xs);
1351 cmap = DEVICE_X_COLORMAP (XDEVICE(device));
1352 depth = DEVICE_X_DEPTH (XDEVICE(device));
1353 visual = DEVICE_X_VISUAL (XDEVICE(device));
1356 cmap = DEVICE_X_COLORMAP (XDEVICE(device));
1357 depth = DEVICE_X_DEPTH (XDEVICE(device));
1358 visual = DEVICE_X_VISUAL (XDEVICE(device));
1361 x_initialize_pixmap_image_instance (ii, 1, type);
1363 assert (!NILP (data));
1367 xzero (xpmattrs); /* want XpmInitAttributes() */
1368 xpmattrs.valuemask = XpmReturnPixels;
1371 /* Without this, we get a 1-bit version of the color image, which
1372 isn't quite right. With this, we get the mono image, which might
1373 be very different looking. */
1374 xpmattrs.valuemask |= XpmColorKey;
1375 xpmattrs.color_key = XPM_MONO;
1377 xpmattrs.valuemask |= XpmDepth;
1381 xpmattrs.closeness = 65535;
1382 xpmattrs.valuemask |= XpmCloseness;
1383 xpmattrs.depth = depth;
1384 xpmattrs.valuemask |= XpmDepth;
1385 xpmattrs.visual = visual;
1386 xpmattrs.valuemask |= XpmVisual;
1387 xpmattrs.colormap = cmap;
1388 xpmattrs.valuemask |= XpmColormap;
1391 color_symbols = extract_xpm_color_names (&xpmattrs, device, domain,
1392 color_symbol_alist);
1394 result = XpmCreatePixmapFromBuffer (dpy,
1395 XtWindow(DEVICE_XT_APP_SHELL (XDEVICE(device))),
1396 (char *) XSTRING_DATA (data),
1397 &pixmap, &mask, &xpmattrs);
1401 xfree (color_symbols);
1402 xpmattrs.colorsymbols = 0; /* in case XpmFreeAttr is too smart... */
1403 xpmattrs.numsymbols = 0;
1410 case XpmFileInvalid:
1412 xpm_free (&xpmattrs);
1413 signal_image_error ("invalid XPM data", data);
1415 case XpmColorFailed:
1418 xpm_free (&xpmattrs);
1421 /* second time; blow out. */
1422 signal_double_file_error ("Reading pixmap data",
1423 "color allocation failed",
1428 if (! (dest_mask & IMAGE_MONO_PIXMAP_MASK))
1430 /* second time; blow out. */
1431 signal_double_file_error ("Reading pixmap data",
1432 "color allocation failed",
1436 IMAGE_INSTANCE_TYPE (ii) = IMAGE_MONO_PIXMAP;
1442 xpm_free (&xpmattrs);
1443 signal_double_file_error ("Parsing pixmap data",
1444 "out of memory", data);
1448 xpm_free (&xpmattrs);
1449 signal_double_file_error_2 ("Parsing pixmap data",
1450 "unknown error code",
1451 make_int (result), data);
1456 h = xpmattrs.height;
1459 int npixels = xpmattrs.npixels;
1464 pixels = xnew_array (Pixel, npixels);
1465 memcpy (pixels, xpmattrs.pixels, npixels * sizeof (Pixel));
1470 IMAGE_INSTANCE_X_PIXMAP (ii) = pixmap;
1471 IMAGE_INSTANCE_PIXMAP_MASK (ii) = (void*)mask;
1472 IMAGE_INSTANCE_X_COLORMAP (ii) = cmap;
1473 IMAGE_INSTANCE_X_PIXELS (ii) = pixels;
1474 IMAGE_INSTANCE_X_NPIXELS (ii) = npixels;
1475 IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = w;
1476 IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = h;
1477 IMAGE_INSTANCE_PIXMAP_FILENAME (ii) =
1478 find_keyword_in_vector (instantiator, Q_file);
1483 case IMAGE_MONO_PIXMAP:
1486 case IMAGE_COLOR_PIXMAP:
1488 IMAGE_INSTANCE_PIXMAP_DEPTH (ii) = depth;
1494 int npixels = xpmattrs.npixels;
1495 Pixel *pixels = xpmattrs.pixels;
1498 int xhot = 0, yhot = 0;
1500 if (xpmattrs.valuemask & XpmHotspot)
1502 xhot = xpmattrs.x_hotspot;
1503 XSETINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii), xpmattrs.x_hotspot);
1505 if (xpmattrs.valuemask & XpmHotspot)
1507 yhot = xpmattrs.y_hotspot;
1508 XSETINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii), xpmattrs.y_hotspot);
1510 check_pointer_sizes (xs, w, h, instantiator);
1512 /* If the loaded pixmap has colors allocated (meaning it came from an
1513 XPM file), then use those as the default colors for the cursor we
1514 create. Otherwise, default to pointer_fg and pointer_bg.
1518 /* With an XBM file, it's obvious which bit is foreground
1519 and which is background, or rather, it's implicit: in
1520 an XBM file, a 1 bit is foreground, and a 0 bit is
1523 XCreatePixmapCursor() assumes this property of the
1524 pixmap it is called with as well; the `foreground'
1525 color argument is used for the 1 bits.
1527 With an XPM file, it's tricker, since the elements of
1528 the pixmap don't represent FG and BG, but are actual
1529 pixel values. So we need to figure out which of those
1530 pixels is the foreground color and which is the
1531 background. We do it by comparing RGB and assuming
1532 that the darker color is the foreground. This works
1533 with the result of xbmtopbm|ppmtoxpm, at least.
1535 It might be nice if there was some way to tag the
1536 colors in the XPM file with whether they are the
1537 foreground - perhaps with logical color names somehow?
1539 Once we have decided which color is the foreground, we
1540 need to ensure that that color corresponds to a `1' bit
1541 in the Pixmap. The XPM library wrote into the (1-bit)
1542 pixmap with XPutPixel, which will ignore all but the
1543 least significant bit.
1545 This means that a 1 bit in the image corresponds to
1546 `fg' only if `fg.pixel' is odd.
1548 (This also means that the image will be all the same
1549 color if both `fg' and `bg' are odd or even, but we can
1550 safely assume that that won't happen if the XPM file is
1553 The desired result is that the image use `1' to
1554 represent the foreground color, and `0' to represent
1555 the background color. So, we may need to invert the
1556 image to accomplish this; we invert if fg is
1557 odd. (Remember that WhitePixel and BlackPixel are not
1558 necessarily 1 and 0 respectively, though I think it
1559 might be safe to assume that one of them is always 1
1560 and the other is always 0. We also pretty much need to
1561 assume that one is even and the other is odd.)
1564 fg.pixel = pixels[0]; /* pick a pixel at random. */
1565 bg.pixel = fg.pixel;
1566 for (i = 1; i < npixels; i++) /* Look for an "other" pixel value.*/
1568 bg.pixel = pixels[i];
1569 if (fg.pixel != bg.pixel)
1573 /* If (fg.pixel == bg.pixel) then probably something has
1574 gone wrong, but I don't think signalling an error would
1577 XQueryColor (dpy, cmap, &fg);
1578 XQueryColor (dpy, cmap, &bg);
1580 /* If the foreground is lighter than the background, swap them.
1581 (This occurs semi-randomly, depending on the ordering of the
1582 color list in the XPM file.)
1585 unsigned short fg_total = ((fg.red / 3) + (fg.green / 3)
1587 unsigned short bg_total = ((bg.red / 3) + (bg.green / 3)
1589 if (fg_total > bg_total)
1598 /* If the fg pixel corresponds to a `0' in the bitmap, invert it.
1599 (This occurs (only?) on servers with Black=0, White=1.)
1601 if ((fg.pixel & 1) == 0)
1605 gcv.function = GXxor;
1607 gc = XCreateGC (dpy, pixmap, (GCFunction | GCForeground),
1609 XFillRectangle (dpy, pixmap, gc, 0, 0, w, h);
1615 generate_cursor_fg_bg (device, &pointer_fg, &pointer_bg,
1617 IMAGE_INSTANCE_PIXMAP_FG (ii) = pointer_fg;
1618 IMAGE_INSTANCE_PIXMAP_BG (ii) = pointer_bg;
1621 IMAGE_INSTANCE_X_CURSOR (ii) =
1623 (dpy, pixmap, mask, &fg, &bg, xhot, yhot);
1632 xpm_free (&xpmattrs); /* after we've read pixels and hotspot */
1635 #endif /* HAVE_XPM */
1640 /**********************************************************************
1642 **********************************************************************/
1644 /* This is about to get redefined! */
1647 /* We have to define SYSV32 so that compface.h includes string.h
1648 instead of strings.h. */
1653 #include <compface.h>
1657 /* JMP_BUF cannot be used here because if it doesn't get defined
1658 to jmp_buf we end up with a conflicting type error with the
1659 definition in compface.h */
1660 extern jmp_buf comp_env;
1664 x_xface_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1665 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1666 int dest_mask, Lisp_Object domain)
1668 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1672 const char * volatile emsg = 0;
1673 const char * volatile dstring;
1675 assert (!NILP (data));
1677 LISP_STRING_TO_EXTERNAL (data, dstring, Qbinary);
1679 if ((p = strchr (dstring, ':')))
1684 /* Must use setjmp not SETJMP because we used jmp_buf above not JMP_BUF */
1685 if (!(stattis = setjmp (comp_env)))
1687 UnCompAll ((char *) dstring);
1694 emsg = "uncompface: internal error";
1697 emsg = "uncompface: insufficient or invalid data";
1700 emsg = "uncompface: excess data ignored";
1705 signal_simple_error_2 (emsg, data, Qimage);
1707 bp = bits = (char *) alloca (PIXELS / 8);
1709 /* the compface library exports char F[], which uses a single byte per
1710 pixel to represent a 48x48 bitmap. Yuck. */
1711 for (i = 0, p = F; i < (PIXELS / 8); ++i)
1714 /* reverse the bit order of each byte... */
1715 for (b = n = 0; b < 8; ++b)
1722 xbm_instantiate_1 (image_instance, instantiator, pointer_fg,
1723 pointer_bg, dest_mask, 48, 48, bits);
1726 #endif /* HAVE_XFACE */
1729 /**********************************************************************
1731 **********************************************************************/
1734 autodetect_validate (Lisp_Object instantiator)
1736 data_must_be_present (instantiator);
1740 autodetect_normalize (Lisp_Object instantiator,
1741 Lisp_Object console_type,
1742 Lisp_Object dest_mask)
1744 Lisp_Object file = find_keyword_in_vector (instantiator, Q_data);
1745 Lisp_Object filename = Qnil;
1746 Lisp_Object data = Qnil;
1747 struct gcpro gcpro1, gcpro2, gcpro3;
1748 Lisp_Object alist = Qnil;
1750 GCPRO3 (filename, data, alist);
1752 if (NILP (file)) /* no conversion necessary */
1753 RETURN_UNGCPRO (instantiator);
1755 alist = tagged_vector_to_alist (instantiator);
1757 filename = locate_pixmap_file (file);
1758 if (!NILP (filename))
1761 /* #### Apparently some versions of XpmReadFileToData, which is
1762 called by pixmap_to_lisp_data, don't return an error value
1763 if the given file is not a valid XPM file. Instead, they
1764 just seg fault. It is definitely caused by passing a
1765 bitmap. To try and avoid this we check for bitmaps first. */
1767 data = bitmap_to_lisp_data (filename, &xhot, &yhot, 1);
1771 alist = remassq_no_quit (Q_data, alist);
1772 alist = Fcons (Fcons (Q_file, filename),
1773 Fcons (Fcons (Q_data, data), alist));
1775 alist = Fcons (Fcons (Q_hotspot_x, make_int (xhot)),
1778 alist = Fcons (Fcons (Q_hotspot_y, make_int (yhot)),
1781 alist = xbm_mask_file_munging (alist, filename, Qnil, console_type);
1784 Lisp_Object result = alist_to_tagged_vector (Qxbm, alist);
1786 RETURN_UNGCPRO (result);
1791 data = pixmap_to_lisp_data (filename, 1);
1795 alist = remassq_no_quit (Q_data, alist);
1796 alist = Fcons (Fcons (Q_file, filename),
1797 Fcons (Fcons (Q_data, data), alist));
1798 alist = Fcons (Fcons (Q_color_symbols,
1799 evaluate_xpm_color_symbols ()),
1802 Lisp_Object result = alist_to_tagged_vector (Qxpm, alist);
1804 RETURN_UNGCPRO (result);
1810 /* If we couldn't convert it, just put it back as it is.
1811 We might try to further frob it later as a cursor-font
1812 specification. (We can't do that now because we don't know
1813 what dest-types it's going to be instantiated into.) */
1815 Lisp_Object result = alist_to_tagged_vector (Qautodetect, alist);
1817 RETURN_UNGCPRO (result);
1822 autodetect_possible_dest_types (void)
1825 IMAGE_MONO_PIXMAP_MASK |
1826 IMAGE_COLOR_PIXMAP_MASK |
1827 IMAGE_POINTER_MASK |
1832 autodetect_instantiate (Lisp_Object image_instance,
1833 Lisp_Object instantiator,
1834 Lisp_Object pointer_fg,
1835 Lisp_Object pointer_bg,
1836 int dest_mask, Lisp_Object domain)
1838 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1839 struct gcpro gcpro1, gcpro2, gcpro3;
1840 Lisp_Object alist = Qnil;
1841 Lisp_Object result = Qnil;
1842 int is_cursor_font = 0;
1844 GCPRO3 (data, alist, result);
1846 alist = tagged_vector_to_alist (instantiator);
1847 if (dest_mask & IMAGE_POINTER_MASK)
1849 const char *name_ext;
1850 LISP_STRING_TO_EXTERNAL (data, name_ext, Qfile_name);
1851 if (XmuCursorNameToIndex (name_ext) != -1)
1853 result = alist_to_tagged_vector (Qcursor_font, alist);
1858 if (!is_cursor_font)
1859 result = alist_to_tagged_vector (Qstring, alist);
1863 cursor_font_instantiate (image_instance, result, pointer_fg,
1864 pointer_bg, dest_mask, domain);
1866 string_instantiate (image_instance, result, pointer_fg,
1867 pointer_bg, dest_mask, domain);
1873 /**********************************************************************
1875 **********************************************************************/
1878 font_validate (Lisp_Object instantiator)
1880 data_must_be_present (instantiator);
1883 /* XmuCvtStringToCursor is bogus in the following ways:
1885 - When it can't convert the given string to a real cursor, it will
1886 sometimes return a "success" value, after triggering a BadPixmap
1887 error. It then gives you a cursor that will itself generate BadCursor
1888 errors. So we install this error handler to catch/notice the X error
1889 and take that as meaning "couldn't convert."
1891 - When you tell it to find a cursor file that doesn't exist, it prints
1892 an error message on stderr. You can't make it not do that.
1894 - Also, using Xmu means we can't properly hack Lisp_Image_Instance
1895 objects, or XPM files, or $XBMLANGPATH.
1898 /* Duplicate the behavior of XmuCvtStringToCursor() to bypass its bogusness. */
1900 static int XLoadFont_got_error;
1903 XLoadFont_error_handler (Display *dpy, XErrorEvent *xerror)
1905 XLoadFont_got_error = 1;
1910 safe_XLoadFont (Display *dpy, char *name)
1913 int (*old_handler) (Display *, XErrorEvent *);
1914 XLoadFont_got_error = 0;
1916 old_handler = XSetErrorHandler (XLoadFont_error_handler);
1917 font = XLoadFont (dpy, name);
1919 XSetErrorHandler (old_handler);
1920 if (XLoadFont_got_error) return 0;
1925 font_possible_dest_types (void)
1927 return IMAGE_POINTER_MASK;
1931 font_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1932 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1933 int dest_mask, Lisp_Object domain)
1935 /* This function can GC */
1936 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1937 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1938 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
1942 char source_name[MAXPATHLEN], mask_name[MAXPATHLEN], dummy;
1943 int source_char, mask_char;
1945 Lisp_Object foreground, background;
1947 if (!DEVICE_X_P (XDEVICE (device)))
1948 signal_simple_error ("Not an X device", device);
1950 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
1952 if (!STRINGP (data) ||
1953 strncmp ("FONT ", (char *) XSTRING_DATA (data), 5))
1954 signal_simple_error ("Invalid font-glyph instantiator",
1957 if (!(dest_mask & IMAGE_POINTER_MASK))
1958 incompatible_image_types (instantiator, dest_mask, IMAGE_POINTER_MASK);
1960 foreground = find_keyword_in_vector (instantiator, Q_foreground);
1961 if (NILP (foreground))
1962 foreground = pointer_fg;
1963 background = find_keyword_in_vector (instantiator, Q_background);
1964 if (NILP (background))
1965 background = pointer_bg;
1967 generate_cursor_fg_bg (device, &foreground, &background, &fg, &bg);
1969 count = sscanf ((char *) XSTRING_DATA (data),
1970 "FONT %s %d %s %d %c",
1971 source_name, &source_char,
1972 mask_name, &mask_char, &dummy);
1973 /* Allow "%s %d %d" as well... */
1974 if (count == 3 && (1 == sscanf (mask_name, "%d %c", &mask_char, &dummy)))
1975 count = 4, mask_name[0] = 0;
1977 if (count != 2 && count != 4)
1978 signal_simple_error ("invalid cursor specification", data);
1979 source = safe_XLoadFont (dpy, source_name);
1981 signal_simple_error_2 ("couldn't load font",
1982 build_string (source_name),
1986 else if (!mask_name[0])
1990 mask = safe_XLoadFont (dpy, mask_name);
1993 Fsignal (Qerror, list3 (build_string ("couldn't load font"),
1994 build_string (mask_name), data));
1999 /* #### call XQueryTextExtents() and check_pointer_sizes() here. */
2001 x_initialize_pixmap_image_instance (ii, 1, IMAGE_POINTER);
2002 IMAGE_INSTANCE_X_CURSOR (ii) =
2003 XCreateGlyphCursor (dpy, source, mask, source_char, mask_char,
2005 XIMAGE_INSTANCE_PIXMAP_FG (image_instance) = foreground;
2006 XIMAGE_INSTANCE_PIXMAP_BG (image_instance) = background;
2007 XUnloadFont (dpy, source);
2008 if (mask && mask != source) XUnloadFont (dpy, mask);
2012 /**********************************************************************
2014 **********************************************************************/
2017 cursor_font_validate (Lisp_Object instantiator)
2019 data_must_be_present (instantiator);
2023 cursor_font_possible_dest_types (void)
2025 return IMAGE_POINTER_MASK;
2029 cursor_font_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2030 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2031 int dest_mask, Lisp_Object domain)
2033 /* This function can GC */
2034 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
2035 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2036 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
2039 const char *name_ext;
2040 Lisp_Object foreground, background;
2042 if (!DEVICE_X_P (XDEVICE (device)))
2043 signal_simple_error ("Not an X device", device);
2045 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
2047 if (!(dest_mask & IMAGE_POINTER_MASK))
2048 incompatible_image_types (instantiator, dest_mask, IMAGE_POINTER_MASK);
2050 LISP_STRING_TO_EXTERNAL (data, name_ext, Qfile_name);
2051 if ((i = XmuCursorNameToIndex (name_ext)) == -1)
2052 signal_simple_error ("Unrecognized cursor-font name", data);
2054 x_initialize_pixmap_image_instance (ii, 1, IMAGE_POINTER);
2055 IMAGE_INSTANCE_X_CURSOR (ii) = XCreateFontCursor (dpy, i);
2056 foreground = find_keyword_in_vector (instantiator, Q_foreground);
2057 if (NILP (foreground))
2058 foreground = pointer_fg;
2059 background = find_keyword_in_vector (instantiator, Q_background);
2060 if (NILP (background))
2061 background = pointer_bg;
2062 maybe_recolor_cursor (image_instance, foreground, background);
2066 x_colorize_image_instance (Lisp_Object image_instance,
2067 Lisp_Object foreground, Lisp_Object background)
2069 Lisp_Image_Instance *p;
2071 p = XIMAGE_INSTANCE (image_instance);
2073 switch (IMAGE_INSTANCE_TYPE (p))
2075 case IMAGE_MONO_PIXMAP:
2076 IMAGE_INSTANCE_TYPE (p) = IMAGE_COLOR_PIXMAP;
2077 /* Make sure there aren't two pointers to the same mask, causing
2078 it to get freed twice. */
2079 IMAGE_INSTANCE_PIXMAP_MASK (p) = 0;
2087 Display *dpy = DEVICE_X_DISPLAY (XDEVICE (IMAGE_INSTANCE_DEVICE (p)));
2088 Drawable draw = XtWindow(DEVICE_XT_APP_SHELL (XDEVICE (IMAGE_INSTANCE_DEVICE (p))));
2089 Dimension d = DEVICE_X_DEPTH (XDEVICE (IMAGE_INSTANCE_DEVICE (p)));
2090 Pixmap new = XCreatePixmap (dpy, draw,
2091 IMAGE_INSTANCE_PIXMAP_WIDTH (p),
2092 IMAGE_INSTANCE_PIXMAP_HEIGHT (p), d);
2096 color = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (foreground));
2097 gcv.foreground = color.pixel;
2098 color = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (background));
2099 gcv.background = color.pixel;
2100 gc = XCreateGC (dpy, new, GCBackground|GCForeground, &gcv);
2101 XCopyPlane (dpy, IMAGE_INSTANCE_X_PIXMAP (p), new, gc, 0, 0,
2102 IMAGE_INSTANCE_PIXMAP_WIDTH (p),
2103 IMAGE_INSTANCE_PIXMAP_HEIGHT (p),
2106 IMAGE_INSTANCE_X_PIXMAP (p) = new;
2107 IMAGE_INSTANCE_PIXMAP_DEPTH (p) = d;
2108 IMAGE_INSTANCE_PIXMAP_FG (p) = foreground;
2109 IMAGE_INSTANCE_PIXMAP_BG (p) = background;
2115 /************************************************************************/
2116 /* subwindow and widget support */
2117 /************************************************************************/
2119 /* unmap the image if it is a widget. This is used by redisplay via
2120 redisplay_unmap_subwindows */
2122 x_unmap_subwindow (Lisp_Image_Instance *p)
2124 if (IMAGE_INSTANCE_TYPE (p) == IMAGE_SUBWINDOW)
2127 (IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY (p),
2128 IMAGE_INSTANCE_X_CLIPWINDOW (p));
2130 else /* must be a widget */
2132 XtUnmapWidget (IMAGE_INSTANCE_X_CLIPWIDGET (p));
2136 /* map the subwindow. This is used by redisplay via
2137 redisplay_output_subwindow */
2139 x_map_subwindow (Lisp_Image_Instance *p, int x, int y,
2140 struct display_glyph_area* dga)
2142 if (IMAGE_INSTANCE_TYPE (p) == IMAGE_SUBWINDOW)
2144 Window subwindow = IMAGE_INSTANCE_X_SUBWINDOW_ID (p);
2145 XMoveResizeWindow (IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY (p),
2146 IMAGE_INSTANCE_X_CLIPWINDOW (p),
2147 x, y, dga->width, dga->height);
2148 XMoveWindow (IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY (p),
2149 subwindow, -dga->xoffset, -dga->yoffset);
2150 if (!IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (p))
2151 XMapWindow (IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY (p),
2152 IMAGE_INSTANCE_X_CLIPWINDOW (p));
2154 else /* must be a widget */
2156 XtConfigureWidget (IMAGE_INSTANCE_X_CLIPWIDGET (p),
2157 x + IMAGE_INSTANCE_X_WIDGET_XOFFSET (p),
2158 y + IMAGE_INSTANCE_X_WIDGET_YOFFSET (p),
2159 dga->width, dga->height, 0);
2160 XtMoveWidget (IMAGE_INSTANCE_X_WIDGET_ID (p),
2161 -dga->xoffset, -dga->yoffset);
2162 if (!IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (p))
2163 XtMapWidget (IMAGE_INSTANCE_X_CLIPWIDGET (p));
2167 /* when you click on a widget you may activate another widget this
2168 needs to be checked and all appropriate widgets updated */
2170 x_redisplay_subwindow (Lisp_Image_Instance *p)
2172 /* Update the subwindow size if necessary. */
2173 if (IMAGE_INSTANCE_SIZE_CHANGED (p))
2175 XResizeWindow (IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY (p),
2176 IMAGE_INSTANCE_X_SUBWINDOW_ID (p),
2177 IMAGE_INSTANCE_WIDTH (p),
2178 IMAGE_INSTANCE_HEIGHT (p));
2182 /* Update all attributes that have changed. Lwlib actually does most
2185 x_redisplay_widget (Lisp_Image_Instance *p)
2187 /* This function can GC if IN_REDISPLAY is false. */
2189 widget_value* wv = 0;
2191 /* First get the items if they have changed since this is a
2192 structural change. As such it will nuke all added values so we
2193 need to update most other things after the items have changed.*/
2194 if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (p))
2196 Lisp_Object image_instance;
2198 XSETIMAGE_INSTANCE (image_instance, p);
2199 wv = gui_items_to_widget_values
2200 (image_instance, IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (p),
2201 /* #### this is not right; we need to keep track of which widgets
2202 want accelerators and which don't */ 0);
2203 wv->change = STRUCTURAL_CHANGE;
2207 /* Assume the lotus position, breath deeply and chant to
2208 yourself lwlibsux, lwlibsux ... lw_get_all_values returns a
2209 reference to the real values rather than a copy thus any
2210 changes we make to the values we get back will look like they
2211 have already been applied. If we rebuild the widget tree then
2212 we may lose propertie. */
2213 wv = copy_widget_value_tree (lw_get_all_values
2214 (IMAGE_INSTANCE_X_WIDGET_LWID (p)),
2218 /* Possibly update the colors and font */
2219 if (IMAGE_INSTANCE_WIDGET_FACE_CHANGED (p)
2221 XFRAME (IMAGE_INSTANCE_FRAME (p))->faces_changed
2223 IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (p))
2225 update_widget_face (wv, p, IMAGE_INSTANCE_FRAME (p));
2228 /* Possibly update the text. */
2229 if (IMAGE_INSTANCE_TEXT_CHANGED (p))
2232 Lisp_Object val = IMAGE_INSTANCE_WIDGET_TEXT (p);
2233 LISP_STRING_TO_EXTERNAL (val, str, Qnative);
2237 /* Possibly update the size. */
2238 if (IMAGE_INSTANCE_SIZE_CHANGED (p)
2240 IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (p)
2242 IMAGE_INSTANCE_TEXT_CHANGED (p))
2244 assert (IMAGE_INSTANCE_X_WIDGET_ID (p) &&
2245 IMAGE_INSTANCE_X_CLIPWIDGET (p)) ;
2247 if (IMAGE_INSTANCE_X_WIDGET_ID (p)->core.being_destroyed
2248 || !XtIsManaged(IMAGE_INSTANCE_X_WIDGET_ID (p)))
2251 XSETIMAGE_INSTANCE (sw, p);
2252 signal_simple_error ("XEmacs bug: subwindow is deleted", sw);
2255 lw_add_widget_value_arg (wv, XtNwidth,
2256 (Dimension)IMAGE_INSTANCE_WIDTH (p));
2257 lw_add_widget_value_arg (wv, XtNheight,
2258 (Dimension)IMAGE_INSTANCE_HEIGHT (p));
2261 /* now modify the widget */
2262 lw_modify_all_widgets (IMAGE_INSTANCE_X_WIDGET_LWID (p),
2264 free_widget_value_tree (wv);
2268 /* instantiate and x type subwindow */
2270 x_subwindow_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2271 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2272 int dest_mask, Lisp_Object domain)
2274 /* This function can GC */
2275 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2276 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
2277 Lisp_Object frame = DOMAIN_FRAME (domain);
2278 struct frame* f = XFRAME (frame);
2282 XSetWindowAttributes xswa;
2284 unsigned int w = IMAGE_INSTANCE_WIDTH (ii),
2285 h = IMAGE_INSTANCE_HEIGHT (ii);
2287 if (!DEVICE_X_P (XDEVICE (device)))
2288 signal_simple_error ("Not an X device", device);
2290 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
2291 xs = DefaultScreenOfDisplay (dpy);
2293 IMAGE_INSTANCE_TYPE (ii) = IMAGE_SUBWINDOW;
2295 pw = XtWindow (FRAME_X_TEXT_WIDGET (f));
2297 ii->data = xnew_and_zero (struct x_subwindow_data);
2299 IMAGE_INSTANCE_X_SUBWINDOW_PARENT (ii) = pw;
2300 IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY (ii) = DisplayOfScreen (xs);
2302 xswa.backing_store = Always;
2303 valueMask |= CWBackingStore;
2304 xswa.colormap = DefaultColormapOfScreen (xs);
2305 valueMask |= CWColormap;
2307 /* Create a window for clipping */
2308 IMAGE_INSTANCE_X_CLIPWINDOW (ii) =
2309 XCreateWindow (dpy, pw, 0, 0, w, h, 0, CopyFromParent,
2310 InputOutput, CopyFromParent, valueMask,
2313 /* Now put the subwindow inside the clip window. */
2314 win = XCreateWindow (dpy, IMAGE_INSTANCE_X_CLIPWINDOW (ii),
2315 0, 0, w, h, 0, CopyFromParent,
2316 InputOutput, CopyFromParent, valueMask,
2319 IMAGE_INSTANCE_SUBWINDOW_ID (ii) = (void*)win;
2323 /* #### Should this function exist? If there's any doubt I'm not implementing it --andyp */
2324 DEFUN ("change-subwindow-property", Fchange_subwindow_property, 3, 3, 0, /*
2325 For the given SUBWINDOW, set PROPERTY to DATA, which is a string.
2326 Subwindows are not currently implemented.
2328 (subwindow, property, data))
2334 CHECK_SUBWINDOW (subwindow);
2335 CHECK_STRING (property);
2336 CHECK_STRING (data);
2338 sw = XSUBWINDOW (subwindow);
2339 dpy = DisplayOfScreen (LISP_DEVICE_TO_X_SCREEN
2340 (FRAME_DEVICE (XFRAME (sw->frame))));
2342 property_atom = XInternAtom (dpy, (char *) XSTRING_DATA (property), False);
2343 XChangeProperty (dpy, sw->subwindow, property_atom, XA_STRING, 8,
2345 XSTRING_DATA (data),
2346 XSTRING_LENGTH (data));
2355 /************************************************************************/
2357 /************************************************************************/
2360 update_widget_face (widget_value* wv, Lisp_Image_Instance *ii,
2363 #ifdef LWLIB_WIDGETS_MOTIF
2364 XmFontList fontList;
2366 /* Update the foreground. */
2367 Lisp_Object pixel = FACE_FOREGROUND
2368 (IMAGE_INSTANCE_WIDGET_FACE (ii),
2370 XColor fcolor = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (pixel)), bcolor;
2371 lw_add_widget_value_arg (wv, XtNforeground, fcolor.pixel);
2373 /* Update the background. */
2374 pixel = FACE_BACKGROUND (IMAGE_INSTANCE_WIDGET_FACE (ii),
2376 bcolor = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (pixel));
2377 lw_add_widget_value_arg (wv, XtNbackground, bcolor.pixel);
2379 #ifdef LWLIB_WIDGETS_MOTIF
2380 fontList = XmFontListCreate
2381 (FONT_INSTANCE_X_FONT
2382 (XFONT_INSTANCE (query_string_font
2383 (IMAGE_INSTANCE_WIDGET_TEXT (ii),
2384 IMAGE_INSTANCE_WIDGET_FACE (ii),
2385 domain))), XmSTRING_DEFAULT_CHARSET);
2386 lw_add_widget_value_arg (wv, XmNfontList, (XtArgVal)fontList);
2388 lw_add_widget_value_arg
2389 (wv, XtNfont, (XtArgVal)FONT_INSTANCE_X_FONT
2390 (XFONT_INSTANCE (query_string_font
2391 (IMAGE_INSTANCE_WIDGET_TEXT (ii),
2392 IMAGE_INSTANCE_WIDGET_FACE (ii),
2394 wv->change = VISIBLE_CHANGE;
2395 /* #### Megahack - but its just getting too complicated to do this
2396 in the right place. */
2397 if (EQ (IMAGE_INSTANCE_WIDGET_TYPE (ii), Qtab_control))
2398 update_tab_widget_face (wv, ii, domain);
2402 update_tab_widget_face (widget_value* wv, Lisp_Image_Instance *ii,
2407 widget_value* val = wv->contents, *cur;
2409 /* Give each child label the correct foreground color. */
2410 Lisp_Object pixel = FACE_FOREGROUND
2411 (IMAGE_INSTANCE_WIDGET_FACE (ii),
2413 XColor fcolor = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (pixel));
2414 lw_add_widget_value_arg (val, XtNtabForeground, fcolor.pixel);
2415 wv->change = VISIBLE_CHANGE;
2416 val->change = VISIBLE_CHANGE;
2418 for (cur = val->next; cur; cur = cur->next)
2420 cur->change = VISIBLE_CHANGE;
2423 lw_copy_widget_value_args (val, cur);
2430 x_widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2431 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2432 int dest_mask, Lisp_Object domain,
2433 const char* type, widget_value* wv)
2435 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2436 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii), pixel;
2437 struct device* d = XDEVICE (device);
2438 Lisp_Object frame = DOMAIN_FRAME (domain);
2439 struct frame* f = XFRAME (frame);
2444 int id = new_lwlib_id ();
2445 widget_value* clip_wv;
2446 XColor fcolor, bcolor;
2448 if (!DEVICE_X_P (d))
2449 signal_simple_error ("Not an X device", device);
2451 /* have to set the type this late in case there is no device
2452 instantiation for a widget. But we can go ahead and do it without
2453 checking because there is always a generic instantiator. */
2454 IMAGE_INSTANCE_TYPE (ii) = IMAGE_WIDGET;
2456 if (!NILP (IMAGE_INSTANCE_WIDGET_TEXT (ii)))
2457 LISP_STRING_TO_EXTERNAL (IMAGE_INSTANCE_WIDGET_TEXT (ii), nm, Qnative);
2459 ii->data = xnew_and_zero (struct x_subwindow_data);
2461 /* Create a clip window to contain the subwidget. Incredibly the
2462 XEmacs manager seems to be the most appropriate widget for
2463 this. Nothing else is simple enough and yet does what is
2465 clip_wv = xmalloc_widget_value ();
2467 lw_add_widget_value_arg (clip_wv, XtNresize, False);
2468 lw_add_widget_value_arg (clip_wv, XtNwidth,
2469 (Dimension)IMAGE_INSTANCE_WIDTH (ii));
2470 lw_add_widget_value_arg (clip_wv, XtNheight,
2471 (Dimension)IMAGE_INSTANCE_HEIGHT (ii));
2472 clip_wv->enabled = True;
2474 clip_wv->name = xstrdup ("clip-window");
2475 clip_wv->value = xstrdup ("clip-window");
2477 IMAGE_INSTANCE_X_CLIPWIDGET (ii)
2478 = lw_create_widget ("clip-window", "clip-window", new_lwlib_id (),
2479 clip_wv, FRAME_X_CONTAINER_WIDGET (f),
2482 free_widget_value_tree (clip_wv);
2484 /* copy any args we were given */
2486 lw_add_value_args_to_args (wv, al, &ac);
2488 /* Fixup the colors. We have to do this *before* the widget gets
2489 created so that Motif will fix up the shadow colors
2490 correctly. Once the widget is created Motif won't do this
2492 pixel = FACE_FOREGROUND
2493 (IMAGE_INSTANCE_WIDGET_FACE (ii),
2494 IMAGE_INSTANCE_FRAME (ii));
2495 fcolor = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (pixel));
2497 pixel = FACE_BACKGROUND
2498 (IMAGE_INSTANCE_WIDGET_FACE (ii),
2499 IMAGE_INSTANCE_FRAME (ii));
2500 bcolor = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (pixel));
2502 lw_add_widget_value_arg (wv, XtNbackground, bcolor.pixel);
2503 lw_add_widget_value_arg (wv, XtNforeground, fcolor.pixel);
2504 /* we cannot allow widgets to resize themselves */
2505 lw_add_widget_value_arg (wv, XtNresize, False);
2506 lw_add_widget_value_arg (wv, XtNwidth,
2507 (Dimension)IMAGE_INSTANCE_WIDTH (ii));
2508 lw_add_widget_value_arg (wv, XtNheight,
2509 (Dimension)IMAGE_INSTANCE_HEIGHT (ii));
2510 /* update the font. */
2511 update_widget_face (wv, ii, domain);
2513 wid = lw_create_widget (type, wv->name, id, wv, IMAGE_INSTANCE_X_CLIPWIDGET (ii),
2514 False, 0, popup_selection_callback, 0);
2516 IMAGE_INSTANCE_SUBWINDOW_ID (ii) = (void*)wid;
2517 IMAGE_INSTANCE_X_WIDGET_LWID (ii) = id;
2518 /* because the EmacsManager is the widgets parent we have to
2519 offset the redisplay of the widget by the amount the text
2520 widget is inside the manager. */
2522 XtSetArg (al [ac], XtNx, &IMAGE_INSTANCE_X_WIDGET_XOFFSET (ii)); ac++;
2523 XtSetArg (al [ac], XtNy, &IMAGE_INSTANCE_X_WIDGET_YOFFSET (ii)); ac++;
2524 XtGetValues (FRAME_X_TEXT_WIDGET (f), al, ac);
2526 XtSetMappedWhenManaged (wid, TRUE);
2528 free_widget_value_tree (wv);
2529 /* A kludgy but simple way to make sure the callback for a widget
2530 doesn't get deleted. */
2531 gcpro_popup_callbacks (id);
2534 /* get properties of a control */
2536 x_widget_property (Lisp_Object image_instance, Lisp_Object prop)
2538 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2539 /* get the text from a control */
2540 if (EQ (prop, Q_text))
2542 widget_value* wv = lw_get_all_values (IMAGE_INSTANCE_X_WIDGET_LWID (ii));
2543 return build_ext_string (wv->value, Qnative);
2548 /* Instantiate a layout control for putting other widgets in. */
2550 x_native_layout_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2551 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2552 int dest_mask, Lisp_Object domain)
2554 x_widget_instantiate (image_instance, instantiator, pointer_fg,
2555 pointer_bg, dest_mask, domain, "layout", 0);
2558 /* Instantiate a button widget. Unfortunately instantiated widgets are
2559 particular to a frame since they need to have a parent. It's not
2560 like images where you just select the image into the context you
2561 want to display it in and BitBlt it. So images instances can have a
2562 many-to-one relationship with things you see, whereas widgets can
2563 only be one-to-one (i.e. per frame) */
2565 x_button_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2566 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2567 int dest_mask, Lisp_Object domain)
2569 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2570 Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM (ii);
2571 Lisp_Object glyph = find_keyword_in_vector (instantiator, Q_image);
2572 widget_value* wv = gui_items_to_widget_values (image_instance, gui, 1);
2576 if (!IMAGE_INSTANCEP (glyph))
2577 glyph = glyph_image_instance (glyph, domain, ERROR_ME, 1);
2580 x_widget_instantiate (image_instance, instantiator, pointer_fg,
2581 pointer_bg, dest_mask, domain, "button", wv);
2583 /* add the image if one was given */
2584 if (!NILP (glyph) && IMAGE_INSTANCEP (glyph)
2585 && IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (glyph)))
2589 #ifdef LWLIB_WIDGETS_MOTIF
2590 XtSetArg (al [ac], XmNlabelType, XmPIXMAP); ac++;
2591 XtSetArg (al [ac], XmNlabelPixmap, XIMAGE_INSTANCE_X_PIXMAP (glyph));ac++;
2593 XtSetArg (al [ac], XtNpixmap, XIMAGE_INSTANCE_X_PIXMAP (glyph)); ac++;
2595 XtSetValues (IMAGE_INSTANCE_X_WIDGET_ID (ii), al, ac);
2599 /* Update a button's clicked state.
2601 #### This is overkill, but it works. Right now this causes all
2602 button instances to flash for some reason buried deep in lwlib. In
2603 theory this should be the Right Thing to do since lwlib should only
2604 merge in changed values - and if nothing has changed then nothing
2605 should get done. This may be because of the args stuff,
2606 i.e. although the arg contents may be the same the args look
2607 different and so are re-applied to the widget. */
2609 x_button_redisplay (Lisp_Object image_instance)
2611 /* This function can GC if IN_REDISPLAY is false. */
2612 Lisp_Image_Instance *p = XIMAGE_INSTANCE (image_instance);
2614 gui_items_to_widget_values (image_instance,
2615 IMAGE_INSTANCE_WIDGET_ITEMS (p), 1);
2617 /* now modify the widget */
2618 lw_modify_all_widgets (IMAGE_INSTANCE_X_WIDGET_LWID (p),
2620 free_widget_value_tree (wv);
2623 /* get properties of a button */
2625 x_button_property (Lisp_Object image_instance, Lisp_Object prop)
2627 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2628 /* check the state of a button */
2629 if (EQ (prop, Q_selected))
2631 widget_value* wv = lw_get_all_values (IMAGE_INSTANCE_X_WIDGET_LWID (ii));
2641 /* instantiate a progress gauge */
2643 x_progress_gauge_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2644 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2645 int dest_mask, Lisp_Object domain)
2647 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2648 Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM (ii);
2649 widget_value* wv = gui_items_to_widget_values (image_instance, gui, 0);
2651 x_widget_instantiate (image_instance, instantiator, pointer_fg,
2652 pointer_bg, dest_mask, domain, "progress", wv);
2655 /* set the properties of a progress gauge */
2657 x_progress_gauge_redisplay (Lisp_Object image_instance)
2659 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2661 if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii))
2665 #ifdef ERROR_CHECK_GLYPHS
2666 assert (GUI_ITEMP (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii)));
2668 val = XGUI_ITEM (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii))->value;
2669 XtSetArg (al[0], XtNvalue, XINT (val));
2670 XtSetValues (IMAGE_INSTANCE_X_WIDGET_ID (ii), al, 1);
2674 /* instantiate an edit control */
2676 x_edit_field_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2677 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2678 int dest_mask, Lisp_Object domain)
2680 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2681 Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM (ii);
2682 widget_value* wv = gui_items_to_widget_values (image_instance, gui, 0);
2684 x_widget_instantiate (image_instance, instantiator, pointer_fg,
2685 pointer_bg, dest_mask, domain, "text-field", wv);
2688 #if defined (LWLIB_WIDGETS_MOTIF) && XmVERSION > 1
2689 /* instantiate a combo control */
2691 x_combo_box_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2692 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2693 int dest_mask, Lisp_Object domain)
2695 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2696 widget_value * wv = 0;
2697 /* This is not done generically because of sizing problems under
2699 widget_instantiate (image_instance, instantiator, pointer_fg,
2700 pointer_bg, dest_mask, domain);
2702 wv = gui_items_to_widget_values (image_instance,
2703 IMAGE_INSTANCE_WIDGET_ITEMS (ii), 0);
2705 x_widget_instantiate (image_instance, instantiator, pointer_fg,
2706 pointer_bg, dest_mask, domain, "combo-box", wv);
2711 x_tab_control_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2712 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2713 int dest_mask, Lisp_Object domain)
2715 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2717 gui_items_to_widget_values (image_instance,
2718 IMAGE_INSTANCE_WIDGET_ITEMS (ii), 0);
2719 update_tab_widget_face (wv, ii,
2720 IMAGE_INSTANCE_FRAME (ii));
2721 x_widget_instantiate (image_instance, instantiator, pointer_fg,
2722 pointer_bg, dest_mask, domain, "tab-control", wv);
2725 /* Set the properties of a tab control */
2727 x_tab_control_redisplay (Lisp_Object image_instance)
2729 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2731 if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii)
2733 IMAGE_INSTANCE_WIDGET_ACTION_OCCURRED (ii))
2735 /* If only the order has changed then simply select the first
2736 one of the pending set. This stops horrendous rebuilding -
2737 and hence flicker - of the tabs each time you click on
2739 if (tab_control_order_only_changed (image_instance))
2741 Lisp_Object rest, selected =
2742 gui_item_list_find_selected
2743 (NILP (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii)) ?
2744 XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)) :
2745 XCDR (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii)));
2747 LIST_LOOP (rest, XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)))
2749 if (gui_item_equal_sans_selected (XCAR (rest), selected, 0))
2751 /* There may be an encapsulated way of doing this,
2752 but I couldn't find it. */
2753 Lisp_Object old_selected =gui_item_list_find_selected
2754 (XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)));
2757 unsigned int num_children, i;
2760 LISP_STRING_TO_EXTERNAL (XGUI_ITEM (XCAR (rest))->name,
2762 /* The name may contain a `.' which confuses
2763 XtNameToWidget, so we do it ourselves. */
2764 children = XtCompositeChildren (IMAGE_INSTANCE_X_WIDGET_ID (ii),
2766 for (i = 0; i < num_children; i++)
2768 if (!strcmp (XtName (children [i]), name))
2770 XtSetArg (al [0], XtNtopWidget, children [i]);
2771 XtSetValues (IMAGE_INSTANCE_X_WIDGET_ID (ii), al, 1);
2775 /* Pick up the new selected item. */
2776 XGUI_ITEM (old_selected)->selected =
2777 XGUI_ITEM (XCAR (rest))->selected;
2778 XGUI_ITEM (XCAR (rest))->selected =
2779 XGUI_ITEM (selected)->selected;
2780 /* We're not actually changing the items anymore. */
2781 IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii) = 0;
2782 IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii) = Qnil;
2788 /* Possibly update the face. */
2789 if (IMAGE_INSTANCE_WIDGET_FACE_CHANGED (ii)
2791 XFRAME (IMAGE_INSTANCE_FRAME (ii))->faces_changed
2793 IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii))
2795 /* See previous comments on the brokeness of lwlib.
2797 #### There's actually not much point in doing this here
2798 since, colors will have been set appropriately by
2799 x_redisplay_widget. */
2800 widget_value* wv =copy_widget_value_tree
2802 (IMAGE_INSTANCE_X_WIDGET_LWID (ii)),
2805 update_tab_widget_face (wv, ii,
2806 IMAGE_INSTANCE_FRAME (ii));
2808 lw_modify_all_widgets (IMAGE_INSTANCE_X_WIDGET_LWID (ii), wv, True);
2809 free_widget_value_tree (wv);
2813 /* instantiate a static control possible for putting other things in */
2815 x_label_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2816 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2817 int dest_mask, Lisp_Object domain)
2819 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2820 Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM (ii);
2821 widget_value* wv = gui_items_to_widget_values (image_instance, gui, 0);
2823 x_widget_instantiate (image_instance, instantiator, pointer_fg,
2824 pointer_bg, dest_mask, domain, "button", wv);
2826 #endif /* HAVE_WIDGETS */
2829 /************************************************************************/
2830 /* initialization */
2831 /************************************************************************/
2834 syms_of_glyphs_x (void)
2837 DEFSUBR (Fchange_subwindow_property);
2842 console_type_create_glyphs_x (void)
2846 CONSOLE_HAS_METHOD (x, print_image_instance);
2847 CONSOLE_HAS_METHOD (x, finalize_image_instance);
2848 CONSOLE_HAS_METHOD (x, image_instance_equal);
2849 CONSOLE_HAS_METHOD (x, image_instance_hash);
2850 CONSOLE_HAS_METHOD (x, colorize_image_instance);
2851 CONSOLE_HAS_METHOD (x, init_image_instance_from_eimage);
2852 CONSOLE_HAS_METHOD (x, locate_pixmap_file);
2853 CONSOLE_HAS_METHOD (x, unmap_subwindow);
2854 CONSOLE_HAS_METHOD (x, map_subwindow);
2855 CONSOLE_HAS_METHOD (x, redisplay_widget);
2856 CONSOLE_HAS_METHOD (x, redisplay_subwindow);
2860 image_instantiator_format_create_glyphs_x (void)
2862 IIFORMAT_VALID_CONSOLE (x, nothing);
2863 IIFORMAT_VALID_CONSOLE (x, string);
2865 IIFORMAT_VALID_CONSOLE (x, layout);
2867 IIFORMAT_VALID_CONSOLE (x, formatted_string);
2868 IIFORMAT_VALID_CONSOLE (x, inherit);
2870 INITIALIZE_DEVICE_IIFORMAT (x, xpm);
2871 IIFORMAT_HAS_DEVMETHOD (x, xpm, instantiate);
2874 IIFORMAT_VALID_CONSOLE (x, jpeg);
2877 IIFORMAT_VALID_CONSOLE (x, tiff);
2880 IIFORMAT_VALID_CONSOLE (x, png);
2883 IIFORMAT_VALID_CONSOLE (x, gif);
2885 INITIALIZE_DEVICE_IIFORMAT (x, xbm);
2886 IIFORMAT_HAS_DEVMETHOD (x, xbm, instantiate);
2888 INITIALIZE_DEVICE_IIFORMAT (x, subwindow);
2889 IIFORMAT_HAS_DEVMETHOD (x, subwindow, instantiate);
2892 INITIALIZE_DEVICE_IIFORMAT (x, native_layout);
2893 IIFORMAT_HAS_DEVMETHOD (x, native_layout, instantiate);
2895 INITIALIZE_DEVICE_IIFORMAT (x, button);
2896 IIFORMAT_HAS_DEVMETHOD (x, button, property);
2897 IIFORMAT_HAS_DEVMETHOD (x, button, instantiate);
2898 IIFORMAT_HAS_DEVMETHOD (x, button, redisplay);
2899 /* general widget methods. */
2900 INITIALIZE_DEVICE_IIFORMAT (x, widget);
2901 IIFORMAT_HAS_DEVMETHOD (x, widget, property);
2902 /* progress gauge */
2903 INITIALIZE_DEVICE_IIFORMAT (x, progress_gauge);
2904 IIFORMAT_HAS_DEVMETHOD (x, progress_gauge, redisplay);
2905 IIFORMAT_HAS_DEVMETHOD (x, progress_gauge, instantiate);
2907 INITIALIZE_DEVICE_IIFORMAT (x, edit_field);
2908 IIFORMAT_HAS_DEVMETHOD (x, edit_field, instantiate);
2909 #if defined (LWLIB_WIDGETS_MOTIF) && XmVERSION > 1
2911 INITIALIZE_DEVICE_IIFORMAT (x, combo_box);
2912 IIFORMAT_HAS_DEVMETHOD (x, combo_box, instantiate);
2913 IIFORMAT_HAS_SHARED_DEVMETHOD (x, combo_box, redisplay, tab_control);
2915 /* tab control widget */
2916 INITIALIZE_DEVICE_IIFORMAT (x, tab_control);
2917 IIFORMAT_HAS_DEVMETHOD (x, tab_control, instantiate);
2918 IIFORMAT_HAS_DEVMETHOD (x, tab_control, redisplay);
2920 INITIALIZE_DEVICE_IIFORMAT (x, label);
2921 IIFORMAT_HAS_DEVMETHOD (x, label, instantiate);
2923 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (cursor_font, "cursor-font");
2924 IIFORMAT_VALID_CONSOLE (x, cursor_font);
2926 IIFORMAT_HAS_METHOD (cursor_font, validate);
2927 IIFORMAT_HAS_METHOD (cursor_font, possible_dest_types);
2928 IIFORMAT_HAS_METHOD (cursor_font, instantiate);
2930 IIFORMAT_VALID_KEYWORD (cursor_font, Q_data, check_valid_string);
2931 IIFORMAT_VALID_KEYWORD (cursor_font, Q_foreground, check_valid_string);
2932 IIFORMAT_VALID_KEYWORD (cursor_font, Q_background, check_valid_string);
2934 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (font, "font");
2936 IIFORMAT_HAS_METHOD (font, validate);
2937 IIFORMAT_HAS_METHOD (font, possible_dest_types);
2938 IIFORMAT_HAS_METHOD (font, instantiate);
2939 IIFORMAT_VALID_CONSOLE (x, font);
2941 IIFORMAT_VALID_KEYWORD (font, Q_data, check_valid_string);
2942 IIFORMAT_VALID_KEYWORD (font, Q_foreground, check_valid_string);
2943 IIFORMAT_VALID_KEYWORD (font, Q_background, check_valid_string);
2946 INITIALIZE_DEVICE_IIFORMAT (x, xface);
2947 IIFORMAT_HAS_DEVMETHOD (x, xface, instantiate);
2950 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (autodetect,
2953 IIFORMAT_HAS_METHOD (autodetect, validate);
2954 IIFORMAT_HAS_METHOD (autodetect, normalize);
2955 IIFORMAT_HAS_METHOD (autodetect, possible_dest_types);
2956 IIFORMAT_HAS_METHOD (autodetect, instantiate);
2957 IIFORMAT_VALID_CONSOLE (x, autodetect);
2959 IIFORMAT_VALID_KEYWORD (autodetect, Q_data, check_valid_string);
2963 vars_of_glyphs_x (void)
2965 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path /*
2966 A list of the directories in which X bitmap files may be found.
2967 If nil, this is initialized from the "*bitmapFilePath" resource.
2968 This is used by the `make-image-instance' function (however, note that if
2969 the environment variable XBMLANGPATH is set, it is consulted first).
2971 Vx_bitmap_file_path = Qnil;
2975 complex_vars_of_glyphs_x (void)
2977 #define BUILD_GLYPH_INST(variable, name) \
2978 Fadd_spec_to_specifier \
2979 (GLYPH_IMAGE (XGLYPH (variable)), \
2980 vector3 (Qxbm, Q_data, \
2981 list3 (make_int (name##_width), \
2982 make_int (name##_height), \
2983 make_ext_string (name##_bits, \
2984 sizeof (name##_bits), \
2988 BUILD_GLYPH_INST (Vtruncation_glyph, truncator);
2989 BUILD_GLYPH_INST (Vcontinuation_glyph, continuer);
2990 BUILD_GLYPH_INST (Vxemacs_logo, xemacs);
2991 BUILD_GLYPH_INST (Vhscroll_glyph, hscroll);
2993 #undef BUILD_GLYPH_INST