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, 2002 Andy Piper
9 This file is part of XEmacs.
11 XEmacs is free software; you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by the
13 Free Software Foundation; either version 2, or (at your option) any
16 XEmacs is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 You should have received a copy of the GNU General Public License
21 along with XEmacs; see the file COPYING. If not, write to
22 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23 Boston, MA 02111-1307, USA. */
25 /* Synched up with: Not in FSF. */
27 /* 7-8-00 This file is more or less Mule-ized in my Mule workspace. */
29 /* Original author: Jamie Zawinski for 19.8
30 font-truename stuff added by Jamie Zawinski for 19.10
31 subwindow support added by Chuck Thompson
32 additional XPM support added by Chuck Thompson
33 initial X-Face support added by Stig
34 rewritten/restructured by Ben Wing for 19.12/19.13
35 GIF/JPEG support added by Ben Wing for 19.14
36 PNG support added by Bill Perry for 19.14
37 Improved GIF/JPEG support added by Bill Perry for 19.14
38 Cleanup/simplification of error handling by Ben Wing for 19.14
39 Pointer/icon overhaul, more restructuring by Ben Wing for 19.14
40 GIF support changed to external GIFlib 3.1 by Jareth Hein for 21.0
41 Many changes for color work and optimizations by Jareth Hein for 21.0
42 Switch of GIF/JPEG/PNG to new EImage intermediate code by Jareth Hein for 21.0
43 TIFF code by Jareth Hein for 21.0
44 GIF/JPEG/PNG/TIFF code moved to new glyph-eimage.c by Andy Piper for 21.0
45 Subwindow and Widget support by Andy Piper for 21.2
48 Support the GrayScale, StaticColor and StaticGray visual classes.
49 Convert images.el to C and stick it in here?
55 #include "console-x.h"
57 #include "objects-x.h"
78 #include "file-coding.h"
81 #ifdef LWLIB_WIDGETS_MOTIF
84 #include <X11/IntrinsicP.h>
87 # define FOUR_BYTE_TYPE unsigned int
89 # define FOUR_BYTE_TYPE unsigned long
91 # define FOUR_BYTE_TYPE unsigned short
93 #error What kind of strange-ass system are we running on?
96 #define LISP_DEVICE_TO_X_SCREEN(dev) XDefaultScreenOfDisplay (DEVICE_X_DISPLAY (XDEVICE (dev)))
98 DECLARE_IMAGE_INSTANTIATOR_FORMAT (nothing);
99 DECLARE_IMAGE_INSTANTIATOR_FORMAT (string);
100 DECLARE_IMAGE_INSTANTIATOR_FORMAT (formatted_string);
101 DECLARE_IMAGE_INSTANTIATOR_FORMAT (inherit);
103 DECLARE_IMAGE_INSTANTIATOR_FORMAT (jpeg);
106 DECLARE_IMAGE_INSTANTIATOR_FORMAT (tiff);
109 DECLARE_IMAGE_INSTANTIATOR_FORMAT (png);
112 DECLARE_IMAGE_INSTANTIATOR_FORMAT (gif);
115 DEFINE_DEVICE_IIFORMAT (x, xpm);
117 DEFINE_DEVICE_IIFORMAT (x, xbm);
118 DEFINE_DEVICE_IIFORMAT (x, subwindow);
120 DEFINE_DEVICE_IIFORMAT (x, xface);
123 DEFINE_IMAGE_INSTANTIATOR_FORMAT (cursor_font);
124 Lisp_Object Qcursor_font;
126 DEFINE_IMAGE_INSTANTIATOR_FORMAT (font);
128 DEFINE_IMAGE_INSTANTIATOR_FORMAT (autodetect);
131 DECLARE_IMAGE_INSTANTIATOR_FORMAT (layout);
132 DEFINE_DEVICE_IIFORMAT (x, widget);
133 DEFINE_DEVICE_IIFORMAT (x, native_layout);
134 DEFINE_DEVICE_IIFORMAT (x, button);
135 DEFINE_DEVICE_IIFORMAT (x, progress_gauge);
136 DEFINE_DEVICE_IIFORMAT (x, edit_field);
137 #if defined (LWLIB_WIDGETS_MOTIF) && XmVERSION > 1
138 DEFINE_DEVICE_IIFORMAT (x, combo_box);
140 DEFINE_DEVICE_IIFORMAT (x, tab_control);
141 DEFINE_DEVICE_IIFORMAT (x, label);
144 static void cursor_font_instantiate (Lisp_Object image_instance,
145 Lisp_Object instantiator,
146 Lisp_Object pointer_fg,
147 Lisp_Object pointer_bg,
153 update_widget_face (widget_value* wv,
154 Lisp_Image_Instance* ii, Lisp_Object domain);
156 update_tab_widget_face (widget_value* wv,
157 Lisp_Image_Instance* ii, Lisp_Object domain);
160 emacs_Xt_handle_widget_losing_focus (struct frame* f, Widget losing_widget);
162 enqueue_focus_event (Widget wants_it, Lisp_Object frame, int in_p);
167 /************************************************************************/
168 /* image instance methods */
169 /************************************************************************/
171 /************************************************************************/
172 /* convert from a series of RGB triples to an XImage formated for the */
174 /************************************************************************/
176 convert_EImage_to_XImage (Lisp_Object device, int width, int height,
177 unsigned char *pic, unsigned long **pixtbl,
184 int depth, bitmap_pad, bits_per_pixel, byte_cnt, i, j;
186 unsigned char *data, *ip, *dp;
187 quant_table *qtable = 0;
193 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
194 cmap = DEVICE_X_COLORMAP (XDEVICE(device));
195 vis = DEVICE_X_VISUAL (XDEVICE(device));
196 depth = DEVICE_X_DEPTH(XDEVICE(device));
198 if (vis->class == GrayScale || vis->class == StaticColor ||
199 vis->class == StaticGray)
201 /* #### Implement me!!! */
205 if (vis->class == PseudoColor)
207 /* Quantize the image and get a histogram while we're at it.
208 Do this first to save memory */
209 qtable = build_EImage_quantable(pic, width, height, 256);
210 if (qtable == NULL) return NULL;
213 bitmap_pad = ((depth > 16) ? 32 :
217 outimg = XCreateImage (dpy, vis,
218 depth, ZPixmap, 0, 0, width, height,
220 if (!outimg) return NULL;
222 bits_per_pixel = outimg->bits_per_pixel;
223 byte_cnt = bits_per_pixel >> 3;
225 data = (unsigned char *) xmalloc (outimg->bytes_per_line * height);
228 XDestroyImage (outimg);
231 outimg->data = (char *) data;
233 if (vis->class == PseudoColor)
235 unsigned long pixarray[256];
238 /* use our quantize table to allocate the colors */
240 *pixtbl = xnew_array (unsigned long, pixcount);
243 /* #### should implement a sort by popularity to assure proper allocation */
245 for (i = 0; i < qtable->num_active_colors; i++)
250 color.red = qtable->rm[i] ? qtable->rm[i] << 8 : 0;
251 color.green = qtable->gm[i] ? qtable->gm[i] << 8 : 0;
252 color.blue = qtable->bm[i] ? qtable->bm[i] << 8 : 0;
253 color.flags = DoRed | DoGreen | DoBlue;
254 res = allocate_nearest_color (dpy, cmap, vis, &color);
255 if (res > 0 && res < 3)
257 DO_REALLOC(*pixtbl, pixcount, n+1, unsigned long);
258 (*pixtbl)[n] = color.pixel;
261 pixarray[i] = color.pixel;
265 for (i = 0; i < height; i++)
267 dp = data + (i * outimg->bytes_per_line);
268 for (j = 0; j < width; j++)
273 conv.val = pixarray[QUANT_GET_COLOR(qtable,rd,gr,bl)];
274 #ifdef WORDS_BIGENDIAN
275 if (outimg->byte_order == MSBFirst)
276 for (q = 4-byte_cnt; q < 4; q++) *dp++ = conv.cp[q];
278 for (q = 3; q >= 4-byte_cnt; q--) *dp++ = conv.cp[q];
280 if (outimg->byte_order == MSBFirst)
281 for (q = byte_cnt-1; q >= 0; q--) *dp++ = conv.cp[q];
283 for (q = 0; q < byte_cnt; q++) *dp++ = conv.cp[q];
289 unsigned long rshift,gshift,bshift,rbits,gbits,bbits,junk;
290 junk = vis->red_mask;
292 while ((junk & 0x1) == 0)
303 junk = vis->green_mask;
305 while ((junk & 0x1) == 0)
316 junk = vis->blue_mask;
318 while ((junk & 0x1) == 0)
330 for (i = 0; i < height; i++)
332 dp = data + (i * outimg->bytes_per_line);
333 for (j = 0; j < width; j++)
336 rd = *ip++ << (rbits - 8);
338 rd = *ip++ >> (8 - rbits);
340 gr = *ip++ << (gbits - 8);
342 gr = *ip++ >> (8 - gbits);
344 bl = *ip++ << (bbits - 8);
346 bl = *ip++ >> (8 - bbits);
348 conv.val = (rd << rshift) | (gr << gshift) | (bl << bshift);
349 #ifdef WORDS_BIGENDIAN
350 if (outimg->byte_order == MSBFirst)
351 for (q = 4-byte_cnt; q < 4; q++) *dp++ = conv.cp[q];
353 for (q = 3; q >= 4-byte_cnt; q--) *dp++ = conv.cp[q];
355 if (outimg->byte_order == MSBFirst)
356 for (q = byte_cnt-1; q >= 0; q--) *dp++ = conv.cp[q];
358 for (q = 0; q < byte_cnt; q++) *dp++ = conv.cp[q];
369 x_print_image_instance (Lisp_Image_Instance *p,
370 Lisp_Object printcharfun,
375 switch (IMAGE_INSTANCE_TYPE (p))
377 case IMAGE_MONO_PIXMAP:
378 case IMAGE_COLOR_PIXMAP:
380 sprintf (buf, " (0x%lx", (unsigned long) IMAGE_INSTANCE_X_PIXMAP (p));
381 write_c_string (buf, printcharfun);
382 if (IMAGE_INSTANCE_X_MASK (p))
384 sprintf (buf, "/0x%lx", (unsigned long) IMAGE_INSTANCE_X_MASK (p));
385 write_c_string (buf, printcharfun);
387 write_c_string (")", printcharfun);
395 extern int debug_widget_instances;
399 x_finalize_image_instance (Lisp_Image_Instance *p)
404 if (DEVICE_LIVE_P (XDEVICE (IMAGE_INSTANCE_DEVICE (p))))
406 Display *dpy = DEVICE_X_DISPLAY
407 (XDEVICE (IMAGE_INSTANCE_DEVICE (p)));
411 else if (IMAGE_INSTANCE_TYPE (p) == IMAGE_WIDGET)
413 if (IMAGE_INSTANCE_SUBWINDOW_ID (p))
416 debug_widget_instances--;
417 stderr_out ("widget destroyed, %d left\n", debug_widget_instances);
419 lw_destroy_widget (IMAGE_INSTANCE_X_WIDGET_ID (p));
420 lw_destroy_widget (IMAGE_INSTANCE_X_CLIPWIDGET (p));
422 /* We can release the callbacks again. */
423 ungcpro_popup_callbacks (IMAGE_INSTANCE_X_WIDGET_LWID (p));
425 IMAGE_INSTANCE_X_WIDGET_ID (p) = 0;
426 IMAGE_INSTANCE_X_CLIPWIDGET (p) = 0;
430 else if (IMAGE_INSTANCE_TYPE (p) == IMAGE_SUBWINDOW)
432 if (IMAGE_INSTANCE_SUBWINDOW_ID (p))
433 XDestroyWindow (dpy, IMAGE_INSTANCE_X_SUBWINDOW_ID (p));
434 IMAGE_INSTANCE_SUBWINDOW_ID (p) = 0;
439 if (IMAGE_INSTANCE_PIXMAP_TIMEOUT (p))
440 disable_glyph_animated_timeout (IMAGE_INSTANCE_PIXMAP_TIMEOUT (p));
442 if (IMAGE_INSTANCE_X_MASK (p) &&
443 IMAGE_INSTANCE_X_MASK (p) != IMAGE_INSTANCE_X_PIXMAP (p))
444 XFreePixmap (dpy, IMAGE_INSTANCE_X_MASK (p));
445 IMAGE_INSTANCE_PIXMAP_MASK (p) = 0;
447 if (IMAGE_INSTANCE_X_PIXMAP_SLICES (p))
449 for (i = 0; i < IMAGE_INSTANCE_PIXMAP_MAXSLICE (p); i++)
450 if (IMAGE_INSTANCE_X_PIXMAP_SLICE (p,i))
452 XFreePixmap (dpy, IMAGE_INSTANCE_X_PIXMAP_SLICE (p,i));
453 IMAGE_INSTANCE_X_PIXMAP_SLICE (p, i) = 0;
455 xfree (IMAGE_INSTANCE_X_PIXMAP_SLICES (p));
456 IMAGE_INSTANCE_X_PIXMAP_SLICES (p) = 0;
459 if (IMAGE_INSTANCE_X_CURSOR (p))
461 XFreeCursor (dpy, IMAGE_INSTANCE_X_CURSOR (p));
462 IMAGE_INSTANCE_X_CURSOR (p) = 0;
465 if (IMAGE_INSTANCE_X_NPIXELS (p) != 0)
468 IMAGE_INSTANCE_X_COLORMAP (p),
469 IMAGE_INSTANCE_X_PIXELS (p),
470 IMAGE_INSTANCE_X_NPIXELS (p), 0);
471 IMAGE_INSTANCE_X_NPIXELS (p) = 0;
475 /* You can sometimes have pixels without a live device. I forget
476 why, but that's why we free them here if we have a pixmap type
477 image instance. It probably means that we might also get a memory
478 leak with widgets. */
479 if (IMAGE_INSTANCE_TYPE (p) != IMAGE_WIDGET
480 && IMAGE_INSTANCE_TYPE (p) != IMAGE_SUBWINDOW
481 && IMAGE_INSTANCE_X_PIXELS (p))
483 xfree (IMAGE_INSTANCE_X_PIXELS (p));
484 IMAGE_INSTANCE_X_PIXELS (p) = 0;
492 x_image_instance_equal (Lisp_Image_Instance *p1,
493 Lisp_Image_Instance *p2, int depth)
495 switch (IMAGE_INSTANCE_TYPE (p1))
497 case IMAGE_MONO_PIXMAP:
498 case IMAGE_COLOR_PIXMAP:
500 if (IMAGE_INSTANCE_X_COLORMAP (p1) != IMAGE_INSTANCE_X_COLORMAP (p2) ||
501 IMAGE_INSTANCE_X_NPIXELS (p1) != IMAGE_INSTANCE_X_NPIXELS (p2))
512 x_image_instance_hash (Lisp_Image_Instance *p, int depth)
514 switch (IMAGE_INSTANCE_TYPE (p))
516 case IMAGE_MONO_PIXMAP:
517 case IMAGE_COLOR_PIXMAP:
519 return IMAGE_INSTANCE_X_NPIXELS (p);
525 /* Set all the slots in an image instance structure to reasonable
526 default values. This is used somewhere within an instantiate
527 method. It is assumed that the device slot within the image
528 instance is already set -- this is the case when instantiate
529 methods are called. */
532 x_initialize_pixmap_image_instance (Lisp_Image_Instance *ii,
534 enum image_instance_type type)
536 ii->data = xnew_and_zero (struct x_image_instance_data);
537 IMAGE_INSTANCE_PIXMAP_MAXSLICE (ii) = slices;
538 IMAGE_INSTANCE_X_PIXMAP_SLICES (ii) =
539 xnew_array_and_zero (Pixmap, slices);
540 IMAGE_INSTANCE_TYPE (ii) = type;
541 IMAGE_INSTANCE_PIXMAP_FILENAME (ii) = Qnil;
542 IMAGE_INSTANCE_PIXMAP_MASK_FILENAME (ii) = Qnil;
543 IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii) = Qnil;
544 IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii) = Qnil;
545 IMAGE_INSTANCE_PIXMAP_FG (ii) = Qnil;
546 IMAGE_INSTANCE_PIXMAP_BG (ii) = Qnil;
550 /************************************************************************/
551 /* pixmap file functions */
552 /************************************************************************/
554 /* Where bitmaps are; initialized from resource database */
555 Lisp_Object Vx_bitmap_file_path;
558 #define BITMAPDIR "/usr/include/X11/bitmaps"
561 #define USE_XBMLANGPATH
563 /* Given a pixmap filename, look through all of the "standard" places
564 where the file might be located. Return a full pathname if found;
565 otherwise, return Qnil. */
568 x_locate_pixmap_file (Lisp_Object name)
570 /* This function can GC if IN_REDISPLAY is false */
573 /* Check non-absolute pathnames with a directory component relative to
574 the search path; that's the way Xt does it. */
575 /* #### Unix-specific */
576 if (XSTRING_BYTE (name, 0) == '/' ||
577 (XSTRING_BYTE (name, 0) == '.' &&
578 (XSTRING_BYTE (name, 1) == '/' ||
579 (XSTRING_BYTE (name, 1) == '.' &&
580 (XSTRING_BYTE (name, 2) == '/')))))
582 if (!NILP (Ffile_readable_p (name)))
583 return Fexpand_file_name (name, Qnil);
588 if (NILP (Vdefault_x_device))
589 /* This may occur during initialization. */
592 /* We only check the bitmapFilePath resource on the original X device. */
593 display = DEVICE_X_DISPLAY (XDEVICE (Vdefault_x_device));
595 #ifdef USE_XBMLANGPATH
597 char *path = egetenv ("XBMLANGPATH");
598 SubstitutionRec subs[1];
600 subs[0].substitution = (char *) XSTRING_DATA (name);
601 /* #### Motif uses a big hairy default if $XBMLANGPATH isn't set.
602 We don't. If you want it used, set it. */
604 (path = XtResolvePathname (display, "bitmaps", 0, 0, path,
605 subs, XtNumber (subs), 0)))
607 name = build_string (path);
614 if (NILP (Vx_bitmap_file_path))
618 if (XrmGetResource (XtDatabase (display),
619 "bitmapFilePath", "BitmapFilePath", &type, &value)
620 && !strcmp (type, "String"))
621 Vx_bitmap_file_path = decode_env_path (0, (char *) value.addr);
622 Vx_bitmap_file_path = nconc2 (Vx_bitmap_file_path,
623 (decode_path (BITMAPDIR)));
628 if (locate_file (Vx_bitmap_file_path, name, Qnil, &found, R_OK) < 0)
630 Lisp_Object temp = list1 (Vdata_directory);
634 locate_file (temp, name, Qnil, &found, R_OK);
643 locate_pixmap_file (Lisp_Object name)
645 return x_locate_pixmap_file (name);
650 write_lisp_string_to_temp_file (Lisp_Object string, char *filename_out)
652 Lisp_Object instream, outstream;
653 Lstream *istr, *ostr;
654 char tempbuf[1024]; /* some random amount */
657 static Extbyte_dynarr *conversion_out_dynarr;
658 Bytecount bstart, bend;
659 struct gcpro gcpro1, gcpro2;
661 Lisp_Object conv_out_stream;
666 /* This function can GC */
667 if (!conversion_out_dynarr)
668 conversion_out_dynarr = Dynarr_new (Extbyte);
670 Dynarr_reset (conversion_out_dynarr);
672 /* Create the temporary file ... */
673 sprintf (filename_out, "/tmp/emacs%d.XXXXXX", (int) getpid ());
674 mktemp (filename_out);
675 tmpfil = fopen (filename_out, "w");
680 int old_errno = errno;
682 unlink (filename_out);
685 report_file_error ("Creating temp file",
686 list1 (build_string (filename_out)));
689 CHECK_STRING (string);
690 get_string_range_byte (string, Qnil, Qnil, &bstart, &bend,
691 GB_HISTORICAL_STRING_BEHAVIOR);
692 instream = make_lisp_string_input_stream (string, bstart, bend);
693 istr = XLSTREAM (instream);
694 /* setup the out stream */
695 outstream = make_dynarr_output_stream((unsigned_char_dynarr *)conversion_out_dynarr);
696 ostr = XLSTREAM (outstream);
698 /* setup the conversion stream */
699 conv_out_stream = make_encoding_output_stream (ostr, Fget_coding_system(Qbinary));
700 costr = XLSTREAM (conv_out_stream);
701 GCPRO3 (instream, outstream, conv_out_stream);
703 GCPRO2 (instream, outstream);
706 /* Get the data while doing the conversion */
709 Lstream_data_count size_in_bytes = Lstream_read (istr, tempbuf, sizeof (tempbuf));
712 /* It does seem the flushes are necessary... */
714 Lstream_write (costr, tempbuf, size_in_bytes);
715 Lstream_flush (costr);
717 Lstream_write (ostr, tempbuf, size_in_bytes);
719 Lstream_flush (ostr);
720 if (fwrite ((unsigned char *)Dynarr_atp(conversion_out_dynarr, 0),
721 Dynarr_length(conversion_out_dynarr), 1, tmpfil) != 1)
726 /* reset the dynarr */
727 Lstream_rewind(ostr);
730 if (fclose (tmpfil) != 0)
732 Lstream_close (istr);
734 Lstream_close (costr);
736 Lstream_close (ostr);
739 Lstream_delete (istr);
740 Lstream_delete (ostr);
742 Lstream_delete (costr);
746 report_file_error ("Writing temp file",
747 list1 (build_string (filename_out)));
752 /************************************************************************/
753 /* cursor functions */
754 /************************************************************************/
756 /* Check that this server supports cursors of size WIDTH * HEIGHT. If
757 not, signal an error. INSTANTIATOR is only used in the error
761 check_pointer_sizes (Screen *xs, unsigned int width, unsigned int height,
762 Lisp_Object instantiator)
764 unsigned int best_width, best_height;
765 if (! XQueryBestCursor (DisplayOfScreen (xs), RootWindowOfScreen (xs),
766 width, height, &best_width, &best_height))
767 /* this means that an X error of some sort occurred (we trap
768 these so they're not fatal). */
769 signal_simple_error ("XQueryBestCursor() failed?", instantiator);
771 if (width > best_width || height > best_height)
772 error_with_frob (instantiator,
773 "pointer too large (%dx%d): "
774 "server requires %dx%d or smaller",
775 width, height, best_width, best_height);
780 generate_cursor_fg_bg (Lisp_Object device, Lisp_Object *foreground,
781 Lisp_Object *background, XColor *xfg, XColor *xbg)
783 if (!NILP (*foreground) && !COLOR_INSTANCEP (*foreground))
785 Fmake_color_instance (*foreground, device,
786 encode_error_behavior_flag (ERROR_ME));
787 if (COLOR_INSTANCEP (*foreground))
788 *xfg = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (*foreground));
792 xfg->red = xfg->green = xfg->blue = 0;
795 if (!NILP (*background) && !COLOR_INSTANCEP (*background))
797 Fmake_color_instance (*background, device,
798 encode_error_behavior_flag (ERROR_ME));
799 if (COLOR_INSTANCEP (*background))
800 *xbg = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (*background));
804 xbg->red = xbg->green = xbg->blue = USHRT_MAX;
809 maybe_recolor_cursor (Lisp_Object image_instance, Lisp_Object foreground,
810 Lisp_Object background)
812 Lisp_Object device = XIMAGE_INSTANCE_DEVICE (image_instance);
815 generate_cursor_fg_bg (device, &foreground, &background, &xfg, &xbg);
816 if (!NILP (foreground) || !NILP (background))
818 XRecolorCursor (DEVICE_X_DISPLAY (XDEVICE (device)),
819 XIMAGE_INSTANCE_X_CURSOR (image_instance),
821 XIMAGE_INSTANCE_PIXMAP_FG (image_instance) = foreground;
822 XIMAGE_INSTANCE_PIXMAP_BG (image_instance) = background;
827 /************************************************************************/
828 /* color pixmap functions */
829 /************************************************************************/
831 /* Initialize an image instance from an XImage.
833 DEST_MASK specifies the mask of allowed image types.
835 PIXELS and NPIXELS specify an array of pixels that are used in
836 the image. These need to be kept around for the duration of the
837 image. When the image instance is freed, XFreeColors() will
838 automatically be called on all the pixels specified here; thus,
839 you should have allocated the pixels yourself using XAllocColor()
840 or the like. The array passed in is used directly without
841 being copied, so it should be heap data created with xmalloc().
842 It will be freed using xfree() when the image instance is
845 If this fails, signal an error. INSTANTIATOR is only used
846 in the error message.
848 #### This should be able to handle conversion into `pointer'.
849 Use the same code as for `xpm'. */
852 init_image_instance_from_x_image (Lisp_Image_Instance *ii,
856 unsigned long *pixels,
859 Lisp_Object instantiator)
861 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
867 if (!DEVICE_X_P (XDEVICE (device)))
868 signal_simple_error ("Not an X device", device);
870 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
871 d = XtWindow(DEVICE_XT_APP_SHELL (XDEVICE (device)));
873 if (!(dest_mask & IMAGE_COLOR_PIXMAP_MASK))
874 incompatible_image_types (instantiator, dest_mask,
875 IMAGE_COLOR_PIXMAP_MASK);
877 pixmap = XCreatePixmap (dpy, d, ximage->width,
878 ximage->height, ximage->depth);
880 signal_simple_error ("Unable to create pixmap", instantiator);
882 gc = XCreateGC (dpy, pixmap, 0, NULL);
885 XFreePixmap (dpy, pixmap);
886 signal_simple_error ("Unable to create GC", instantiator);
889 XPutImage (dpy, pixmap, gc, ximage, 0, 0, 0, 0,
890 ximage->width, ximage->height);
894 x_initialize_pixmap_image_instance (ii, slices, IMAGE_COLOR_PIXMAP);
896 IMAGE_INSTANCE_PIXMAP_FILENAME (ii) =
897 find_keyword_in_vector (instantiator, Q_file);
899 /* Fixup a set of pixmaps. */
900 IMAGE_INSTANCE_X_PIXMAP (ii) = pixmap;
902 IMAGE_INSTANCE_PIXMAP_MASK (ii) = 0;
903 IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = ximage->width;
904 IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = ximage->height;
905 IMAGE_INSTANCE_PIXMAP_DEPTH (ii) = ximage->depth;
906 IMAGE_INSTANCE_X_COLORMAP (ii) = cmap;
907 IMAGE_INSTANCE_X_PIXELS (ii) = pixels;
908 IMAGE_INSTANCE_X_NPIXELS (ii) = npixels;
912 image_instance_add_x_image (Lisp_Image_Instance *ii,
915 Lisp_Object instantiator)
917 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
923 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
924 d = XtWindow(DEVICE_XT_APP_SHELL (XDEVICE (device)));
926 pixmap = XCreatePixmap (dpy, d, ximage->width,
927 ximage->height, ximage->depth);
929 signal_simple_error ("Unable to create pixmap", instantiator);
931 gc = XCreateGC (dpy, pixmap, 0, NULL);
934 XFreePixmap (dpy, pixmap);
935 signal_simple_error ("Unable to create GC", instantiator);
938 XPutImage (dpy, pixmap, gc, ximage, 0, 0, 0, 0,
939 ximage->width, ximage->height);
943 IMAGE_INSTANCE_X_PIXMAP_SLICE (ii, slice) = pixmap;
947 x_init_image_instance_from_eimage (Lisp_Image_Instance *ii,
948 int width, int height,
950 unsigned char *eimage,
952 Lisp_Object instantiator,
955 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
956 Colormap cmap = DEVICE_X_COLORMAP (XDEVICE(device));
957 unsigned long *pixtbl = NULL;
962 for (slice = 0; slice < slices; slice++)
964 ximage = convert_EImage_to_XImage (device, width, height,
965 eimage + (width * height * 3 * slice),
969 if (pixtbl) xfree (pixtbl);
970 signal_image_error("EImage to XImage conversion failed", instantiator);
973 /* Now create the pixmap and set up the image instance */
975 init_image_instance_from_x_image (ii, ximage, dest_mask,
976 cmap, pixtbl, npixels, slices,
979 image_instance_add_x_image (ii, ximage, slice, instantiator);
985 xfree (ximage->data);
988 XDestroyImage (ximage);
994 int read_bitmap_data_from_file (const char *filename, unsigned int *width,
995 unsigned int *height, unsigned char **datap,
996 int *x_hot, int *y_hot)
998 return XmuReadBitmapDataFromFile (filename, width, height,
999 datap, x_hot, y_hot);
1002 /* Given inline data for a mono pixmap, create and return the
1003 corresponding X object. */
1006 pixmap_from_xbm_inline (Lisp_Object device, int width, int height,
1007 /* Note that data is in ext-format! */
1010 return XCreatePixmapFromBitmapData
1011 (DEVICE_X_DISPLAY (XDEVICE (device)),
1012 XtWindow (DEVICE_XT_APP_SHELL (XDEVICE (device))),
1013 (char *) bits, width, height,
1017 /* Given inline data for a mono pixmap, initialize the given
1018 image instance accordingly. */
1021 init_image_instance_from_xbm_inline (Lisp_Image_Instance *ii,
1022 int width, int height,
1023 /* Note that data is in ext-format! */
1025 Lisp_Object instantiator,
1026 Lisp_Object pointer_fg,
1027 Lisp_Object pointer_bg,
1030 Lisp_Object mask_filename)
1032 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
1033 Lisp_Object foreground = find_keyword_in_vector (instantiator, Q_foreground);
1034 Lisp_Object background = find_keyword_in_vector (instantiator, Q_background);
1038 enum image_instance_type type;
1040 if (!DEVICE_X_P (XDEVICE (device)))
1041 signal_simple_error ("Not an X device", device);
1043 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
1044 draw = XtWindow(DEVICE_XT_APP_SHELL (XDEVICE (device)));
1045 scr = DefaultScreenOfDisplay (dpy);
1047 if ((dest_mask & IMAGE_MONO_PIXMAP_MASK) &&
1048 (dest_mask & IMAGE_COLOR_PIXMAP_MASK))
1050 if (!NILP (foreground) || !NILP (background))
1051 type = IMAGE_COLOR_PIXMAP;
1053 type = IMAGE_MONO_PIXMAP;
1055 else if (dest_mask & IMAGE_MONO_PIXMAP_MASK)
1056 type = IMAGE_MONO_PIXMAP;
1057 else if (dest_mask & IMAGE_COLOR_PIXMAP_MASK)
1058 type = IMAGE_COLOR_PIXMAP;
1059 else if (dest_mask & IMAGE_POINTER_MASK)
1060 type = IMAGE_POINTER;
1062 incompatible_image_types (instantiator, dest_mask,
1063 IMAGE_MONO_PIXMAP_MASK | IMAGE_COLOR_PIXMAP_MASK
1064 | IMAGE_POINTER_MASK);
1066 x_initialize_pixmap_image_instance (ii, 1, type);
1067 IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = width;
1068 IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = height;
1069 IMAGE_INSTANCE_PIXMAP_FILENAME (ii) =
1070 find_keyword_in_vector (instantiator, Q_file);
1074 case IMAGE_MONO_PIXMAP:
1076 IMAGE_INSTANCE_X_PIXMAP (ii) =
1077 pixmap_from_xbm_inline (device, width, height, (Extbyte *) bits);
1081 case IMAGE_COLOR_PIXMAP:
1083 Dimension d = DEVICE_X_DEPTH (XDEVICE(device));
1084 unsigned long fg = BlackPixelOfScreen (scr);
1085 unsigned long bg = WhitePixelOfScreen (scr);
1087 if (!NILP (foreground) && !COLOR_INSTANCEP (foreground))
1089 Fmake_color_instance (foreground, device,
1090 encode_error_behavior_flag (ERROR_ME));
1092 if (COLOR_INSTANCEP (foreground))
1093 fg = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (foreground)).pixel;
1095 if (!NILP (background) && !COLOR_INSTANCEP (background))
1097 Fmake_color_instance (background, device,
1098 encode_error_behavior_flag (ERROR_ME));
1100 if (COLOR_INSTANCEP (background))
1101 bg = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (background)).pixel;
1103 /* We used to duplicate the pixels using XAllocColor(), to protect
1104 against their getting freed. Just as easy to just store the
1105 color instances here and GC-protect them, so this doesn't
1107 IMAGE_INSTANCE_PIXMAP_FG (ii) = foreground;
1108 IMAGE_INSTANCE_PIXMAP_BG (ii) = background;
1109 IMAGE_INSTANCE_X_PIXMAP (ii) =
1110 XCreatePixmapFromBitmapData (dpy, draw,
1111 (char *) bits, width, height,
1113 IMAGE_INSTANCE_PIXMAP_DEPTH (ii) = d;
1119 XColor fg_color, bg_color;
1122 check_pointer_sizes (scr, width, height, instantiator);
1125 XCreatePixmapFromBitmapData (dpy, draw,
1126 (char *) bits, width, height,
1129 if (NILP (foreground))
1130 foreground = pointer_fg;
1131 if (NILP (background))
1132 background = pointer_bg;
1133 generate_cursor_fg_bg (device, &foreground, &background,
1134 &fg_color, &bg_color);
1136 IMAGE_INSTANCE_PIXMAP_FG (ii) = foreground;
1137 IMAGE_INSTANCE_PIXMAP_BG (ii) = background;
1138 IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii) =
1139 find_keyword_in_vector (instantiator, Q_hotspot_x);
1140 IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii) =
1141 find_keyword_in_vector (instantiator, Q_hotspot_y);
1142 IMAGE_INSTANCE_X_CURSOR (ii) =
1144 (dpy, source, mask, &fg_color, &bg_color,
1145 !NILP (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii)) ?
1146 XINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii)) : 0,
1147 !NILP (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii)) ?
1148 XINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii)) : 0);
1158 xbm_instantiate_1 (Lisp_Object image_instance, Lisp_Object instantiator,
1159 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1160 int dest_mask, int width, int height,
1161 /* Note that data is in ext-format! */
1164 Lisp_Object mask_data = find_keyword_in_vector (instantiator, Q_mask_data);
1165 Lisp_Object mask_file = find_keyword_in_vector (instantiator, Q_mask_file);
1166 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1169 if (!NILP (mask_data))
1171 const char *ext_data;
1173 LISP_STRING_TO_EXTERNAL (XCAR (XCDR (XCDR (mask_data))), ext_data, Qbinary);
1174 mask = pixmap_from_xbm_inline (IMAGE_INSTANCE_DEVICE (ii),
1175 XINT (XCAR (mask_data)),
1176 XINT (XCAR (XCDR (mask_data))),
1180 init_image_instance_from_xbm_inline (ii, width, height, bits,
1181 instantiator, pointer_fg, pointer_bg,
1182 dest_mask, mask, mask_file);
1185 /* Instantiate method for XBM's. */
1188 x_xbm_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1189 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1190 int dest_mask, Lisp_Object domain)
1192 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1193 const char *ext_data;
1195 assert (!NILP (data));
1197 LISP_STRING_TO_EXTERNAL (XCAR (XCDR (XCDR (data))), ext_data, Qbinary);
1199 xbm_instantiate_1 (image_instance, instantiator, pointer_fg,
1200 pointer_bg, dest_mask, XINT (XCAR (data)),
1201 XINT (XCAR (XCDR (data))), ext_data);
1207 /**********************************************************************
1209 **********************************************************************/
1210 /* xpm 3.2g and better has XpmCreatePixmapFromBuffer()...
1211 There was no version number in xpm.h before 3.3, but this should do.
1213 #if (XpmVersion >= 3) || defined(XpmExactColors)
1214 # define XPM_DOES_BUFFERS
1217 #ifndef XPM_DOES_BUFFERS
1218 Your version of XPM is too old. You cannot compile with it.
1219 Upgrade to version 3.2g or better or compile with --with-xpm=no.
1220 #endif /* !XPM_DOES_BUFFERS */
1222 static XpmColorSymbol *
1223 extract_xpm_color_names (XpmAttributes *xpmattrs, Lisp_Object device,
1225 Lisp_Object color_symbol_alist)
1227 /* This function can GC */
1228 Display *dpy = DEVICE_X_DISPLAY (XDEVICE(device));
1229 Colormap cmap = DEVICE_X_COLORMAP (XDEVICE(device));
1232 Lisp_Object results = Qnil;
1234 XpmColorSymbol *symbols;
1235 struct gcpro gcpro1, gcpro2;
1237 GCPRO2 (results, device);
1239 /* We built up results to be (("name" . #<color>) ...) so that if an
1240 error happens we don't lose any malloc()ed data, or more importantly,
1241 leave any pixels allocated in the server. */
1243 LIST_LOOP (rest, color_symbol_alist)
1245 Lisp_Object cons = XCAR (rest);
1246 Lisp_Object name = XCAR (cons);
1247 Lisp_Object value = XCDR (cons);
1250 if (STRINGP (value))
1252 Fmake_color_instance
1253 (value, device, encode_error_behavior_flag (ERROR_ME_NOT));
1256 assert (COLOR_SPECIFIERP (value));
1257 value = Fspecifier_instance (value, domain, Qnil, Qnil);
1261 results = noseeum_cons (noseeum_cons (name, value), results);
1264 UNGCPRO; /* no more evaluation */
1266 if (i == 0) return 0;
1268 symbols = xnew_array (XpmColorSymbol, i);
1269 xpmattrs->valuemask |= XpmColorSymbols;
1270 xpmattrs->colorsymbols = symbols;
1271 xpmattrs->numsymbols = i;
1275 Lisp_Object cons = XCAR (results);
1276 color = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (XCDR (cons)));
1277 /* Duplicate the pixel value so that we still have a lock on it if
1278 the pixel we were passed is later freed. */
1279 if (! XAllocColor (dpy, cmap, &color))
1280 ABORT (); /* it must be allocable since we're just duplicating it */
1282 symbols [i].name = (char *) XSTRING_DATA (XCAR (cons));
1283 symbols [i].pixel = color.pixel;
1284 symbols [i].value = 0;
1285 free_cons (XCONS (cons));
1287 results = XCDR (results);
1288 free_cons (XCONS (cons));
1294 xpm_free (XpmAttributes *xpmattrs)
1296 /* Could conceivably lose if XpmXXX returned an error without first
1297 initializing this structure, if we didn't know that initializing it
1298 to all zeros was ok (and also that it's ok to call XpmFreeAttributes()
1299 multiple times, since it zeros slots as it frees them...) */
1300 XpmFreeAttributes (xpmattrs);
1304 x_xpm_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1305 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1306 int dest_mask, Lisp_Object domain)
1308 /* This function can GC */
1309 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1310 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
1311 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1319 XpmAttributes xpmattrs;
1321 XpmColorSymbol *color_symbols;
1322 Lisp_Object color_symbol_alist = find_keyword_in_vector (instantiator,
1324 enum image_instance_type type;
1328 if (!DEVICE_X_P (XDEVICE (device)))
1329 signal_simple_error ("Not an X device", device);
1331 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
1332 xs = DefaultScreenOfDisplay (dpy);
1334 if (dest_mask & IMAGE_COLOR_PIXMAP_MASK)
1335 type = IMAGE_COLOR_PIXMAP;
1336 else if (dest_mask & IMAGE_MONO_PIXMAP_MASK)
1337 type = IMAGE_MONO_PIXMAP;
1338 else if (dest_mask & IMAGE_POINTER_MASK)
1339 type = IMAGE_POINTER;
1341 incompatible_image_types (instantiator, dest_mask,
1342 IMAGE_MONO_PIXMAP_MASK | IMAGE_COLOR_PIXMAP_MASK
1343 | IMAGE_POINTER_MASK);
1344 force_mono = (type != IMAGE_COLOR_PIXMAP);
1347 /* Although I haven't found it documented yet, it appears that pointers are
1348 always colored via the default window colormap... Sigh. */
1349 if (type == IMAGE_POINTER)
1351 cmap = DefaultColormap(dpy, DefaultScreen(dpy));
1352 depth = DefaultDepthOfScreen (xs);
1353 visual = DefaultVisualOfScreen (xs);
1357 cmap = DEVICE_X_COLORMAP (XDEVICE(device));
1358 depth = DEVICE_X_DEPTH (XDEVICE(device));
1359 visual = DEVICE_X_VISUAL (XDEVICE(device));
1362 cmap = DEVICE_X_COLORMAP (XDEVICE(device));
1363 depth = DEVICE_X_DEPTH (XDEVICE(device));
1364 visual = DEVICE_X_VISUAL (XDEVICE(device));
1367 x_initialize_pixmap_image_instance (ii, 1, type);
1369 assert (!NILP (data));
1373 xzero (xpmattrs); /* want XpmInitAttributes() */
1374 xpmattrs.valuemask = XpmReturnPixels;
1377 /* Without this, we get a 1-bit version of the color image, which
1378 isn't quite right. With this, we get the mono image, which might
1379 be very different looking. */
1380 xpmattrs.valuemask |= XpmColorKey;
1381 xpmattrs.color_key = XPM_MONO;
1383 xpmattrs.valuemask |= XpmDepth;
1387 xpmattrs.closeness = 65535;
1388 xpmattrs.valuemask |= XpmCloseness;
1389 xpmattrs.depth = depth;
1390 xpmattrs.valuemask |= XpmDepth;
1391 xpmattrs.visual = visual;
1392 xpmattrs.valuemask |= XpmVisual;
1393 xpmattrs.colormap = cmap;
1394 xpmattrs.valuemask |= XpmColormap;
1397 color_symbols = extract_xpm_color_names (&xpmattrs, device, domain,
1398 color_symbol_alist);
1400 result = XpmCreatePixmapFromBuffer (dpy,
1401 XtWindow(DEVICE_XT_APP_SHELL (XDEVICE(device))),
1402 (char *) XSTRING_DATA (data),
1403 &pixmap, &mask, &xpmattrs);
1407 xfree (color_symbols);
1408 xpmattrs.colorsymbols = 0; /* in case XpmFreeAttr is too smart... */
1409 xpmattrs.numsymbols = 0;
1416 case XpmFileInvalid:
1418 xpm_free (&xpmattrs);
1419 signal_image_error ("invalid XPM data", data);
1421 case XpmColorFailed:
1424 xpm_free (&xpmattrs);
1427 /* second time; blow out. */
1428 signal_double_file_error ("Reading pixmap data",
1429 "color allocation failed",
1434 if (! (dest_mask & IMAGE_MONO_PIXMAP_MASK))
1436 /* second time; blow out. */
1437 signal_double_file_error ("Reading pixmap data",
1438 "color allocation failed",
1442 IMAGE_INSTANCE_TYPE (ii) = IMAGE_MONO_PIXMAP;
1448 xpm_free (&xpmattrs);
1449 signal_double_file_error ("Parsing pixmap data",
1450 "out of memory", data);
1454 xpm_free (&xpmattrs);
1455 signal_double_file_error_2 ("Parsing pixmap data",
1456 "unknown error code",
1457 make_int (result), data);
1462 h = xpmattrs.height;
1465 int npixels = xpmattrs.npixels;
1470 pixels = xnew_array (Pixel, npixels);
1471 memcpy (pixels, xpmattrs.pixels, npixels * sizeof (Pixel));
1476 IMAGE_INSTANCE_X_PIXMAP (ii) = pixmap;
1477 IMAGE_INSTANCE_PIXMAP_MASK (ii) = (void*)mask;
1478 IMAGE_INSTANCE_X_COLORMAP (ii) = cmap;
1479 IMAGE_INSTANCE_X_PIXELS (ii) = pixels;
1480 IMAGE_INSTANCE_X_NPIXELS (ii) = npixels;
1481 IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = w;
1482 IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = h;
1483 IMAGE_INSTANCE_PIXMAP_FILENAME (ii) =
1484 find_keyword_in_vector (instantiator, Q_file);
1489 case IMAGE_MONO_PIXMAP:
1492 case IMAGE_COLOR_PIXMAP:
1494 IMAGE_INSTANCE_PIXMAP_DEPTH (ii) = depth;
1500 int npixels = xpmattrs.npixels;
1501 Pixel *pixels = xpmattrs.pixels;
1504 int xhot = 0, yhot = 0;
1506 if (xpmattrs.valuemask & XpmHotspot)
1508 xhot = xpmattrs.x_hotspot;
1509 XSETINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii), xpmattrs.x_hotspot);
1511 if (xpmattrs.valuemask & XpmHotspot)
1513 yhot = xpmattrs.y_hotspot;
1514 XSETINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii), xpmattrs.y_hotspot);
1516 check_pointer_sizes (xs, w, h, instantiator);
1518 /* If the loaded pixmap has colors allocated (meaning it came from an
1519 XPM file), then use those as the default colors for the cursor we
1520 create. Otherwise, default to pointer_fg and pointer_bg.
1524 /* With an XBM file, it's obvious which bit is foreground
1525 and which is background, or rather, it's implicit: in
1526 an XBM file, a 1 bit is foreground, and a 0 bit is
1529 XCreatePixmapCursor() assumes this property of the
1530 pixmap it is called with as well; the `foreground'
1531 color argument is used for the 1 bits.
1533 With an XPM file, it's tricker, since the elements of
1534 the pixmap don't represent FG and BG, but are actual
1535 pixel values. So we need to figure out which of those
1536 pixels is the foreground color and which is the
1537 background. We do it by comparing RGB and assuming
1538 that the darker color is the foreground. This works
1539 with the result of xbmtopbm|ppmtoxpm, at least.
1541 It might be nice if there was some way to tag the
1542 colors in the XPM file with whether they are the
1543 foreground - perhaps with logical color names somehow?
1545 Once we have decided which color is the foreground, we
1546 need to ensure that that color corresponds to a `1' bit
1547 in the Pixmap. The XPM library wrote into the (1-bit)
1548 pixmap with XPutPixel, which will ignore all but the
1549 least significant bit.
1551 This means that a 1 bit in the image corresponds to
1552 `fg' only if `fg.pixel' is odd.
1554 (This also means that the image will be all the same
1555 color if both `fg' and `bg' are odd or even, but we can
1556 safely assume that that won't happen if the XPM file is
1559 The desired result is that the image use `1' to
1560 represent the foreground color, and `0' to represent
1561 the background color. So, we may need to invert the
1562 image to accomplish this; we invert if fg is
1563 odd. (Remember that WhitePixel and BlackPixel are not
1564 necessarily 1 and 0 respectively, though I think it
1565 might be safe to assume that one of them is always 1
1566 and the other is always 0. We also pretty much need to
1567 assume that one is even and the other is odd.)
1570 fg.pixel = pixels[0]; /* pick a pixel at random. */
1571 bg.pixel = fg.pixel;
1572 for (i = 1; i < npixels; i++) /* Look for an "other" pixel value.*/
1574 bg.pixel = pixels[i];
1575 if (fg.pixel != bg.pixel)
1579 /* If (fg.pixel == bg.pixel) then probably something has
1580 gone wrong, but I don't think signalling an error would
1583 XQueryColor (dpy, cmap, &fg);
1584 XQueryColor (dpy, cmap, &bg);
1586 /* If the foreground is lighter than the background, swap them.
1587 (This occurs semi-randomly, depending on the ordering of the
1588 color list in the XPM file.)
1591 unsigned short fg_total = ((fg.red / 3) + (fg.green / 3)
1593 unsigned short bg_total = ((bg.red / 3) + (bg.green / 3)
1595 if (fg_total > bg_total)
1604 /* If the fg pixel corresponds to a `0' in the bitmap, invert it.
1605 (This occurs (only?) on servers with Black=0, White=1.)
1607 if ((fg.pixel & 1) == 0)
1611 gcv.function = GXxor;
1613 gc = XCreateGC (dpy, pixmap, (GCFunction | GCForeground),
1615 XFillRectangle (dpy, pixmap, gc, 0, 0, w, h);
1621 generate_cursor_fg_bg (device, &pointer_fg, &pointer_bg,
1623 IMAGE_INSTANCE_PIXMAP_FG (ii) = pointer_fg;
1624 IMAGE_INSTANCE_PIXMAP_BG (ii) = pointer_bg;
1627 IMAGE_INSTANCE_X_CURSOR (ii) =
1629 (dpy, pixmap, mask, &fg, &bg, xhot, yhot);
1638 xpm_free (&xpmattrs); /* after we've read pixels and hotspot */
1641 #endif /* HAVE_XPM */
1646 /**********************************************************************
1648 **********************************************************************/
1650 /* This is about to get redefined! */
1653 /* We have to define SYSV32 so that compface.h includes string.h
1654 instead of strings.h. */
1659 #include <compface.h>
1663 /* JMP_BUF cannot be used here because if it doesn't get defined
1664 to jmp_buf we end up with a conflicting type error with the
1665 definition in compface.h */
1666 extern jmp_buf comp_env;
1670 x_xface_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1671 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1672 int dest_mask, Lisp_Object domain)
1674 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1678 const char * volatile emsg = 0;
1679 const char * volatile dstring;
1681 assert (!NILP (data));
1683 LISP_STRING_TO_EXTERNAL (data, dstring, Qbinary);
1685 if ((p = strchr (dstring, ':')))
1690 /* Must use setjmp not SETJMP because we used jmp_buf above not JMP_BUF */
1691 if (!(stattis = setjmp (comp_env)))
1693 UnCompAll ((char *) dstring);
1700 emsg = "uncompface: internal error";
1703 emsg = "uncompface: insufficient or invalid data";
1706 emsg = "uncompface: excess data ignored";
1711 signal_simple_error_2 (emsg, data, Qimage);
1713 bp = bits = (char *) alloca (PIXELS / 8);
1715 /* the compface library exports char F[], which uses a single byte per
1716 pixel to represent a 48x48 bitmap. Yuck. */
1717 for (i = 0, p = F; i < (PIXELS / 8); ++i)
1720 /* reverse the bit order of each byte... */
1721 for (b = n = 0; b < 8; ++b)
1728 xbm_instantiate_1 (image_instance, instantiator, pointer_fg,
1729 pointer_bg, dest_mask, 48, 48, bits);
1732 #endif /* HAVE_XFACE */
1735 /**********************************************************************
1737 **********************************************************************/
1740 autodetect_validate (Lisp_Object instantiator)
1742 data_must_be_present (instantiator);
1746 autodetect_normalize (Lisp_Object instantiator,
1747 Lisp_Object console_type,
1748 Lisp_Object dest_mask)
1750 Lisp_Object file = find_keyword_in_vector (instantiator, Q_data);
1751 Lisp_Object filename = Qnil;
1752 Lisp_Object data = Qnil;
1753 struct gcpro gcpro1, gcpro2, gcpro3;
1754 Lisp_Object alist = Qnil;
1756 GCPRO3 (filename, data, alist);
1758 if (NILP (file)) /* no conversion necessary */
1759 RETURN_UNGCPRO (instantiator);
1761 alist = tagged_vector_to_alist (instantiator);
1763 filename = locate_pixmap_file (file);
1764 if (!NILP (filename))
1767 /* #### Apparently some versions of XpmReadFileToData, which is
1768 called by pixmap_to_lisp_data, don't return an error value
1769 if the given file is not a valid XPM file. Instead, they
1770 just seg fault. It is definitely caused by passing a
1771 bitmap. To try and avoid this we check for bitmaps first. */
1773 data = bitmap_to_lisp_data (filename, &xhot, &yhot, 1);
1777 alist = remassq_no_quit (Q_data, alist);
1778 alist = Fcons (Fcons (Q_file, filename),
1779 Fcons (Fcons (Q_data, data), alist));
1781 alist = Fcons (Fcons (Q_hotspot_x, make_int (xhot)),
1784 alist = Fcons (Fcons (Q_hotspot_y, make_int (yhot)),
1787 alist = xbm_mask_file_munging (alist, filename, Qnil, console_type);
1790 Lisp_Object result = alist_to_tagged_vector (Qxbm, alist);
1792 RETURN_UNGCPRO (result);
1797 data = pixmap_to_lisp_data (filename, 1);
1801 alist = remassq_no_quit (Q_data, alist);
1802 alist = Fcons (Fcons (Q_file, filename),
1803 Fcons (Fcons (Q_data, data), alist));
1804 alist = Fcons (Fcons (Q_color_symbols,
1805 evaluate_xpm_color_symbols ()),
1808 Lisp_Object result = alist_to_tagged_vector (Qxpm, alist);
1810 RETURN_UNGCPRO (result);
1816 /* If we couldn't convert it, just put it back as it is.
1817 We might try to further frob it later as a cursor-font
1818 specification. (We can't do that now because we don't know
1819 what dest-types it's going to be instantiated into.) */
1821 Lisp_Object result = alist_to_tagged_vector (Qautodetect, alist);
1823 RETURN_UNGCPRO (result);
1828 autodetect_possible_dest_types (void)
1831 IMAGE_MONO_PIXMAP_MASK |
1832 IMAGE_COLOR_PIXMAP_MASK |
1833 IMAGE_POINTER_MASK |
1838 autodetect_instantiate (Lisp_Object image_instance,
1839 Lisp_Object instantiator,
1840 Lisp_Object pointer_fg,
1841 Lisp_Object pointer_bg,
1842 int dest_mask, Lisp_Object domain)
1844 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1845 struct gcpro gcpro1, gcpro2, gcpro3;
1846 Lisp_Object alist = Qnil;
1847 Lisp_Object result = Qnil;
1848 int is_cursor_font = 0;
1850 GCPRO3 (data, alist, result);
1852 alist = tagged_vector_to_alist (instantiator);
1853 if (dest_mask & IMAGE_POINTER_MASK)
1855 const char *name_ext;
1856 LISP_STRING_TO_EXTERNAL (data, name_ext, Qfile_name);
1857 if (XmuCursorNameToIndex (name_ext) != -1)
1859 result = alist_to_tagged_vector (Qcursor_font, alist);
1864 if (!is_cursor_font)
1865 result = alist_to_tagged_vector (Qstring, alist);
1869 cursor_font_instantiate (image_instance, result, pointer_fg,
1870 pointer_bg, dest_mask, domain);
1872 string_instantiate (image_instance, result, pointer_fg,
1873 pointer_bg, dest_mask, domain);
1879 /**********************************************************************
1881 **********************************************************************/
1884 font_validate (Lisp_Object instantiator)
1886 data_must_be_present (instantiator);
1889 /* XmuCvtStringToCursor is bogus in the following ways:
1891 - When it can't convert the given string to a real cursor, it will
1892 sometimes return a "success" value, after triggering a BadPixmap
1893 error. It then gives you a cursor that will itself generate BadCursor
1894 errors. So we install this error handler to catch/notice the X error
1895 and take that as meaning "couldn't convert."
1897 - When you tell it to find a cursor file that doesn't exist, it prints
1898 an error message on stderr. You can't make it not do that.
1900 - Also, using Xmu means we can't properly hack Lisp_Image_Instance
1901 objects, or XPM files, or $XBMLANGPATH.
1904 /* Duplicate the behavior of XmuCvtStringToCursor() to bypass its bogusness. */
1906 static int XLoadFont_got_error;
1909 XLoadFont_error_handler (Display *dpy, XErrorEvent *xerror)
1911 XLoadFont_got_error = 1;
1916 safe_XLoadFont (Display *dpy, char *name)
1919 int (*old_handler) (Display *, XErrorEvent *);
1920 XLoadFont_got_error = 0;
1922 old_handler = XSetErrorHandler (XLoadFont_error_handler);
1923 font = XLoadFont (dpy, name);
1925 XSetErrorHandler (old_handler);
1926 if (XLoadFont_got_error) return 0;
1931 font_possible_dest_types (void)
1933 return IMAGE_POINTER_MASK;
1937 font_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1938 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1939 int dest_mask, Lisp_Object domain)
1941 /* This function can GC */
1942 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1943 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1944 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
1948 char source_name[MAXPATHLEN], mask_name[MAXPATHLEN], dummy;
1949 int source_char, mask_char;
1951 Lisp_Object foreground, background;
1953 if (!DEVICE_X_P (XDEVICE (device)))
1954 signal_simple_error ("Not an X device", device);
1956 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
1958 if (!STRINGP (data) ||
1959 strncmp ("FONT ", (char *) XSTRING_DATA (data), 5))
1960 signal_simple_error ("Invalid font-glyph instantiator",
1963 if (!(dest_mask & IMAGE_POINTER_MASK))
1964 incompatible_image_types (instantiator, dest_mask, IMAGE_POINTER_MASK);
1966 foreground = find_keyword_in_vector (instantiator, Q_foreground);
1967 if (NILP (foreground))
1968 foreground = pointer_fg;
1969 background = find_keyword_in_vector (instantiator, Q_background);
1970 if (NILP (background))
1971 background = pointer_bg;
1973 generate_cursor_fg_bg (device, &foreground, &background, &fg, &bg);
1975 count = sscanf ((char *) XSTRING_DATA (data),
1976 "FONT %s %d %s %d %c",
1977 source_name, &source_char,
1978 mask_name, &mask_char, &dummy);
1979 /* Allow "%s %d %d" as well... */
1980 if (count == 3 && (1 == sscanf (mask_name, "%d %c", &mask_char, &dummy)))
1981 count = 4, mask_name[0] = 0;
1983 if (count != 2 && count != 4)
1984 signal_simple_error ("invalid cursor specification", data);
1985 source = safe_XLoadFont (dpy, source_name);
1987 signal_simple_error_2 ("couldn't load font",
1988 build_string (source_name),
1992 else if (!mask_name[0])
1996 mask = safe_XLoadFont (dpy, mask_name);
1999 Fsignal (Qerror, list3 (build_string ("couldn't load font"),
2000 build_string (mask_name), data));
2005 /* #### call XQueryTextExtents() and check_pointer_sizes() here. */
2007 x_initialize_pixmap_image_instance (ii, 1, IMAGE_POINTER);
2008 IMAGE_INSTANCE_X_CURSOR (ii) =
2009 XCreateGlyphCursor (dpy, source, mask, source_char, mask_char,
2011 XIMAGE_INSTANCE_PIXMAP_FG (image_instance) = foreground;
2012 XIMAGE_INSTANCE_PIXMAP_BG (image_instance) = background;
2013 XUnloadFont (dpy, source);
2014 if (mask && mask != source) XUnloadFont (dpy, mask);
2018 /**********************************************************************
2020 **********************************************************************/
2023 cursor_font_validate (Lisp_Object instantiator)
2025 data_must_be_present (instantiator);
2029 cursor_font_possible_dest_types (void)
2031 return IMAGE_POINTER_MASK;
2035 cursor_font_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2036 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2037 int dest_mask, Lisp_Object domain)
2039 /* This function can GC */
2040 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
2041 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2042 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
2045 const char *name_ext;
2046 Lisp_Object foreground, background;
2048 if (!DEVICE_X_P (XDEVICE (device)))
2049 signal_simple_error ("Not an X device", device);
2051 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
2053 if (!(dest_mask & IMAGE_POINTER_MASK))
2054 incompatible_image_types (instantiator, dest_mask, IMAGE_POINTER_MASK);
2056 LISP_STRING_TO_EXTERNAL (data, name_ext, Qfile_name);
2057 if ((i = XmuCursorNameToIndex (name_ext)) == -1)
2058 signal_simple_error ("Unrecognized cursor-font name", data);
2060 x_initialize_pixmap_image_instance (ii, 1, IMAGE_POINTER);
2061 IMAGE_INSTANCE_X_CURSOR (ii) = XCreateFontCursor (dpy, i);
2062 foreground = find_keyword_in_vector (instantiator, Q_foreground);
2063 if (NILP (foreground))
2064 foreground = pointer_fg;
2065 background = find_keyword_in_vector (instantiator, Q_background);
2066 if (NILP (background))
2067 background = pointer_bg;
2068 maybe_recolor_cursor (image_instance, foreground, background);
2072 x_colorize_image_instance (Lisp_Object image_instance,
2073 Lisp_Object foreground, Lisp_Object background)
2075 Lisp_Image_Instance *p;
2077 p = XIMAGE_INSTANCE (image_instance);
2079 switch (IMAGE_INSTANCE_TYPE (p))
2081 case IMAGE_MONO_PIXMAP:
2082 IMAGE_INSTANCE_TYPE (p) = IMAGE_COLOR_PIXMAP;
2083 /* Make sure there aren't two pointers to the same mask, causing
2084 it to get freed twice. */
2085 IMAGE_INSTANCE_PIXMAP_MASK (p) = 0;
2093 Display *dpy = DEVICE_X_DISPLAY (XDEVICE (IMAGE_INSTANCE_DEVICE (p)));
2094 Drawable draw = XtWindow(DEVICE_XT_APP_SHELL (XDEVICE (IMAGE_INSTANCE_DEVICE (p))));
2095 Dimension d = DEVICE_X_DEPTH (XDEVICE (IMAGE_INSTANCE_DEVICE (p)));
2096 Pixmap new = XCreatePixmap (dpy, draw,
2097 IMAGE_INSTANCE_PIXMAP_WIDTH (p),
2098 IMAGE_INSTANCE_PIXMAP_HEIGHT (p), d);
2102 color = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (foreground));
2103 gcv.foreground = color.pixel;
2104 color = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (background));
2105 gcv.background = color.pixel;
2106 gc = XCreateGC (dpy, new, GCBackground|GCForeground, &gcv);
2107 XCopyPlane (dpy, IMAGE_INSTANCE_X_PIXMAP (p), new, gc, 0, 0,
2108 IMAGE_INSTANCE_PIXMAP_WIDTH (p),
2109 IMAGE_INSTANCE_PIXMAP_HEIGHT (p),
2112 IMAGE_INSTANCE_X_PIXMAP (p) = new;
2113 IMAGE_INSTANCE_PIXMAP_DEPTH (p) = d;
2114 IMAGE_INSTANCE_PIXMAP_FG (p) = foreground;
2115 IMAGE_INSTANCE_PIXMAP_BG (p) = background;
2121 /************************************************************************/
2122 /* subwindow and widget support */
2123 /************************************************************************/
2125 /* unmap the image if it is a widget. This is used by redisplay via
2126 redisplay_unmap_subwindows */
2128 x_unmap_subwindow (Lisp_Image_Instance *p)
2130 if (IMAGE_INSTANCE_TYPE (p) == IMAGE_SUBWINDOW)
2133 (IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY (p),
2134 IMAGE_INSTANCE_X_CLIPWINDOW (p));
2136 else /* must be a widget */
2138 /* Since we are being unmapped we want the enclosing frame to
2139 get focus. The losing with simple scrolling but is the safest
2141 emacs_Xt_handle_widget_losing_focus
2142 ( XFRAME (IMAGE_INSTANCE_FRAME (p)),
2143 IMAGE_INSTANCE_X_WIDGET_ID (p));
2144 XtUnmapWidget (IMAGE_INSTANCE_X_CLIPWIDGET (p));
2148 /* map the subwindow. This is used by redisplay via
2149 redisplay_output_subwindow */
2151 x_map_subwindow (Lisp_Image_Instance *p, int x, int y,
2152 struct display_glyph_area* dga)
2154 assert (dga->width > 0 && dga->height > 0);
2155 if (IMAGE_INSTANCE_TYPE (p) == IMAGE_SUBWINDOW)
2157 Window subwindow = IMAGE_INSTANCE_X_SUBWINDOW_ID (p);
2158 XMoveResizeWindow (IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY (p),
2159 IMAGE_INSTANCE_X_CLIPWINDOW (p),
2160 x, y, dga->width, dga->height);
2161 XMoveWindow (IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY (p),
2162 subwindow, -dga->xoffset, -dga->yoffset);
2163 if (!IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (p))
2164 XMapWindow (IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY (p),
2165 IMAGE_INSTANCE_X_CLIPWINDOW (p));
2167 else /* must be a widget */
2169 XtConfigureWidget (IMAGE_INSTANCE_X_CLIPWIDGET (p),
2170 x + IMAGE_INSTANCE_X_WIDGET_XOFFSET (p),
2171 y + IMAGE_INSTANCE_X_WIDGET_YOFFSET (p),
2172 dga->width, dga->height, 0);
2173 XtMoveWidget (IMAGE_INSTANCE_X_WIDGET_ID (p),
2174 -dga->xoffset, -dga->yoffset);
2175 if (!IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (p))
2176 XtMapWidget (IMAGE_INSTANCE_X_CLIPWIDGET (p));
2177 /* See comments in glyphs-msw.c about keyboard focus. */
2178 if (IMAGE_INSTANCE_WANTS_INITIAL_FOCUS (p)) {
2179 /* #### FIXME to pop-up the find dialog we map the text-field
2180 seven times! This doesn't show on a fast linux box but does
2181 under X on windows. */
2182 enqueue_focus_event (IMAGE_INSTANCE_X_WIDGET_ID (p),
2183 IMAGE_INSTANCE_FRAME (p), 1);
2188 /* when you click on a widget you may activate another widget this
2189 needs to be checked and all appropriate widgets updated */
2191 x_redisplay_subwindow (Lisp_Image_Instance *p)
2193 /* Update the subwindow size if necessary. */
2194 if (IMAGE_INSTANCE_SIZE_CHANGED (p))
2196 XResizeWindow (IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY (p),
2197 IMAGE_INSTANCE_X_SUBWINDOW_ID (p),
2198 IMAGE_INSTANCE_WIDTH (p),
2199 IMAGE_INSTANCE_HEIGHT (p));
2203 /* Update all attributes that have changed. Lwlib actually does most
2206 x_redisplay_widget (Lisp_Image_Instance *p)
2208 /* This function can GC if IN_REDISPLAY is false. */
2210 widget_value* wv = 0;
2212 /* First get the items if they have changed since this is a
2213 structural change. As such it will nuke all added values so we
2214 need to update most other things after the items have changed.*/
2215 if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (p))
2217 Lisp_Object image_instance;
2219 XSETIMAGE_INSTANCE (image_instance, p);
2220 wv = gui_items_to_widget_values
2221 (image_instance, IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (p),
2222 /* #### this is not right; we need to keep track of which widgets
2223 want accelerators and which don't */ 0);
2224 wv->change = STRUCTURAL_CHANGE;
2228 /* Assume the lotus position, breath deeply and chant to
2229 yourself lwlibsux, lwlibsux ... lw_get_all_values returns a
2230 reference to the real values rather than a copy thus any
2231 changes we make to the values we get back will look like they
2232 have already been applied. If we rebuild the widget tree then
2233 we may lose properties. */
2234 wv = copy_widget_value_tree (lw_get_all_values
2235 (IMAGE_INSTANCE_X_WIDGET_LWID (p)),
2239 /* Possibly update the colors and font */
2240 if (IMAGE_INSTANCE_WIDGET_FACE_CHANGED (p)
2242 /* #### This is not sufficient because it will not cope with widgets
2243 that are not currently visible. Once redisplay has done the
2244 visible ones it will clear this flag so that when new ones
2245 become visible they will not be updated. */
2246 XFRAME (IMAGE_INSTANCE_FRAME (p))->faces_changed
2248 XFRAME (IMAGE_INSTANCE_FRAME (p))->frame_changed
2250 IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (p))
2252 update_widget_face (wv, p, IMAGE_INSTANCE_FRAME (p));
2255 /* Possibly update the text. */
2256 if (IMAGE_INSTANCE_TEXT_CHANGED (p))
2259 Lisp_Object val = IMAGE_INSTANCE_WIDGET_TEXT (p);
2260 LISP_STRING_TO_EXTERNAL (val, str, Qnative);
2264 /* Possibly update the size. */
2265 if (IMAGE_INSTANCE_SIZE_CHANGED (p)
2267 IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (p)
2269 IMAGE_INSTANCE_TEXT_CHANGED (p))
2271 assert (IMAGE_INSTANCE_X_WIDGET_ID (p) &&
2272 IMAGE_INSTANCE_X_CLIPWIDGET (p)) ;
2274 if (IMAGE_INSTANCE_X_WIDGET_ID (p)->core.being_destroyed
2275 || !XtIsManaged(IMAGE_INSTANCE_X_WIDGET_ID (p)))
2278 XSETIMAGE_INSTANCE (sw, p);
2279 signal_simple_error ("XEmacs bug: subwindow is deleted", sw);
2282 lw_add_widget_value_arg (wv, XtNwidth,
2283 (Dimension)IMAGE_INSTANCE_WIDTH (p));
2284 lw_add_widget_value_arg (wv, XtNheight,
2285 (Dimension)IMAGE_INSTANCE_HEIGHT (p));
2288 /* Adjust offsets within the frame. */
2289 if (XFRAME (IMAGE_INSTANCE_FRAME (p))->size_changed)
2292 XtSetArg (al [0], XtNx, &IMAGE_INSTANCE_X_WIDGET_XOFFSET (p));
2293 XtSetArg (al [1], XtNy, &IMAGE_INSTANCE_X_WIDGET_YOFFSET (p));
2294 XtGetValues (FRAME_X_TEXT_WIDGET
2295 (XFRAME (IMAGE_INSTANCE_FRAME (p))), al, 2);
2298 /* now modify the widget */
2299 lw_modify_all_widgets (IMAGE_INSTANCE_X_WIDGET_LWID (p),
2301 free_widget_value_tree (wv);
2305 /* instantiate and x type subwindow */
2307 x_subwindow_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2308 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2309 int dest_mask, Lisp_Object domain)
2311 /* This function can GC */
2312 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2313 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
2314 Lisp_Object frame = DOMAIN_FRAME (domain);
2315 struct frame* f = XFRAME (frame);
2319 XSetWindowAttributes xswa;
2321 unsigned int w = IMAGE_INSTANCE_WIDTH (ii),
2322 h = IMAGE_INSTANCE_HEIGHT (ii);
2324 if (!DEVICE_X_P (XDEVICE (device)))
2325 signal_simple_error ("Not an X device", device);
2327 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
2328 xs = DefaultScreenOfDisplay (dpy);
2330 IMAGE_INSTANCE_TYPE (ii) = IMAGE_SUBWINDOW;
2332 pw = XtWindow (FRAME_X_TEXT_WIDGET (f));
2334 ii->data = xnew_and_zero (struct x_subwindow_data);
2336 IMAGE_INSTANCE_X_SUBWINDOW_PARENT (ii) = pw;
2337 IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY (ii) = DisplayOfScreen (xs);
2339 xswa.backing_store = Always;
2340 valueMask |= CWBackingStore;
2341 xswa.colormap = DefaultColormapOfScreen (xs);
2342 valueMask |= CWColormap;
2344 /* Create a window for clipping */
2345 IMAGE_INSTANCE_X_CLIPWINDOW (ii) =
2346 XCreateWindow (dpy, pw, 0, 0, w, h, 0, CopyFromParent,
2347 InputOutput, CopyFromParent, valueMask,
2350 /* Now put the subwindow inside the clip window. */
2351 win = XCreateWindow (dpy, IMAGE_INSTANCE_X_CLIPWINDOW (ii),
2352 0, 0, w, h, 0, CopyFromParent,
2353 InputOutput, CopyFromParent, valueMask,
2356 IMAGE_INSTANCE_SUBWINDOW_ID (ii) = (void*)win;
2359 /* Account for some of the limitations with widget images. */
2361 x_widget_border_width (void)
2363 return DEFAULT_WIDGET_BORDER_WIDTH * 2;
2368 /* #### Should this function exist? If there's any doubt I'm not implementing it --andyp */
2369 DEFUN ("change-subwindow-property", Fchange_subwindow_property, 3, 3, 0, /*
2370 For the given SUBWINDOW, set PROPERTY to DATA, which is a string.
2371 Subwindows are not currently implemented.
2373 (subwindow, property, data))
2379 CHECK_SUBWINDOW (subwindow);
2380 CHECK_STRING (property);
2381 CHECK_STRING (data);
2383 sw = XSUBWINDOW (subwindow);
2384 dpy = DisplayOfScreen (LISP_DEVICE_TO_X_SCREEN
2385 (FRAME_DEVICE (XFRAME (sw->frame))));
2387 property_atom = XInternAtom (dpy, (char *) XSTRING_DATA (property), False);
2388 XChangeProperty (dpy, sw->subwindow, property_atom, XA_STRING, 8,
2390 XSTRING_DATA (data),
2391 XSTRING_LENGTH (data));
2400 /************************************************************************/
2402 /************************************************************************/
2405 update_widget_face (widget_value* wv, Lisp_Image_Instance *ii,
2408 #ifdef LWLIB_WIDGETS_MOTIF
2409 XmFontList fontList;
2411 /* Update the foreground. */
2412 Lisp_Object pixel = FACE_FOREGROUND
2413 (IMAGE_INSTANCE_WIDGET_FACE (ii),
2415 XColor fcolor = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (pixel)), bcolor;
2416 lw_add_widget_value_arg (wv, XtNforeground, fcolor.pixel);
2418 /* Update the background. */
2419 pixel = FACE_BACKGROUND (IMAGE_INSTANCE_WIDGET_FACE (ii),
2421 bcolor = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (pixel));
2422 lw_add_widget_value_arg (wv, XtNbackground, bcolor.pixel);
2424 #ifdef LWLIB_WIDGETS_MOTIF
2425 fontList = XmFontListCreate
2426 (FONT_INSTANCE_X_FONT
2427 (XFONT_INSTANCE (query_string_font
2428 (IMAGE_INSTANCE_WIDGET_TEXT (ii),
2429 IMAGE_INSTANCE_WIDGET_FACE (ii),
2430 domain))), XmSTRING_DEFAULT_CHARSET);
2431 lw_add_widget_value_arg (wv, XmNfontList, (XtArgVal)fontList);
2433 lw_add_widget_value_arg
2434 (wv, XtNfont, (XtArgVal)FONT_INSTANCE_X_FONT
2435 (XFONT_INSTANCE (query_string_font
2436 (IMAGE_INSTANCE_WIDGET_TEXT (ii),
2437 IMAGE_INSTANCE_WIDGET_FACE (ii),
2439 wv->change = VISIBLE_CHANGE;
2440 /* #### Megahack - but its just getting too complicated to do this
2441 in the right place. */
2442 if (EQ (IMAGE_INSTANCE_WIDGET_TYPE (ii), Qtab_control))
2443 update_tab_widget_face (wv, ii, domain);
2447 update_tab_widget_face (widget_value* wv, Lisp_Image_Instance *ii,
2452 widget_value* val = wv->contents, *cur;
2454 /* Give each child label the correct foreground color. */
2455 Lisp_Object pixel = FACE_FOREGROUND
2456 (IMAGE_INSTANCE_WIDGET_FACE (ii),
2458 XColor fcolor = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (pixel));
2459 lw_add_widget_value_arg (val, XtNtabForeground, fcolor.pixel);
2460 wv->change = VISIBLE_CHANGE;
2461 val->change = VISIBLE_CHANGE;
2463 for (cur = val->next; cur; cur = cur->next)
2465 cur->change = VISIBLE_CHANGE;
2468 lw_copy_widget_value_args (val, cur);
2475 x_widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2476 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2477 int dest_mask, Lisp_Object domain,
2478 const char* type, widget_value* wv)
2480 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2481 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii), pixel;
2482 struct device* d = XDEVICE (device);
2483 Lisp_Object frame = DOMAIN_FRAME (domain);
2484 struct frame* f = XFRAME (frame);
2489 int id = new_lwlib_id ();
2490 widget_value* clip_wv;
2491 XColor fcolor, bcolor;
2493 if (!DEVICE_X_P (d))
2494 signal_simple_error ("Not an X device", device);
2496 /* have to set the type this late in case there is no device
2497 instantiation for a widget. But we can go ahead and do it without
2498 checking because there is always a generic instantiator. */
2499 IMAGE_INSTANCE_TYPE (ii) = IMAGE_WIDGET;
2501 if (!NILP (IMAGE_INSTANCE_WIDGET_TEXT (ii)))
2502 LISP_STRING_TO_EXTERNAL (IMAGE_INSTANCE_WIDGET_TEXT (ii), nm, Qnative);
2504 ii->data = xnew_and_zero (struct x_subwindow_data);
2506 /* Create a clip window to contain the subwidget. Incredibly the
2507 XEmacs manager seems to be the most appropriate widget for
2508 this. Nothing else is simple enough and yet does what is
2510 clip_wv = xmalloc_widget_value ();
2512 lw_add_widget_value_arg (clip_wv, XtNresize, False);
2513 lw_add_widget_value_arg (clip_wv, XtNwidth,
2514 (Dimension)IMAGE_INSTANCE_WIDTH (ii));
2515 lw_add_widget_value_arg (clip_wv, XtNheight,
2516 (Dimension)IMAGE_INSTANCE_HEIGHT (ii));
2517 clip_wv->enabled = True;
2519 clip_wv->name = xstrdup ("clip-window");
2520 clip_wv->value = xstrdup ("clip-window");
2522 IMAGE_INSTANCE_X_CLIPWIDGET (ii)
2523 = lw_create_widget ("clip-window", "clip-window", new_lwlib_id (),
2524 clip_wv, FRAME_X_CONTAINER_WIDGET (f),
2527 free_widget_value_tree (clip_wv);
2529 /* create a sensible name. */
2530 if (wv->name == 0 || strcmp(wv->name, "") == 0)
2531 wv->name = xstrdup (type);
2533 /* copy any args we were given */
2535 lw_add_value_args_to_args (wv, al, &ac);
2537 /* Fixup the colors. We have to do this *before* the widget gets
2538 created so that Motif will fix up the shadow colors
2539 correctly. Once the widget is created Motif won't do this
2541 pixel = FACE_FOREGROUND
2542 (IMAGE_INSTANCE_WIDGET_FACE (ii),
2543 IMAGE_INSTANCE_FRAME (ii));
2544 fcolor = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (pixel));
2546 pixel = FACE_BACKGROUND
2547 (IMAGE_INSTANCE_WIDGET_FACE (ii),
2548 IMAGE_INSTANCE_FRAME (ii));
2549 bcolor = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (pixel));
2551 lw_add_widget_value_arg (wv, XtNbackground, bcolor.pixel);
2552 lw_add_widget_value_arg (wv, XtNforeground, fcolor.pixel);
2553 /* we cannot allow widgets to resize themselves */
2554 lw_add_widget_value_arg (wv, XtNresize, False);
2555 lw_add_widget_value_arg (wv, XtNwidth,
2556 (Dimension)IMAGE_INSTANCE_WIDTH (ii));
2557 lw_add_widget_value_arg (wv, XtNheight,
2558 (Dimension)IMAGE_INSTANCE_HEIGHT (ii));
2559 /* update the font. */
2560 update_widget_face (wv, ii, domain);
2562 wid = lw_create_widget (type, wv->name, id, wv, IMAGE_INSTANCE_X_CLIPWIDGET (ii),
2563 False, 0, popup_selection_callback, 0);
2565 IMAGE_INSTANCE_SUBWINDOW_ID (ii) = (void*)wid;
2566 IMAGE_INSTANCE_X_WIDGET_LWID (ii) = id;
2567 /* because the EmacsManager is the widgets parent we have to
2568 offset the redisplay of the widget by the amount the text
2569 widget is inside the manager. */
2571 XtSetArg (al [ac], XtNx, &IMAGE_INSTANCE_X_WIDGET_XOFFSET (ii)); ac++;
2572 XtSetArg (al [ac], XtNy, &IMAGE_INSTANCE_X_WIDGET_YOFFSET (ii)); ac++;
2573 XtGetValues (FRAME_X_TEXT_WIDGET (f), al, ac);
2575 XtSetMappedWhenManaged (wid, TRUE);
2577 free_widget_value_tree (wv);
2578 /* A kludgy but simple way to make sure the callback for a widget
2579 doesn't get deleted. */
2580 gcpro_popup_callbacks (id);
2583 /* get properties of a control */
2585 x_widget_property (Lisp_Object image_instance, Lisp_Object prop)
2587 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2588 /* get the text from a control */
2589 if (EQ (prop, Q_text))
2591 widget_value* wv = lw_get_all_values (IMAGE_INSTANCE_X_WIDGET_LWID (ii));
2592 return build_ext_string (wv->value, Qnative);
2597 /* Instantiate a layout control for putting other widgets in. */
2599 x_native_layout_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2600 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2601 int dest_mask, Lisp_Object domain)
2603 x_widget_instantiate (image_instance, instantiator, pointer_fg,
2604 pointer_bg, dest_mask, domain, "layout", 0);
2607 /* Instantiate a button widget. Unfortunately instantiated widgets are
2608 particular to a frame since they need to have a parent. It's not
2609 like images where you just select the image into the context you
2610 want to display it in and BitBlt it. So images instances can have a
2611 many-to-one relationship with things you see, whereas widgets can
2612 only be one-to-one (i.e. per frame) */
2614 x_button_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2615 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2616 int dest_mask, Lisp_Object domain)
2618 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2619 Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM (ii);
2620 Lisp_Object glyph = find_keyword_in_vector (instantiator, Q_image);
2621 widget_value* wv = gui_items_to_widget_values (image_instance, gui, 1);
2625 if (!IMAGE_INSTANCEP (glyph))
2626 glyph = glyph_image_instance (glyph, domain, ERROR_ME, 1);
2629 x_widget_instantiate (image_instance, instantiator, pointer_fg,
2630 pointer_bg, dest_mask, domain, "button", wv);
2632 /* add the image if one was given */
2633 if (!NILP (glyph) && IMAGE_INSTANCEP (glyph)
2634 && IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (glyph)))
2638 #ifdef LWLIB_WIDGETS_MOTIF
2639 XtSetArg (al [ac], XmNlabelType, XmPIXMAP); ac++;
2640 XtSetArg (al [ac], XmNlabelPixmap, XIMAGE_INSTANCE_X_PIXMAP (glyph));ac++;
2642 XtSetArg (al [ac], XtNpixmap, XIMAGE_INSTANCE_X_PIXMAP (glyph)); ac++;
2644 XtSetValues (IMAGE_INSTANCE_X_WIDGET_ID (ii), al, ac);
2648 /* Update a button's clicked state.
2650 #### This is overkill, but it works. Right now this causes all
2651 button instances to flash for some reason buried deep in lwlib. In
2652 theory this should be the Right Thing to do since lwlib should only
2653 merge in changed values - and if nothing has changed then nothing
2654 should get done. This may be because of the args stuff,
2655 i.e. although the arg contents may be the same the args look
2656 different and so are re-applied to the widget. */
2658 x_button_redisplay (Lisp_Object image_instance)
2660 /* This function can GC if IN_REDISPLAY is false. */
2661 Lisp_Image_Instance *p = XIMAGE_INSTANCE (image_instance);
2663 gui_items_to_widget_values (image_instance,
2664 IMAGE_INSTANCE_WIDGET_ITEMS (p), 1);
2666 /* now modify the widget */
2667 lw_modify_all_widgets (IMAGE_INSTANCE_X_WIDGET_LWID (p),
2669 free_widget_value_tree (wv);
2672 /* get properties of a button */
2674 x_button_property (Lisp_Object image_instance, Lisp_Object prop)
2676 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2677 /* check the state of a button */
2678 if (EQ (prop, Q_selected))
2680 widget_value* wv = lw_get_all_values (IMAGE_INSTANCE_X_WIDGET_LWID (ii));
2690 /* instantiate a progress gauge */
2692 x_progress_gauge_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2693 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2694 int dest_mask, Lisp_Object domain)
2696 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2697 Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM (ii);
2698 widget_value* wv = gui_items_to_widget_values (image_instance, gui, 0);
2700 x_widget_instantiate (image_instance, instantiator, pointer_fg,
2701 pointer_bg, dest_mask, domain, "progress", wv);
2704 /* set the properties of a progress gauge */
2706 x_progress_gauge_redisplay (Lisp_Object image_instance)
2708 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2710 if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii))
2714 #ifdef ERROR_CHECK_GLYPHS
2715 assert (GUI_ITEMP (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii)));
2717 val = XGUI_ITEM (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii))->value;
2718 XtSetArg (al[0], XtNvalue, XINT (val));
2719 XtSetValues (IMAGE_INSTANCE_X_WIDGET_ID (ii), al, 1);
2723 /* instantiate an edit control */
2725 x_edit_field_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2726 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2727 int dest_mask, Lisp_Object domain)
2729 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2730 Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM (ii);
2731 widget_value* wv = gui_items_to_widget_values (image_instance, gui, 0);
2733 x_widget_instantiate (image_instance, instantiator, pointer_fg,
2734 pointer_bg, dest_mask, domain, "text-field", wv);
2737 #if defined (LWLIB_WIDGETS_MOTIF) && XmVERSION > 1
2738 /* instantiate a combo control */
2740 x_combo_box_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2741 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2742 int dest_mask, Lisp_Object domain)
2744 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2745 widget_value * wv = 0;
2746 /* This is not done generically because of sizing problems under
2748 widget_instantiate (image_instance, instantiator, pointer_fg,
2749 pointer_bg, dest_mask, domain);
2751 wv = gui_items_to_widget_values (image_instance,
2752 IMAGE_INSTANCE_WIDGET_ITEMS (ii), 0);
2754 x_widget_instantiate (image_instance, instantiator, pointer_fg,
2755 pointer_bg, dest_mask, domain, "combo-box", wv);
2760 x_tab_control_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2761 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2762 int dest_mask, Lisp_Object domain)
2764 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2766 gui_items_to_widget_values (image_instance,
2767 IMAGE_INSTANCE_WIDGET_ITEMS (ii), 0);
2768 update_tab_widget_face (wv, ii,
2769 IMAGE_INSTANCE_FRAME (ii));
2770 x_widget_instantiate (image_instance, instantiator, pointer_fg,
2771 pointer_bg, dest_mask, domain, "tab-control", wv);
2774 /* Set the properties of a tab control */
2776 x_tab_control_redisplay (Lisp_Object image_instance)
2778 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2780 if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii)
2782 IMAGE_INSTANCE_WIDGET_ACTION_OCCURRED (ii))
2784 /* If only the order has changed then simply select the first
2785 one of the pending set. This stops horrendous rebuilding -
2786 and hence flicker - of the tabs each time you click on
2788 if (tab_control_order_only_changed (image_instance))
2790 Lisp_Object rest, selected =
2791 gui_item_list_find_selected
2792 (NILP (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii)) ?
2793 XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)) :
2794 XCDR (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii)));
2796 LIST_LOOP (rest, XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)))
2798 if (gui_item_equal_sans_selected (XCAR (rest), selected, 0))
2800 /* There may be an encapsulated way of doing this,
2801 but I couldn't find it. */
2802 Lisp_Object old_selected =gui_item_list_find_selected
2803 (XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)));
2806 unsigned int num_children, i;
2809 LISP_STRING_TO_EXTERNAL (XGUI_ITEM (XCAR (rest))->name,
2811 /* The name may contain a `.' which confuses
2812 XtNameToWidget, so we do it ourselves. */
2813 children = XtCompositeChildren (IMAGE_INSTANCE_X_WIDGET_ID (ii),
2815 for (i = 0; i < num_children; i++)
2817 if (!strcmp (XtName (children [i]), name))
2819 XtSetArg (al [0], XtNtopWidget, children [i]);
2820 XtSetArg (al [1], XtNhighlightWidget,
2822 XtSetValues (IMAGE_INSTANCE_X_WIDGET_ID (ii), al, 2);
2826 /* Pick up the new selected item. */
2827 XGUI_ITEM (old_selected)->selected =
2828 XGUI_ITEM (XCAR (rest))->selected;
2829 XGUI_ITEM (XCAR (rest))->selected =
2830 XGUI_ITEM (selected)->selected;
2831 /* We're not actually changing the items anymore. */
2832 IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii) = 0;
2833 IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii) = Qnil;
2839 /* Possibly update the face. */
2840 if (IMAGE_INSTANCE_WIDGET_FACE_CHANGED (ii)
2842 XFRAME (IMAGE_INSTANCE_FRAME (ii))->faces_changed
2844 IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii))
2846 /* See previous comments on the brokeness of lwlib.
2848 #### There's actually not much point in doing this here
2849 since, colors will have been set appropriately by
2850 x_redisplay_widget. */
2851 widget_value* wv =copy_widget_value_tree
2853 (IMAGE_INSTANCE_X_WIDGET_LWID (ii)),
2856 update_tab_widget_face (wv, ii,
2857 IMAGE_INSTANCE_FRAME (ii));
2859 lw_modify_all_widgets (IMAGE_INSTANCE_X_WIDGET_LWID (ii), wv, True);
2860 free_widget_value_tree (wv);
2864 /* instantiate a static control possible for putting other things in */
2866 x_label_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2867 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2868 int dest_mask, Lisp_Object domain)
2870 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2871 Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM (ii);
2872 widget_value* wv = gui_items_to_widget_values (image_instance, gui, 0);
2874 x_widget_instantiate (image_instance, instantiator, pointer_fg,
2875 pointer_bg, dest_mask, domain, "button", wv);
2877 #endif /* HAVE_WIDGETS */
2880 /************************************************************************/
2881 /* initialization */
2882 /************************************************************************/
2885 syms_of_glyphs_x (void)
2888 DEFSUBR (Fchange_subwindow_property);
2893 console_type_create_glyphs_x (void)
2897 CONSOLE_HAS_METHOD (x, print_image_instance);
2898 CONSOLE_HAS_METHOD (x, finalize_image_instance);
2899 CONSOLE_HAS_METHOD (x, image_instance_equal);
2900 CONSOLE_HAS_METHOD (x, image_instance_hash);
2901 CONSOLE_HAS_METHOD (x, colorize_image_instance);
2902 CONSOLE_HAS_METHOD (x, init_image_instance_from_eimage);
2903 CONSOLE_HAS_METHOD (x, locate_pixmap_file);
2904 CONSOLE_HAS_METHOD (x, unmap_subwindow);
2905 CONSOLE_HAS_METHOD (x, map_subwindow);
2906 CONSOLE_HAS_METHOD (x, redisplay_widget);
2907 CONSOLE_HAS_METHOD (x, redisplay_subwindow);
2908 CONSOLE_HAS_METHOD (x, widget_border_width);
2912 image_instantiator_format_create_glyphs_x (void)
2914 IIFORMAT_VALID_CONSOLE (x, nothing);
2915 IIFORMAT_VALID_CONSOLE (x, string);
2917 IIFORMAT_VALID_CONSOLE (x, layout);
2919 IIFORMAT_VALID_CONSOLE (x, formatted_string);
2920 IIFORMAT_VALID_CONSOLE (x, inherit);
2922 INITIALIZE_DEVICE_IIFORMAT (x, xpm);
2923 IIFORMAT_HAS_DEVMETHOD (x, xpm, instantiate);
2926 IIFORMAT_VALID_CONSOLE (x, jpeg);
2929 IIFORMAT_VALID_CONSOLE (x, tiff);
2932 IIFORMAT_VALID_CONSOLE (x, png);
2935 IIFORMAT_VALID_CONSOLE (x, gif);
2937 INITIALIZE_DEVICE_IIFORMAT (x, xbm);
2938 IIFORMAT_HAS_DEVMETHOD (x, xbm, instantiate);
2940 INITIALIZE_DEVICE_IIFORMAT (x, subwindow);
2941 IIFORMAT_HAS_DEVMETHOD (x, subwindow, instantiate);
2944 INITIALIZE_DEVICE_IIFORMAT (x, native_layout);
2945 IIFORMAT_HAS_DEVMETHOD (x, native_layout, instantiate);
2947 INITIALIZE_DEVICE_IIFORMAT (x, button);
2948 IIFORMAT_HAS_DEVMETHOD (x, button, property);
2949 IIFORMAT_HAS_DEVMETHOD (x, button, instantiate);
2950 IIFORMAT_HAS_DEVMETHOD (x, button, redisplay);
2951 /* general widget methods. */
2952 INITIALIZE_DEVICE_IIFORMAT (x, widget);
2953 IIFORMAT_HAS_DEVMETHOD (x, widget, property);
2954 /* progress gauge */
2955 INITIALIZE_DEVICE_IIFORMAT (x, progress_gauge);
2956 IIFORMAT_HAS_DEVMETHOD (x, progress_gauge, redisplay);
2957 IIFORMAT_HAS_DEVMETHOD (x, progress_gauge, instantiate);
2959 INITIALIZE_DEVICE_IIFORMAT (x, edit_field);
2960 IIFORMAT_HAS_DEVMETHOD (x, edit_field, instantiate);
2961 #if defined (LWLIB_WIDGETS_MOTIF) && XmVERSION > 1
2963 INITIALIZE_DEVICE_IIFORMAT (x, combo_box);
2964 IIFORMAT_HAS_DEVMETHOD (x, combo_box, instantiate);
2965 IIFORMAT_HAS_SHARED_DEVMETHOD (x, combo_box, redisplay, tab_control);
2967 /* tab control widget */
2968 INITIALIZE_DEVICE_IIFORMAT (x, tab_control);
2969 IIFORMAT_HAS_DEVMETHOD (x, tab_control, instantiate);
2970 IIFORMAT_HAS_DEVMETHOD (x, tab_control, redisplay);
2972 INITIALIZE_DEVICE_IIFORMAT (x, label);
2973 IIFORMAT_HAS_DEVMETHOD (x, label, instantiate);
2975 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (cursor_font, "cursor-font");
2976 IIFORMAT_VALID_CONSOLE (x, cursor_font);
2978 IIFORMAT_HAS_METHOD (cursor_font, validate);
2979 IIFORMAT_HAS_METHOD (cursor_font, possible_dest_types);
2980 IIFORMAT_HAS_METHOD (cursor_font, instantiate);
2982 IIFORMAT_VALID_KEYWORD (cursor_font, Q_data, check_valid_string);
2983 IIFORMAT_VALID_KEYWORD (cursor_font, Q_foreground, check_valid_string);
2984 IIFORMAT_VALID_KEYWORD (cursor_font, Q_background, check_valid_string);
2986 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (font, "font");
2988 IIFORMAT_HAS_METHOD (font, validate);
2989 IIFORMAT_HAS_METHOD (font, possible_dest_types);
2990 IIFORMAT_HAS_METHOD (font, instantiate);
2991 IIFORMAT_VALID_CONSOLE (x, font);
2993 IIFORMAT_VALID_KEYWORD (font, Q_data, check_valid_string);
2994 IIFORMAT_VALID_KEYWORD (font, Q_foreground, check_valid_string);
2995 IIFORMAT_VALID_KEYWORD (font, Q_background, check_valid_string);
2998 INITIALIZE_DEVICE_IIFORMAT (x, xface);
2999 IIFORMAT_HAS_DEVMETHOD (x, xface, instantiate);
3002 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (autodetect,
3005 IIFORMAT_HAS_METHOD (autodetect, validate);
3006 IIFORMAT_HAS_METHOD (autodetect, normalize);
3007 IIFORMAT_HAS_METHOD (autodetect, possible_dest_types);
3008 /* #### autodetect is flawed IMO:
3009 1. It makes the assumption that you can detect whether the user
3010 wanted a cursor or a string based on the data, since the data is a
3011 string you have to prioritise cursors. Instead we will force users
3012 to pick the appropriate image type, this is what we do under
3014 2. It doesn't fit with the new domain model - you cannot tell which
3015 domain it needs to be instantiated in until you've actually
3016 instantiated it, which mucks up caching.
3017 3. It only copes with cursors and strings which seems bogus. */
3018 IIFORMAT_HAS_SHARED_METHOD (autodetect, governing_domain, subwindow);
3019 IIFORMAT_HAS_METHOD (autodetect, instantiate);
3020 IIFORMAT_VALID_CONSOLE (x, autodetect);
3022 IIFORMAT_VALID_KEYWORD (autodetect, Q_data, check_valid_string);
3026 vars_of_glyphs_x (void)
3028 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path /*
3029 A list of the directories in which X bitmap files may be found.
3030 If nil, this is initialized from the "*bitmapFilePath" resource.
3031 This is used by the `make-image-instance' function (however, note that if
3032 the environment variable XBMLANGPATH is set, it is consulted first).
3034 Vx_bitmap_file_path = Qnil;
3038 complex_vars_of_glyphs_x (void)
3040 #define BUILD_GLYPH_INST(variable, name) \
3041 Fadd_spec_to_specifier \
3042 (GLYPH_IMAGE (XGLYPH (variable)), \
3043 vector3 (Qxbm, Q_data, \
3044 list3 (make_int (name##_width), \
3045 make_int (name##_height), \
3046 make_ext_string ((Extbyte *) name##_bits, \
3047 sizeof (name##_bits), \
3051 BUILD_GLYPH_INST (Vtruncation_glyph, truncator);
3052 BUILD_GLYPH_INST (Vcontinuation_glyph, continuer);
3053 BUILD_GLYPH_INST (Vxemacs_logo, xemacs);
3054 BUILD_GLYPH_INST (Vhscroll_glyph, hscroll);
3056 #undef BUILD_GLYPH_INST