1 /* Generic glyph/image implementation + display tables
2 Copyright (C) 1994, 1995 Board of Trustees, University of Illinois.
3 Copyright (C) 1995 Tinker Systems
4 Copyright (C) 1995, 1996, 2000 Ben Wing
5 Copyright (C) 1995 Sun Microsystems
6 Copyright (C) 1998, 1999, 2000 Andy Piper
8 This file is part of XEmacs.
10 XEmacs is free software; you can redistribute it and/or modify it
11 under the terms of the GNU General Public License as published by the
12 Free Software Foundation; either version 2, or (at your option) any
15 XEmacs is distributed in the hope that it will be useful, but WITHOUT
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 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 /* Written by Ben Wing and Chuck Thompson. Heavily modified /
28 rewritten by Andy Piper. */
33 #include "blocktype.h"
45 #include "redisplay.h"
46 #include "specifier.h"
53 Lisp_Object Qimage_conversion_error;
55 Lisp_Object Qglyphp, Qcontrib_p, Qbaseline;
56 Lisp_Object Qbuffer_glyph_p, Qpointer_glyph_p, Qicon_glyph_p;
57 Lisp_Object Qnothing_image_instance_p, Qtext_image_instance_p;
58 Lisp_Object Qmono_pixmap_image_instance_p;
59 Lisp_Object Qcolor_pixmap_image_instance_p;
60 Lisp_Object Qpointer_image_instance_p;
61 Lisp_Object Qsubwindow_image_instance_p;
62 Lisp_Object Qwidget_image_instance_p;
63 Lisp_Object Qconst_glyph_variable;
64 Lisp_Object Qmono_pixmap, Qcolor_pixmap, Qsubwindow;
65 Lisp_Object Q_file, Q_data, Q_face, Q_pixel_width, Q_pixel_height;
66 Lisp_Object Qformatted_string;
67 Lisp_Object Vcurrent_display_table;
68 Lisp_Object Vtruncation_glyph, Vcontinuation_glyph, Voctal_escape_glyph;
69 Lisp_Object Vcontrol_arrow_glyph, Vinvisible_text_glyph, Vhscroll_glyph;
70 Lisp_Object Vxemacs_logo;
71 Lisp_Object Vthe_nothing_vector;
72 Lisp_Object Vimage_instantiator_format_list;
73 Lisp_Object Vimage_instance_type_list;
74 Lisp_Object Vglyph_type_list;
76 int disable_animated_pixmaps;
78 DEFINE_IMAGE_INSTANTIATOR_FORMAT (nothing);
79 DEFINE_IMAGE_INSTANTIATOR_FORMAT (inherit);
80 DEFINE_IMAGE_INSTANTIATOR_FORMAT (string);
81 DEFINE_IMAGE_INSTANTIATOR_FORMAT (formatted_string);
82 DEFINE_IMAGE_INSTANTIATOR_FORMAT (subwindow);
83 DEFINE_IMAGE_INSTANTIATOR_FORMAT (text);
84 DEFINE_IMAGE_INSTANTIATOR_FORMAT (pointer);
86 #ifdef HAVE_WINDOW_SYSTEM
87 DEFINE_IMAGE_INSTANTIATOR_FORMAT (xbm);
90 Lisp_Object Q_mask_file, Q_mask_data, Q_hotspot_x, Q_hotspot_y;
91 Lisp_Object Q_foreground, Q_background;
93 #define BitmapSuccess 0
94 #define BitmapOpenFailed 1
95 #define BitmapFileInvalid 2
96 #define BitmapNoMemory 3
101 DEFINE_IMAGE_INSTANTIATOR_FORMAT (xface);
106 DEFINE_IMAGE_INSTANTIATOR_FORMAT (xpm);
108 Lisp_Object Q_color_symbols;
111 typedef struct image_instantiator_format_entry image_instantiator_format_entry;
112 struct image_instantiator_format_entry
116 struct image_instantiator_methods *meths;
121 Dynarr_declare (struct image_instantiator_format_entry);
122 } image_instantiator_format_entry_dynarr;
124 /* This contains one entry per format, per device it's defined on. */
125 image_instantiator_format_entry_dynarr *
126 the_image_instantiator_format_entry_dynarr;
128 static Lisp_Object allocate_image_instance (Lisp_Object governing_domain,
130 static void image_validate (Lisp_Object instantiator);
131 static void glyph_property_was_changed (Lisp_Object glyph,
132 Lisp_Object property,
134 static void set_image_instance_dirty_p (Lisp_Object instance, int dirty);
135 static void register_ignored_expose (struct frame* f, int x, int y, int width, int height);
136 static void cache_subwindow_instance_in_frame_maybe (Lisp_Object instance);
137 /* Unfortunately windows and X are different. In windows BeginPaint()
138 will prevent WM_PAINT messages being generated so it is unnecessary
139 to register exposures as they will not occur. Under X they will
141 int hold_ignored_expose_registration;
143 EXFUN (Fimage_instance_type, 1);
144 EXFUN (Fglyph_type, 1);
145 EXFUN (Fnext_window, 4);
148 /****************************************************************************
149 * Image Instantiators *
150 ****************************************************************************/
152 struct image_instantiator_methods *
153 decode_device_ii_format (Lisp_Object device, Lisp_Object format,
158 if (!SYMBOLP (format))
160 if (ERRB_EQ (errb, ERROR_ME))
161 CHECK_SYMBOL (format);
165 for (i = 0; i < Dynarr_length (the_image_instantiator_format_entry_dynarr);
169 Dynarr_at (the_image_instantiator_format_entry_dynarr, i).
172 Lisp_Object d = Dynarr_at (the_image_instantiator_format_entry_dynarr, i).
174 if ((NILP (d) && NILP (device))
177 EQ (CONSOLE_TYPE (XCONSOLE
178 (DEVICE_CONSOLE (XDEVICE (device)))), d)))
179 return Dynarr_at (the_image_instantiator_format_entry_dynarr, i).meths;
183 maybe_signal_simple_error ("Invalid image-instantiator format", format,
189 struct image_instantiator_methods *
190 decode_image_instantiator_format (Lisp_Object format, Error_behavior errb)
192 return decode_device_ii_format (Qnil, format, errb);
196 valid_image_instantiator_format_p (Lisp_Object format, Lisp_Object locale)
199 struct image_instantiator_methods* meths =
200 decode_image_instantiator_format (format, ERROR_ME_NOT);
201 Lisp_Object contype = Qnil;
202 /* mess with the locale */
203 if (!NILP (locale) && SYMBOLP (locale))
207 struct console* console = decode_console (locale);
208 contype = console ? CONSOLE_TYPE (console) : locale;
210 /* nothing is valid in all locales */
211 if (EQ (format, Qnothing))
213 /* reject unknown formats */
214 else if (NILP (contype) || !meths)
217 for (i = 0; i < Dynarr_length (meths->consoles); i++)
218 if (EQ (contype, Dynarr_at (meths->consoles, i).symbol))
223 DEFUN ("valid-image-instantiator-format-p", Fvalid_image_instantiator_format_p,
225 Given an IMAGE-INSTANTIATOR-FORMAT, return non-nil if it is valid.
226 If LOCALE is non-nil then the format is checked in that domain.
227 If LOCALE is nil the current console is used.
229 Valid formats are some subset of 'nothing, 'string, 'formatted-string,
230 'xpm, 'xbm, 'xface, 'gif, 'jpeg, 'png, 'tiff, 'cursor-font, 'font,
231 'autodetect, 'subwindow, 'inherit, 'mswindows-resource, 'bmp,
232 'native-layout, 'layout, 'label, 'tab-control, 'tree-view,
233 'progress-gauge, 'scrollbar, 'combo-box, 'edit-field, 'button,
234 'widget, 'pointer, and 'text, depending on how XEmacs was compiled.
236 (image_instantiator_format, locale))
238 return valid_image_instantiator_format_p (image_instantiator_format,
243 DEFUN ("image-instantiator-format-list", Fimage_instantiator_format_list,
245 Return a list of valid image-instantiator formats.
249 return Fcopy_sequence (Vimage_instantiator_format_list);
253 add_entry_to_device_ii_format_list (Lisp_Object device, Lisp_Object symbol,
254 struct image_instantiator_methods *meths)
256 struct image_instantiator_format_entry entry;
258 entry.symbol = symbol;
259 entry.device = device;
261 Dynarr_add (the_image_instantiator_format_entry_dynarr, entry);
262 if (NILP (memq_no_quit (symbol, Vimage_instantiator_format_list)))
263 Vimage_instantiator_format_list =
264 Fcons (symbol, Vimage_instantiator_format_list);
268 add_entry_to_image_instantiator_format_list (Lisp_Object symbol,
270 image_instantiator_methods *meths)
272 add_entry_to_device_ii_format_list (Qnil, symbol, meths);
276 get_image_conversion_list (Lisp_Object console_type)
278 return &decode_console_type (console_type, ERROR_ME)->image_conversion_list;
281 DEFUN ("set-console-type-image-conversion-list", Fset_console_type_image_conversion_list,
283 Set the image-conversion-list for consoles of the given TYPE.
284 The image-conversion-list specifies how image instantiators that
285 are strings should be interpreted. Each element of the list should be
286 a list of two elements (a regular expression string and a vector) or
287 a list of three elements (the preceding two plus an integer index into
288 the vector). The string is converted to the vector associated with the
289 first matching regular expression. If a vector index is specified, the
290 string itself is substituted into that position in the vector.
292 Note: The conversion above is applied when the image instantiator is
293 added to an image specifier, not when the specifier is actually
294 instantiated. Therefore, changing the image-conversion-list only affects
295 newly-added instantiators. Existing instantiators in glyphs and image
296 specifiers will not be affected.
298 (console_type, list))
301 Lisp_Object *imlist = get_image_conversion_list (console_type);
303 /* Check the list to make sure that it only has valid entries. */
305 EXTERNAL_LIST_LOOP (tail, list)
307 Lisp_Object mapping = XCAR (tail);
309 /* Mapping form should be (STRING VECTOR) or (STRING VECTOR INTEGER) */
310 if (!CONSP (mapping) ||
311 !CONSP (XCDR (mapping)) ||
312 (!NILP (XCDR (XCDR (mapping))) &&
313 (!CONSP (XCDR (XCDR (mapping))) ||
314 !NILP (XCDR (XCDR (XCDR (mapping)))))))
315 signal_simple_error ("Invalid mapping form", mapping);
318 Lisp_Object exp = XCAR (mapping);
319 Lisp_Object typevec = XCAR (XCDR (mapping));
320 Lisp_Object pos = Qnil;
325 CHECK_VECTOR (typevec);
326 if (!NILP (XCDR (XCDR (mapping))))
328 pos = XCAR (XCDR (XCDR (mapping)));
330 if (XINT (pos) < 0 ||
331 XINT (pos) >= XVECTOR_LENGTH (typevec))
333 (pos, Qzero, make_int (XVECTOR_LENGTH (typevec) - 1));
336 newvec = Fcopy_sequence (typevec);
338 XVECTOR_DATA (newvec)[XINT (pos)] = exp;
340 image_validate (newvec);
345 *imlist = Fcopy_tree (list, Qt);
349 DEFUN ("console-type-image-conversion-list", Fconsole_type_image_conversion_list,
351 Return the image-conversion-list for devices of the given TYPE.
352 The image-conversion-list specifies how to interpret image string
353 instantiators for the specified console type. See
354 `set-console-type-image-conversion-list' for a description of its syntax.
358 return Fcopy_tree (*get_image_conversion_list (console_type), Qt);
361 /* Process a string instantiator according to the image-conversion-list for
362 CONSOLE_TYPE. Returns a vector. */
365 process_image_string_instantiator (Lisp_Object data,
366 Lisp_Object console_type,
371 LIST_LOOP (tail, *get_image_conversion_list (console_type))
373 Lisp_Object mapping = XCAR (tail);
374 Lisp_Object exp = XCAR (mapping);
375 Lisp_Object typevec = XCAR (XCDR (mapping));
377 /* if the result is of a type that can't be instantiated
378 (e.g. a string when we're dealing with a pointer glyph),
381 IIFORMAT_METH (decode_image_instantiator_format
382 (XVECTOR_DATA (typevec)[0], ERROR_ME),
383 possible_dest_types, ())))
385 if (fast_string_match (exp, 0, data, 0, -1, 0, ERROR_ME, 0) >= 0)
387 if (!NILP (XCDR (XCDR (mapping))))
389 int pos = XINT (XCAR (XCDR (XCDR (mapping))));
390 Lisp_Object newvec = Fcopy_sequence (typevec);
391 XVECTOR_DATA (newvec)[pos] = data;
400 signal_simple_error ("Unable to interpret glyph instantiator",
407 find_keyword_in_vector_or_given (Lisp_Object vector, Lisp_Object keyword,
408 Lisp_Object default_)
411 int instantiator_len;
413 elt = XVECTOR_DATA (vector);
414 instantiator_len = XVECTOR_LENGTH (vector);
419 while (instantiator_len > 0)
421 if (EQ (elt[0], keyword))
424 instantiator_len -= 2;
431 find_keyword_in_vector (Lisp_Object vector, Lisp_Object keyword)
433 return find_keyword_in_vector_or_given (vector, keyword, Qnil);
437 check_valid_string (Lisp_Object data)
443 check_valid_vector (Lisp_Object data)
449 check_valid_face (Lisp_Object data)
455 check_valid_int (Lisp_Object data)
461 file_or_data_must_be_present (Lisp_Object instantiator)
463 if (NILP (find_keyword_in_vector (instantiator, Q_file)) &&
464 NILP (find_keyword_in_vector (instantiator, Q_data)))
465 signal_simple_error ("Must supply either :file or :data",
470 data_must_be_present (Lisp_Object instantiator)
472 if (NILP (find_keyword_in_vector (instantiator, Q_data)))
473 signal_simple_error ("Must supply :data", instantiator);
477 face_must_be_present (Lisp_Object instantiator)
479 if (NILP (find_keyword_in_vector (instantiator, Q_face)))
480 signal_simple_error ("Must supply :face", instantiator);
483 /* utility function useful in retrieving data from a file. */
486 make_string_from_file (Lisp_Object file)
488 /* This function can call lisp */
489 int count = specpdl_depth ();
490 Lisp_Object temp_buffer;
494 specbind (Qinhibit_quit, Qt);
495 record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
496 temp_buffer = Fget_buffer_create (build_string (" *pixmap conversion*"));
497 GCPRO1 (temp_buffer);
498 set_buffer_internal (XBUFFER (temp_buffer));
499 Ferase_buffer (Qnil);
500 specbind (intern ("format-alist"), Qnil);
501 Finsert_file_contents_internal (file, Qnil, Qnil, Qnil, Qnil, Qnil, Qnil);
502 data = Fbuffer_substring (Qnil, Qnil, Qnil);
503 unbind_to (count, Qnil);
508 /* The following two functions are provided to make it easier for
509 the normalize methods to work with keyword-value vectors.
510 Hash tables are kind of heavyweight for this purpose.
511 (If vectors were resizable, we could avoid this problem;
512 but they're not.) An alternative approach that might be
513 more efficient but require more work is to use a type of
514 assoc-Dynarr and provide primitives for deleting elements out
515 of it. (However, you'd also have to add an unwind-protect
516 to make sure the Dynarr got freed in case of an error in
517 the normalization process.) */
520 tagged_vector_to_alist (Lisp_Object vector)
522 Lisp_Object *elt = XVECTOR_DATA (vector);
523 int len = XVECTOR_LENGTH (vector);
524 Lisp_Object result = Qnil;
527 for (len -= 2; len >= 1; len -= 2)
528 result = Fcons (Fcons (elt[len], elt[len+1]), result);
534 alist_to_tagged_vector (Lisp_Object tag, Lisp_Object alist)
536 int len = 1 + 2 * XINT (Flength (alist));
537 Lisp_Object *elt = alloca_array (Lisp_Object, len);
543 LIST_LOOP (rest, alist)
545 Lisp_Object pair = XCAR (rest);
546 elt[i] = XCAR (pair);
547 elt[i+1] = XCDR (pair);
551 return Fvector (len, elt);
554 #ifdef ERROR_CHECK_GLYPHS
556 check_instance_cache_mapper (Lisp_Object key, Lisp_Object value,
559 /* This function can GC */
560 /* value can be nil; we cache failures as well as successes */
564 VOID_TO_LISP (window, flag_closure);
565 assert (EQ (XIMAGE_INSTANCE_DOMAIN (value), window));
572 check_window_subwindow_cache (struct window* w)
576 XSETWINDOW (window, w);
578 assert (!NILP (w->subwindow_instance_cache));
579 elisp_maphash (check_instance_cache_mapper,
580 w->subwindow_instance_cache,
581 LISP_TO_VOID (window));
585 check_image_instance_structure (Lisp_Object instance)
587 /* Weird nothing images exist at startup when the console is
589 if (!NOTHING_IMAGE_INSTANCEP (instance))
590 assert (DOMAIN_LIVE_P (instance));
591 if (WINDOWP (XIMAGE_INSTANCE_DOMAIN (instance)))
592 check_window_subwindow_cache
593 (XWINDOW (XIMAGE_INSTANCE_DOMAIN (instance)));
597 /* Determine what kind of domain governs the image instance.
598 Verify that the given domain is at least as specific, and extract
599 the governing domain from it. */
601 get_image_instantiator_governing_domain (Lisp_Object instantiator,
604 int governing_domain;
606 struct image_instantiator_methods *meths =
607 decode_image_instantiator_format (XVECTOR_DATA (instantiator)[0],
609 governing_domain = IIFORMAT_METH_OR_GIVEN (meths, governing_domain, (),
610 GOVERNING_DOMAIN_DEVICE);
612 if (governing_domain == GOVERNING_DOMAIN_WINDOW
613 && NILP (DOMAIN_WINDOW (domain)))
614 signal_simple_error_2 ("Domain for this instantiator must be resolvable to a window",
615 instantiator, domain);
616 else if (governing_domain == GOVERNING_DOMAIN_FRAME
617 && NILP (DOMAIN_FRAME (domain)))
618 signal_simple_error_2
619 ("Domain for this instantiator must be resolvable to a frame",
620 instantiator, domain);
622 if (governing_domain == GOVERNING_DOMAIN_WINDOW)
623 domain = DOMAIN_WINDOW (domain);
624 else if (governing_domain == GOVERNING_DOMAIN_FRAME)
625 domain = DOMAIN_FRAME (domain);
626 else if (governing_domain == GOVERNING_DOMAIN_DEVICE)
627 domain = DOMAIN_DEVICE (domain);
635 normalize_image_instantiator (Lisp_Object instantiator,
637 Lisp_Object dest_mask)
639 if (IMAGE_INSTANCEP (instantiator))
642 if (STRINGP (instantiator))
643 instantiator = process_image_string_instantiator (instantiator, contype,
646 assert (VECTORP (instantiator));
647 /* We have to always store the actual pixmap data and not the
648 filename even though this is a potential memory pig. We have to
649 do this because it is quite possible that we will need to
650 instantiate a new instance of the pixmap and the file will no
651 longer exist (e.g. w3 pixmaps are almost always from temporary
655 struct image_instantiator_methods *meths;
657 GCPRO1 (instantiator);
659 meths = decode_image_instantiator_format (XVECTOR_DATA (instantiator)[0],
661 RETURN_UNGCPRO (IIFORMAT_METH_OR_GIVEN (meths, normalize,
662 (instantiator, contype),
668 instantiate_image_instantiator (Lisp_Object governing_domain,
670 Lisp_Object instantiator,
671 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
672 int dest_mask, Lisp_Object glyph)
674 Lisp_Object ii = allocate_image_instance (governing_domain, glyph);
675 Lisp_Image_Instance* p = XIMAGE_INSTANCE (ii);
676 struct image_instantiator_methods *meths, *device_meths;
680 if (!valid_image_instantiator_format_p (XVECTOR_DATA (instantiator)[0],
681 DOMAIN_DEVICE (governing_domain)))
683 ("Image instantiator format is invalid in this locale.",
686 meths = decode_image_instantiator_format (XVECTOR_DATA (instantiator)[0],
688 MAYBE_IIFORMAT_METH (meths, instantiate, (ii, instantiator, pointer_fg,
689 pointer_bg, dest_mask, domain));
691 /* Now do device specific instantiation. */
692 device_meths = decode_device_ii_format (DOMAIN_DEVICE (governing_domain),
693 XVECTOR_DATA (instantiator)[0],
696 if (!HAS_IIFORMAT_METH_P (meths, instantiate)
697 && (!device_meths || !HAS_IIFORMAT_METH_P (device_meths, instantiate)))
699 ("Don't know how to instantiate this image instantiator?",
702 /* In general native window system methods will require sane
703 geometry values, thus the instance needs to have been laid-out
704 before they get called. */
705 image_instance_layout (ii, XIMAGE_INSTANCE_WIDTH (ii),
706 XIMAGE_INSTANCE_HEIGHT (ii), domain);
708 MAYBE_IIFORMAT_METH (device_meths, instantiate, (ii, instantiator, pointer_fg,
709 pointer_bg, dest_mask, domain));
710 /* Do post instantiation. */
711 MAYBE_IIFORMAT_METH (meths, post_instantiate, (ii, instantiator, domain));
712 MAYBE_IIFORMAT_METH (device_meths, post_instantiate, (ii, instantiator, domain));
715 IMAGE_INSTANCE_INITIALIZED (p) = 1;
716 /* Now that we're done verify that we really are laid out. */
717 if (IMAGE_INSTANCE_LAYOUT_CHANGED (p))
718 image_instance_layout (ii, XIMAGE_INSTANCE_WIDTH (ii),
719 XIMAGE_INSTANCE_HEIGHT (ii), domain);
721 /* We *must* have a clean image at this point. */
722 IMAGE_INSTANCE_TEXT_CHANGED (p) = 0;
723 IMAGE_INSTANCE_SIZE_CHANGED (p) = 0;
724 IMAGE_INSTANCE_LAYOUT_CHANGED (p) = 0;
725 IMAGE_INSTANCE_DIRTYP (p) = 0;
727 assert ( XIMAGE_INSTANCE_HEIGHT (ii) >= 0
728 && XIMAGE_INSTANCE_WIDTH (ii) >= 0 );
730 ERROR_CHECK_IMAGE_INSTANCE (ii);
736 /****************************************************************************
737 * Image-Instance Object *
738 ****************************************************************************/
740 Lisp_Object Qimage_instancep;
743 mark_image_instance (Lisp_Object obj)
745 Lisp_Image_Instance *i = XIMAGE_INSTANCE (obj);
747 /* #### I want to check the instance here, but there are way too
748 many instances of the instance being marked while the domain is
749 dead. For instance you can get marked through an event when using
752 ERROR_CHECK_IMAGE_INSTANCE (obj);
755 mark_object (i->name);
756 /* Is this legal in marking? We may get in the situation where the
757 domain has been deleted - making the instance unusable. It seems
758 better to remove the domain so that it can be finalized. */
759 if (!DOMAIN_LIVE_P (i->domain))
762 mark_object (i->domain);
764 /* We don't mark the glyph reference since that would create a
765 circularity preventing GC. */
766 switch (IMAGE_INSTANCE_TYPE (i))
769 mark_object (IMAGE_INSTANCE_TEXT_STRING (i));
771 case IMAGE_MONO_PIXMAP:
772 case IMAGE_COLOR_PIXMAP:
773 mark_object (IMAGE_INSTANCE_PIXMAP_FILENAME (i));
774 mark_object (IMAGE_INSTANCE_PIXMAP_MASK_FILENAME (i));
775 mark_object (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (i));
776 mark_object (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (i));
777 mark_object (IMAGE_INSTANCE_PIXMAP_FG (i));
778 mark_object (IMAGE_INSTANCE_PIXMAP_BG (i));
782 mark_object (IMAGE_INSTANCE_WIDGET_TYPE (i));
783 mark_object (IMAGE_INSTANCE_WIDGET_PROPS (i));
784 mark_object (IMAGE_INSTANCE_WIDGET_FACE (i));
785 mark_object (IMAGE_INSTANCE_WIDGET_ITEMS (i));
786 mark_object (IMAGE_INSTANCE_LAYOUT_CHILDREN (i));
787 mark_object (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (i));
788 mark_object (IMAGE_INSTANCE_WIDGET_HEIGHT_SUBR (i));
789 mark_object (IMAGE_INSTANCE_WIDGET_WIDTH_SUBR (i));
790 case IMAGE_SUBWINDOW:
797 /* The image may have been previously finalized (yes that's wierd,
798 see Fdelete_frame() and mark_window_as_deleted()), in which case
799 the domain will be nil, so cope with this. */
800 if (!NILP (IMAGE_INSTANCE_DEVICE (i)))
801 MAYBE_DEVMETH (XDEVICE (IMAGE_INSTANCE_DEVICE (i)),
802 mark_image_instance, (i));
808 print_image_instance (Lisp_Object obj, Lisp_Object printcharfun,
812 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (obj);
815 error ("printing unreadable object #<image-instance 0x%x>",
817 write_c_string ("#<image-instance (", printcharfun);
818 print_internal (Fimage_instance_type (obj), printcharfun, 0);
819 write_c_string (") ", printcharfun);
820 if (!NILP (ii->name))
822 print_internal (ii->name, printcharfun, 1);
823 write_c_string (" ", printcharfun);
825 write_c_string ("on ", printcharfun);
826 print_internal (ii->domain, printcharfun, 0);
827 write_c_string (" ", printcharfun);
828 switch (IMAGE_INSTANCE_TYPE (ii))
834 print_internal (IMAGE_INSTANCE_TEXT_STRING (ii), printcharfun, 1);
837 case IMAGE_MONO_PIXMAP:
838 case IMAGE_COLOR_PIXMAP:
840 if (STRINGP (IMAGE_INSTANCE_PIXMAP_FILENAME (ii)))
843 Lisp_Object filename = IMAGE_INSTANCE_PIXMAP_FILENAME (ii);
844 s = strrchr ((char *) XSTRING_DATA (filename), '/');
846 print_internal (build_string (s + 1), printcharfun, 1);
848 print_internal (filename, printcharfun, 1);
850 if (IMAGE_INSTANCE_PIXMAP_DEPTH (ii) > 1)
851 sprintf (buf, " %dx%dx%d", IMAGE_INSTANCE_PIXMAP_WIDTH (ii),
852 IMAGE_INSTANCE_PIXMAP_HEIGHT (ii),
853 IMAGE_INSTANCE_PIXMAP_DEPTH (ii));
855 sprintf (buf, " %dx%d", IMAGE_INSTANCE_PIXMAP_WIDTH (ii),
856 IMAGE_INSTANCE_PIXMAP_HEIGHT (ii));
857 write_c_string (buf, printcharfun);
858 if (!NILP (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii)) ||
859 !NILP (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii)))
861 write_c_string (" @", printcharfun);
862 if (!NILP (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii)))
864 long_to_string (buf, XINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii)));
865 write_c_string (buf, printcharfun);
868 write_c_string ("??", printcharfun);
869 write_c_string (",", printcharfun);
870 if (!NILP (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii)))
872 long_to_string (buf, XINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii)));
873 write_c_string (buf, printcharfun);
876 write_c_string ("??", printcharfun);
878 if (!NILP (IMAGE_INSTANCE_PIXMAP_FG (ii)) ||
879 !NILP (IMAGE_INSTANCE_PIXMAP_BG (ii)))
881 write_c_string (" (", printcharfun);
882 if (!NILP (IMAGE_INSTANCE_PIXMAP_FG (ii)))
886 (IMAGE_INSTANCE_PIXMAP_FG (ii))->name, printcharfun, 0);
888 write_c_string ("/", printcharfun);
889 if (!NILP (IMAGE_INSTANCE_PIXMAP_BG (ii)))
893 (IMAGE_INSTANCE_PIXMAP_BG (ii))->name, printcharfun, 0);
895 write_c_string (")", printcharfun);
900 print_internal (IMAGE_INSTANCE_WIDGET_TYPE (ii), printcharfun, 0);
902 if (GUI_ITEMP (IMAGE_INSTANCE_WIDGET_ITEM (ii)))
904 write_c_string (" ", printcharfun);
905 print_internal (IMAGE_INSTANCE_WIDGET_TEXT (ii), printcharfun, 1);
908 if (!NILP (IMAGE_INSTANCE_WIDGET_FACE (ii)))
910 write_c_string (" face=", printcharfun);
912 (IMAGE_INSTANCE_WIDGET_FACE (ii), printcharfun, 0);
916 case IMAGE_SUBWINDOW:
917 sprintf (buf, " %dx%d", IMAGE_INSTANCE_WIDTH (ii),
918 IMAGE_INSTANCE_HEIGHT (ii));
919 write_c_string (buf, printcharfun);
921 /* This is stolen from frame.c. Subwindows are strange in that they
922 are specific to a particular frame so we want to print in their
923 description what that frame is. */
925 write_c_string (" on #<", printcharfun);
927 struct frame* f = XFRAME (IMAGE_INSTANCE_FRAME (ii));
929 if (!FRAME_LIVE_P (f))
930 write_c_string ("dead", printcharfun);
932 write_c_string (DEVICE_TYPE_NAME (XDEVICE (FRAME_DEVICE (f))),
935 write_c_string ("-frame>", printcharfun);
936 sprintf (buf, " 0x%p", IMAGE_INSTANCE_SUBWINDOW_ID (ii));
937 write_c_string (buf, printcharfun);
945 MAYBE_DEVMETH (DOMAIN_XDEVICE (ii->domain), print_image_instance,
946 (ii, printcharfun, escapeflag));
947 sprintf (buf, " 0x%x>", ii->header.uid);
948 write_c_string (buf, printcharfun);
952 finalize_image_instance (void *header, int for_disksave)
954 Lisp_Image_Instance *i = (Lisp_Image_Instance *) header;
956 /* objects like this exist at dump time, so don't bomb out. */
957 if (IMAGE_INSTANCE_TYPE (i) == IMAGE_NOTHING
959 NILP (IMAGE_INSTANCE_DEVICE (i)))
961 if (for_disksave) finalose (i);
963 /* We can't use the domain here, because it might have
965 MAYBE_DEVMETH (XDEVICE (IMAGE_INSTANCE_DEVICE (i)),
966 finalize_image_instance, (i));
968 /* Make sure we don't try this twice. */
969 IMAGE_INSTANCE_DEVICE (i) = Qnil;
973 image_instance_equal (Lisp_Object obj1, Lisp_Object obj2, int depth)
975 Lisp_Image_Instance *i1 = XIMAGE_INSTANCE (obj1);
976 Lisp_Image_Instance *i2 = XIMAGE_INSTANCE (obj2);
978 ERROR_CHECK_IMAGE_INSTANCE (obj1);
979 ERROR_CHECK_IMAGE_INSTANCE (obj2);
981 if (!EQ (IMAGE_INSTANCE_DOMAIN (i1),
982 IMAGE_INSTANCE_DOMAIN (i2))
983 || IMAGE_INSTANCE_TYPE (i1) != IMAGE_INSTANCE_TYPE (i2)
984 || IMAGE_INSTANCE_WIDTH (i1) != IMAGE_INSTANCE_WIDTH (i2)
985 || IMAGE_INSTANCE_MARGIN_WIDTH (i1) !=
986 IMAGE_INSTANCE_MARGIN_WIDTH (i2)
987 || IMAGE_INSTANCE_HEIGHT (i1) != IMAGE_INSTANCE_HEIGHT (i2)
988 || IMAGE_INSTANCE_XOFFSET (i1) != IMAGE_INSTANCE_XOFFSET (i2)
989 || IMAGE_INSTANCE_YOFFSET (i1) != IMAGE_INSTANCE_YOFFSET (i2))
991 if (!internal_equal (IMAGE_INSTANCE_NAME (i1), IMAGE_INSTANCE_NAME (i2),
995 switch (IMAGE_INSTANCE_TYPE (i1))
1001 if (!internal_equal (IMAGE_INSTANCE_TEXT_STRING (i1),
1002 IMAGE_INSTANCE_TEXT_STRING (i2),
1007 case IMAGE_MONO_PIXMAP:
1008 case IMAGE_COLOR_PIXMAP:
1010 if (!(IMAGE_INSTANCE_PIXMAP_DEPTH (i1) ==
1011 IMAGE_INSTANCE_PIXMAP_DEPTH (i2) &&
1012 IMAGE_INSTANCE_PIXMAP_SLICE (i1) ==
1013 IMAGE_INSTANCE_PIXMAP_SLICE (i2) &&
1014 EQ (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (i1),
1015 IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (i2)) &&
1016 EQ (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (i1),
1017 IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (i2)) &&
1018 internal_equal (IMAGE_INSTANCE_PIXMAP_FILENAME (i1),
1019 IMAGE_INSTANCE_PIXMAP_FILENAME (i2),
1021 internal_equal (IMAGE_INSTANCE_PIXMAP_MASK_FILENAME (i1),
1022 IMAGE_INSTANCE_PIXMAP_MASK_FILENAME (i2),
1028 if (!(EQ (IMAGE_INSTANCE_WIDGET_TYPE (i1),
1029 IMAGE_INSTANCE_WIDGET_TYPE (i2))
1030 && IMAGE_INSTANCE_SUBWINDOW_ID (i1) ==
1031 IMAGE_INSTANCE_SUBWINDOW_ID (i2)
1033 EQ (IMAGE_INSTANCE_WIDGET_FACE (i1),
1034 IMAGE_INSTANCE_WIDGET_TYPE (i2))
1035 && internal_equal (IMAGE_INSTANCE_WIDGET_ITEMS (i1),
1036 IMAGE_INSTANCE_WIDGET_ITEMS (i2),
1038 && internal_equal (IMAGE_INSTANCE_LAYOUT_CHILDREN (i1),
1039 IMAGE_INSTANCE_LAYOUT_CHILDREN (i2),
1041 && internal_equal (IMAGE_INSTANCE_WIDGET_PROPS (i1),
1042 IMAGE_INSTANCE_WIDGET_PROPS (i2),
1044 && internal_equal (IMAGE_INSTANCE_WIDGET_WIDTH_SUBR (i1),
1045 IMAGE_INSTANCE_WIDGET_WIDTH_SUBR (i2),
1047 && internal_equal (IMAGE_INSTANCE_WIDGET_HEIGHT_SUBR (i1),
1048 IMAGE_INSTANCE_WIDGET_HEIGHT_SUBR (i2),
1054 case IMAGE_SUBWINDOW:
1055 if (!(IMAGE_INSTANCE_SUBWINDOW_ID (i1) ==
1056 IMAGE_INSTANCE_SUBWINDOW_ID (i2)))
1064 return DEVMETH_OR_GIVEN (DOMAIN_XDEVICE (i1->domain),
1065 image_instance_equal, (i1, i2, depth), 1);
1068 /* Image instance domain manipulators. We can't error check in these
1069 otherwise we get into infinite recursion. */
1071 image_instance_device (Lisp_Object instance)
1073 return XIMAGE_INSTANCE_DEVICE (instance);
1077 image_instance_frame (Lisp_Object instance)
1079 return XIMAGE_INSTANCE_FRAME (instance);
1083 image_instance_window (Lisp_Object instance)
1085 return DOMAIN_WINDOW (XIMAGE_INSTANCE_DOMAIN (instance));
1089 image_instance_live_p (Lisp_Object instance)
1091 return DOMAIN_LIVE_P (XIMAGE_INSTANCE_DOMAIN (instance));
1094 static unsigned long
1095 image_instance_hash (Lisp_Object obj, int depth)
1097 Lisp_Image_Instance *i = XIMAGE_INSTANCE (obj);
1098 unsigned long hash = HASH4 (LISP_HASH (IMAGE_INSTANCE_DOMAIN (i)),
1099 IMAGE_INSTANCE_WIDTH (i),
1100 IMAGE_INSTANCE_MARGIN_WIDTH (i),
1101 IMAGE_INSTANCE_HEIGHT (i));
1103 ERROR_CHECK_IMAGE_INSTANCE (obj);
1105 switch (IMAGE_INSTANCE_TYPE (i))
1111 hash = HASH2 (hash, internal_hash (IMAGE_INSTANCE_TEXT_STRING (i),
1115 case IMAGE_MONO_PIXMAP:
1116 case IMAGE_COLOR_PIXMAP:
1118 hash = HASH4 (hash, IMAGE_INSTANCE_PIXMAP_DEPTH (i),
1119 IMAGE_INSTANCE_PIXMAP_SLICE (i),
1120 internal_hash (IMAGE_INSTANCE_PIXMAP_FILENAME (i),
1125 /* We need the hash to be equivalent to what should be
1128 LISP_HASH (IMAGE_INSTANCE_WIDGET_TYPE (i)),
1129 internal_hash (IMAGE_INSTANCE_WIDGET_PROPS (i), depth + 1),
1130 internal_hash (IMAGE_INSTANCE_WIDGET_ITEMS (i), depth + 1),
1131 internal_hash (IMAGE_INSTANCE_LAYOUT_CHILDREN (i),
1133 case IMAGE_SUBWINDOW:
1134 hash = HASH2 (hash, (int) IMAGE_INSTANCE_SUBWINDOW_ID (i));
1141 return HASH2 (hash, DEVMETH_OR_GIVEN
1142 (XDEVICE (image_instance_device (obj)),
1143 image_instance_hash, (i, depth),
1147 DEFINE_LRECORD_IMPLEMENTATION ("image-instance", image_instance,
1148 mark_image_instance, print_image_instance,
1149 finalize_image_instance, image_instance_equal,
1150 image_instance_hash, 0,
1151 Lisp_Image_Instance);
1154 allocate_image_instance (Lisp_Object governing_domain, Lisp_Object glyph)
1156 Lisp_Image_Instance *lp =
1157 alloc_lcrecord_type (Lisp_Image_Instance, &lrecord_image_instance);
1161 /* It's not possible to simply keep a record of the domain in which
1162 the instance was instantiated. This is because caching may mean
1163 that the domain becomes invalid but the instance remains
1164 valid. However, the only truly relevant domain is the domain in
1165 which the instance is cached since this is the one that will be
1166 common to the instances. */
1167 lp->domain = governing_domain;
1168 /* The cache domain is not quite sufficient since the domain can get
1169 deleted before the image instance does. We need to know the
1170 domain device in order to finalize the image instance
1171 properly. We therefore record the device also. */
1172 lp->device = DOMAIN_DEVICE (governing_domain);
1173 lp->type = IMAGE_NOTHING;
1177 lp->width = IMAGE_UNSPECIFIED_GEOMETRY;
1178 lp->margin_width = 0;
1179 lp->height = IMAGE_UNSPECIFIED_GEOMETRY;
1181 /* So that layouts get done. */
1182 lp->layout_changed = 1;
1183 lp->initialized = 0;
1185 XSETIMAGE_INSTANCE (val, lp);
1186 MARK_GLYPHS_CHANGED;
1191 static enum image_instance_type
1192 decode_image_instance_type (Lisp_Object type, Error_behavior errb)
1194 if (ERRB_EQ (errb, ERROR_ME))
1195 CHECK_SYMBOL (type);
1197 if (EQ (type, Qnothing)) return IMAGE_NOTHING;
1198 if (EQ (type, Qtext)) return IMAGE_TEXT;
1199 if (EQ (type, Qmono_pixmap)) return IMAGE_MONO_PIXMAP;
1200 if (EQ (type, Qcolor_pixmap)) return IMAGE_COLOR_PIXMAP;
1201 if (EQ (type, Qpointer)) return IMAGE_POINTER;
1202 if (EQ (type, Qsubwindow)) return IMAGE_SUBWINDOW;
1203 if (EQ (type, Qwidget)) return IMAGE_WIDGET;
1205 maybe_signal_simple_error ("Invalid image-instance type", type,
1208 return IMAGE_UNKNOWN; /* not reached */
1212 encode_image_instance_type (enum image_instance_type type)
1216 case IMAGE_NOTHING: return Qnothing;
1217 case IMAGE_TEXT: return Qtext;
1218 case IMAGE_MONO_PIXMAP: return Qmono_pixmap;
1219 case IMAGE_COLOR_PIXMAP: return Qcolor_pixmap;
1220 case IMAGE_POINTER: return Qpointer;
1221 case IMAGE_SUBWINDOW: return Qsubwindow;
1222 case IMAGE_WIDGET: return Qwidget;
1227 return Qnil; /* not reached */
1231 decode_image_instance_type_list (Lisp_Object list)
1241 enum image_instance_type type =
1242 decode_image_instance_type (list, ERROR_ME);
1243 return image_instance_type_to_mask (type);
1246 EXTERNAL_LIST_LOOP (rest, list)
1248 enum image_instance_type type =
1249 decode_image_instance_type (XCAR (rest), ERROR_ME);
1250 mask |= image_instance_type_to_mask (type);
1257 encode_image_instance_type_list (int mask)
1260 Lisp_Object result = Qnil;
1266 result = Fcons (encode_image_instance_type
1267 ((enum image_instance_type) count), result);
1271 return Fnreverse (result);
1275 incompatible_image_types (Lisp_Object instantiator, int given_dest_mask,
1276 int desired_dest_mask)
1281 (emacs_doprnt_string_lisp_2
1283 "No compatible image-instance types given: wanted one of %s, got %s",
1285 encode_image_instance_type_list (desired_dest_mask),
1286 encode_image_instance_type_list (given_dest_mask)),
1291 valid_image_instance_type_p (Lisp_Object type)
1293 return !NILP (memq_no_quit (type, Vimage_instance_type_list));
1296 DEFUN ("valid-image-instance-type-p", Fvalid_image_instance_type_p, 1, 1, 0, /*
1297 Given an IMAGE-INSTANCE-TYPE, return non-nil if it is valid.
1298 Valid types are some subset of 'nothing, 'text, 'mono-pixmap, 'color-pixmap,
1299 'pointer, 'subwindow, and 'widget, depending on how XEmacs was compiled.
1301 (image_instance_type))
1303 return valid_image_instance_type_p (image_instance_type) ? Qt : Qnil;
1306 DEFUN ("image-instance-type-list", Fimage_instance_type_list, 0, 0, 0, /*
1307 Return a list of valid image-instance types.
1311 return Fcopy_sequence (Vimage_instance_type_list);
1315 decode_error_behavior_flag (Lisp_Object no_error)
1317 if (NILP (no_error)) return ERROR_ME;
1318 else if (EQ (no_error, Qt)) return ERROR_ME_NOT;
1319 else return ERROR_ME_WARN;
1323 encode_error_behavior_flag (Error_behavior errb)
1325 if (ERRB_EQ (errb, ERROR_ME))
1327 else if (ERRB_EQ (errb, ERROR_ME_NOT))
1331 assert (ERRB_EQ (errb, ERROR_ME_WARN));
1336 /* Recurse up the hierarchy looking for the topmost glyph. This means
1337 that instances in layouts will inherit face properties from their
1339 Lisp_Object image_instance_parent_glyph (Lisp_Image_Instance* ii)
1341 if (IMAGE_INSTANCEP (IMAGE_INSTANCE_PARENT (ii)))
1343 return image_instance_parent_glyph
1344 (XIMAGE_INSTANCE (IMAGE_INSTANCE_PARENT (ii)));
1346 return IMAGE_INSTANCE_PARENT (ii);
1350 make_image_instance_1 (Lisp_Object data, Lisp_Object domain,
1351 Lisp_Object dest_types)
1354 struct gcpro gcpro1;
1356 Lisp_Object governing_domain;
1358 if (IMAGE_INSTANCEP (data))
1359 signal_simple_error ("Image instances not allowed here", data);
1360 image_validate (data);
1361 domain = decode_domain (domain);
1362 /* instantiate_image_instantiator() will abort if given an
1363 image instance ... */
1364 dest_mask = decode_image_instance_type_list (dest_types);
1365 data = normalize_image_instantiator (data,
1366 DEVICE_TYPE (DOMAIN_XDEVICE (domain)),
1367 make_int (dest_mask));
1369 /* After normalizing the data, it's always either an image instance (which
1370 we filtered out above) or a vector. */
1371 if (EQ (XVECTOR_DATA (data)[0], Qinherit))
1372 signal_simple_error ("Inheritance not allowed here", data);
1374 get_image_instantiator_governing_domain (data, domain);
1375 ii = instantiate_image_instantiator (governing_domain, domain, data,
1376 Qnil, Qnil, dest_mask, Qnil);
1377 RETURN_UNGCPRO (ii);
1380 DEFUN ("make-image-instance", Fmake_image_instance, 1, 4, 0, /*
1381 Return a new `image-instance' object.
1383 Image-instance objects encapsulate the way a particular image (pixmap,
1384 etc.) is displayed on a particular device. In most circumstances, you
1385 do not need to directly create image instances; use a glyph instead.
1386 However, it may occasionally be useful to explicitly create image
1387 instances, if you want more control over the instantiation process.
1389 DATA is an image instantiator, which describes the image; see
1390 `make-image-specifier' for a description of the allowed values.
1392 DEST-TYPES should be a list of allowed image instance types that can
1393 be generated. The recognized image instance types are
1396 Nothing is displayed.
1398 Displayed as text. The foreground and background colors and the
1399 font of the text are specified independent of the pixmap. Typically
1400 these attributes will come from the face of the surrounding text,
1401 unless a face is specified for the glyph in which the image appears.
1403 Displayed as a mono pixmap (a pixmap with only two colors where the
1404 foreground and background can be specified independent of the pixmap;
1405 typically the pixmap assumes the foreground and background colors of
1406 the text around it, unless a face is specified for the glyph in which
1409 Displayed as a color pixmap.
1411 Used as the mouse pointer for a window.
1413 A child window that is treated as an image. This allows (e.g.)
1414 another program to be responsible for drawing into the window.
1416 A child window that contains a window-system widget, e.g. a push
1417 button, text field, or slider.
1419 The DEST-TYPES list is unordered. If multiple destination types are
1420 possible for a given instantiator, the "most natural" type for the
1421 instantiator's format is chosen. (For XBM, the most natural types are
1422 `mono-pixmap', followed by `color-pixmap', followed by `pointer'. For
1423 the other normal image formats, the most natural types are
1424 `color-pixmap', followed by `mono-pixmap', followed by `pointer'. For
1425 the string and formatted-string formats, the most natural types are
1426 `text', followed by `mono-pixmap' (not currently implemented),
1427 followed by `color-pixmap' (not currently implemented). For MS
1428 Windows resources, the most natural type for pointer resources is
1429 `pointer', and for the others it's `color-pixmap'. The other formats
1430 can only be instantiated as one type. (If you want to control more
1431 specifically the order of the types into which an image is
1432 instantiated, just call `make-image-instance' repeatedly until it
1433 succeeds, passing less and less preferred destination types each
1436 See `make-image-specifier' for a description of the different image
1437 instantiator formats.
1439 If DEST-TYPES is omitted, all possible types are allowed.
1441 DOMAIN specifies the domain to which the image instance will be attached.
1442 This domain is termed the \"governing domain\". The type of the governing
1443 domain depends on the image instantiator format. (Although, more correctly,
1444 it should probably depend on the image instance type.) For example, pixmap
1445 image instances are specific to a device, but widget image instances are
1446 specific to a particular XEmacs window because in order to display such a
1447 widget when two windows onto the same buffer want to display the widget,
1448 two separate underlying widgets must be created. (That's because a widget
1449 is actually a child window-system window, and all window-system windows have
1450 a unique existence on the screen.) This means that the governing domain for
1451 a pixmap image instance will be some device (most likely, the only existing
1452 device), whereas the governing domain for a widget image instance will be
1455 If you specify an overly general DOMAIN (e.g. a frame when a window was
1456 wanted), an error is signaled. If you specify an overly specific DOMAIN
1457 \(e.g. a window when a device was wanted), the corresponding general domain
1458 is fetched and used instead. For `make-image-instance', it makes no
1459 difference whether you specify an overly specific domain or the properly
1460 general domain derived from it. However, it does matter when creating an
1461 image instance by instantiating a specifier or glyph (e.g. with
1462 `glyph-image-instance'), because the more specific domain causes spec lookup
1463 to start there and proceed to more general domains. (It would also matter
1464 when creating an image instance with an instantiator format of `inherit',
1465 but we currently disallow this. #### We should fix this.)
1467 If omitted, DOMAIN defaults to the selected window.
1469 NO-ERROR controls what happens when the image cannot be generated.
1470 If nil, an error message is generated. If t, no messages are
1471 generated and this function returns nil. If anything else, a warning
1472 message is generated and this function returns nil.
1474 (data, domain, dest_types, no_error))
1476 Error_behavior errb = decode_error_behavior_flag (no_error);
1478 return call_with_suspended_errors ((lisp_fn_t) make_image_instance_1,
1480 3, data, domain, dest_types);
1483 DEFUN ("image-instance-p", Fimage_instance_p, 1, 1, 0, /*
1484 Return non-nil if OBJECT is an image instance.
1488 return IMAGE_INSTANCEP (object) ? Qt : Qnil;
1491 DEFUN ("image-instance-type", Fimage_instance_type, 1, 1, 0, /*
1492 Return the type of the given image instance.
1493 The return value will be one of 'nothing, 'text, 'mono-pixmap,
1494 'color-pixmap, 'pointer, or 'subwindow.
1498 CHECK_IMAGE_INSTANCE (image_instance);
1499 ERROR_CHECK_IMAGE_INSTANCE (image_instance);
1500 return encode_image_instance_type (XIMAGE_INSTANCE_TYPE (image_instance));
1503 DEFUN ("image-instance-name", Fimage_instance_name, 1, 1, 0, /*
1504 Return the name of the given image instance.
1508 CHECK_IMAGE_INSTANCE (image_instance);
1509 return XIMAGE_INSTANCE_NAME (image_instance);
1512 DEFUN ("image-instance-domain", Fimage_instance_domain, 1, 1, 0, /*
1513 Return the governing domain of the given image instance.
1514 The governing domain of an image instance is the domain that the image
1515 instance is specific to. It is NOT necessarily the domain that was
1516 given to the call to `specifier-instance' that resulted in the creation
1517 of this image instance. See `make-image-instance' for more information
1518 on governing domains.
1522 CHECK_IMAGE_INSTANCE (image_instance);
1523 return XIMAGE_INSTANCE_DOMAIN (image_instance);
1526 DEFUN ("image-instance-string", Fimage_instance_string, 1, 1, 0, /*
1527 Return the string of the given image instance.
1528 This will only be non-nil for text image instances and widgets.
1532 CHECK_IMAGE_INSTANCE (image_instance);
1533 if (XIMAGE_INSTANCE_TYPE (image_instance) == IMAGE_TEXT)
1534 return XIMAGE_INSTANCE_TEXT_STRING (image_instance);
1535 else if (XIMAGE_INSTANCE_TYPE (image_instance) == IMAGE_WIDGET)
1536 return XIMAGE_INSTANCE_WIDGET_TEXT (image_instance);
1541 DEFUN ("image-instance-property", Fimage_instance_property, 2, 2, 0, /*
1542 Return the given property of the given image instance.
1543 Returns nil if the property or the property method do not exist for
1544 the image instance in the domain.
1546 (image_instance, prop))
1548 Lisp_Image_Instance* ii;
1549 Lisp_Object type, ret;
1550 struct image_instantiator_methods* meths;
1552 CHECK_IMAGE_INSTANCE (image_instance);
1553 ERROR_CHECK_IMAGE_INSTANCE (image_instance);
1554 CHECK_SYMBOL (prop);
1555 ii = XIMAGE_INSTANCE (image_instance);
1557 /* ... then try device specific methods ... */
1558 type = encode_image_instance_type (IMAGE_INSTANCE_TYPE (ii));
1559 meths = decode_device_ii_format (image_instance_device (image_instance),
1560 type, ERROR_ME_NOT);
1561 if (meths && HAS_IIFORMAT_METH_P (meths, property)
1563 !UNBOUNDP (ret = IIFORMAT_METH (meths, property, (image_instance, prop))))
1567 /* ... then format specific methods ... */
1568 meths = decode_device_ii_format (Qnil, type, ERROR_ME_NOT);
1569 if (meths && HAS_IIFORMAT_METH_P (meths, property)
1571 !UNBOUNDP (ret = IIFORMAT_METH (meths, property, (image_instance, prop))))
1579 DEFUN ("set-image-instance-property", Fset_image_instance_property, 3, 3, 0, /*
1580 Set the given property of the given image instance.
1581 Does nothing if the property or the property method do not exist for
1582 the image instance in the domain.
1584 WARNING: If you are thinking about using this function, think again.
1585 You probably want to be using `set-glyph-image' to change the glyph's
1586 specifier. Be especially wary if you are thinking of calling this
1587 function after having called `glyph-image-instance'. Unless you are
1588 absolutely sure what you're doing, pretty much the only legitimate
1589 uses for this function are setting user-specified info in a widget,
1590 such as text in a text field. */
1591 (image_instance, prop, val))
1593 Lisp_Image_Instance* ii;
1594 Lisp_Object type, ret;
1595 struct image_instantiator_methods* meths;
1597 CHECK_IMAGE_INSTANCE (image_instance);
1598 ERROR_CHECK_IMAGE_INSTANCE (image_instance);
1599 CHECK_SYMBOL (prop);
1600 ii = XIMAGE_INSTANCE (image_instance);
1601 type = encode_image_instance_type (IMAGE_INSTANCE_TYPE (ii));
1602 /* try device specific methods first ... */
1603 meths = decode_device_ii_format (image_instance_device (image_instance),
1604 type, ERROR_ME_NOT);
1605 if (meths && HAS_IIFORMAT_METH_P (meths, set_property)
1608 IIFORMAT_METH (meths, set_property, (image_instance, prop, val))))
1614 /* ... then format specific methods ... */
1615 meths = decode_device_ii_format (Qnil, type, ERROR_ME_NOT);
1616 if (meths && HAS_IIFORMAT_METH_P (meths, set_property)
1619 IIFORMAT_METH (meths, set_property, (image_instance, prop, val))))
1629 /* Make sure the image instance gets redisplayed. */
1630 set_image_instance_dirty_p (image_instance, 1);
1631 /* Force the glyph to be laid out again. */
1632 IMAGE_INSTANCE_LAYOUT_CHANGED (ii) = 1;
1634 MARK_SUBWINDOWS_STATE_CHANGED;
1635 MARK_GLYPHS_CHANGED;
1640 DEFUN ("image-instance-file-name", Fimage_instance_file_name, 1, 1, 0, /*
1641 Return the file name from which IMAGE-INSTANCE was read, if known.
1645 CHECK_IMAGE_INSTANCE (image_instance);
1646 ERROR_CHECK_IMAGE_INSTANCE (image_instance);
1648 switch (XIMAGE_INSTANCE_TYPE (image_instance))
1650 case IMAGE_MONO_PIXMAP:
1651 case IMAGE_COLOR_PIXMAP:
1653 return XIMAGE_INSTANCE_PIXMAP_FILENAME (image_instance);
1660 DEFUN ("image-instance-mask-file-name", Fimage_instance_mask_file_name, 1, 1, 0, /*
1661 Return the file name from which IMAGE-INSTANCE's mask was read, if known.
1665 CHECK_IMAGE_INSTANCE (image_instance);
1666 ERROR_CHECK_IMAGE_INSTANCE (image_instance);
1668 switch (XIMAGE_INSTANCE_TYPE (image_instance))
1670 case IMAGE_MONO_PIXMAP:
1671 case IMAGE_COLOR_PIXMAP:
1673 return XIMAGE_INSTANCE_PIXMAP_MASK_FILENAME (image_instance);
1680 DEFUN ("image-instance-depth", Fimage_instance_depth, 1, 1, 0, /*
1681 Return the depth of the image instance.
1682 This is 0 for a bitmap, or a positive integer for a pixmap.
1686 CHECK_IMAGE_INSTANCE (image_instance);
1687 ERROR_CHECK_IMAGE_INSTANCE (image_instance);
1689 switch (XIMAGE_INSTANCE_TYPE (image_instance))
1691 case IMAGE_MONO_PIXMAP:
1692 case IMAGE_COLOR_PIXMAP:
1694 return make_int (XIMAGE_INSTANCE_PIXMAP_DEPTH (image_instance));
1701 DEFUN ("image-instance-height", Fimage_instance_height, 1, 1, 0, /*
1702 Return the height of the image instance, in pixels.
1706 CHECK_IMAGE_INSTANCE (image_instance);
1707 ERROR_CHECK_IMAGE_INSTANCE (image_instance);
1709 switch (XIMAGE_INSTANCE_TYPE (image_instance))
1711 case IMAGE_MONO_PIXMAP:
1712 case IMAGE_COLOR_PIXMAP:
1714 case IMAGE_SUBWINDOW:
1716 return make_int (XIMAGE_INSTANCE_HEIGHT (image_instance));
1723 DEFUN ("image-instance-width", Fimage_instance_width, 1, 1, 0, /*
1724 Return the width of the image instance, in pixels.
1728 CHECK_IMAGE_INSTANCE (image_instance);
1729 ERROR_CHECK_IMAGE_INSTANCE (image_instance);
1731 switch (XIMAGE_INSTANCE_TYPE (image_instance))
1733 case IMAGE_MONO_PIXMAP:
1734 case IMAGE_COLOR_PIXMAP:
1736 case IMAGE_SUBWINDOW:
1738 return make_int (XIMAGE_INSTANCE_WIDTH (image_instance));
1745 DEFUN ("image-instance-hotspot-x", Fimage_instance_hotspot_x, 1, 1, 0, /*
1746 Return the X coordinate of the image instance's hotspot, if known.
1747 This is a point relative to the origin of the pixmap. When an image is
1748 used as a mouse pointer, the hotspot is the point on the image that sits
1749 over the location that the pointer points to. This is, for example, the
1750 tip of the arrow or the center of the crosshairs.
1751 This will always be nil for a non-pointer image instance.
1755 CHECK_IMAGE_INSTANCE (image_instance);
1756 ERROR_CHECK_IMAGE_INSTANCE (image_instance);
1758 switch (XIMAGE_INSTANCE_TYPE (image_instance))
1760 case IMAGE_MONO_PIXMAP:
1761 case IMAGE_COLOR_PIXMAP:
1763 return XIMAGE_INSTANCE_PIXMAP_HOTSPOT_X (image_instance);
1770 DEFUN ("image-instance-hotspot-y", Fimage_instance_hotspot_y, 1, 1, 0, /*
1771 Return the Y coordinate of the image instance's hotspot, if known.
1772 This is a point relative to the origin of the pixmap. When an image is
1773 used as a mouse pointer, the hotspot is the point on the image that sits
1774 over the location that the pointer points to. This is, for example, the
1775 tip of the arrow or the center of the crosshairs.
1776 This will always be nil for a non-pointer image instance.
1780 CHECK_IMAGE_INSTANCE (image_instance);
1781 ERROR_CHECK_IMAGE_INSTANCE (image_instance);
1783 switch (XIMAGE_INSTANCE_TYPE (image_instance))
1785 case IMAGE_MONO_PIXMAP:
1786 case IMAGE_COLOR_PIXMAP:
1788 return XIMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (image_instance);
1795 DEFUN ("image-instance-foreground", Fimage_instance_foreground, 1, 1, 0, /*
1796 Return the foreground color of IMAGE-INSTANCE, if applicable.
1797 This will be a color instance or nil. (It will only be non-nil for
1798 colorized mono pixmaps and for pointers.)
1802 CHECK_IMAGE_INSTANCE (image_instance);
1803 ERROR_CHECK_IMAGE_INSTANCE (image_instance);
1805 switch (XIMAGE_INSTANCE_TYPE (image_instance))
1807 case IMAGE_MONO_PIXMAP:
1808 case IMAGE_COLOR_PIXMAP:
1810 return XIMAGE_INSTANCE_PIXMAP_FG (image_instance);
1813 return FACE_FOREGROUND (
1814 XIMAGE_INSTANCE_WIDGET_FACE (image_instance),
1815 XIMAGE_INSTANCE_FRAME
1823 DEFUN ("image-instance-background", Fimage_instance_background, 1, 1, 0, /*
1824 Return the background color of IMAGE-INSTANCE, if applicable.
1825 This will be a color instance or nil. (It will only be non-nil for
1826 colorized mono pixmaps and for pointers.)
1830 CHECK_IMAGE_INSTANCE (image_instance);
1831 ERROR_CHECK_IMAGE_INSTANCE (image_instance);
1833 switch (XIMAGE_INSTANCE_TYPE (image_instance))
1835 case IMAGE_MONO_PIXMAP:
1836 case IMAGE_COLOR_PIXMAP:
1838 return XIMAGE_INSTANCE_PIXMAP_BG (image_instance);
1841 return FACE_BACKGROUND (
1842 XIMAGE_INSTANCE_WIDGET_FACE (image_instance),
1843 XIMAGE_INSTANCE_FRAME
1852 DEFUN ("colorize-image-instance", Fcolorize_image_instance, 3, 3, 0, /*
1853 Make the image instance be displayed in the given colors.
1854 This function returns a new image instance that is exactly like the
1855 specified one except that (if possible) the foreground and background
1856 colors and as specified. Currently, this only does anything if the image
1857 instance is a mono pixmap; otherwise, the same image instance is returned.
1859 (image_instance, foreground, background))
1864 CHECK_IMAGE_INSTANCE (image_instance);
1865 ERROR_CHECK_IMAGE_INSTANCE (image_instance);
1866 CHECK_COLOR_INSTANCE (foreground);
1867 CHECK_COLOR_INSTANCE (background);
1869 device = image_instance_device (image_instance);
1870 if (!HAS_DEVMETH_P (XDEVICE (device), colorize_image_instance))
1871 return image_instance;
1873 /* #### There should be a copy_image_instance(), which calls a
1874 device-specific method to copy the window-system subobject. */
1875 new = allocate_image_instance (XIMAGE_INSTANCE_DOMAIN (image_instance),
1877 copy_lcrecord (XIMAGE_INSTANCE (new), XIMAGE_INSTANCE (image_instance));
1878 /* note that if this method returns non-zero, this method MUST
1879 copy any window-system resources, so that when one image instance is
1880 freed, the other one is not hosed. */
1881 if (!DEVMETH (XDEVICE (device), colorize_image_instance, (new, foreground,
1883 return image_instance;
1888 /************************************************************************/
1889 /* Geometry calculations */
1890 /************************************************************************/
1892 /* Find out desired geometry of the image instance. If there is no
1893 special function then just return the width and / or height. */
1895 image_instance_query_geometry (Lisp_Object image_instance,
1896 int* width, int* height,
1897 enum image_instance_geometry disp,
1900 Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance);
1902 struct image_instantiator_methods* meths;
1903 ERROR_CHECK_IMAGE_INSTANCE (image_instance);
1905 type = encode_image_instance_type (IMAGE_INSTANCE_TYPE (ii));
1906 meths = decode_device_ii_format (Qnil, type, ERROR_ME_NOT);
1908 if (meths && HAS_IIFORMAT_METH_P (meths, query_geometry))
1910 IIFORMAT_METH (meths, query_geometry, (image_instance, width, height,
1916 *width = IMAGE_INSTANCE_WIDTH (ii);
1918 *height = IMAGE_INSTANCE_HEIGHT (ii);
1922 /* Layout the image instance using the provided dimensions. Layout
1923 widgets are going to do different kinds of calculations to
1924 determine what size to give things so we could make the layout
1925 function relatively simple to take account of that. An alternative
1926 approach is to consider separately the two cases, one where you
1927 don't mind what size you have (normal widgets) and one where you
1928 want to specifiy something (layout widgets). */
1930 image_instance_layout (Lisp_Object image_instance,
1931 int width, int height, Lisp_Object domain)
1933 Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance);
1935 struct image_instantiator_methods* meths;
1937 ERROR_CHECK_IMAGE_INSTANCE (image_instance);
1939 /* Nothing is as nothing does. */
1940 if (NOTHING_IMAGE_INSTANCEP (image_instance))
1943 type = encode_image_instance_type (IMAGE_INSTANCE_TYPE (ii));
1944 meths = decode_device_ii_format (Qnil, type, ERROR_ME_NOT);
1946 /* If geometry is unspecified then get some reasonable values for it. */
1947 if (width == IMAGE_UNSPECIFIED_GEOMETRY
1949 height == IMAGE_UNSPECIFIED_GEOMETRY)
1951 int dwidth = IMAGE_UNSPECIFIED_GEOMETRY;
1952 int dheight = IMAGE_UNSPECIFIED_GEOMETRY;
1954 /* Get the desired geometry. */
1955 if (meths && HAS_IIFORMAT_METH_P (meths, query_geometry))
1957 IIFORMAT_METH (meths, query_geometry, (image_instance, &dwidth, &dheight,
1958 IMAGE_DESIRED_GEOMETRY,
1963 dwidth = IMAGE_INSTANCE_WIDTH (ii);
1964 dheight = IMAGE_INSTANCE_HEIGHT (ii);
1967 /* Compare with allowed geometry. */
1968 if (width == IMAGE_UNSPECIFIED_GEOMETRY)
1970 if (height == IMAGE_UNSPECIFIED_GEOMETRY)
1974 /* If we don't have sane values then we cannot layout at this point and
1975 must just return. */
1976 if (width == IMAGE_UNSPECIFIED_GEOMETRY
1978 height == IMAGE_UNSPECIFIED_GEOMETRY)
1981 /* At this point width and height should contain sane values. Thus
1982 we set the glyph geometry and lay it out. */
1983 if (IMAGE_INSTANCE_WIDTH (ii) != width
1985 IMAGE_INSTANCE_HEIGHT (ii) != height)
1987 IMAGE_INSTANCE_SIZE_CHANGED (ii) = 1;
1990 IMAGE_INSTANCE_WIDTH (ii) = width;
1991 IMAGE_INSTANCE_HEIGHT (ii) = height;
1993 if (IIFORMAT_METH_OR_GIVEN (meths, layout,
1994 (image_instance, width, height, domain), 1))
1995 /* Do not clear the dirty flag here - redisplay will do this for
1997 IMAGE_INSTANCE_LAYOUT_CHANGED (ii) = 0;
2001 * Mark image instance in W as dirty if (a) W's faces have changed and
2002 * (b) GLYPH_OR_II instance in W is a string.
2004 * Return non-zero if instance has been marked dirty.
2007 invalidate_glyph_geometry_maybe (Lisp_Object glyph_or_ii, struct window* w)
2009 if (XFRAME(WINDOW_FRAME(w))->faces_changed)
2011 Lisp_Object image = glyph_or_ii;
2013 if (GLYPHP (glyph_or_ii))
2016 XSETWINDOW (window, w);
2017 image = glyph_image_instance (glyph_or_ii, window, ERROR_ME_NOT, 1);
2020 if (TEXT_IMAGE_INSTANCEP (image))
2022 Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image);
2023 IMAGE_INSTANCE_DIRTYP (ii) = 1;
2024 IMAGE_INSTANCE_LAYOUT_CHANGED (ii) = 1;
2025 if (GLYPHP (glyph_or_ii))
2026 XGLYPH_DIRTYP (glyph_or_ii) = 1;
2035 /************************************************************************/
2037 /************************************************************************/
2039 signal_image_error (const char *reason, Lisp_Object frob)
2041 signal_error (Qimage_conversion_error,
2042 list2 (build_translated_string (reason), frob));
2046 signal_image_error_2 (const char *reason, Lisp_Object frob0, Lisp_Object frob1)
2048 signal_error (Qimage_conversion_error,
2049 list3 (build_translated_string (reason), frob0, frob1));
2052 /****************************************************************************
2054 ****************************************************************************/
2057 nothing_possible_dest_types (void)
2059 return IMAGE_NOTHING_MASK;
2063 nothing_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2064 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2065 int dest_mask, Lisp_Object domain)
2067 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2069 if (dest_mask & IMAGE_NOTHING_MASK)
2071 IMAGE_INSTANCE_TYPE (ii) = IMAGE_NOTHING;
2072 IMAGE_INSTANCE_HEIGHT (ii) = 0;
2073 IMAGE_INSTANCE_WIDTH (ii) = 0;
2076 incompatible_image_types (instantiator, dest_mask, IMAGE_NOTHING_MASK);
2080 /****************************************************************************
2082 ****************************************************************************/
2085 inherit_validate (Lisp_Object instantiator)
2087 face_must_be_present (instantiator);
2091 inherit_normalize (Lisp_Object inst, Lisp_Object console_type)
2095 assert (XVECTOR_LENGTH (inst) == 3);
2096 face = XVECTOR_DATA (inst)[2];
2098 inst = vector3 (Qinherit, Q_face, Fget_face (face));
2103 inherit_possible_dest_types (void)
2105 return IMAGE_MONO_PIXMAP_MASK;
2109 inherit_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2110 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2111 int dest_mask, Lisp_Object domain)
2113 /* handled specially in image_instantiate */
2118 /****************************************************************************
2120 ****************************************************************************/
2123 string_validate (Lisp_Object instantiator)
2125 data_must_be_present (instantiator);
2129 string_possible_dest_types (void)
2131 return IMAGE_TEXT_MASK;
2134 /* Called from autodetect_instantiate() */
2136 string_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2137 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2138 int dest_mask, Lisp_Object domain)
2140 Lisp_Object string = find_keyword_in_vector (instantiator, Q_data);
2141 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2143 /* Should never get here with a domain other than a window. */
2144 assert (!NILP (string) && WINDOWP (DOMAIN_WINDOW (domain)));
2145 if (dest_mask & IMAGE_TEXT_MASK)
2147 IMAGE_INSTANCE_TYPE (ii) = IMAGE_TEXT;
2148 IMAGE_INSTANCE_TEXT_STRING (ii) = string;
2151 incompatible_image_types (instantiator, dest_mask, IMAGE_TEXT_MASK);
2154 /* Sort out the size of the text that is being displayed. Calculating
2155 it dynamically allows us to change the text and still see
2156 everything. Note that the following methods are for text not string
2157 since that is what the instantiated type is. The first method is a
2158 helper that is used elsewhere for calculating text geometry. */
2160 query_string_geometry (Lisp_Object string, Lisp_Object face,
2161 int* width, int* height, int* descent, Lisp_Object domain)
2163 struct font_metric_info fm;
2164 unsigned char charsets[NUM_LEADING_BYTES];
2165 struct face_cachel frame_cachel;
2166 struct face_cachel *cachel;
2167 Lisp_Object frame = DOMAIN_FRAME (domain);
2169 /* Compute height */
2172 /* Compute string metric info */
2173 find_charsets_in_bufbyte_string (charsets,
2174 XSTRING_DATA (string),
2175 XSTRING_LENGTH (string));
2177 /* Fallback to the default face if none was provided. */
2180 reset_face_cachel (&frame_cachel);
2181 update_face_cachel_data (&frame_cachel, frame, face);
2182 cachel = &frame_cachel;
2186 cachel = WINDOW_FACE_CACHEL (DOMAIN_XWINDOW (domain),
2190 ensure_face_cachel_complete (cachel, domain, charsets);
2191 face_cachel_charset_font_metric_info (cachel, charsets, &fm);
2193 *height = fm.ascent + fm.descent;
2194 /* #### descent only gets set if we query the height as well. */
2196 *descent = fm.descent;
2203 *width = redisplay_frame_text_width_string (XFRAME (frame),
2207 *width = redisplay_frame_text_width_string (XFRAME (frame),
2214 query_string_font (Lisp_Object string, Lisp_Object face, Lisp_Object domain)
2216 unsigned char charsets[NUM_LEADING_BYTES];
2217 struct face_cachel frame_cachel;
2218 struct face_cachel *cachel;
2220 Lisp_Object frame = DOMAIN_FRAME (domain);
2222 /* Compute string font info */
2223 find_charsets_in_bufbyte_string (charsets,
2224 XSTRING_DATA (string),
2225 XSTRING_LENGTH (string));
2227 reset_face_cachel (&frame_cachel);
2228 update_face_cachel_data (&frame_cachel, frame, face);
2229 cachel = &frame_cachel;
2231 ensure_face_cachel_complete (cachel, domain, charsets);
2233 for (i = 0; i < NUM_LEADING_BYTES; i++)
2237 return FACE_CACHEL_FONT (cachel,
2238 CHARSET_BY_LEADING_BYTE (i +
2244 return Qnil; /* NOT REACHED */
2248 text_query_geometry (Lisp_Object image_instance,
2249 int* width, int* height,
2250 enum image_instance_geometry disp, Lisp_Object domain)
2252 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2255 query_string_geometry (IMAGE_INSTANCE_TEXT_STRING (ii),
2256 IMAGE_INSTANCE_FACE (ii),
2257 width, height, &descent, domain);
2259 /* The descent gets set as a side effect of querying the
2261 IMAGE_INSTANCE_TEXT_DESCENT (ii) = descent;
2264 /* set the properties of a string */
2266 text_set_property (Lisp_Object image_instance, Lisp_Object prop,
2269 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2271 if (EQ (prop, Q_data))
2274 IMAGE_INSTANCE_TEXT_STRING (ii) = val;
2282 /****************************************************************************
2283 * formatted-string *
2284 ****************************************************************************/
2287 formatted_string_validate (Lisp_Object instantiator)
2289 data_must_be_present (instantiator);
2293 formatted_string_possible_dest_types (void)
2295 return IMAGE_TEXT_MASK;
2299 formatted_string_instantiate (Lisp_Object image_instance,
2300 Lisp_Object instantiator,
2301 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2302 int dest_mask, Lisp_Object domain)
2304 /* #### implement this */
2305 warn_when_safe (Qunimplemented, Qnotice,
2306 "`formatted-string' not yet implemented; assuming `string'");
2308 string_instantiate (image_instance, instantiator,
2309 pointer_fg, pointer_bg, dest_mask, domain);
2313 /************************************************************************/
2314 /* pixmap file functions */
2315 /************************************************************************/
2317 /* If INSTANTIATOR refers to inline data, return Qnil.
2318 If INSTANTIATOR refers to data in a file, return the full filename
2319 if it exists; otherwise, return a cons of (filename).
2321 FILE_KEYWORD and DATA_KEYWORD are symbols specifying the
2322 keywords used to look up the file and inline data,
2323 respectively, in the instantiator. Normally these would
2324 be Q_file and Q_data, but might be different for mask data. */
2327 potential_pixmap_file_instantiator (Lisp_Object instantiator,
2328 Lisp_Object file_keyword,
2329 Lisp_Object data_keyword,
2330 Lisp_Object console_type)
2335 assert (VECTORP (instantiator));
2337 data = find_keyword_in_vector (instantiator, data_keyword);
2338 file = find_keyword_in_vector (instantiator, file_keyword);
2340 if (!NILP (file) && NILP (data))
2342 Lisp_Object retval = MAYBE_LISP_CONTYPE_METH
2343 (decode_console_type(console_type, ERROR_ME),
2344 locate_pixmap_file, (file));
2349 return Fcons (file, Qnil); /* should have been file */
2356 simple_image_type_normalize (Lisp_Object inst, Lisp_Object console_type,
2357 Lisp_Object image_type_tag)
2359 /* This function can call lisp */
2360 Lisp_Object file = Qnil;
2361 struct gcpro gcpro1, gcpro2;
2362 Lisp_Object alist = Qnil;
2364 GCPRO2 (file, alist);
2366 /* Now, convert any file data into inline data. At the end of this,
2367 `data' will contain the inline data (if any) or Qnil, and `file'
2368 will contain the name this data was derived from (if known) or
2371 Note that if we cannot generate any regular inline data, we
2374 file = potential_pixmap_file_instantiator (inst, Q_file, Q_data,
2377 if (CONSP (file)) /* failure locating filename */
2378 signal_double_file_error ("Opening pixmap file",
2379 "no such file or directory",
2382 if (NILP (file)) /* no conversion necessary */
2383 RETURN_UNGCPRO (inst);
2385 alist = tagged_vector_to_alist (inst);
2388 Lisp_Object data = make_string_from_file (file);
2389 alist = remassq_no_quit (Q_file, alist);
2390 /* there can't be a :data at this point. */
2391 alist = Fcons (Fcons (Q_file, file),
2392 Fcons (Fcons (Q_data, data), alist));
2396 Lisp_Object result = alist_to_tagged_vector (image_type_tag, alist);
2398 RETURN_UNGCPRO (result);
2403 #ifdef HAVE_WINDOW_SYSTEM
2404 /**********************************************************************
2406 **********************************************************************/
2408 /* Check if DATA represents a valid inline XBM spec (i.e. a list
2409 of (width height bits), with checking done on the dimensions).
2410 If not, signal an error. */
2413 check_valid_xbm_inline (Lisp_Object data)
2415 Lisp_Object width, height, bits;
2417 if (!CONSP (data) ||
2418 !CONSP (XCDR (data)) ||
2419 !CONSP (XCDR (XCDR (data))) ||
2420 !NILP (XCDR (XCDR (XCDR (data)))))
2421 signal_simple_error ("Must be list of 3 elements", data);
2423 width = XCAR (data);
2424 height = XCAR (XCDR (data));
2425 bits = XCAR (XCDR (XCDR (data)));
2427 CHECK_STRING (bits);
2429 if (!NATNUMP (width))
2430 signal_simple_error ("Width must be a natural number", width);
2432 if (!NATNUMP (height))
2433 signal_simple_error ("Height must be a natural number", height);
2435 if (((XINT (width) * XINT (height)) / 8) > XSTRING_CHAR_LENGTH (bits))
2436 signal_simple_error ("data is too short for width and height",
2437 vector3 (width, height, bits));
2440 /* Validate method for XBM's. */
2443 xbm_validate (Lisp_Object instantiator)
2445 file_or_data_must_be_present (instantiator);
2448 /* Given a filename that is supposed to contain XBM data, return
2449 the inline representation of it as (width height bits). Return
2450 the hotspot through XHOT and YHOT, if those pointers are not 0.
2451 If there is no hotspot, XHOT and YHOT will contain -1.
2453 If the function fails:
2455 -- if OK_IF_DATA_INVALID is set and the data was invalid,
2457 -- maybe return an error, or return Qnil.
2460 #ifdef HAVE_X_WINDOWS
2461 #include <X11/Xlib.h>
2463 #define XFree(data) free(data)
2467 bitmap_to_lisp_data (Lisp_Object name, int *xhot, int *yhot,
2468 int ok_if_data_invalid)
2473 const char *filename_ext;
2475 TO_EXTERNAL_FORMAT (LISP_STRING, name,
2476 C_STRING_ALLOCA, filename_ext,
2478 result = read_bitmap_data_from_file (filename_ext, &w, &h,
2481 if (result == BitmapSuccess)
2484 int len = (w + 7) / 8 * h;
2486 retval = list3 (make_int (w), make_int (h),
2487 make_ext_string (data, len, Qbinary));
2488 XFree ((char *) data);
2494 case BitmapOpenFailed:
2496 /* should never happen */
2497 signal_double_file_error ("Opening bitmap file",
2498 "no such file or directory",
2501 case BitmapFileInvalid:
2503 if (ok_if_data_invalid)
2505 signal_double_file_error ("Reading bitmap file",
2506 "invalid data in file",
2509 case BitmapNoMemory:
2511 signal_double_file_error ("Reading bitmap file",
2517 signal_double_file_error_2 ("Reading bitmap file",
2518 "unknown error code",
2519 make_int (result), name);
2523 return Qnil; /* not reached */
2527 xbm_mask_file_munging (Lisp_Object alist, Lisp_Object file,
2528 Lisp_Object mask_file, Lisp_Object console_type)
2530 /* This is unclean but it's fairly standard -- a number of the
2531 bitmaps in /usr/include/X11/bitmaps use it -- so we support
2533 if (NILP (mask_file)
2534 /* don't override explicitly specified mask data. */
2535 && NILP (assq_no_quit (Q_mask_data, alist))
2538 mask_file = MAYBE_LISP_CONTYPE_METH
2539 (decode_console_type(console_type, ERROR_ME),
2540 locate_pixmap_file, (concat2 (file, build_string ("Mask"))));
2541 if (NILP (mask_file))
2542 mask_file = MAYBE_LISP_CONTYPE_METH
2543 (decode_console_type(console_type, ERROR_ME),
2544 locate_pixmap_file, (concat2 (file, build_string ("msk"))));
2547 if (!NILP (mask_file))
2549 Lisp_Object mask_data =
2550 bitmap_to_lisp_data (mask_file, 0, 0, 0);
2551 alist = remassq_no_quit (Q_mask_file, alist);
2552 /* there can't be a :mask-data at this point. */
2553 alist = Fcons (Fcons (Q_mask_file, mask_file),
2554 Fcons (Fcons (Q_mask_data, mask_data), alist));
2560 /* Normalize method for XBM's. */
2563 xbm_normalize (Lisp_Object inst, Lisp_Object console_type)
2565 Lisp_Object file = Qnil, mask_file = Qnil;
2566 struct gcpro gcpro1, gcpro2, gcpro3;
2567 Lisp_Object alist = Qnil;
2569 GCPRO3 (file, mask_file, alist);
2571 /* Now, convert any file data into inline data for both the regular
2572 data and the mask data. At the end of this, `data' will contain
2573 the inline data (if any) or Qnil, and `file' will contain
2574 the name this data was derived from (if known) or Qnil.
2575 Likewise for `mask_file' and `mask_data'.
2577 Note that if we cannot generate any regular inline data, we
2580 file = potential_pixmap_file_instantiator (inst, Q_file, Q_data,
2582 mask_file = potential_pixmap_file_instantiator (inst, Q_mask_file,
2583 Q_mask_data, console_type);
2585 if (CONSP (file)) /* failure locating filename */
2586 signal_double_file_error ("Opening bitmap file",
2587 "no such file or directory",
2590 if (NILP (file) && NILP (mask_file)) /* no conversion necessary */
2591 RETURN_UNGCPRO (inst);
2593 alist = tagged_vector_to_alist (inst);
2598 Lisp_Object data = bitmap_to_lisp_data (file, &xhot, &yhot, 0);
2599 alist = remassq_no_quit (Q_file, alist);
2600 /* there can't be a :data at this point. */
2601 alist = Fcons (Fcons (Q_file, file),
2602 Fcons (Fcons (Q_data, data), alist));
2604 if (xhot != -1 && NILP (assq_no_quit (Q_hotspot_x, alist)))
2605 alist = Fcons (Fcons (Q_hotspot_x, make_int (xhot)),
2607 if (yhot != -1 && NILP (assq_no_quit (Q_hotspot_y, alist)))
2608 alist = Fcons (Fcons (Q_hotspot_y, make_int (yhot)),
2612 alist = xbm_mask_file_munging (alist, file, mask_file, console_type);
2615 Lisp_Object result = alist_to_tagged_vector (Qxbm, alist);
2617 RETURN_UNGCPRO (result);
2623 xbm_possible_dest_types (void)
2626 IMAGE_MONO_PIXMAP_MASK |
2627 IMAGE_COLOR_PIXMAP_MASK |
2635 /**********************************************************************
2637 **********************************************************************/
2640 xface_validate (Lisp_Object instantiator)
2642 file_or_data_must_be_present (instantiator);
2646 xface_normalize (Lisp_Object inst, Lisp_Object console_type)
2648 /* This function can call lisp */
2649 Lisp_Object file = Qnil, mask_file = Qnil;
2650 struct gcpro gcpro1, gcpro2, gcpro3;
2651 Lisp_Object alist = Qnil;
2653 GCPRO3 (file, mask_file, alist);
2655 /* Now, convert any file data into inline data for both the regular
2656 data and the mask data. At the end of this, `data' will contain
2657 the inline data (if any) or Qnil, and `file' will contain
2658 the name this data was derived from (if known) or Qnil.
2659 Likewise for `mask_file' and `mask_data'.
2661 Note that if we cannot generate any regular inline data, we
2664 file = potential_pixmap_file_instantiator (inst, Q_file, Q_data,
2666 mask_file = potential_pixmap_file_instantiator (inst, Q_mask_file,
2667 Q_mask_data, console_type);
2669 if (CONSP (file)) /* failure locating filename */
2670 signal_double_file_error ("Opening bitmap file",
2671 "no such file or directory",
2674 if (NILP (file) && NILP (mask_file)) /* no conversion necessary */
2675 RETURN_UNGCPRO (inst);
2677 alist = tagged_vector_to_alist (inst);
2680 Lisp_Object data = make_string_from_file (file);
2681 alist = remassq_no_quit (Q_file, alist);
2682 /* there can't be a :data at this point. */
2683 alist = Fcons (Fcons (Q_file, file),
2684 Fcons (Fcons (Q_data, data), alist));
2687 alist = xbm_mask_file_munging (alist, file, mask_file, console_type);
2690 Lisp_Object result = alist_to_tagged_vector (Qxface, alist);
2692 RETURN_UNGCPRO (result);
2697 xface_possible_dest_types (void)
2700 IMAGE_MONO_PIXMAP_MASK |
2701 IMAGE_COLOR_PIXMAP_MASK |
2705 #endif /* HAVE_XFACE */
2710 /**********************************************************************
2712 **********************************************************************/
2715 pixmap_to_lisp_data (Lisp_Object name, int ok_if_data_invalid)
2721 TO_EXTERNAL_FORMAT (LISP_STRING, name,
2722 C_STRING_ALLOCA, fname,
2724 result = XpmReadFileToData (fname, &data);
2726 if (result == XpmSuccess)
2728 Lisp_Object retval = Qnil;
2729 struct buffer *old_buffer = current_buffer;
2730 Lisp_Object temp_buffer =
2731 Fget_buffer_create (build_string (" *pixmap conversion*"));
2733 int height, width, ncolors;
2734 struct gcpro gcpro1, gcpro2, gcpro3;
2735 int speccount = specpdl_depth ();
2737 GCPRO3 (name, retval, temp_buffer);
2739 specbind (Qinhibit_quit, Qt);
2740 set_buffer_internal (XBUFFER (temp_buffer));
2741 Ferase_buffer (Qnil);
2743 buffer_insert_c_string (current_buffer, "/* XPM */\r");
2744 buffer_insert_c_string (current_buffer, "static char *pixmap[] = {\r");
2746 sscanf (data[0], "%d %d %d", &height, &width, &ncolors);
2747 for (elt = 0; elt <= width + ncolors; elt++)
2749 buffer_insert_c_string (current_buffer, "\"");
2750 buffer_insert_c_string (current_buffer, data[elt]);
2752 if (elt < width + ncolors)
2753 buffer_insert_c_string (current_buffer, "\",\r");
2755 buffer_insert_c_string (current_buffer, "\"};\r");
2758 retval = Fbuffer_substring (Qnil, Qnil, Qnil);
2761 set_buffer_internal (old_buffer);
2762 unbind_to (speccount, Qnil);
2764 RETURN_UNGCPRO (retval);
2769 case XpmFileInvalid:
2771 if (ok_if_data_invalid)
2773 signal_image_error ("invalid XPM data in file", name);
2777 signal_double_file_error ("Reading pixmap file",
2778 "out of memory", name);
2782 /* should never happen? */
2783 signal_double_file_error ("Opening pixmap file",
2784 "no such file or directory", name);
2788 signal_double_file_error_2 ("Parsing pixmap file",
2789 "unknown error code",
2790 make_int (result), name);
2795 return Qnil; /* not reached */
2799 check_valid_xpm_color_symbols (Lisp_Object data)
2803 for (rest = data; !NILP (rest); rest = XCDR (rest))
2805 if (!CONSP (rest) ||
2806 !CONSP (XCAR (rest)) ||
2807 !STRINGP (XCAR (XCAR (rest))) ||
2808 (!STRINGP (XCDR (XCAR (rest))) &&
2809 !COLOR_SPECIFIERP (XCDR (XCAR (rest)))))
2810 signal_simple_error ("Invalid color symbol alist", data);
2815 xpm_validate (Lisp_Object instantiator)
2817 file_or_data_must_be_present (instantiator);
2820 Lisp_Object Vxpm_color_symbols;
2823 evaluate_xpm_color_symbols (void)
2825 Lisp_Object rest, results = Qnil;
2826 struct gcpro gcpro1, gcpro2;
2828 GCPRO2 (rest, results);
2829 for (rest = Vxpm_color_symbols; !NILP (rest); rest = XCDR (rest))
2831 Lisp_Object name, value, cons;
2837 CHECK_STRING (name);
2838 value = XCDR (cons);
2840 value = XCAR (value);
2841 value = Feval (value);
2844 if (!STRINGP (value) && !COLOR_SPECIFIERP (value))
2846 ("Result from xpm-color-symbols eval must be nil, string, or color",
2848 results = Fcons (Fcons (name, value), results);
2850 UNGCPRO; /* no more evaluation */
2855 xpm_normalize (Lisp_Object inst, Lisp_Object console_type)
2857 Lisp_Object file = Qnil;
2858 Lisp_Object color_symbols;
2859 struct gcpro gcpro1, gcpro2;
2860 Lisp_Object alist = Qnil;
2862 GCPRO2 (file, alist);
2864 /* Now, convert any file data into inline data. At the end of this,
2865 `data' will contain the inline data (if any) or Qnil, and
2866 `file' will contain the name this data was derived from (if
2869 Note that if we cannot generate any regular inline data, we
2872 file = potential_pixmap_file_instantiator (inst, Q_file, Q_data,
2875 if (CONSP (file)) /* failure locating filename */
2876 signal_double_file_error ("Opening pixmap file",
2877 "no such file or directory",
2880 color_symbols = find_keyword_in_vector_or_given (inst, Q_color_symbols,
2883 if (NILP (file) && !UNBOUNDP (color_symbols))
2884 /* no conversion necessary */
2885 RETURN_UNGCPRO (inst);
2887 alist = tagged_vector_to_alist (inst);
2891 Lisp_Object data = pixmap_to_lisp_data (file, 0);
2892 alist = remassq_no_quit (Q_file, alist);
2893 /* there can't be a :data at this point. */
2894 alist = Fcons (Fcons (Q_file, file),
2895 Fcons (Fcons (Q_data, data), alist));
2898 if (UNBOUNDP (color_symbols))
2900 color_symbols = evaluate_xpm_color_symbols ();
2901 alist = Fcons (Fcons (Q_color_symbols, color_symbols),
2906 Lisp_Object result = alist_to_tagged_vector (Qxpm, alist);
2908 RETURN_UNGCPRO (result);
2913 xpm_possible_dest_types (void)
2916 IMAGE_MONO_PIXMAP_MASK |
2917 IMAGE_COLOR_PIXMAP_MASK |
2921 #endif /* HAVE_XPM */
2924 /****************************************************************************
2925 * Image Specifier Object *
2926 ****************************************************************************/
2928 DEFINE_SPECIFIER_TYPE (image);
2931 image_create (Lisp_Object obj)
2933 Lisp_Specifier *image = XIMAGE_SPECIFIER (obj);
2935 IMAGE_SPECIFIER_ALLOWED (image) = ~0; /* all are allowed */
2936 IMAGE_SPECIFIER_ATTACHEE (image) = Qnil;
2937 IMAGE_SPECIFIER_ATTACHEE_PROPERTY (image) = Qnil;
2941 image_mark (Lisp_Object obj)
2943 Lisp_Specifier *image = XIMAGE_SPECIFIER (obj);
2945 mark_object (IMAGE_SPECIFIER_ATTACHEE (image));
2946 mark_object (IMAGE_SPECIFIER_ATTACHEE_PROPERTY (image));
2950 image_instantiate_cache_result (Lisp_Object locative)
2952 /* locative = (instance instantiator . subtable)
2954 So we are using the instantiator as the key and the instance as
2955 the value. Since the hashtable is key-weak this means that the
2956 image instance will stay around as long as the instantiator stays
2957 around. The instantiator is stored in the `image' slot of the
2958 glyph, so as long as the glyph is marked the instantiator will be
2959 as well and hence the cached image instance also.*/
2960 Fputhash (XCAR (XCDR (locative)), XCAR (locative), XCDR (XCDR (locative)));
2961 free_cons (XCONS (XCDR (locative)));
2962 free_cons (XCONS (locative));
2966 /* Given a specification for an image, return an instance of
2967 the image which matches the given instantiator and which can be
2968 displayed in the given domain. */
2971 image_instantiate (Lisp_Object specifier, Lisp_Object matchspec,
2972 Lisp_Object domain, Lisp_Object instantiator,
2975 Lisp_Object glyph = IMAGE_SPECIFIER_ATTACHEE (XIMAGE_SPECIFIER (specifier));
2976 int dest_mask = XIMAGE_SPECIFIER_ALLOWED (specifier);
2977 int pointerp = dest_mask & image_instance_type_to_mask (IMAGE_POINTER);
2979 if (IMAGE_INSTANCEP (instantiator))
2981 /* make sure that the image instance's governing domain and type are
2983 Lisp_Object governing_domain = XIMAGE_INSTANCE_DOMAIN (instantiator);
2985 if ((DEVICEP (governing_domain)
2986 && EQ (governing_domain, DOMAIN_DEVICE (domain)))
2987 || (FRAMEP (governing_domain)
2988 && EQ (governing_domain, DOMAIN_FRAME (domain)))
2989 || (WINDOWP (governing_domain)
2990 && EQ (governing_domain, DOMAIN_WINDOW (domain))))
2993 image_instance_type_to_mask (XIMAGE_INSTANCE_TYPE (instantiator));
2994 if (mask & dest_mask)
2995 return instantiator;
2997 signal_simple_error ("Type of image instance not allowed here",
3001 signal_simple_error_2 ("Wrong domain for image instance",
3002 instantiator, domain);
3004 else if (VECTORP (instantiator)
3005 && EQ (XVECTOR_DATA (instantiator)[0], Qinherit))
3007 assert (XVECTOR_LENGTH (instantiator) == 3);
3008 return (FACE_PROPERTY_INSTANCE
3009 (Fget_face (XVECTOR_DATA (instantiator)[2]),
3010 Qbackground_pixmap, domain, 0, depth));
3014 Lisp_Object instance = Qnil;
3015 Lisp_Object subtable = Qnil;
3016 Lisp_Object ls3 = Qnil;
3017 Lisp_Object pointer_fg = Qnil;
3018 Lisp_Object pointer_bg = Qnil;
3019 Lisp_Object governing_domain =
3020 get_image_instantiator_governing_domain (instantiator, domain);
3021 struct gcpro gcpro1;
3025 /* We have to put subwindow, widget and text image instances in
3026 a per-window cache so that we can see the same glyph in
3027 different windows. We use governing_domain to determine the type
3028 of image_instance that will be created. */
3032 pointer_fg = FACE_FOREGROUND (Vpointer_face, domain);
3033 pointer_bg = FACE_BACKGROUND (Vpointer_face, domain);
3034 ls3 = list3 (instantiator, pointer_fg, pointer_bg);
3037 /* First look in the device cache. */
3038 if (DEVICEP (governing_domain))
3040 subtable = Fgethash (make_int (dest_mask),
3041 XDEVICE (governing_domain)->
3042 image_instance_cache,
3044 if (UNBOUNDP (subtable))
3046 /* For the image instance cache, we do comparisons with
3047 EQ rather than with EQUAL, as we do for color and
3048 font names. The reasons are:
3050 1) pixmap data can be very long, and thus the hashing
3051 and comparing will take awhile.
3053 2) It's not so likely that we'll run into things that
3054 are EQUAL but not EQ (that can happen a lot with
3055 faces, because their specifiers are copied around);
3056 but pixmaps tend not to be in faces.
3058 However, if the image-instance could be a pointer, we
3059 have to use EQUAL because we massaged the
3060 instantiator into a cons3 also containing the
3061 foreground and background of the pointer face. */
3063 subtable = make_lisp_hash_table
3064 (20, pointerp ? HASH_TABLE_KEY_CAR_WEAK
3065 : HASH_TABLE_KEY_WEAK,
3066 pointerp ? HASH_TABLE_EQUAL
3068 Fputhash (make_int (dest_mask), subtable,
3069 XDEVICE (governing_domain)->image_instance_cache);
3070 instance = Qunbound;
3074 instance = Fgethash (pointerp ? ls3 : instantiator,
3075 subtable, Qunbound);
3078 else if (WINDOWP (governing_domain))
3080 /* Subwindows have a per-window cache and have to be treated
3083 Fgethash (instantiator,
3084 XWINDOW (governing_domain)->subwindow_instance_cache,
3088 abort (); /* We're not allowed anything else currently. */
3090 /* If we don't have an instance at this point then create
3092 if (UNBOUNDP (instance))
3094 Lisp_Object locative =
3096 noseeum_cons (pointerp ? ls3 : instantiator,
3097 DEVICEP (governing_domain) ? subtable
3098 : XWINDOW (governing_domain)
3099 ->subwindow_instance_cache));
3100 int speccount = specpdl_depth ();
3102 /* Make sure we cache the failures, too. Use an
3103 unwind-protect to catch such errors. If we fail, the
3104 unwind-protect records nil in the hash table. If we
3105 succeed, we change the car of the locative to the
3106 resulting instance, which gets recorded instead. */
3107 record_unwind_protect (image_instantiate_cache_result,
3110 instantiate_image_instantiator (governing_domain,
3111 domain, instantiator,
3112 pointer_fg, pointer_bg,
3115 /* We need a per-frame cache for redisplay. */
3116 cache_subwindow_instance_in_frame_maybe (instance);
3118 Fsetcar (locative, instance);
3119 #ifdef ERROR_CHECK_GLYPHS
3120 if (image_instance_type_to_mask (XIMAGE_INSTANCE_TYPE (instance))
3121 & (IMAGE_SUBWINDOW_MASK | IMAGE_WIDGET_MASK))
3122 assert (EQ (XIMAGE_INSTANCE_FRAME (instance),
3123 DOMAIN_FRAME (domain)));
3125 unbind_to (speccount, Qnil);
3126 #ifdef ERROR_CHECK_GLYPHS
3127 if (image_instance_type_to_mask (XIMAGE_INSTANCE_TYPE (instance))
3128 & (IMAGE_SUBWINDOW_MASK | IMAGE_WIDGET_MASK))
3129 assert (EQ (Fgethash ((pointerp ? ls3 : instantiator),
3130 XWINDOW (governing_domain)
3131 ->subwindow_instance_cache,
3132 Qunbound), instance));
3138 if (NILP (instance))
3139 signal_simple_error ("Can't instantiate image (probably cached)",
3141 #ifdef ERROR_CHECK_GLYPHS
3142 if (image_instance_type_to_mask (XIMAGE_INSTANCE_TYPE (instance))
3143 & (IMAGE_SUBWINDOW_MASK | IMAGE_WIDGET_MASK))
3144 assert (EQ (XIMAGE_INSTANCE_FRAME (instance),
3145 DOMAIN_FRAME (domain)));
3147 ERROR_CHECK_IMAGE_INSTANCE (instance);
3148 RETURN_UNGCPRO (instance);
3152 return Qnil; /* not reached */
3155 /* Validate an image instantiator. */
3158 image_validate (Lisp_Object instantiator)
3160 if (IMAGE_INSTANCEP (instantiator) || STRINGP (instantiator))
3162 else if (VECTORP (instantiator))
3164 Lisp_Object *elt = XVECTOR_DATA (instantiator);
3165 int instantiator_len = XVECTOR_LENGTH (instantiator);
3166 struct image_instantiator_methods *meths;
3167 Lisp_Object already_seen = Qnil;
3168 struct gcpro gcpro1;
3171 if (instantiator_len < 1)
3172 signal_simple_error ("Vector length must be at least 1",
3175 meths = decode_image_instantiator_format (elt[0], ERROR_ME);
3176 if (!(instantiator_len & 1))
3178 ("Must have alternating keyword/value pairs", instantiator);
3180 GCPRO1 (already_seen);
3182 for (i = 1; i < instantiator_len; i += 2)
3184 Lisp_Object keyword = elt[i];
3185 Lisp_Object value = elt[i+1];
3188 CHECK_SYMBOL (keyword);
3189 if (!SYMBOL_IS_KEYWORD (keyword))
3190 signal_simple_error ("Symbol must begin with a colon", keyword);
3192 for (j = 0; j < Dynarr_length (meths->keywords); j++)
3193 if (EQ (keyword, Dynarr_at (meths->keywords, j).keyword))
3196 if (j == Dynarr_length (meths->keywords))
3197 signal_simple_error ("Unrecognized keyword", keyword);
3199 if (!Dynarr_at (meths->keywords, j).multiple_p)
3201 if (!NILP (memq_no_quit (keyword, already_seen)))
3203 ("Keyword may not appear more than once", keyword);
3204 already_seen = Fcons (keyword, already_seen);
3207 (Dynarr_at (meths->keywords, j).validate) (value);
3212 MAYBE_IIFORMAT_METH (meths, validate, (instantiator));
3215 signal_simple_error ("Must be string or vector", instantiator);
3219 image_after_change (Lisp_Object specifier, Lisp_Object locale)
3221 Lisp_Object attachee =
3222 IMAGE_SPECIFIER_ATTACHEE (XIMAGE_SPECIFIER (specifier));
3223 Lisp_Object property =
3224 IMAGE_SPECIFIER_ATTACHEE_PROPERTY (XIMAGE_SPECIFIER (specifier));
3225 if (FACEP (attachee))
3226 face_property_was_changed (attachee, property, locale);
3227 else if (GLYPHP (attachee))
3228 glyph_property_was_changed (attachee, property, locale);
3232 set_image_attached_to (Lisp_Object obj, Lisp_Object face_or_glyph,
3233 Lisp_Object property)
3235 Lisp_Specifier *image = XIMAGE_SPECIFIER (obj);
3237 IMAGE_SPECIFIER_ATTACHEE (image) = face_or_glyph;
3238 IMAGE_SPECIFIER_ATTACHEE_PROPERTY (image) = property;
3242 image_going_to_add (Lisp_Object specifier, Lisp_Object locale,
3243 Lisp_Object tag_set, Lisp_Object instantiator)
3245 Lisp_Object possible_console_types = Qnil;
3247 Lisp_Object retlist = Qnil;
3248 struct gcpro gcpro1, gcpro2;
3250 LIST_LOOP (rest, Vconsole_type_list)
3252 Lisp_Object contype = XCAR (rest);
3253 if (!NILP (memq_no_quit (contype, tag_set)))
3254 possible_console_types = Fcons (contype, possible_console_types);
3257 if (XINT (Flength (possible_console_types)) > 1)
3258 /* two conflicting console types specified */
3261 if (NILP (possible_console_types))
3262 possible_console_types = Vconsole_type_list;
3264 GCPRO2 (retlist, possible_console_types);
3266 LIST_LOOP (rest, possible_console_types)
3268 Lisp_Object contype = XCAR (rest);
3269 Lisp_Object newinst = call_with_suspended_errors
3270 ((lisp_fn_t) normalize_image_instantiator,
3271 Qnil, Qimage, ERROR_ME_NOT, 3, instantiator, contype,
3272 make_int (XIMAGE_SPECIFIER_ALLOWED (specifier)));
3274 if (!NILP (newinst))
3277 if (NILP (memq_no_quit (contype, tag_set)))
3278 newtag = Fcons (contype, tag_set);
3281 retlist = Fcons (Fcons (newtag, newinst), retlist);
3290 /* Copy an image instantiator. We can't use Fcopy_tree since widgets
3291 may contain circular references which would send Fcopy_tree into
3294 image_copy_vector_instantiator (Lisp_Object instantiator)
3297 struct image_instantiator_methods *meths;
3299 int instantiator_len;
3301 CHECK_VECTOR (instantiator);
3303 instantiator = Fcopy_sequence (instantiator);
3304 elt = XVECTOR_DATA (instantiator);
3305 instantiator_len = XVECTOR_LENGTH (instantiator);
3307 meths = decode_image_instantiator_format (elt[0], ERROR_ME);
3309 for (i = 1; i < instantiator_len; i += 2)
3312 Lisp_Object keyword = elt[i];
3313 Lisp_Object value = elt[i+1];
3315 /* Find the keyword entry. */
3316 for (j = 0; j < Dynarr_length (meths->keywords); j++)
3318 if (EQ (keyword, Dynarr_at (meths->keywords, j).keyword))
3322 /* Only copy keyword values that should be copied. */
3323 if (Dynarr_at (meths->keywords, j).copy_p
3325 (CONSP (value) || VECTORP (value)))
3327 elt [i+1] = Fcopy_tree (value, Qt);
3331 return instantiator;
3335 image_copy_instantiator (Lisp_Object arg)
3340 rest = arg = Fcopy_sequence (arg);
3341 while (CONSP (rest))
3343 Lisp_Object elt = XCAR (rest);
3345 XCAR (rest) = Fcopy_tree (elt, Qt);
3346 else if (VECTORP (elt))
3347 XCAR (rest) = image_copy_vector_instantiator (elt);
3348 if (VECTORP (XCDR (rest))) /* hack for (a b . [c d]) */
3349 XCDR (rest) = Fcopy_tree (XCDR (rest), Qt);
3353 else if (VECTORP (arg))
3355 arg = image_copy_vector_instantiator (arg);
3360 DEFUN ("image-specifier-p", Fimage_specifier_p, 1, 1, 0, /*
3361 Return non-nil if OBJECT is an image specifier.
3362 See `make-image-specifier' for a description of image instantiators.
3366 return IMAGE_SPECIFIERP (object) ? Qt : Qnil;
3370 /****************************************************************************
3372 ****************************************************************************/
3375 mark_glyph (Lisp_Object obj)
3377 Lisp_Glyph *glyph = XGLYPH (obj);
3379 mark_object (glyph->image);
3380 mark_object (glyph->contrib_p);
3381 mark_object (glyph->baseline);
3382 mark_object (glyph->face);
3384 return glyph->plist;
3388 print_glyph (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
3390 Lisp_Glyph *glyph = XGLYPH (obj);
3394 error ("printing unreadable object #<glyph 0x%x>", glyph->header.uid);
3396 write_c_string ("#<glyph (", printcharfun);
3397 print_internal (Fglyph_type (obj), printcharfun, 0);
3398 write_c_string (") ", printcharfun);
3399 print_internal (glyph->image, printcharfun, 1);
3400 sprintf (buf, "0x%x>", glyph->header.uid);
3401 write_c_string (buf, printcharfun);
3404 /* Glyphs are equal if all of their display attributes are equal. We
3405 don't compare names or doc-strings, because that would make equal
3408 This isn't concerned with "unspecified" attributes, that's what
3409 #'glyph-differs-from-default-p is for. */
3411 glyph_equal (Lisp_Object obj1, Lisp_Object obj2, int depth)
3413 Lisp_Glyph *g1 = XGLYPH (obj1);
3414 Lisp_Glyph *g2 = XGLYPH (obj2);
3418 return (internal_equal (g1->image, g2->image, depth) &&
3419 internal_equal (g1->contrib_p, g2->contrib_p, depth) &&
3420 internal_equal (g1->baseline, g2->baseline, depth) &&
3421 internal_equal (g1->face, g2->face, depth) &&
3422 !plists_differ (g1->plist, g2->plist, 0, 0, depth + 1));
3425 static unsigned long
3426 glyph_hash (Lisp_Object obj, int depth)
3430 /* No need to hash all of the elements; that would take too long.
3431 Just hash the most common ones. */
3432 return HASH2 (internal_hash (XGLYPH (obj)->image, depth),
3433 internal_hash (XGLYPH (obj)->face, depth));
3437 glyph_getprop (Lisp_Object obj, Lisp_Object prop)
3439 Lisp_Glyph *g = XGLYPH (obj);
3441 if (EQ (prop, Qimage)) return g->image;
3442 if (EQ (prop, Qcontrib_p)) return g->contrib_p;
3443 if (EQ (prop, Qbaseline)) return g->baseline;
3444 if (EQ (prop, Qface)) return g->face;
3446 return external_plist_get (&g->plist, prop, 0, ERROR_ME);
3450 glyph_putprop (Lisp_Object obj, Lisp_Object prop, Lisp_Object value)
3452 if (EQ (prop, Qimage) ||
3453 EQ (prop, Qcontrib_p) ||
3454 EQ (prop, Qbaseline))
3457 if (EQ (prop, Qface))
3459 XGLYPH (obj)->face = Fget_face (value);
3463 external_plist_put (&XGLYPH (obj)->plist, prop, value, 0, ERROR_ME);
3468 glyph_remprop (Lisp_Object obj, Lisp_Object prop)
3470 if (EQ (prop, Qimage) ||
3471 EQ (prop, Qcontrib_p) ||
3472 EQ (prop, Qbaseline))
3475 if (EQ (prop, Qface))
3477 XGLYPH (obj)->face = Qnil;
3481 return external_remprop (&XGLYPH (obj)->plist, prop, 0, ERROR_ME);
3485 glyph_plist (Lisp_Object obj)
3487 Lisp_Glyph *glyph = XGLYPH (obj);
3488 Lisp_Object result = glyph->plist;
3490 result = cons3 (Qface, glyph->face, result);
3491 result = cons3 (Qbaseline, glyph->baseline, result);
3492 result = cons3 (Qcontrib_p, glyph->contrib_p, result);
3493 result = cons3 (Qimage, glyph->image, result);
3498 static const struct lrecord_description glyph_description[] = {
3499 { XD_LISP_OBJECT, offsetof (Lisp_Glyph, image) },
3500 { XD_LISP_OBJECT, offsetof (Lisp_Glyph, contrib_p) },
3501 { XD_LISP_OBJECT, offsetof (Lisp_Glyph, baseline) },
3502 { XD_LISP_OBJECT, offsetof (Lisp_Glyph, face) },
3503 { XD_LISP_OBJECT, offsetof (Lisp_Glyph, plist) },
3507 DEFINE_LRECORD_IMPLEMENTATION_WITH_PROPS ("glyph", glyph,
3508 mark_glyph, print_glyph, 0,
3509 glyph_equal, glyph_hash, glyph_description,
3510 glyph_getprop, glyph_putprop,
3511 glyph_remprop, glyph_plist,
3515 allocate_glyph (enum glyph_type type,
3516 void (*after_change) (Lisp_Object glyph, Lisp_Object property,
3517 Lisp_Object locale))
3519 /* This function can GC */
3520 Lisp_Object obj = Qnil;
3521 Lisp_Glyph *g = alloc_lcrecord_type (Lisp_Glyph, &lrecord_glyph);
3524 g->image = Fmake_specifier (Qimage); /* This function can GC */
3529 XIMAGE_SPECIFIER_ALLOWED (g->image) =
3530 IMAGE_NOTHING_MASK | IMAGE_TEXT_MASK
3531 | IMAGE_MONO_PIXMAP_MASK | IMAGE_COLOR_PIXMAP_MASK
3532 | IMAGE_SUBWINDOW_MASK | IMAGE_WIDGET_MASK;
3535 XIMAGE_SPECIFIER_ALLOWED (g->image) =
3536 IMAGE_NOTHING_MASK | IMAGE_POINTER_MASK;
3539 XIMAGE_SPECIFIER_ALLOWED (g->image) =
3540 IMAGE_NOTHING_MASK | IMAGE_MONO_PIXMAP_MASK
3541 | IMAGE_COLOR_PIXMAP_MASK;
3547 /* I think Fmake_specifier can GC. I think set_specifier_fallback can GC. */
3548 /* We're getting enough reports of odd behavior in this area it seems */
3549 /* best to GCPRO everything. */
3551 Lisp_Object tem1 = list1 (Fcons (Qnil, Vthe_nothing_vector));
3552 Lisp_Object tem2 = list1 (Fcons (Qnil, Qt));
3553 Lisp_Object tem3 = list1 (Fcons (Qnil, Qnil));
3554 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
3556 GCPRO4 (obj, tem1, tem2, tem3);
3558 set_specifier_fallback (g->image, tem1);
3559 g->contrib_p = Fmake_specifier (Qboolean);
3560 set_specifier_fallback (g->contrib_p, tem2);
3561 /* #### should have a specifier for the following */
3562 g->baseline = Fmake_specifier (Qgeneric);
3563 set_specifier_fallback (g->baseline, tem3);
3566 g->after_change = after_change;
3569 set_image_attached_to (g->image, obj, Qimage);
3576 static enum glyph_type
3577 decode_glyph_type (Lisp_Object type, Error_behavior errb)
3580 return GLYPH_BUFFER;
3582 if (ERRB_EQ (errb, ERROR_ME))
3583 CHECK_SYMBOL (type);
3585 if (EQ (type, Qbuffer)) return GLYPH_BUFFER;
3586 if (EQ (type, Qpointer)) return GLYPH_POINTER;
3587 if (EQ (type, Qicon)) return GLYPH_ICON;
3589 maybe_signal_simple_error ("Invalid glyph type", type, Qimage, errb);
3591 return GLYPH_UNKNOWN;
3595 valid_glyph_type_p (Lisp_Object type)
3597 return !NILP (memq_no_quit (type, Vglyph_type_list));
3600 DEFUN ("valid-glyph-type-p", Fvalid_glyph_type_p, 1, 1, 0, /*
3601 Given a GLYPH-TYPE, return non-nil if it is valid.
3602 Valid types are `buffer', `pointer', and `icon'.
3606 return valid_glyph_type_p (glyph_type) ? Qt : Qnil;
3609 DEFUN ("glyph-type-list", Fglyph_type_list, 0, 0, 0, /*
3610 Return a list of valid glyph types.
3614 return Fcopy_sequence (Vglyph_type_list);
3617 DEFUN ("make-glyph-internal", Fmake_glyph_internal, 0, 1, 0, /*
3618 Create and return a new uninitialized glyph or type TYPE.
3620 TYPE specifies the type of the glyph; this should be one of `buffer',
3621 `pointer', or `icon', and defaults to `buffer'. The type of the glyph
3622 specifies in which contexts the glyph can be used, and controls the
3623 allowable image types into which the glyph's image can be
3626 `buffer' glyphs can be used as the begin-glyph or end-glyph of an
3627 extent, in the modeline, and in the toolbar. Their image can be
3628 instantiated as `nothing', `mono-pixmap', `color-pixmap', `text',
3631 `pointer' glyphs can be used to specify the mouse pointer. Their
3632 image can be instantiated as `pointer'.
3634 `icon' glyphs can be used to specify the icon used when a frame is
3635 iconified. Their image can be instantiated as `mono-pixmap' and
3640 enum glyph_type typeval = decode_glyph_type (type, ERROR_ME);
3641 return allocate_glyph (typeval, 0);
3644 DEFUN ("glyphp", Fglyphp, 1, 1, 0, /*
3645 Return non-nil if OBJECT is a glyph.
3647 A glyph is an object used for pixmaps, widgets and the like. It is used
3648 in begin-glyphs and end-glyphs attached to extents, in marginal and textual
3649 annotations, in overlay arrows (overlay-arrow-* variables), in toolbar
3650 buttons, and the like. Much more detailed information can be found at
3651 `make-glyph'. Its image is described using an image specifier --
3652 see `make-image-specifier'. See also `make-image-instance' for further
3657 return GLYPHP (object) ? Qt : Qnil;
3660 DEFUN ("glyph-type", Fglyph_type, 1, 1, 0, /*
3661 Return the type of the given glyph.
3662 The return value will be one of 'buffer, 'pointer, or 'icon.
3666 CHECK_GLYPH (glyph);
3667 switch (XGLYPH_TYPE (glyph))
3670 case GLYPH_BUFFER: return Qbuffer;
3671 case GLYPH_POINTER: return Qpointer;
3672 case GLYPH_ICON: return Qicon;
3677 glyph_image_instance (Lisp_Object glyph, Lisp_Object domain,
3678 Error_behavior errb, int no_quit)
3680 Lisp_Object specifier = GLYPH_IMAGE (XGLYPH (glyph));
3682 /* This can never return Qunbound. All glyphs have 'nothing as
3684 Lisp_Object image_instance = specifier_instance (specifier, Qunbound,
3685 domain, errb, no_quit, 0,
3687 assert (!UNBOUNDP (image_instance));
3688 ERROR_CHECK_IMAGE_INSTANCE (image_instance);
3690 return image_instance;
3694 glyph_image_instance_maybe (Lisp_Object glyph_or_image, Lisp_Object window)
3696 Lisp_Object instance = glyph_or_image;
3698 if (GLYPHP (glyph_or_image))
3699 instance = glyph_image_instance (glyph_or_image, window, ERROR_ME_NOT, 1);
3704 /*****************************************************************************
3707 Return the width of the given GLYPH on the given WINDOW.
3708 Calculations are done based on recursively querying the geometry of
3709 the associated image instances.
3710 ****************************************************************************/
3712 glyph_width (Lisp_Object glyph_or_image, Lisp_Object domain)
3714 Lisp_Object instance = glyph_image_instance_maybe (glyph_or_image,
3716 if (!IMAGE_INSTANCEP (instance))
3719 if (XIMAGE_INSTANCE_NEEDS_LAYOUT (instance))
3720 image_instance_layout (instance, IMAGE_UNSPECIFIED_GEOMETRY,
3721 IMAGE_UNSPECIFIED_GEOMETRY, domain);
3723 return XIMAGE_INSTANCE_WIDTH (instance);
3726 DEFUN ("glyph-width", Fglyph_width, 1, 2, 0, /*
3727 Return the width of GLYPH on WINDOW.
3728 This may not be exact as it does not take into account all of the context
3729 that redisplay will.
3733 XSETWINDOW (window, decode_window (window));
3734 CHECK_GLYPH (glyph);
3736 return make_int (glyph_width (glyph, window));
3740 glyph_ascent (Lisp_Object glyph_or_image, Lisp_Object domain)
3742 Lisp_Object instance = glyph_image_instance_maybe (glyph_or_image,
3744 if (!IMAGE_INSTANCEP (instance))
3747 if (XIMAGE_INSTANCE_NEEDS_LAYOUT (instance))
3748 image_instance_layout (instance, IMAGE_UNSPECIFIED_GEOMETRY,
3749 IMAGE_UNSPECIFIED_GEOMETRY, domain);
3751 if (XIMAGE_INSTANCE_TYPE (instance) == IMAGE_TEXT)
3752 return XIMAGE_INSTANCE_TEXT_ASCENT (instance);
3754 return XIMAGE_INSTANCE_HEIGHT (instance);
3758 glyph_descent (Lisp_Object glyph_or_image, Lisp_Object domain)
3760 Lisp_Object instance = glyph_image_instance_maybe (glyph_or_image,
3762 if (!IMAGE_INSTANCEP (instance))
3765 if (XIMAGE_INSTANCE_NEEDS_LAYOUT (instance))
3766 image_instance_layout (instance, IMAGE_UNSPECIFIED_GEOMETRY,
3767 IMAGE_UNSPECIFIED_GEOMETRY, domain);
3769 if (XIMAGE_INSTANCE_TYPE (instance) == IMAGE_TEXT)
3770 return XIMAGE_INSTANCE_TEXT_DESCENT (instance);
3775 /* strictly a convenience function. */
3777 glyph_height (Lisp_Object glyph_or_image, Lisp_Object domain)
3779 Lisp_Object instance = glyph_image_instance_maybe (glyph_or_image,
3782 if (!IMAGE_INSTANCEP (instance))
3785 if (XIMAGE_INSTANCE_NEEDS_LAYOUT (instance))
3786 image_instance_layout (instance, IMAGE_UNSPECIFIED_GEOMETRY,
3787 IMAGE_UNSPECIFIED_GEOMETRY, domain);
3789 return XIMAGE_INSTANCE_HEIGHT (instance);
3792 DEFUN ("glyph-ascent", Fglyph_ascent, 1, 2, 0, /*
3793 Return the ascent value of GLYPH on WINDOW.
3794 This may not be exact as it does not take into account all of the context
3795 that redisplay will.
3799 XSETWINDOW (window, decode_window (window));
3800 CHECK_GLYPH (glyph);
3802 return make_int (glyph_ascent (glyph, window));
3805 DEFUN ("glyph-descent", Fglyph_descent, 1, 2, 0, /*
3806 Return the descent value of GLYPH on WINDOW.
3807 This may not be exact as it does not take into account all of the context
3808 that redisplay will.
3812 XSETWINDOW (window, decode_window (window));
3813 CHECK_GLYPH (glyph);
3815 return make_int (glyph_descent (glyph, window));
3818 /* This is redundant but I bet a lot of people expect it to exist. */
3819 DEFUN ("glyph-height", Fglyph_height, 1, 2, 0, /*
3820 Return the height of GLYPH on WINDOW.
3821 This may not be exact as it does not take into account all of the context
3822 that redisplay will.
3826 XSETWINDOW (window, decode_window (window));
3827 CHECK_GLYPH (glyph);
3829 return make_int (glyph_height (glyph, window));
3833 set_glyph_dirty_p (Lisp_Object glyph_or_image, Lisp_Object window, int dirty)
3835 Lisp_Object instance = glyph_or_image;
3837 if (!NILP (glyph_or_image))
3839 if (GLYPHP (glyph_or_image))
3841 instance = glyph_image_instance (glyph_or_image, window,
3843 XGLYPH_DIRTYP (glyph_or_image) = dirty;
3846 if (!IMAGE_INSTANCEP (instance))
3849 XIMAGE_INSTANCE_DIRTYP (instance) = dirty;
3854 set_image_instance_dirty_p (Lisp_Object instance, int dirty)
3856 if (IMAGE_INSTANCEP (instance))
3858 XIMAGE_INSTANCE_DIRTYP (instance) = dirty;
3859 /* Now cascade up the hierarchy. */
3860 set_image_instance_dirty_p (XIMAGE_INSTANCE_PARENT (instance),
3863 else if (GLYPHP (instance))
3865 XGLYPH_DIRTYP (instance) = dirty;
3869 /* #### do we need to cache this info to speed things up? */
3872 glyph_baseline (Lisp_Object glyph, Lisp_Object domain)
3874 if (!GLYPHP (glyph))
3878 Lisp_Object retval =
3879 specifier_instance_no_quit (GLYPH_BASELINE (XGLYPH (glyph)),
3880 /* #### look into ERROR_ME_NOT */
3881 Qunbound, domain, ERROR_ME_NOT,
3883 if (!NILP (retval) && !INTP (retval))
3885 else if (INTP (retval))
3887 if (XINT (retval) < 0)
3889 if (XINT (retval) > 100)
3890 retval = make_int (100);
3897 glyph_face (Lisp_Object glyph, Lisp_Object domain)
3899 /* #### Domain parameter not currently used but it will be */
3900 return GLYPHP (glyph) ? GLYPH_FACE (XGLYPH (glyph)) : Qnil;
3904 glyph_contrib_p (Lisp_Object glyph, Lisp_Object domain)
3906 if (!GLYPHP (glyph))
3909 return !NILP (specifier_instance_no_quit
3910 (GLYPH_CONTRIB_P (XGLYPH (glyph)), Qunbound, domain,
3911 /* #### look into ERROR_ME_NOT */
3912 ERROR_ME_NOT, 0, Qzero));
3916 glyph_property_was_changed (Lisp_Object glyph, Lisp_Object property,
3919 if (XGLYPH (glyph)->after_change)
3920 (XGLYPH (glyph)->after_change) (glyph, property, locale);
3923 #if 0 /* Not used for now */
3925 glyph_query_geometry (Lisp_Object glyph_or_image, Lisp_Object window,
3926 unsigned int* width, unsigned int* height,
3927 enum image_instance_geometry disp, Lisp_Object domain)
3929 Lisp_Object instance = glyph_or_image;
3931 if (GLYPHP (glyph_or_image))
3932 instance = glyph_image_instance (glyph_or_image, window, ERROR_ME_NOT, 1);
3934 image_instance_query_geometry (instance, width, height, disp, domain);
3938 glyph_layout (Lisp_Object glyph_or_image, Lisp_Object window,
3939 unsigned int width, unsigned int height, Lisp_Object domain)
3941 Lisp_Object instance = glyph_or_image;
3943 if (GLYPHP (glyph_or_image))
3944 instance = glyph_image_instance (glyph_or_image, window, ERROR_ME_NOT, 1);
3946 image_instance_layout (instance, width, height, domain);
3951 /*****************************************************************************
3952 * glyph cachel functions *
3953 *****************************************************************************/
3955 /* #### All of this is 95% copied from face cachels. Consider
3958 Why do we need glyph_cachels? Simply because a glyph_cachel captures
3959 per-window information about a particular glyph. A glyph itself is
3960 not created in any particular context, so if we were to rely on a
3961 glyph to tell us about its dirtiness we would not be able to reset
3962 the dirty flag after redisplaying it as it may exist in other
3963 contexts. When we have redisplayed we need to know which glyphs to
3964 reset the dirty flags on - the glyph_cachels give us a nice list we
3965 can iterate through doing this. */
3967 mark_glyph_cachels (glyph_cachel_dynarr *elements)
3974 for (elt = 0; elt < Dynarr_length (elements); elt++)
3976 struct glyph_cachel *cachel = Dynarr_atp (elements, elt);
3977 mark_object (cachel->glyph);
3982 update_glyph_cachel_data (struct window *w, Lisp_Object glyph,
3983 struct glyph_cachel *cachel)
3985 if (!cachel->updated || NILP (cachel->glyph) || !EQ (cachel->glyph, glyph)
3986 || XGLYPH_DIRTYP (cachel->glyph)
3987 || XFRAME(WINDOW_FRAME(w))->faces_changed)
3989 Lisp_Object window, instance;
3991 XSETWINDOW (window, w);
3993 cachel->glyph = glyph;
3994 /* Speed things up slightly by grabbing the glyph instantiation
3995 and passing it to the size functions. */
3996 instance = glyph_image_instance (glyph, window, ERROR_ME_NOT, 1);
3998 if (!IMAGE_INSTANCEP (instance))
4001 /* Mark text instance of the glyph dirty if faces have changed,
4002 because its geometry might have changed. */
4003 invalidate_glyph_geometry_maybe (instance, w);
4005 /* #### Do the following 2 lines buy us anything? --kkm */
4006 XGLYPH_DIRTYP (glyph) = XIMAGE_INSTANCE_DIRTYP (instance);
4007 cachel->dirty = XGLYPH_DIRTYP (glyph);
4008 cachel->width = glyph_width (instance, window);
4009 cachel->ascent = glyph_ascent (instance, window);
4010 cachel->descent = glyph_descent (instance, window);
4013 cachel->updated = 1;
4017 add_glyph_cachel (struct window *w, Lisp_Object glyph)
4019 struct glyph_cachel new_cachel;
4022 new_cachel.glyph = Qnil;
4024 update_glyph_cachel_data (w, glyph, &new_cachel);
4025 Dynarr_add (w->glyph_cachels, new_cachel);
4029 get_glyph_cachel_index (struct window *w, Lisp_Object glyph)
4036 for (elt = 0; elt < Dynarr_length (w->glyph_cachels); elt++)
4038 struct glyph_cachel *cachel =
4039 Dynarr_atp (w->glyph_cachels, elt);
4041 if (EQ (cachel->glyph, glyph) && !NILP (glyph))
4043 update_glyph_cachel_data (w, glyph, cachel);
4048 /* If we didn't find the glyph, add it and then return its index. */
4049 add_glyph_cachel (w, glyph);
4054 reset_glyph_cachels (struct window *w)
4056 Dynarr_reset (w->glyph_cachels);
4057 get_glyph_cachel_index (w, Vcontinuation_glyph);
4058 get_glyph_cachel_index (w, Vtruncation_glyph);
4059 get_glyph_cachel_index (w, Vhscroll_glyph);
4060 get_glyph_cachel_index (w, Vcontrol_arrow_glyph);
4061 get_glyph_cachel_index (w, Voctal_escape_glyph);
4062 get_glyph_cachel_index (w, Vinvisible_text_glyph);
4066 mark_glyph_cachels_as_not_updated (struct window *w)
4070 /* We need to have a dirty flag to tell if the glyph has changed.
4071 We can check to see if each glyph variable is actually a
4072 completely different glyph, though. */
4073 #define FROB(glyph_obj, gindex) \
4074 update_glyph_cachel_data (w, glyph_obj, \
4075 Dynarr_atp (w->glyph_cachels, gindex))
4077 FROB (Vcontinuation_glyph, CONT_GLYPH_INDEX);
4078 FROB (Vtruncation_glyph, TRUN_GLYPH_INDEX);
4079 FROB (Vhscroll_glyph, HSCROLL_GLYPH_INDEX);
4080 FROB (Vcontrol_arrow_glyph, CONTROL_GLYPH_INDEX);
4081 FROB (Voctal_escape_glyph, OCT_ESC_GLYPH_INDEX);
4082 FROB (Vinvisible_text_glyph, INVIS_GLYPH_INDEX);
4085 for (elt = 0; elt < Dynarr_length (w->glyph_cachels); elt++)
4087 Dynarr_atp (w->glyph_cachels, elt)->updated = 0;
4091 /* Unset the dirty bit on all the glyph cachels that have it. */
4093 mark_glyph_cachels_as_clean (struct window* w)
4097 XSETWINDOW (window, w);
4098 for (elt = 0; elt < Dynarr_length (w->glyph_cachels); elt++)
4100 struct glyph_cachel *cachel = Dynarr_atp (w->glyph_cachels, elt);
4102 set_glyph_dirty_p (cachel->glyph, window, 0);
4106 #ifdef MEMORY_USAGE_STATS
4109 compute_glyph_cachel_usage (glyph_cachel_dynarr *glyph_cachels,
4110 struct overhead_stats *ovstats)
4115 total += Dynarr_memory_usage (glyph_cachels, ovstats);
4120 #endif /* MEMORY_USAGE_STATS */
4124 /*****************************************************************************
4125 * subwindow cachel functions *
4126 *****************************************************************************/
4127 /* Subwindows are curious in that you have to physically unmap them to
4128 not display them. It is problematic deciding what to do in
4129 redisplay. We have two caches - a per-window instance cache that
4130 keeps track of subwindows on a window, these are linked to their
4131 instantiator in the hashtable and when the instantiator goes away
4132 we want the instance to go away also. However we also have a
4133 per-frame instance cache that we use to determine if a subwindow is
4134 obscuring an area that we want to clear. We need to be able to flip
4135 through this quickly so a hashtable is not suitable hence the
4136 subwindow_cachels. This is a weak list so unreference instances
4137 will get deleted properly. */
4139 /* redisplay in general assumes that drawing something will erase
4140 what was there before. unfortunately this does not apply to
4141 subwindows that need to be specifically unmapped in order to
4142 disappear. we take a brute force approach - on the basis that its
4143 cheap - and unmap all subwindows in a display line */
4145 /* Put new instances in the frame subwindow cache. This is less costly than
4146 doing it every time something gets mapped, and deleted instances will be
4147 removed automatically. */
4149 cache_subwindow_instance_in_frame_maybe (Lisp_Object instance)
4151 Lisp_Image_Instance* ii = XIMAGE_INSTANCE (instance);
4152 if (!NILP (DOMAIN_FRAME (IMAGE_INSTANCE_DOMAIN (ii))))
4154 struct frame* f = DOMAIN_XFRAME (IMAGE_INSTANCE_DOMAIN (ii));
4155 XWEAK_LIST_LIST (FRAME_SUBWINDOW_CACHE (f))
4156 = Fcons (instance, XWEAK_LIST_LIST (FRAME_SUBWINDOW_CACHE (f)));
4160 /* Unmap and finalize all subwindow instances in the frame cache. This
4161 is necessary because GC will not guarantee the order things get
4162 deleted in and moreover, frame finalization deletes the window
4163 system windows before deleting XEmacs windows, and hence
4166 free_frame_subwindow_instance_cache (struct frame* f)
4170 LIST_LOOP (rest, XWEAK_LIST_LIST (FRAME_SUBWINDOW_CACHE (f)))
4172 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (XCAR (rest));
4173 /* Make sure that the subwindow is unmapped so that window
4174 deletion will not try and do it again. */
4175 unmap_subwindow (XCAR (rest));
4176 finalize_image_instance (ii, 0);
4180 /* Unmap and remove all instances from the frame cache. */
4182 reset_frame_subwindow_instance_cache (struct frame* f)
4186 LIST_LOOP (rest, XWEAK_LIST_LIST (FRAME_SUBWINDOW_CACHE (f)))
4188 Lisp_Object value = XCAR (rest);
4189 /* Make sure that the subwindow is unmapped so that window
4190 deletion will not try and do it again. */
4191 unmap_subwindow (value);
4192 XWEAK_LIST_LIST (FRAME_SUBWINDOW_CACHE (f))
4193 = delq_no_quit (value, XWEAK_LIST_LIST (FRAME_SUBWINDOW_CACHE (f)));
4197 /*****************************************************************************
4198 * subwindow exposure ignorance *
4199 *****************************************************************************/
4200 /* when we unmap subwindows the associated window system will generate
4201 expose events. This we do not want as redisplay already copes with
4202 the repainting necessary. Worse, we can get in an endless cycle of
4203 redisplay if we are not careful. Thus we keep a per-frame list of
4204 expose events that are going to come and ignore them as
4207 struct expose_ignore_blocktype
4209 Blocktype_declare (struct expose_ignore);
4210 } *the_expose_ignore_blocktype;
4213 check_for_ignored_expose (struct frame* f, int x, int y, int width, int height)
4215 struct expose_ignore *ei, *prev;
4216 /* the ignore list is FIFO so we should generally get a match with
4217 the first element in the list */
4218 for (ei = f->subwindow_exposures, prev = 0; ei; ei = ei->next)
4220 /* Checking for exact matches just isn't good enough as we
4221 mighte get exposures for partially obscure subwindows, thus
4222 we have to check for overlaps. Being conservative we will
4223 check for exposures wholly contained by the subwindow, this
4224 might give us what we want.*/
4225 if (ei->x <= x && ei->y <= y
4226 && ei->x + ei->width >= x + width
4227 && ei->y + ei->height >= y + height)
4229 #ifdef DEBUG_WIDGETS
4230 stderr_out ("ignored %d+%d, %dx%d for exposure %d+%d, %dx%d\n",
4231 x, y, width, height, ei->x, ei->y, ei->width, ei->height);
4234 f->subwindow_exposures = ei->next;
4236 prev->next = ei->next;
4238 if (ei == f->subwindow_exposures_tail)
4239 f->subwindow_exposures_tail = prev;
4241 Blocktype_free (the_expose_ignore_blocktype, ei);
4250 register_ignored_expose (struct frame* f, int x, int y, int width, int height)
4252 if (!hold_ignored_expose_registration)
4254 struct expose_ignore *ei;
4256 ei = Blocktype_alloc (the_expose_ignore_blocktype);
4262 ei->height = height;
4264 /* we have to add the exposure to the end of the list, since we
4265 want to check the oldest events first. for speed we keep a record
4266 of the end so that we can add right to it. */
4267 if (f->subwindow_exposures_tail)
4269 f->subwindow_exposures_tail->next = ei;
4271 if (!f->subwindow_exposures)
4273 f->subwindow_exposures = ei;
4275 f->subwindow_exposures_tail = ei;
4279 /****************************************************************************
4280 find_matching_subwindow
4282 See if there is a subwindow that completely encloses the requested
4284 ****************************************************************************/
4285 int find_matching_subwindow (struct frame* f, int x, int y, int width, int height)
4289 LIST_LOOP (rest, XWEAK_LIST_LIST (FRAME_SUBWINDOW_CACHE (f)))
4291 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (XCAR (rest));
4293 if (IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (ii)
4295 IMAGE_INSTANCE_DISPLAY_X (ii) <= x
4297 IMAGE_INSTANCE_DISPLAY_Y (ii) <= y
4299 IMAGE_INSTANCE_DISPLAY_X (ii)
4300 + IMAGE_INSTANCE_DISPLAY_WIDTH (ii) >= x + width
4302 IMAGE_INSTANCE_DISPLAY_Y (ii)
4303 + IMAGE_INSTANCE_DISPLAY_HEIGHT (ii) >= y + height)
4312 /*****************************************************************************
4313 * subwindow functions *
4314 *****************************************************************************/
4316 /* Update the displayed characteristics of a subwindow. This function
4317 should generally only get called if the subwindow is actually
4320 update_subwindow (Lisp_Object subwindow)
4322 Lisp_Image_Instance* ii = XIMAGE_INSTANCE (subwindow);
4323 int count = specpdl_depth ();
4325 /* The update method is allowed to call eval. Since it is quite
4326 common for this function to get called from somewhere in
4327 redisplay we need to make sure that quits are ignored. Otherwise
4328 Fsignal will abort. */
4329 specbind (Qinhibit_quit, Qt);
4331 ERROR_CHECK_IMAGE_INSTANCE (subwindow);
4333 if (WIDGET_IMAGE_INSTANCEP (subwindow))
4335 if (image_instance_changed (subwindow))
4336 update_widget (subwindow);
4337 /* Reset the changed flags. */
4338 IMAGE_INSTANCE_WIDGET_FACE_CHANGED (ii) = 0;
4339 IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii) = 0;
4340 IMAGE_INSTANCE_TEXT_CHANGED (ii) = 0;
4342 else if (IMAGE_INSTANCE_TYPE (ii) == IMAGE_SUBWINDOW
4344 !NILP (IMAGE_INSTANCE_FRAME (ii)))
4346 MAYBE_DEVMETH (DOMAIN_XDEVICE (ii->domain),
4347 update_subwindow, (ii));
4350 IMAGE_INSTANCE_SIZE_CHANGED (ii) = 0;
4351 /* This function is typically called by redisplay just before
4352 outputting the information to the screen. Thus we record a hash
4353 of the output to determine whether on-screen is the same as
4354 recorded structure. This approach has limitations in there is a
4355 good chance that hash values will be different for the same
4356 visual appearance. However, we would rather that then the other
4357 way round - it simply means that we will get more displays than
4358 we might need. We can get better hashing by making the depth
4359 negative - currently it will recurse down 7 levels.*/
4360 IMAGE_INSTANCE_DISPLAY_HASH (ii) = internal_hash (subwindow,
4361 IMAGE_INSTANCE_HASH_DEPTH);
4363 unbind_to (count, Qnil);
4367 image_instance_changed (Lisp_Object subwindow)
4369 Lisp_Image_Instance* ii = XIMAGE_INSTANCE (subwindow);
4371 if (internal_hash (subwindow, IMAGE_INSTANCE_HASH_DEPTH) !=
4372 IMAGE_INSTANCE_DISPLAY_HASH (ii))
4374 /* #### I think there is probably a bug here. This gets called for
4375 layouts - and yet the pending items are always nil for
4376 layouts. We are saved by layout optimization, but I'm undecided
4377 as to what the correct fix is. */
4378 else if (WIDGET_IMAGE_INSTANCEP (subwindow)
4379 && (!internal_equal (IMAGE_INSTANCE_WIDGET_ITEMS (ii),
4380 IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii), 0)
4381 || !NILP (IMAGE_INSTANCE_LAYOUT_CHILDREN (ii))))
4387 /* Update all the subwindows on a frame. */
4389 update_widget_instances (Lisp_Object frame)
4394 /* Its possible for the preceeding callback to have deleted the
4395 frame, so cope with this. */
4396 if (!FRAMEP (frame) || !FRAME_LIVE_P (XFRAME (frame)))
4399 CHECK_FRAME (frame);
4402 /* If we get called we know something has changed. */
4403 LIST_LOOP (rest, XWEAK_LIST_LIST (FRAME_SUBWINDOW_CACHE (f)))
4405 Lisp_Object widget = XCAR (rest);
4407 if (XIMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (widget)
4409 image_instance_changed (widget))
4411 set_image_instance_dirty_p (widget, 1);
4412 MARK_FRAME_GLYPHS_CHANGED (f);
4417 /* remove a subwindow from its frame */
4418 void unmap_subwindow (Lisp_Object subwindow)
4420 Lisp_Image_Instance* ii = XIMAGE_INSTANCE (subwindow);
4423 ERROR_CHECK_IMAGE_INSTANCE (subwindow);
4425 if (!image_instance_type_to_mask (IMAGE_INSTANCE_TYPE (ii))
4426 & (IMAGE_WIDGET_MASK | IMAGE_SUBWINDOW_MASK)
4428 !IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (ii))
4431 #ifdef DEBUG_WIDGETS
4432 stderr_out ("unmapping subwindow %d\n", IMAGE_INSTANCE_SUBWINDOW_ID (ii));
4434 f = XFRAME (IMAGE_INSTANCE_FRAME (ii));
4436 /* make sure we don't get expose events */
4437 register_ignored_expose (f, IMAGE_INSTANCE_DISPLAY_X (ii),
4438 IMAGE_INSTANCE_DISPLAY_Y (ii),
4439 IMAGE_INSTANCE_DISPLAY_WIDTH (ii),
4440 IMAGE_INSTANCE_DISPLAY_HEIGHT (ii));
4441 IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (ii) = 0;
4443 MAYBE_DEVMETH (XDEVICE (IMAGE_INSTANCE_DEVICE (ii)),
4444 unmap_subwindow, (ii));
4447 /* show a subwindow in its frame */
4448 void map_subwindow (Lisp_Object subwindow, int x, int y,
4449 struct display_glyph_area *dga)
4451 Lisp_Image_Instance* ii = XIMAGE_INSTANCE (subwindow);
4454 ERROR_CHECK_IMAGE_INSTANCE (subwindow);
4456 if (!image_instance_type_to_mask (IMAGE_INSTANCE_TYPE (ii))
4457 & (IMAGE_WIDGET_MASK | IMAGE_SUBWINDOW_MASK))
4460 #ifdef DEBUG_WIDGETS
4461 stderr_out ("mapping subwindow %d, %dx%d@%d+%d\n",
4462 IMAGE_INSTANCE_SUBWINDOW_ID (ii),
4463 dga->width, dga->height, x, y);
4465 f = XFRAME (IMAGE_INSTANCE_FRAME (ii));
4466 IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (ii) = 1;
4467 IMAGE_INSTANCE_DISPLAY_X (ii) = x;
4468 IMAGE_INSTANCE_DISPLAY_Y (ii) = y;
4469 IMAGE_INSTANCE_DISPLAY_WIDTH (ii) = dga->width;
4470 IMAGE_INSTANCE_DISPLAY_HEIGHT (ii) = dga->height;
4472 MAYBE_DEVMETH (DOMAIN_XDEVICE (ii->domain),
4473 map_subwindow, (ii, x, y, dga));
4477 subwindow_possible_dest_types (void)
4479 return IMAGE_SUBWINDOW_MASK;
4483 subwindow_governing_domain (void)
4485 return GOVERNING_DOMAIN_WINDOW;
4488 /* Partially instantiate a subwindow. */
4490 subwindow_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
4491 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
4492 int dest_mask, Lisp_Object domain)
4494 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
4495 Lisp_Object device = image_instance_device (image_instance);
4496 Lisp_Object frame = DOMAIN_FRAME (domain);
4497 Lisp_Object width = find_keyword_in_vector (instantiator, Q_pixel_width);
4498 Lisp_Object height = find_keyword_in_vector (instantiator, Q_pixel_height);
4501 signal_simple_error ("No selected frame", device);
4503 if (!(dest_mask & IMAGE_SUBWINDOW_MASK))
4504 incompatible_image_types (instantiator, dest_mask, IMAGE_SUBWINDOW_MASK);
4507 IMAGE_INSTANCE_SUBWINDOW_ID (ii) = 0;
4508 IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (ii) = 0;
4513 if (XINT (width) > 1)
4515 IMAGE_INSTANCE_WIDTH (ii) = w;
4516 IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii) = 0;
4522 if (XINT (height) > 1)
4524 IMAGE_INSTANCE_HEIGHT (ii) = h;
4525 IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii) = 0;
4529 /* This is just a backup in case no-one has assigned a suitable geometry.
4530 #### It should really query the enclose window for geometry. */
4532 subwindow_query_geometry (Lisp_Object image_instance, int* width,
4533 int* height, enum image_instance_geometry disp,
4536 if (width) *width = 20;
4537 if (height) *height = 20;
4540 DEFUN ("subwindowp", Fsubwindowp, 1, 1, 0, /*
4541 Return non-nil if OBJECT is a subwindow.
4545 CHECK_IMAGE_INSTANCE (object);
4546 return (XIMAGE_INSTANCE_TYPE (object) == IMAGE_SUBWINDOW) ? Qt : Qnil;
4549 DEFUN ("image-instance-subwindow-id", Fimage_instance_subwindow_id, 1, 1, 0, /*
4550 Return the window id of SUBWINDOW as a number.
4554 CHECK_SUBWINDOW_IMAGE_INSTANCE (subwindow);
4555 return make_int ((int) XIMAGE_INSTANCE_SUBWINDOW_ID (subwindow));
4558 DEFUN ("resize-subwindow", Fresize_subwindow, 1, 3, 0, /*
4559 Resize SUBWINDOW to WIDTH x HEIGHT.
4560 If a value is nil that parameter is not changed.
4562 (subwindow, width, height))
4565 Lisp_Image_Instance* ii;
4567 CHECK_SUBWINDOW_IMAGE_INSTANCE (subwindow);
4568 ii = XIMAGE_INSTANCE (subwindow);
4571 neww = IMAGE_INSTANCE_WIDTH (ii);
4573 neww = XINT (width);
4576 newh = IMAGE_INSTANCE_HEIGHT (ii);
4578 newh = XINT (height);
4580 /* The actual resizing gets done asychronously by
4581 update_subwindow. */
4582 IMAGE_INSTANCE_HEIGHT (ii) = newh;
4583 IMAGE_INSTANCE_WIDTH (ii) = neww;
4584 IMAGE_INSTANCE_SIZE_CHANGED (ii) = 1;
4589 DEFUN ("force-subwindow-map", Fforce_subwindow_map, 1, 1, 0, /*
4590 Generate a Map event for SUBWINDOW.
4594 CHECK_SUBWINDOW_IMAGE_INSTANCE (subwindow);
4596 map_subwindow (subwindow, 0, 0);
4602 /*****************************************************************************
4604 *****************************************************************************/
4606 /* Get the display tables for use currently on window W with face
4607 FACE. #### This will have to be redone. */
4610 get_display_tables (struct window *w, face_index findex,
4611 Lisp_Object *face_table, Lisp_Object *window_table)
4614 tem = WINDOW_FACE_CACHEL_DISPLAY_TABLE (w, findex);
4618 tem = noseeum_cons (tem, Qnil);
4620 tem = w->display_table;
4624 tem = noseeum_cons (tem, Qnil);
4625 *window_table = tem;
4629 display_table_entry (Emchar ch, Lisp_Object face_table,
4630 Lisp_Object window_table)
4634 /* Loop over FACE_TABLE, and then over WINDOW_TABLE. */
4635 for (tail = face_table; 1; tail = XCDR (tail))
4640 if (!NILP (window_table))
4642 tail = window_table;
4643 window_table = Qnil;
4648 table = XCAR (tail);
4650 if (VECTORP (table))
4652 if (ch < XVECTOR_LENGTH (table) && !NILP (XVECTOR_DATA (table)[ch]))
4653 return XVECTOR_DATA (table)[ch];
4657 else if (CHAR_TABLEP (table)
4658 && XCHAR_TABLE_TYPE (table) == CHAR_TABLE_TYPE_CHAR)
4660 return get_char_table (ch, XCHAR_TABLE (table));
4662 else if (CHAR_TABLEP (table)
4663 && XCHAR_TABLE_TYPE (table) == CHAR_TABLE_TYPE_GENERIC)
4665 Lisp_Object gotit = get_char_table (ch, XCHAR_TABLE (table));
4671 else if (RANGE_TABLEP (table))
4673 Lisp_Object gotit = Fget_range_table (make_char (ch), table, Qnil);
4684 /*****************************************************************************
4685 * timeouts for animated glyphs *
4686 *****************************************************************************/
4687 static Lisp_Object Qglyph_animated_timeout_handler;
4689 DEFUN ("glyph-animated-timeout-handler", Fglyph_animated_timeout_handler, 1, 1, 0, /*
4690 Callback function for updating animated images.
4695 CHECK_WEAK_LIST (arg);
4697 if (!NILP (XWEAK_LIST_LIST (arg)) && !NILP (XCAR (XWEAK_LIST_LIST (arg))))
4699 Lisp_Object value = XCAR (XWEAK_LIST_LIST (arg));
4701 if (IMAGE_INSTANCEP (value))
4703 Lisp_Image_Instance* ii = XIMAGE_INSTANCE (value);
4705 if (COLOR_PIXMAP_IMAGE_INSTANCEP (value)
4707 IMAGE_INSTANCE_PIXMAP_MAXSLICE (ii) > 1
4709 !disable_animated_pixmaps)
4711 /* Increment the index of the image slice we are currently
4713 IMAGE_INSTANCE_PIXMAP_SLICE (ii) =
4714 (IMAGE_INSTANCE_PIXMAP_SLICE (ii) + 1)
4715 % IMAGE_INSTANCE_PIXMAP_MAXSLICE (ii);
4716 /* We might need to kick redisplay at this point - but we
4718 MARK_DEVICE_FRAMES_GLYPHS_CHANGED
4719 (XDEVICE (image_instance_device (value)));
4720 /* Cascade dirtiness so that we can have an animated glyph in a layout
4722 set_image_instance_dirty_p (value, 1);
4729 Lisp_Object add_glyph_animated_timeout (EMACS_INT tickms, Lisp_Object image)
4731 Lisp_Object ret = Qnil;
4733 if (tickms > 0 && IMAGE_INSTANCEP (image))
4735 double ms = ((double)tickms) / 1000.0;
4736 struct gcpro gcpro1;
4737 Lisp_Object holder = make_weak_list (WEAK_LIST_SIMPLE);
4740 XWEAK_LIST_LIST (holder) = Fcons (image, Qnil);
4742 ret = Fadd_timeout (make_float (ms),
4743 Qglyph_animated_timeout_handler,
4744 holder, make_float (ms));
4751 void disable_glyph_animated_timeout (int i)
4756 Fdisable_timeout (id);
4760 /*****************************************************************************
4762 *****************************************************************************/
4765 syms_of_glyphs (void)
4767 INIT_LRECORD_IMPLEMENTATION (glyph);
4768 INIT_LRECORD_IMPLEMENTATION (image_instance);
4770 /* image instantiators */
4772 DEFSUBR (Fimage_instantiator_format_list);
4773 DEFSUBR (Fvalid_image_instantiator_format_p);
4774 DEFSUBR (Fset_console_type_image_conversion_list);
4775 DEFSUBR (Fconsole_type_image_conversion_list);
4777 defkeyword (&Q_file, ":file");
4778 defkeyword (&Q_data, ":data");
4779 defkeyword (&Q_face, ":face");
4780 defkeyword (&Q_pixel_height, ":pixel-height");
4781 defkeyword (&Q_pixel_width, ":pixel-width");
4784 defkeyword (&Q_color_symbols, ":color-symbols");
4786 #ifdef HAVE_WINDOW_SYSTEM
4787 defkeyword (&Q_mask_file, ":mask-file");
4788 defkeyword (&Q_mask_data, ":mask-data");
4789 defkeyword (&Q_hotspot_x, ":hotspot-x");
4790 defkeyword (&Q_hotspot_y, ":hotspot-y");
4791 defkeyword (&Q_foreground, ":foreground");
4792 defkeyword (&Q_background, ":background");
4794 /* image specifiers */
4796 DEFSUBR (Fimage_specifier_p);
4797 /* Qimage in general.c */
4799 /* image instances */
4801 defsymbol (&Qimage_instancep, "image-instance-p");
4803 defsymbol (&Qnothing_image_instance_p, "nothing-image-instance-p");
4804 defsymbol (&Qtext_image_instance_p, "text-image-instance-p");
4805 defsymbol (&Qmono_pixmap_image_instance_p, "mono-pixmap-image-instance-p");
4806 defsymbol (&Qcolor_pixmap_image_instance_p, "color-pixmap-image-instance-p");
4807 defsymbol (&Qpointer_image_instance_p, "pointer-image-instance-p");
4808 defsymbol (&Qwidget_image_instance_p, "widget-image-instance-p");
4809 defsymbol (&Qsubwindow_image_instance_p, "subwindow-image-instance-p");
4811 DEFSUBR (Fmake_image_instance);
4812 DEFSUBR (Fimage_instance_p);
4813 DEFSUBR (Fimage_instance_type);
4814 DEFSUBR (Fvalid_image_instance_type_p);
4815 DEFSUBR (Fimage_instance_type_list);
4816 DEFSUBR (Fimage_instance_name);
4817 DEFSUBR (Fimage_instance_domain);
4818 DEFSUBR (Fimage_instance_string);
4819 DEFSUBR (Fimage_instance_file_name);
4820 DEFSUBR (Fimage_instance_mask_file_name);
4821 DEFSUBR (Fimage_instance_depth);
4822 DEFSUBR (Fimage_instance_height);
4823 DEFSUBR (Fimage_instance_width);
4824 DEFSUBR (Fimage_instance_hotspot_x);
4825 DEFSUBR (Fimage_instance_hotspot_y);
4826 DEFSUBR (Fimage_instance_foreground);
4827 DEFSUBR (Fimage_instance_background);
4828 DEFSUBR (Fimage_instance_property);
4829 DEFSUBR (Fset_image_instance_property);
4830 DEFSUBR (Fcolorize_image_instance);
4832 DEFSUBR (Fsubwindowp);
4833 DEFSUBR (Fimage_instance_subwindow_id);
4834 DEFSUBR (Fresize_subwindow);
4835 DEFSUBR (Fforce_subwindow_map);
4837 /* Qnothing defined as part of the "nothing" image-instantiator
4839 /* Qtext defined in general.c */
4840 defsymbol (&Qmono_pixmap, "mono-pixmap");
4841 defsymbol (&Qcolor_pixmap, "color-pixmap");
4842 /* Qpointer defined in general.c */
4846 defsymbol (&Qglyphp, "glyphp");
4847 defsymbol (&Qcontrib_p, "contrib-p");
4848 defsymbol (&Qbaseline, "baseline");
4850 defsymbol (&Qbuffer_glyph_p, "buffer-glyph-p");
4851 defsymbol (&Qpointer_glyph_p, "pointer-glyph-p");
4852 defsymbol (&Qicon_glyph_p, "icon-glyph-p");
4854 defsymbol (&Qconst_glyph_variable, "const-glyph-variable");
4856 DEFSUBR (Fglyph_type);
4857 DEFSUBR (Fvalid_glyph_type_p);
4858 DEFSUBR (Fglyph_type_list);
4860 DEFSUBR (Fmake_glyph_internal);
4861 DEFSUBR (Fglyph_width);
4862 DEFSUBR (Fglyph_ascent);
4863 DEFSUBR (Fglyph_descent);
4864 DEFSUBR (Fglyph_height);
4866 /* Qbuffer defined in general.c. */
4867 /* Qpointer defined above */
4869 /* Unfortunately, timeout handlers must be lisp functions. This is
4870 for animated glyphs. */
4871 defsymbol (&Qglyph_animated_timeout_handler,
4872 "glyph-animated-timeout-handler");
4873 DEFSUBR (Fglyph_animated_timeout_handler);
4876 deferror (&Qimage_conversion_error,
4877 "image-conversion-error",
4878 "image-conversion error", Qio_error);
4882 static const struct lrecord_description image_specifier_description[] = {
4883 { XD_LISP_OBJECT, specifier_data_offset + offsetof (struct image_specifier, attachee) },
4884 { XD_LISP_OBJECT, specifier_data_offset + offsetof (struct image_specifier, attachee_property) },
4889 specifier_type_create_image (void)
4891 /* image specifiers */
4893 INITIALIZE_SPECIFIER_TYPE_WITH_DATA (image, "image", "imagep");
4895 SPECIFIER_HAS_METHOD (image, create);
4896 SPECIFIER_HAS_METHOD (image, mark);
4897 SPECIFIER_HAS_METHOD (image, instantiate);
4898 SPECIFIER_HAS_METHOD (image, validate);
4899 SPECIFIER_HAS_METHOD (image, after_change);
4900 SPECIFIER_HAS_METHOD (image, going_to_add);
4901 SPECIFIER_HAS_METHOD (image, copy_instantiator);
4905 reinit_specifier_type_create_image (void)
4907 REINITIALIZE_SPECIFIER_TYPE (image);
4911 static const struct lrecord_description iike_description_1[] = {
4912 { XD_LISP_OBJECT, offsetof (ii_keyword_entry, keyword) },
4916 static const struct struct_description iike_description = {
4917 sizeof (ii_keyword_entry),
4921 static const struct lrecord_description iiked_description_1[] = {
4922 XD_DYNARR_DESC (ii_keyword_entry_dynarr, &iike_description),
4926 static const struct struct_description iiked_description = {
4927 sizeof (ii_keyword_entry_dynarr),
4931 static const struct lrecord_description iife_description_1[] = {
4932 { XD_LISP_OBJECT, offsetof (image_instantiator_format_entry, symbol) },
4933 { XD_LISP_OBJECT, offsetof (image_instantiator_format_entry, device) },
4934 { XD_STRUCT_PTR, offsetof (image_instantiator_format_entry, meths), 1, &iim_description },
4938 static const struct struct_description iife_description = {
4939 sizeof (image_instantiator_format_entry),
4943 static const struct lrecord_description iifed_description_1[] = {
4944 XD_DYNARR_DESC (image_instantiator_format_entry_dynarr, &iife_description),
4948 static const struct struct_description iifed_description = {
4949 sizeof (image_instantiator_format_entry_dynarr),
4953 static const struct lrecord_description iim_description_1[] = {
4954 { XD_LISP_OBJECT, offsetof (struct image_instantiator_methods, symbol) },
4955 { XD_LISP_OBJECT, offsetof (struct image_instantiator_methods, device) },
4956 { XD_STRUCT_PTR, offsetof (struct image_instantiator_methods, keywords), 1, &iiked_description },
4957 { XD_STRUCT_PTR, offsetof (struct image_instantiator_methods, consoles), 1, &cted_description },
4961 const struct struct_description iim_description = {
4962 sizeof(struct image_instantiator_methods),
4967 image_instantiator_format_create (void)
4969 /* image instantiators */
4971 the_image_instantiator_format_entry_dynarr =
4972 Dynarr_new (image_instantiator_format_entry);
4974 Vimage_instantiator_format_list = Qnil;
4975 staticpro (&Vimage_instantiator_format_list);
4977 dumpstruct (&the_image_instantiator_format_entry_dynarr, &iifed_description);
4979 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (nothing, "nothing");
4981 IIFORMAT_HAS_METHOD (nothing, possible_dest_types);
4982 IIFORMAT_HAS_METHOD (nothing, instantiate);
4984 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (inherit, "inherit");
4986 IIFORMAT_HAS_METHOD (inherit, validate);
4987 IIFORMAT_HAS_METHOD (inherit, normalize);
4988 IIFORMAT_HAS_METHOD (inherit, possible_dest_types);
4989 IIFORMAT_HAS_METHOD (inherit, instantiate);
4991 IIFORMAT_VALID_KEYWORD (inherit, Q_face, check_valid_face);
4993 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (string, "string");
4995 IIFORMAT_HAS_METHOD (string, validate);
4996 IIFORMAT_HAS_SHARED_METHOD (string, governing_domain, subwindow);
4997 IIFORMAT_HAS_METHOD (string, possible_dest_types);
4998 IIFORMAT_HAS_METHOD (string, instantiate);
5000 IIFORMAT_VALID_KEYWORD (string, Q_data, check_valid_string);
5001 /* Do this so we can set strings. */
5002 /* #### Andy, what is this? This is a bogus format and should not be
5003 visible to the user. */
5004 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (text, "text");
5005 IIFORMAT_HAS_METHOD (text, set_property);
5006 IIFORMAT_HAS_METHOD (text, query_geometry);
5008 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (formatted_string, "formatted-string");
5010 IIFORMAT_HAS_METHOD (formatted_string, validate);
5011 IIFORMAT_HAS_METHOD (formatted_string, possible_dest_types);
5012 IIFORMAT_HAS_METHOD (formatted_string, instantiate);
5013 IIFORMAT_VALID_KEYWORD (formatted_string, Q_data, check_valid_string);
5015 /* Do this so pointers have geometry. */
5016 /* #### Andy, what is this? This is a bogus format and should not be
5017 visible to the user. */
5018 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (pointer, "pointer");
5019 IIFORMAT_HAS_SHARED_METHOD (pointer, query_geometry, subwindow);
5022 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (subwindow, "subwindow");
5023 IIFORMAT_HAS_METHOD (subwindow, possible_dest_types);
5024 IIFORMAT_HAS_METHOD (subwindow, governing_domain);
5025 IIFORMAT_HAS_METHOD (subwindow, instantiate);
5026 IIFORMAT_HAS_METHOD (subwindow, query_geometry);
5027 IIFORMAT_VALID_KEYWORD (subwindow, Q_pixel_width, check_valid_int);
5028 IIFORMAT_VALID_KEYWORD (subwindow, Q_pixel_height, check_valid_int);
5030 #ifdef HAVE_WINDOW_SYSTEM
5031 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (xbm, "xbm");
5033 IIFORMAT_HAS_METHOD (xbm, validate);
5034 IIFORMAT_HAS_METHOD (xbm, normalize);
5035 IIFORMAT_HAS_METHOD (xbm, possible_dest_types);
5037 IIFORMAT_VALID_KEYWORD (xbm, Q_data, check_valid_xbm_inline);
5038 IIFORMAT_VALID_KEYWORD (xbm, Q_file, check_valid_string);
5039 IIFORMAT_VALID_KEYWORD (xbm, Q_mask_data, check_valid_xbm_inline);
5040 IIFORMAT_VALID_KEYWORD (xbm, Q_mask_file, check_valid_string);
5041 IIFORMAT_VALID_KEYWORD (xbm, Q_hotspot_x, check_valid_int);
5042 IIFORMAT_VALID_KEYWORD (xbm, Q_hotspot_y, check_valid_int);
5043 IIFORMAT_VALID_KEYWORD (xbm, Q_foreground, check_valid_string);
5044 IIFORMAT_VALID_KEYWORD (xbm, Q_background, check_valid_string);
5045 #endif /* HAVE_WINDOW_SYSTEM */
5048 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (xface, "xface");
5050 IIFORMAT_HAS_METHOD (xface, validate);
5051 IIFORMAT_HAS_METHOD (xface, normalize);
5052 IIFORMAT_HAS_METHOD (xface, possible_dest_types);
5054 IIFORMAT_VALID_KEYWORD (xface, Q_data, check_valid_string);
5055 IIFORMAT_VALID_KEYWORD (xface, Q_file, check_valid_string);
5056 IIFORMAT_VALID_KEYWORD (xface, Q_hotspot_x, check_valid_int);
5057 IIFORMAT_VALID_KEYWORD (xface, Q_hotspot_y, check_valid_int);
5058 IIFORMAT_VALID_KEYWORD (xface, Q_foreground, check_valid_string);
5059 IIFORMAT_VALID_KEYWORD (xface, Q_background, check_valid_string);
5063 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (xpm, "xpm");
5065 IIFORMAT_HAS_METHOD (xpm, validate);
5066 IIFORMAT_HAS_METHOD (xpm, normalize);
5067 IIFORMAT_HAS_METHOD (xpm, possible_dest_types);
5069 IIFORMAT_VALID_KEYWORD (xpm, Q_data, check_valid_string);
5070 IIFORMAT_VALID_KEYWORD (xpm, Q_file, check_valid_string);
5071 IIFORMAT_VALID_KEYWORD (xpm, Q_color_symbols, check_valid_xpm_color_symbols);
5072 #endif /* HAVE_XPM */
5076 reinit_vars_of_glyphs (void)
5078 the_expose_ignore_blocktype =
5079 Blocktype_new (struct expose_ignore_blocktype);
5081 hold_ignored_expose_registration = 0;
5086 vars_of_glyphs (void)
5088 reinit_vars_of_glyphs ();
5090 Vthe_nothing_vector = vector1 (Qnothing);
5091 staticpro (&Vthe_nothing_vector);
5093 /* image instances */
5095 Vimage_instance_type_list = Fcons (Qnothing,
5096 list6 (Qtext, Qmono_pixmap, Qcolor_pixmap,
5097 Qpointer, Qsubwindow, Qwidget));
5098 staticpro (&Vimage_instance_type_list);
5102 Vglyph_type_list = list3 (Qbuffer, Qpointer, Qicon);
5103 staticpro (&Vglyph_type_list);
5105 /* The octal-escape glyph, control-arrow-glyph and
5106 invisible-text-glyph are completely initialized in glyphs.el */
5108 DEFVAR_LISP ("octal-escape-glyph", &Voctal_escape_glyph /*
5109 What to prefix character codes displayed in octal with.
5111 Voctal_escape_glyph = allocate_glyph (GLYPH_BUFFER, redisplay_glyph_changed);
5113 DEFVAR_LISP ("control-arrow-glyph", &Vcontrol_arrow_glyph /*
5114 What to use as an arrow for control characters.
5116 Vcontrol_arrow_glyph = allocate_glyph (GLYPH_BUFFER,
5117 redisplay_glyph_changed);
5119 DEFVAR_LISP ("invisible-text-glyph", &Vinvisible_text_glyph /*
5120 What to use to indicate the presence of invisible text.
5121 This is the glyph that is displayed when an ellipsis is called for
5122 \(see `selective-display-ellipses' and `buffer-invisibility-spec').
5123 Normally this is three dots ("...").
5125 Vinvisible_text_glyph = allocate_glyph (GLYPH_BUFFER,
5126 redisplay_glyph_changed);
5128 /* Partially initialized in glyphs.el */
5129 DEFVAR_LISP ("hscroll-glyph", &Vhscroll_glyph /*
5130 What to display at the beginning of horizontally scrolled lines.
5132 Vhscroll_glyph = allocate_glyph (GLYPH_BUFFER, redisplay_glyph_changed);
5133 #ifdef HAVE_WINDOW_SYSTEM
5139 DEFVAR_LISP ("xpm-color-symbols", &Vxpm_color_symbols /*
5140 Definitions of logical color-names used when reading XPM files.
5141 Elements of this list should be of the form (COLOR-NAME FORM-TO-EVALUATE).
5142 The COLOR-NAME should be a string, which is the name of the color to define;
5143 the FORM should evaluate to a `color' specifier object, or a string to be
5144 passed to `make-color-instance'. If a loaded XPM file references a symbolic
5145 color called COLOR-NAME, it will display as the computed color instead.
5147 The default value of this variable defines the logical color names
5148 \"foreground\" and \"background\" to be the colors of the `default' face.
5150 Vxpm_color_symbols = Qnil; /* initialized in x-faces.el */
5151 #endif /* HAVE_XPM */
5156 DEFVAR_BOOL ("disable-animated-pixmaps", &disable_animated_pixmaps /*
5157 Whether animated pixmaps should be animated.
5160 disable_animated_pixmaps = 0;
5164 specifier_vars_of_glyphs (void)
5166 /* #### Can we GC here? The set_specifier_* calls definitely need */
5168 /* display tables */
5170 DEFVAR_SPECIFIER ("current-display-table", &Vcurrent_display_table /*
5171 *The display table currently in use.
5172 This is a specifier; use `set-specifier' to change it.
5174 Display tables are used to control how characters are displayed. Each
5175 time that redisplay processes a character, it is looked up in all the
5176 display tables that apply (obtained by calling `specifier-instance' on
5177 `current-display-table' and any overriding display tables specified in
5178 currently active faces). The first entry found that matches the
5179 character determines how the character is displayed. If there is no
5180 matching entry, the default display method is used. (Non-control
5181 characters are displayed as themselves and control characters are
5182 displayed according to the buffer-local variable `ctl-arrow'. Control
5183 characters are further affected by `control-arrow-glyph' and
5184 `octal-escape-glyph'.)
5186 Each instantiator in this specifier and the display-table specifiers
5187 in faces is a display table or a list of such tables. If a list, each
5188 table will be searched in turn for an entry matching a particular
5189 character. Each display table is one of
5191 -- a vector, specifying values for characters starting at 0
5192 -- a char table, either of type `char' or `generic'
5195 Each entry in a display table should be one of
5197 -- nil (this entry is ignored and the search continues)
5198 -- a character (use this character; if it happens to be the same as
5199 the original character, default processing happens, otherwise
5200 redisplay attempts to display this character directly;
5201 #### At some point recursive display-table lookup will be
5203 -- a string (display each character in the string directly;
5204 #### At some point recursive display-table lookup will be
5206 -- a glyph (display the glyph;
5207 #### At some point recursive display-table lookup will be
5208 implemented when a string glyph is being processed.)
5209 -- a cons of the form (format "STRING") where STRING is a printf-like
5210 spec used to process the character. #### Unfortunately no
5211 formatting directives other than %% are implemented.
5212 -- a vector (each element of the vector is processed recursively;
5213 in such a case, nil elements in the vector are simply ignored)
5215 #### At some point in the near future, display tables are likely to
5216 be expanded to include other features, such as referencing characters
5217 in particular fonts and allowing the character search to continue
5218 all the way up the chain of specifier instantiators. These features
5219 are necessary to properly display Unicode characters.
5221 Vcurrent_display_table = Fmake_specifier (Qdisplay_table);
5222 set_specifier_fallback (Vcurrent_display_table,
5223 list1 (Fcons (Qnil, Qnil)));
5224 set_specifier_caching (Vcurrent_display_table,
5225 offsetof (struct window, display_table),
5226 some_window_value_changed,
5231 complex_vars_of_glyphs (void)
5233 /* Partially initialized in glyphs-x.c, glyphs.el */
5234 DEFVAR_LISP ("truncation-glyph", &Vtruncation_glyph /*
5235 What to display at the end of truncated lines.
5237 Vtruncation_glyph = allocate_glyph (GLYPH_BUFFER, redisplay_glyph_changed);
5239 /* Partially initialized in glyphs-x.c, glyphs.el */
5240 DEFVAR_LISP ("continuation-glyph", &Vcontinuation_glyph /*
5241 What to display at the end of wrapped lines.
5243 Vcontinuation_glyph = allocate_glyph (GLYPH_BUFFER, redisplay_glyph_changed);
5245 /* Partially initialized in glyphs-x.c, glyphs.el */
5246 DEFVAR_LISP ("xemacs-logo", &Vxemacs_logo /*
5247 The glyph used to display the XEmacs logo at startup.
5249 Vxemacs_logo = allocate_glyph (GLYPH_BUFFER, 0);