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)
728 != IMAGE_UNSPECIFIED_GEOMETRY
729 && XIMAGE_INSTANCE_WIDTH (ii)
730 != IMAGE_UNSPECIFIED_GEOMETRY);
732 ERROR_CHECK_IMAGE_INSTANCE (ii);
738 /****************************************************************************
739 * Image-Instance Object *
740 ****************************************************************************/
742 Lisp_Object Qimage_instancep;
745 mark_image_instance (Lisp_Object obj)
747 Lisp_Image_Instance *i = XIMAGE_INSTANCE (obj);
749 /* #### I want to check the instance here, but there are way too
750 many instances of the instance being marked while the domain is
751 dead. For instance you can get marked through an event when using
754 ERROR_CHECK_IMAGE_INSTANCE (obj);
757 mark_object (i->name);
758 /* Is this legal in marking? We may get in the situation where the
759 domain has been deleted - making the instance unusable. It seems
760 better to remove the domain so that it can be finalized. */
761 if (!DOMAIN_LIVE_P (i->domain))
764 mark_object (i->domain);
766 /* We don't mark the glyph reference since that would create a
767 circularity preventing GC. */
768 switch (IMAGE_INSTANCE_TYPE (i))
771 mark_object (IMAGE_INSTANCE_TEXT_STRING (i));
773 case IMAGE_MONO_PIXMAP:
774 case IMAGE_COLOR_PIXMAP:
775 mark_object (IMAGE_INSTANCE_PIXMAP_FILENAME (i));
776 mark_object (IMAGE_INSTANCE_PIXMAP_MASK_FILENAME (i));
777 mark_object (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (i));
778 mark_object (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (i));
779 mark_object (IMAGE_INSTANCE_PIXMAP_FG (i));
780 mark_object (IMAGE_INSTANCE_PIXMAP_BG (i));
784 mark_object (IMAGE_INSTANCE_WIDGET_TYPE (i));
785 mark_object (IMAGE_INSTANCE_WIDGET_PROPS (i));
786 mark_object (IMAGE_INSTANCE_WIDGET_FACE (i));
787 mark_object (IMAGE_INSTANCE_WIDGET_ITEMS (i));
788 mark_object (IMAGE_INSTANCE_LAYOUT_CHILDREN (i));
789 mark_object (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (i));
790 mark_object (IMAGE_INSTANCE_WIDGET_HEIGHT_SUBR (i));
791 mark_object (IMAGE_INSTANCE_WIDGET_WIDTH_SUBR (i));
792 case IMAGE_SUBWINDOW:
799 /* The image may have been previously finalized (yes that's wierd,
800 see Fdelete_frame() and mark_window_as_deleted()), in which case
801 the domain will be nil, so cope with this. */
802 if (!NILP (IMAGE_INSTANCE_DEVICE (i)))
803 MAYBE_DEVMETH (XDEVICE (IMAGE_INSTANCE_DEVICE (i)),
804 mark_image_instance, (i));
810 print_image_instance (Lisp_Object obj, Lisp_Object printcharfun,
814 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (obj);
817 error ("printing unreadable object #<image-instance 0x%x>",
819 write_c_string ("#<image-instance (", printcharfun);
820 print_internal (Fimage_instance_type (obj), printcharfun, 0);
821 write_c_string (") ", printcharfun);
822 if (!NILP (ii->name))
824 print_internal (ii->name, printcharfun, 1);
825 write_c_string (" ", printcharfun);
827 write_c_string ("on ", printcharfun);
828 print_internal (ii->domain, printcharfun, 0);
829 write_c_string (" ", printcharfun);
830 switch (IMAGE_INSTANCE_TYPE (ii))
836 print_internal (IMAGE_INSTANCE_TEXT_STRING (ii), printcharfun, 1);
839 case IMAGE_MONO_PIXMAP:
840 case IMAGE_COLOR_PIXMAP:
842 if (STRINGP (IMAGE_INSTANCE_PIXMAP_FILENAME (ii)))
845 Lisp_Object filename = IMAGE_INSTANCE_PIXMAP_FILENAME (ii);
846 s = strrchr ((char *) XSTRING_DATA (filename), '/');
848 print_internal (build_string (s + 1), printcharfun, 1);
850 print_internal (filename, printcharfun, 1);
852 if (IMAGE_INSTANCE_PIXMAP_DEPTH (ii) > 1)
853 sprintf (buf, " %dx%dx%d", IMAGE_INSTANCE_PIXMAP_WIDTH (ii),
854 IMAGE_INSTANCE_PIXMAP_HEIGHT (ii),
855 IMAGE_INSTANCE_PIXMAP_DEPTH (ii));
857 sprintf (buf, " %dx%d", IMAGE_INSTANCE_PIXMAP_WIDTH (ii),
858 IMAGE_INSTANCE_PIXMAP_HEIGHT (ii));
859 write_c_string (buf, printcharfun);
860 if (!NILP (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii)) ||
861 !NILP (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii)))
863 write_c_string (" @", printcharfun);
864 if (!NILP (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii)))
866 long_to_string (buf, XINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii)));
867 write_c_string (buf, printcharfun);
870 write_c_string ("??", printcharfun);
871 write_c_string (",", printcharfun);
872 if (!NILP (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii)))
874 long_to_string (buf, XINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii)));
875 write_c_string (buf, printcharfun);
878 write_c_string ("??", printcharfun);
880 if (!NILP (IMAGE_INSTANCE_PIXMAP_FG (ii)) ||
881 !NILP (IMAGE_INSTANCE_PIXMAP_BG (ii)))
883 write_c_string (" (", printcharfun);
884 if (!NILP (IMAGE_INSTANCE_PIXMAP_FG (ii)))
888 (IMAGE_INSTANCE_PIXMAP_FG (ii))->name, printcharfun, 0);
890 write_c_string ("/", printcharfun);
891 if (!NILP (IMAGE_INSTANCE_PIXMAP_BG (ii)))
895 (IMAGE_INSTANCE_PIXMAP_BG (ii))->name, printcharfun, 0);
897 write_c_string (")", printcharfun);
902 print_internal (IMAGE_INSTANCE_WIDGET_TYPE (ii), printcharfun, 0);
904 if (GUI_ITEMP (IMAGE_INSTANCE_WIDGET_ITEM (ii)))
906 write_c_string (" ", printcharfun);
907 print_internal (IMAGE_INSTANCE_WIDGET_TEXT (ii), printcharfun, 1);
910 if (!NILP (IMAGE_INSTANCE_WIDGET_FACE (ii)))
912 write_c_string (" face=", printcharfun);
914 (IMAGE_INSTANCE_WIDGET_FACE (ii), printcharfun, 0);
918 case IMAGE_SUBWINDOW:
919 sprintf (buf, " %dx%d", IMAGE_INSTANCE_WIDTH (ii),
920 IMAGE_INSTANCE_HEIGHT (ii));
921 write_c_string (buf, printcharfun);
923 /* This is stolen from frame.c. Subwindows are strange in that they
924 are specific to a particular frame so we want to print in their
925 description what that frame is. */
927 write_c_string (" on #<", printcharfun);
929 struct frame* f = XFRAME (IMAGE_INSTANCE_FRAME (ii));
931 if (!FRAME_LIVE_P (f))
932 write_c_string ("dead", printcharfun);
934 write_c_string (DEVICE_TYPE_NAME (XDEVICE (FRAME_DEVICE (f))),
937 write_c_string ("-frame>", printcharfun);
938 sprintf (buf, " 0x%p", IMAGE_INSTANCE_SUBWINDOW_ID (ii));
939 write_c_string (buf, printcharfun);
947 MAYBE_DEVMETH (DOMAIN_XDEVICE (ii->domain), print_image_instance,
948 (ii, printcharfun, escapeflag));
949 sprintf (buf, " 0x%x>", ii->header.uid);
950 write_c_string (buf, printcharfun);
954 finalize_image_instance (void *header, int for_disksave)
956 Lisp_Image_Instance *i = (Lisp_Image_Instance *) header;
958 /* objects like this exist at dump time, so don't bomb out. */
959 if (IMAGE_INSTANCE_TYPE (i) == IMAGE_NOTHING
961 NILP (IMAGE_INSTANCE_DEVICE (i)))
963 if (for_disksave) finalose (i);
965 /* We can't use the domain here, because it might have
967 MAYBE_DEVMETH (XDEVICE (IMAGE_INSTANCE_DEVICE (i)),
968 finalize_image_instance, (i));
970 /* Make sure we don't try this twice. */
971 IMAGE_INSTANCE_DEVICE (i) = Qnil;
975 image_instance_equal (Lisp_Object obj1, Lisp_Object obj2, int depth)
977 Lisp_Image_Instance *i1 = XIMAGE_INSTANCE (obj1);
978 Lisp_Image_Instance *i2 = XIMAGE_INSTANCE (obj2);
980 ERROR_CHECK_IMAGE_INSTANCE (obj1);
981 ERROR_CHECK_IMAGE_INSTANCE (obj2);
983 if (!EQ (IMAGE_INSTANCE_DOMAIN (i1),
984 IMAGE_INSTANCE_DOMAIN (i2))
985 || IMAGE_INSTANCE_TYPE (i1) != IMAGE_INSTANCE_TYPE (i2)
986 || IMAGE_INSTANCE_WIDTH (i1) != IMAGE_INSTANCE_WIDTH (i2)
987 || IMAGE_INSTANCE_MARGIN_WIDTH (i1) !=
988 IMAGE_INSTANCE_MARGIN_WIDTH (i2)
989 || IMAGE_INSTANCE_HEIGHT (i1) != IMAGE_INSTANCE_HEIGHT (i2)
990 || IMAGE_INSTANCE_XOFFSET (i1) != IMAGE_INSTANCE_XOFFSET (i2)
991 || IMAGE_INSTANCE_YOFFSET (i1) != IMAGE_INSTANCE_YOFFSET (i2))
993 if (!internal_equal (IMAGE_INSTANCE_NAME (i1), IMAGE_INSTANCE_NAME (i2),
997 switch (IMAGE_INSTANCE_TYPE (i1))
1003 if (!internal_equal (IMAGE_INSTANCE_TEXT_STRING (i1),
1004 IMAGE_INSTANCE_TEXT_STRING (i2),
1009 case IMAGE_MONO_PIXMAP:
1010 case IMAGE_COLOR_PIXMAP:
1012 if (!(IMAGE_INSTANCE_PIXMAP_DEPTH (i1) ==
1013 IMAGE_INSTANCE_PIXMAP_DEPTH (i2) &&
1014 IMAGE_INSTANCE_PIXMAP_SLICE (i1) ==
1015 IMAGE_INSTANCE_PIXMAP_SLICE (i2) &&
1016 EQ (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (i1),
1017 IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (i2)) &&
1018 EQ (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (i1),
1019 IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (i2)) &&
1020 internal_equal (IMAGE_INSTANCE_PIXMAP_FILENAME (i1),
1021 IMAGE_INSTANCE_PIXMAP_FILENAME (i2),
1023 internal_equal (IMAGE_INSTANCE_PIXMAP_MASK_FILENAME (i1),
1024 IMAGE_INSTANCE_PIXMAP_MASK_FILENAME (i2),
1030 if (!(EQ (IMAGE_INSTANCE_WIDGET_TYPE (i1),
1031 IMAGE_INSTANCE_WIDGET_TYPE (i2))
1032 && IMAGE_INSTANCE_SUBWINDOW_ID (i1) ==
1033 IMAGE_INSTANCE_SUBWINDOW_ID (i2)
1035 EQ (IMAGE_INSTANCE_WIDGET_FACE (i1),
1036 IMAGE_INSTANCE_WIDGET_TYPE (i2))
1037 && internal_equal (IMAGE_INSTANCE_WIDGET_ITEMS (i1),
1038 IMAGE_INSTANCE_WIDGET_ITEMS (i2),
1040 && internal_equal (IMAGE_INSTANCE_LAYOUT_CHILDREN (i1),
1041 IMAGE_INSTANCE_LAYOUT_CHILDREN (i2),
1043 && internal_equal (IMAGE_INSTANCE_WIDGET_PROPS (i1),
1044 IMAGE_INSTANCE_WIDGET_PROPS (i2),
1046 && internal_equal (IMAGE_INSTANCE_WIDGET_WIDTH_SUBR (i1),
1047 IMAGE_INSTANCE_WIDGET_WIDTH_SUBR (i2),
1049 && internal_equal (IMAGE_INSTANCE_WIDGET_HEIGHT_SUBR (i1),
1050 IMAGE_INSTANCE_WIDGET_HEIGHT_SUBR (i2),
1056 case IMAGE_SUBWINDOW:
1057 if (!(IMAGE_INSTANCE_SUBWINDOW_ID (i1) ==
1058 IMAGE_INSTANCE_SUBWINDOW_ID (i2)))
1066 return DEVMETH_OR_GIVEN (DOMAIN_XDEVICE (i1->domain),
1067 image_instance_equal, (i1, i2, depth), 1);
1070 /* Image instance domain manipulators. We can't error check in these
1071 otherwise we get into infinite recursion. */
1073 image_instance_device (Lisp_Object instance)
1075 return XIMAGE_INSTANCE_DEVICE (instance);
1079 image_instance_frame (Lisp_Object instance)
1081 return XIMAGE_INSTANCE_FRAME (instance);
1085 image_instance_window (Lisp_Object instance)
1087 return DOMAIN_WINDOW (XIMAGE_INSTANCE_DOMAIN (instance));
1091 image_instance_live_p (Lisp_Object instance)
1093 return DOMAIN_LIVE_P (XIMAGE_INSTANCE_DOMAIN (instance));
1096 static unsigned long
1097 image_instance_hash (Lisp_Object obj, int depth)
1099 Lisp_Image_Instance *i = XIMAGE_INSTANCE (obj);
1100 unsigned long hash = HASH4 (LISP_HASH (IMAGE_INSTANCE_DOMAIN (i)),
1101 IMAGE_INSTANCE_WIDTH (i),
1102 IMAGE_INSTANCE_MARGIN_WIDTH (i),
1103 IMAGE_INSTANCE_HEIGHT (i));
1105 ERROR_CHECK_IMAGE_INSTANCE (obj);
1107 switch (IMAGE_INSTANCE_TYPE (i))
1113 hash = HASH2 (hash, internal_hash (IMAGE_INSTANCE_TEXT_STRING (i),
1117 case IMAGE_MONO_PIXMAP:
1118 case IMAGE_COLOR_PIXMAP:
1120 hash = HASH4 (hash, IMAGE_INSTANCE_PIXMAP_DEPTH (i),
1121 IMAGE_INSTANCE_PIXMAP_SLICE (i),
1122 internal_hash (IMAGE_INSTANCE_PIXMAP_FILENAME (i),
1127 /* We need the hash to be equivalent to what should be
1130 LISP_HASH (IMAGE_INSTANCE_WIDGET_TYPE (i)),
1131 internal_hash (IMAGE_INSTANCE_WIDGET_PROPS (i), depth + 1),
1132 internal_hash (IMAGE_INSTANCE_WIDGET_ITEMS (i), depth + 1),
1133 internal_hash (IMAGE_INSTANCE_LAYOUT_CHILDREN (i),
1135 case IMAGE_SUBWINDOW:
1136 hash = HASH2 (hash, (int) IMAGE_INSTANCE_SUBWINDOW_ID (i));
1143 return HASH2 (hash, DEVMETH_OR_GIVEN
1144 (XDEVICE (image_instance_device (obj)),
1145 image_instance_hash, (i, depth),
1149 DEFINE_LRECORD_IMPLEMENTATION ("image-instance", image_instance,
1150 mark_image_instance, print_image_instance,
1151 finalize_image_instance, image_instance_equal,
1152 image_instance_hash, 0,
1153 Lisp_Image_Instance);
1156 allocate_image_instance (Lisp_Object governing_domain, Lisp_Object glyph)
1158 Lisp_Image_Instance *lp =
1159 alloc_lcrecord_type (Lisp_Image_Instance, &lrecord_image_instance);
1163 /* It's not possible to simply keep a record of the domain in which
1164 the instance was instantiated. This is because caching may mean
1165 that the domain becomes invalid but the instance remains
1166 valid. However, the only truly relevant domain is the domain in
1167 which the instance is cached since this is the one that will be
1168 common to the instances. */
1169 lp->domain = governing_domain;
1170 /* The cache domain is not quite sufficient since the domain can get
1171 deleted before the image instance does. We need to know the
1172 domain device in order to finalize the image instance
1173 properly. We therefore record the device also. */
1174 lp->device = DOMAIN_DEVICE (governing_domain);
1175 lp->type = IMAGE_NOTHING;
1179 lp->width = IMAGE_UNSPECIFIED_GEOMETRY;
1180 lp->margin_width = 0;
1181 lp->height = IMAGE_UNSPECIFIED_GEOMETRY;
1183 /* So that layouts get done. */
1184 lp->layout_changed = 1;
1185 lp->initialized = 0;
1187 XSETIMAGE_INSTANCE (val, lp);
1188 MARK_GLYPHS_CHANGED;
1193 static enum image_instance_type
1194 decode_image_instance_type (Lisp_Object type, Error_behavior errb)
1196 if (ERRB_EQ (errb, ERROR_ME))
1197 CHECK_SYMBOL (type);
1199 if (EQ (type, Qnothing)) return IMAGE_NOTHING;
1200 if (EQ (type, Qtext)) return IMAGE_TEXT;
1201 if (EQ (type, Qmono_pixmap)) return IMAGE_MONO_PIXMAP;
1202 if (EQ (type, Qcolor_pixmap)) return IMAGE_COLOR_PIXMAP;
1203 if (EQ (type, Qpointer)) return IMAGE_POINTER;
1204 if (EQ (type, Qsubwindow)) return IMAGE_SUBWINDOW;
1205 if (EQ (type, Qwidget)) return IMAGE_WIDGET;
1207 maybe_signal_simple_error ("Invalid image-instance type", type,
1210 return IMAGE_UNKNOWN; /* not reached */
1214 encode_image_instance_type (enum image_instance_type type)
1218 case IMAGE_NOTHING: return Qnothing;
1219 case IMAGE_TEXT: return Qtext;
1220 case IMAGE_MONO_PIXMAP: return Qmono_pixmap;
1221 case IMAGE_COLOR_PIXMAP: return Qcolor_pixmap;
1222 case IMAGE_POINTER: return Qpointer;
1223 case IMAGE_SUBWINDOW: return Qsubwindow;
1224 case IMAGE_WIDGET: return Qwidget;
1229 return Qnil; /* not reached */
1233 decode_image_instance_type_list (Lisp_Object list)
1243 enum image_instance_type type =
1244 decode_image_instance_type (list, ERROR_ME);
1245 return image_instance_type_to_mask (type);
1248 EXTERNAL_LIST_LOOP (rest, list)
1250 enum image_instance_type type =
1251 decode_image_instance_type (XCAR (rest), ERROR_ME);
1252 mask |= image_instance_type_to_mask (type);
1259 encode_image_instance_type_list (int mask)
1262 Lisp_Object result = Qnil;
1268 result = Fcons (encode_image_instance_type
1269 ((enum image_instance_type) count), result);
1273 return Fnreverse (result);
1277 incompatible_image_types (Lisp_Object instantiator, int given_dest_mask,
1278 int desired_dest_mask)
1283 (emacs_doprnt_string_lisp_2
1285 "No compatible image-instance types given: wanted one of %s, got %s",
1287 encode_image_instance_type_list (desired_dest_mask),
1288 encode_image_instance_type_list (given_dest_mask)),
1293 valid_image_instance_type_p (Lisp_Object type)
1295 return !NILP (memq_no_quit (type, Vimage_instance_type_list));
1298 DEFUN ("valid-image-instance-type-p", Fvalid_image_instance_type_p, 1, 1, 0, /*
1299 Given an IMAGE-INSTANCE-TYPE, return non-nil if it is valid.
1300 Valid types are some subset of 'nothing, 'text, 'mono-pixmap, 'color-pixmap,
1301 'pointer, 'subwindow, and 'widget, depending on how XEmacs was compiled.
1303 (image_instance_type))
1305 return valid_image_instance_type_p (image_instance_type) ? Qt : Qnil;
1308 DEFUN ("image-instance-type-list", Fimage_instance_type_list, 0, 0, 0, /*
1309 Return a list of valid image-instance types.
1313 return Fcopy_sequence (Vimage_instance_type_list);
1317 decode_error_behavior_flag (Lisp_Object no_error)
1319 if (NILP (no_error)) return ERROR_ME;
1320 else if (EQ (no_error, Qt)) return ERROR_ME_NOT;
1321 else return ERROR_ME_WARN;
1325 encode_error_behavior_flag (Error_behavior errb)
1327 if (ERRB_EQ (errb, ERROR_ME))
1329 else if (ERRB_EQ (errb, ERROR_ME_NOT))
1333 assert (ERRB_EQ (errb, ERROR_ME_WARN));
1338 /* Recurse up the hierarchy looking for the topmost glyph. This means
1339 that instances in layouts will inherit face properties from their
1341 Lisp_Object image_instance_parent_glyph (Lisp_Image_Instance* ii)
1343 if (IMAGE_INSTANCEP (IMAGE_INSTANCE_PARENT (ii)))
1345 return image_instance_parent_glyph
1346 (XIMAGE_INSTANCE (IMAGE_INSTANCE_PARENT (ii)));
1348 return IMAGE_INSTANCE_PARENT (ii);
1352 make_image_instance_1 (Lisp_Object data, Lisp_Object domain,
1353 Lisp_Object dest_types)
1356 struct gcpro gcpro1;
1358 Lisp_Object governing_domain;
1360 if (IMAGE_INSTANCEP (data))
1361 signal_simple_error ("Image instances not allowed here", data);
1362 image_validate (data);
1363 domain = decode_domain (domain);
1364 /* instantiate_image_instantiator() will abort if given an
1365 image instance ... */
1366 dest_mask = decode_image_instance_type_list (dest_types);
1367 data = normalize_image_instantiator (data,
1368 DEVICE_TYPE (DOMAIN_XDEVICE (domain)),
1369 make_int (dest_mask));
1371 /* After normalizing the data, it's always either an image instance (which
1372 we filtered out above) or a vector. */
1373 if (EQ (XVECTOR_DATA (data)[0], Qinherit))
1374 signal_simple_error ("Inheritance not allowed here", data);
1376 get_image_instantiator_governing_domain (data, domain);
1377 ii = instantiate_image_instantiator (governing_domain, domain, data,
1378 Qnil, Qnil, dest_mask, Qnil);
1379 RETURN_UNGCPRO (ii);
1382 DEFUN ("make-image-instance", Fmake_image_instance, 1, 4, 0, /*
1383 Return a new `image-instance' object.
1385 Image-instance objects encapsulate the way a particular image (pixmap,
1386 etc.) is displayed on a particular device. In most circumstances, you
1387 do not need to directly create image instances; use a glyph instead.
1388 However, it may occasionally be useful to explicitly create image
1389 instances, if you want more control over the instantiation process.
1391 DATA is an image instantiator, which describes the image; see
1392 `make-image-specifier' for a description of the allowed values.
1394 DEST-TYPES should be a list of allowed image instance types that can
1395 be generated. The recognized image instance types are
1398 Nothing is displayed.
1400 Displayed as text. The foreground and background colors and the
1401 font of the text are specified independent of the pixmap. Typically
1402 these attributes will come from the face of the surrounding text,
1403 unless a face is specified for the glyph in which the image appears.
1405 Displayed as a mono pixmap (a pixmap with only two colors where the
1406 foreground and background can be specified independent of the pixmap;
1407 typically the pixmap assumes the foreground and background colors of
1408 the text around it, unless a face is specified for the glyph in which
1411 Displayed as a color pixmap.
1413 Used as the mouse pointer for a window.
1415 A child window that is treated as an image. This allows (e.g.)
1416 another program to be responsible for drawing into the window.
1418 A child window that contains a window-system widget, e.g. a push
1419 button, text field, or slider.
1421 The DEST-TYPES list is unordered. If multiple destination types are
1422 possible for a given instantiator, the "most natural" type for the
1423 instantiator's format is chosen. (For XBM, the most natural types are
1424 `mono-pixmap', followed by `color-pixmap', followed by `pointer'. For
1425 the other normal image formats, the most natural types are
1426 `color-pixmap', followed by `mono-pixmap', followed by `pointer'. For
1427 the string and formatted-string formats, the most natural types are
1428 `text', followed by `mono-pixmap' (not currently implemented),
1429 followed by `color-pixmap' (not currently implemented). For MS
1430 Windows resources, the most natural type for pointer resources is
1431 `pointer', and for the others it's `color-pixmap'. The other formats
1432 can only be instantiated as one type. (If you want to control more
1433 specifically the order of the types into which an image is
1434 instantiated, just call `make-image-instance' repeatedly until it
1435 succeeds, passing less and less preferred destination types each
1438 See `make-image-specifier' for a description of the different image
1439 instantiator formats.
1441 If DEST-TYPES is omitted, all possible types are allowed.
1443 DOMAIN specifies the domain to which the image instance will be attached.
1444 This domain is termed the \"governing domain\". The type of the governing
1445 domain depends on the image instantiator format. (Although, more correctly,
1446 it should probably depend on the image instance type.) For example, pixmap
1447 image instances are specific to a device, but widget image instances are
1448 specific to a particular XEmacs window because in order to display such a
1449 widget when two windows onto the same buffer want to display the widget,
1450 two separate underlying widgets must be created. (That's because a widget
1451 is actually a child window-system window, and all window-system windows have
1452 a unique existence on the screen.) This means that the governing domain for
1453 a pixmap image instance will be some device (most likely, the only existing
1454 device), whereas the governing domain for a widget image instance will be
1457 If you specify an overly general DOMAIN (e.g. a frame when a window was
1458 wanted), an error is signaled. If you specify an overly specific DOMAIN
1459 \(e.g. a window when a device was wanted), the corresponding general domain
1460 is fetched and used instead. For `make-image-instance', it makes no
1461 difference whether you specify an overly specific domain or the properly
1462 general domain derived from it. However, it does matter when creating an
1463 image instance by instantiating a specifier or glyph (e.g. with
1464 `glyph-image-instance'), because the more specific domain causes spec lookup
1465 to start there and proceed to more general domains. (It would also matter
1466 when creating an image instance with an instantiator format of `inherit',
1467 but we currently disallow this. #### We should fix this.)
1469 If omitted, DOMAIN defaults to the selected window.
1471 NO-ERROR controls what happens when the image cannot be generated.
1472 If nil, an error message is generated. If t, no messages are
1473 generated and this function returns nil. If anything else, a warning
1474 message is generated and this function returns nil.
1476 (data, domain, dest_types, no_error))
1478 Error_behavior errb = decode_error_behavior_flag (no_error);
1480 return call_with_suspended_errors ((lisp_fn_t) make_image_instance_1,
1482 3, data, domain, dest_types);
1485 DEFUN ("image-instance-p", Fimage_instance_p, 1, 1, 0, /*
1486 Return non-nil if OBJECT is an image instance.
1490 return IMAGE_INSTANCEP (object) ? Qt : Qnil;
1493 DEFUN ("image-instance-type", Fimage_instance_type, 1, 1, 0, /*
1494 Return the type of the given image instance.
1495 The return value will be one of 'nothing, 'text, 'mono-pixmap,
1496 'color-pixmap, 'pointer, or 'subwindow.
1500 CHECK_IMAGE_INSTANCE (image_instance);
1501 ERROR_CHECK_IMAGE_INSTANCE (image_instance);
1502 return encode_image_instance_type (XIMAGE_INSTANCE_TYPE (image_instance));
1505 DEFUN ("image-instance-name", Fimage_instance_name, 1, 1, 0, /*
1506 Return the name of the given image instance.
1510 CHECK_IMAGE_INSTANCE (image_instance);
1511 return XIMAGE_INSTANCE_NAME (image_instance);
1514 DEFUN ("image-instance-domain", Fimage_instance_domain, 1, 1, 0, /*
1515 Return the governing domain of the given image instance.
1516 The governing domain of an image instance is the domain that the image
1517 instance is specific to. It is NOT necessarily the domain that was
1518 given to the call to `specifier-instance' that resulted in the creation
1519 of this image instance. See `make-image-instance' for more information
1520 on governing domains.
1524 CHECK_IMAGE_INSTANCE (image_instance);
1525 return XIMAGE_INSTANCE_DOMAIN (image_instance);
1528 DEFUN ("image-instance-string", Fimage_instance_string, 1, 1, 0, /*
1529 Return the string of the given image instance.
1530 This will only be non-nil for text image instances and widgets.
1534 CHECK_IMAGE_INSTANCE (image_instance);
1535 if (XIMAGE_INSTANCE_TYPE (image_instance) == IMAGE_TEXT)
1536 return XIMAGE_INSTANCE_TEXT_STRING (image_instance);
1537 else if (XIMAGE_INSTANCE_TYPE (image_instance) == IMAGE_WIDGET)
1538 return XIMAGE_INSTANCE_WIDGET_TEXT (image_instance);
1543 DEFUN ("image-instance-property", Fimage_instance_property, 2, 2, 0, /*
1544 Return the given property of the given image instance.
1545 Returns nil if the property or the property method do not exist for
1546 the image instance in the domain.
1548 (image_instance, prop))
1550 Lisp_Image_Instance* ii;
1551 Lisp_Object type, ret;
1552 struct image_instantiator_methods* meths;
1554 CHECK_IMAGE_INSTANCE (image_instance);
1555 ERROR_CHECK_IMAGE_INSTANCE (image_instance);
1556 CHECK_SYMBOL (prop);
1557 ii = XIMAGE_INSTANCE (image_instance);
1559 /* ... then try device specific methods ... */
1560 type = encode_image_instance_type (IMAGE_INSTANCE_TYPE (ii));
1561 meths = decode_device_ii_format (image_instance_device (image_instance),
1562 type, ERROR_ME_NOT);
1563 if (meths && HAS_IIFORMAT_METH_P (meths, property)
1565 !UNBOUNDP (ret = IIFORMAT_METH (meths, property, (image_instance, prop))))
1569 /* ... then format specific methods ... */
1570 meths = decode_device_ii_format (Qnil, type, ERROR_ME_NOT);
1571 if (meths && HAS_IIFORMAT_METH_P (meths, property)
1573 !UNBOUNDP (ret = IIFORMAT_METH (meths, property, (image_instance, prop))))
1581 DEFUN ("set-image-instance-property", Fset_image_instance_property, 3, 3, 0, /*
1582 Set the given property of the given image instance.
1583 Does nothing if the property or the property method do not exist for
1584 the image instance in the domain.
1586 WARNING: If you are thinking about using this function, think again.
1587 You probably want to be using `set-glyph-image' to change the glyph's
1588 specifier. Be especially wary if you are thinking of calling this
1589 function after having called `glyph-image-instance'. Unless you are
1590 absolutely sure what you're doing, pretty much the only legitimate
1591 uses for this function are setting user-specified info in a widget,
1592 such as text in a text field. */
1593 (image_instance, prop, val))
1595 Lisp_Image_Instance* ii;
1596 Lisp_Object type, ret;
1597 struct image_instantiator_methods* meths;
1599 CHECK_IMAGE_INSTANCE (image_instance);
1600 ERROR_CHECK_IMAGE_INSTANCE (image_instance);
1601 CHECK_SYMBOL (prop);
1602 ii = XIMAGE_INSTANCE (image_instance);
1603 type = encode_image_instance_type (IMAGE_INSTANCE_TYPE (ii));
1604 /* try device specific methods first ... */
1605 meths = decode_device_ii_format (image_instance_device (image_instance),
1606 type, ERROR_ME_NOT);
1607 if (meths && HAS_IIFORMAT_METH_P (meths, set_property)
1610 IIFORMAT_METH (meths, set_property, (image_instance, prop, val))))
1616 /* ... then format specific methods ... */
1617 meths = decode_device_ii_format (Qnil, type, ERROR_ME_NOT);
1618 if (meths && HAS_IIFORMAT_METH_P (meths, set_property)
1621 IIFORMAT_METH (meths, set_property, (image_instance, prop, val))))
1631 /* Make sure the image instance gets redisplayed. */
1632 set_image_instance_dirty_p (image_instance, 1);
1633 /* Force the glyph to be laid out again. */
1634 IMAGE_INSTANCE_LAYOUT_CHANGED (ii) = 1;
1636 MARK_SUBWINDOWS_STATE_CHANGED;
1637 MARK_GLYPHS_CHANGED;
1642 DEFUN ("image-instance-file-name", Fimage_instance_file_name, 1, 1, 0, /*
1643 Return the file name from which IMAGE-INSTANCE was read, if known.
1647 CHECK_IMAGE_INSTANCE (image_instance);
1648 ERROR_CHECK_IMAGE_INSTANCE (image_instance);
1650 switch (XIMAGE_INSTANCE_TYPE (image_instance))
1652 case IMAGE_MONO_PIXMAP:
1653 case IMAGE_COLOR_PIXMAP:
1655 return XIMAGE_INSTANCE_PIXMAP_FILENAME (image_instance);
1662 DEFUN ("image-instance-mask-file-name", Fimage_instance_mask_file_name, 1, 1, 0, /*
1663 Return the file name from which IMAGE-INSTANCE's mask was read, if known.
1667 CHECK_IMAGE_INSTANCE (image_instance);
1668 ERROR_CHECK_IMAGE_INSTANCE (image_instance);
1670 switch (XIMAGE_INSTANCE_TYPE (image_instance))
1672 case IMAGE_MONO_PIXMAP:
1673 case IMAGE_COLOR_PIXMAP:
1675 return XIMAGE_INSTANCE_PIXMAP_MASK_FILENAME (image_instance);
1682 DEFUN ("image-instance-depth", Fimage_instance_depth, 1, 1, 0, /*
1683 Return the depth of the image instance.
1684 This is 0 for a bitmap, or a positive integer for a pixmap.
1688 CHECK_IMAGE_INSTANCE (image_instance);
1689 ERROR_CHECK_IMAGE_INSTANCE (image_instance);
1691 switch (XIMAGE_INSTANCE_TYPE (image_instance))
1693 case IMAGE_MONO_PIXMAP:
1694 case IMAGE_COLOR_PIXMAP:
1696 return make_int (XIMAGE_INSTANCE_PIXMAP_DEPTH (image_instance));
1703 DEFUN ("image-instance-height", Fimage_instance_height, 1, 1, 0, /*
1704 Return the height of the image instance, in pixels.
1708 CHECK_IMAGE_INSTANCE (image_instance);
1709 ERROR_CHECK_IMAGE_INSTANCE (image_instance);
1711 switch (XIMAGE_INSTANCE_TYPE (image_instance))
1713 case IMAGE_MONO_PIXMAP:
1714 case IMAGE_COLOR_PIXMAP:
1716 case IMAGE_SUBWINDOW:
1718 return make_int (XIMAGE_INSTANCE_HEIGHT (image_instance));
1725 DEFUN ("image-instance-width", Fimage_instance_width, 1, 1, 0, /*
1726 Return the width of the image instance, in pixels.
1730 CHECK_IMAGE_INSTANCE (image_instance);
1731 ERROR_CHECK_IMAGE_INSTANCE (image_instance);
1733 switch (XIMAGE_INSTANCE_TYPE (image_instance))
1735 case IMAGE_MONO_PIXMAP:
1736 case IMAGE_COLOR_PIXMAP:
1738 case IMAGE_SUBWINDOW:
1740 return make_int (XIMAGE_INSTANCE_WIDTH (image_instance));
1747 DEFUN ("image-instance-hotspot-x", Fimage_instance_hotspot_x, 1, 1, 0, /*
1748 Return the X coordinate of the image instance's hotspot, if known.
1749 This is a point relative to the origin of the pixmap. When an image is
1750 used as a mouse pointer, the hotspot is the point on the image that sits
1751 over the location that the pointer points to. This is, for example, the
1752 tip of the arrow or the center of the crosshairs.
1753 This will always be nil for a non-pointer image instance.
1757 CHECK_IMAGE_INSTANCE (image_instance);
1758 ERROR_CHECK_IMAGE_INSTANCE (image_instance);
1760 switch (XIMAGE_INSTANCE_TYPE (image_instance))
1762 case IMAGE_MONO_PIXMAP:
1763 case IMAGE_COLOR_PIXMAP:
1765 return XIMAGE_INSTANCE_PIXMAP_HOTSPOT_X (image_instance);
1772 DEFUN ("image-instance-hotspot-y", Fimage_instance_hotspot_y, 1, 1, 0, /*
1773 Return the Y coordinate of the image instance's hotspot, if known.
1774 This is a point relative to the origin of the pixmap. When an image is
1775 used as a mouse pointer, the hotspot is the point on the image that sits
1776 over the location that the pointer points to. This is, for example, the
1777 tip of the arrow or the center of the crosshairs.
1778 This will always be nil for a non-pointer image instance.
1782 CHECK_IMAGE_INSTANCE (image_instance);
1783 ERROR_CHECK_IMAGE_INSTANCE (image_instance);
1785 switch (XIMAGE_INSTANCE_TYPE (image_instance))
1787 case IMAGE_MONO_PIXMAP:
1788 case IMAGE_COLOR_PIXMAP:
1790 return XIMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (image_instance);
1797 DEFUN ("image-instance-foreground", Fimage_instance_foreground, 1, 1, 0, /*
1798 Return the foreground color of IMAGE-INSTANCE, if applicable.
1799 This will be a color instance or nil. (It will only be non-nil for
1800 colorized mono pixmaps and for pointers.)
1804 CHECK_IMAGE_INSTANCE (image_instance);
1805 ERROR_CHECK_IMAGE_INSTANCE (image_instance);
1807 switch (XIMAGE_INSTANCE_TYPE (image_instance))
1809 case IMAGE_MONO_PIXMAP:
1810 case IMAGE_COLOR_PIXMAP:
1812 return XIMAGE_INSTANCE_PIXMAP_FG (image_instance);
1815 return FACE_FOREGROUND (
1816 XIMAGE_INSTANCE_WIDGET_FACE (image_instance),
1817 XIMAGE_INSTANCE_FRAME
1825 DEFUN ("image-instance-background", Fimage_instance_background, 1, 1, 0, /*
1826 Return the background color of IMAGE-INSTANCE, if applicable.
1827 This will be a color instance or nil. (It will only be non-nil for
1828 colorized mono pixmaps and for pointers.)
1832 CHECK_IMAGE_INSTANCE (image_instance);
1833 ERROR_CHECK_IMAGE_INSTANCE (image_instance);
1835 switch (XIMAGE_INSTANCE_TYPE (image_instance))
1837 case IMAGE_MONO_PIXMAP:
1838 case IMAGE_COLOR_PIXMAP:
1840 return XIMAGE_INSTANCE_PIXMAP_BG (image_instance);
1843 return FACE_BACKGROUND (
1844 XIMAGE_INSTANCE_WIDGET_FACE (image_instance),
1845 XIMAGE_INSTANCE_FRAME
1854 DEFUN ("colorize-image-instance", Fcolorize_image_instance, 3, 3, 0, /*
1855 Make the image instance be displayed in the given colors.
1856 This function returns a new image instance that is exactly like the
1857 specified one except that (if possible) the foreground and background
1858 colors and as specified. Currently, this only does anything if the image
1859 instance is a mono pixmap; otherwise, the same image instance is returned.
1861 (image_instance, foreground, background))
1866 CHECK_IMAGE_INSTANCE (image_instance);
1867 ERROR_CHECK_IMAGE_INSTANCE (image_instance);
1868 CHECK_COLOR_INSTANCE (foreground);
1869 CHECK_COLOR_INSTANCE (background);
1871 device = image_instance_device (image_instance);
1872 if (!HAS_DEVMETH_P (XDEVICE (device), colorize_image_instance))
1873 return image_instance;
1875 /* #### There should be a copy_image_instance(), which calls a
1876 device-specific method to copy the window-system subobject. */
1877 new = allocate_image_instance (XIMAGE_INSTANCE_DOMAIN (image_instance),
1879 copy_lcrecord (XIMAGE_INSTANCE (new), XIMAGE_INSTANCE (image_instance));
1880 /* note that if this method returns non-zero, this method MUST
1881 copy any window-system resources, so that when one image instance is
1882 freed, the other one is not hosed. */
1883 if (!DEVMETH (XDEVICE (device), colorize_image_instance, (new, foreground,
1885 return image_instance;
1890 /************************************************************************/
1891 /* Geometry calculations */
1892 /************************************************************************/
1894 /* Find out desired geometry of the image instance. If there is no
1895 special function then just return the width and / or height. */
1897 image_instance_query_geometry (Lisp_Object image_instance,
1898 unsigned int* width, unsigned int* height,
1899 enum image_instance_geometry disp,
1902 Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance);
1904 struct image_instantiator_methods* meths;
1905 ERROR_CHECK_IMAGE_INSTANCE (image_instance);
1907 type = encode_image_instance_type (IMAGE_INSTANCE_TYPE (ii));
1908 meths = decode_device_ii_format (Qnil, type, ERROR_ME_NOT);
1910 if (meths && HAS_IIFORMAT_METH_P (meths, query_geometry))
1912 IIFORMAT_METH (meths, query_geometry, (image_instance, width, height,
1918 *width = IMAGE_INSTANCE_WIDTH (ii);
1920 *height = IMAGE_INSTANCE_HEIGHT (ii);
1924 /* Layout the image instance using the provided dimensions. Layout
1925 widgets are going to do different kinds of calculations to
1926 determine what size to give things so we could make the layout
1927 function relatively simple to take account of that. An alternative
1928 approach is to consider separately the two cases, one where you
1929 don't mind what size you have (normal widgets) and one where you
1930 want to specifiy something (layout widgets). */
1932 image_instance_layout (Lisp_Object image_instance,
1933 unsigned int width, unsigned int height,
1936 Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance);
1938 struct image_instantiator_methods* meths;
1940 ERROR_CHECK_IMAGE_INSTANCE (image_instance);
1942 /* Nothing is as nothing does. */
1943 if (NOTHING_IMAGE_INSTANCEP (image_instance))
1946 type = encode_image_instance_type (IMAGE_INSTANCE_TYPE (ii));
1947 meths = decode_device_ii_format (Qnil, type, ERROR_ME_NOT);
1949 /* If geometry is unspecified then get some reasonable values for it. */
1950 if (width == IMAGE_UNSPECIFIED_GEOMETRY
1952 height == IMAGE_UNSPECIFIED_GEOMETRY)
1954 unsigned int dwidth = IMAGE_UNSPECIFIED_GEOMETRY,
1955 dheight = IMAGE_UNSPECIFIED_GEOMETRY;
1957 /* Get the desired geometry. */
1958 if (meths && HAS_IIFORMAT_METH_P (meths, query_geometry))
1960 IIFORMAT_METH (meths, query_geometry, (image_instance, &dwidth, &dheight,
1961 IMAGE_DESIRED_GEOMETRY,
1966 dwidth = IMAGE_INSTANCE_WIDTH (ii);
1967 dheight = IMAGE_INSTANCE_HEIGHT (ii);
1970 /* Compare with allowed geometry. */
1971 if (width == IMAGE_UNSPECIFIED_GEOMETRY)
1973 if (height == IMAGE_UNSPECIFIED_GEOMETRY)
1977 /* If we don't have sane values then we cannot layout at this point and
1978 must just return. */
1979 if (width == IMAGE_UNSPECIFIED_GEOMETRY
1981 height == IMAGE_UNSPECIFIED_GEOMETRY)
1984 /* At this point width and height should contain sane values. Thus
1985 we set the glyph geometry and lay it out. */
1986 if (IMAGE_INSTANCE_WIDTH (ii) != width
1988 IMAGE_INSTANCE_HEIGHT (ii) != height)
1990 IMAGE_INSTANCE_SIZE_CHANGED (ii) = 1;
1993 IMAGE_INSTANCE_WIDTH (ii) = width;
1994 IMAGE_INSTANCE_HEIGHT (ii) = height;
1996 if (IIFORMAT_METH_OR_GIVEN (meths, layout,
1997 (image_instance, width, height, domain), 1))
1998 /* Do not clear the dirty flag here - redisplay will do this for
2000 IMAGE_INSTANCE_LAYOUT_CHANGED (ii) = 0;
2004 * Mark image instance in W as dirty if (a) W's faces have changed and
2005 * (b) GLYPH_OR_II instance in W is a string.
2007 * Return non-zero if instance has been marked dirty.
2010 invalidate_glyph_geometry_maybe (Lisp_Object glyph_or_ii, struct window* w)
2012 if (XFRAME(WINDOW_FRAME(w))->faces_changed)
2014 Lisp_Object image = glyph_or_ii;
2016 if (GLYPHP (glyph_or_ii))
2019 XSETWINDOW (window, w);
2020 image = glyph_image_instance (glyph_or_ii, window, ERROR_ME_NOT, 1);
2023 if (TEXT_IMAGE_INSTANCEP (image))
2025 Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image);
2026 IMAGE_INSTANCE_DIRTYP (ii) = 1;
2027 IMAGE_INSTANCE_LAYOUT_CHANGED (ii) = 1;
2028 if (GLYPHP (glyph_or_ii))
2029 XGLYPH_DIRTYP (glyph_or_ii) = 1;
2038 /************************************************************************/
2040 /************************************************************************/
2042 signal_image_error (const char *reason, Lisp_Object frob)
2044 signal_error (Qimage_conversion_error,
2045 list2 (build_translated_string (reason), frob));
2049 signal_image_error_2 (const char *reason, Lisp_Object frob0, Lisp_Object frob1)
2051 signal_error (Qimage_conversion_error,
2052 list3 (build_translated_string (reason), frob0, frob1));
2055 /****************************************************************************
2057 ****************************************************************************/
2060 nothing_possible_dest_types (void)
2062 return IMAGE_NOTHING_MASK;
2066 nothing_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2067 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2068 int dest_mask, Lisp_Object domain)
2070 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2072 if (dest_mask & IMAGE_NOTHING_MASK)
2074 IMAGE_INSTANCE_TYPE (ii) = IMAGE_NOTHING;
2075 IMAGE_INSTANCE_HEIGHT (ii) = 0;
2076 IMAGE_INSTANCE_WIDTH (ii) = 0;
2079 incompatible_image_types (instantiator, dest_mask, IMAGE_NOTHING_MASK);
2083 /****************************************************************************
2085 ****************************************************************************/
2088 inherit_validate (Lisp_Object instantiator)
2090 face_must_be_present (instantiator);
2094 inherit_normalize (Lisp_Object inst, Lisp_Object console_type)
2098 assert (XVECTOR_LENGTH (inst) == 3);
2099 face = XVECTOR_DATA (inst)[2];
2101 inst = vector3 (Qinherit, Q_face, Fget_face (face));
2106 inherit_possible_dest_types (void)
2108 return IMAGE_MONO_PIXMAP_MASK;
2112 inherit_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2113 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2114 int dest_mask, Lisp_Object domain)
2116 /* handled specially in image_instantiate */
2121 /****************************************************************************
2123 ****************************************************************************/
2126 string_validate (Lisp_Object instantiator)
2128 data_must_be_present (instantiator);
2132 string_possible_dest_types (void)
2134 return IMAGE_TEXT_MASK;
2137 /* Called from autodetect_instantiate() */
2139 string_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2140 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2141 int dest_mask, Lisp_Object domain)
2143 Lisp_Object string = find_keyword_in_vector (instantiator, Q_data);
2144 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2146 /* Should never get here with a domain other than a window. */
2147 assert (!NILP (string) && WINDOWP (DOMAIN_WINDOW (domain)));
2148 if (dest_mask & IMAGE_TEXT_MASK)
2150 IMAGE_INSTANCE_TYPE (ii) = IMAGE_TEXT;
2151 IMAGE_INSTANCE_TEXT_STRING (ii) = string;
2154 incompatible_image_types (instantiator, dest_mask, IMAGE_TEXT_MASK);
2157 /* Sort out the size of the text that is being displayed. Calculating
2158 it dynamically allows us to change the text and still see
2159 everything. Note that the following methods are for text not string
2160 since that is what the instantiated type is. The first method is a
2161 helper that is used elsewhere for calculating text geometry. */
2163 query_string_geometry (Lisp_Object string, Lisp_Object face,
2164 unsigned int* width, unsigned int* height,
2165 unsigned int* descent, Lisp_Object domain)
2167 struct font_metric_info fm;
2168 unsigned char charsets[NUM_LEADING_BYTES];
2169 struct face_cachel frame_cachel;
2170 struct face_cachel *cachel;
2171 Lisp_Object frame = DOMAIN_FRAME (domain);
2173 /* Compute height */
2176 /* Compute string metric info */
2177 find_charsets_in_bufbyte_string (charsets,
2178 XSTRING_DATA (string),
2179 XSTRING_LENGTH (string));
2181 /* Fallback to the default face if none was provided. */
2184 reset_face_cachel (&frame_cachel);
2185 update_face_cachel_data (&frame_cachel, frame, face);
2186 cachel = &frame_cachel;
2190 cachel = WINDOW_FACE_CACHEL (DOMAIN_XWINDOW (domain),
2194 ensure_face_cachel_complete (cachel, domain, charsets);
2195 face_cachel_charset_font_metric_info (cachel, charsets, &fm);
2197 *height = fm.ascent + fm.descent;
2198 /* #### descent only gets set if we query the height as well. */
2200 *descent = fm.descent;
2207 *width = redisplay_frame_text_width_string (XFRAME (frame),
2211 *width = redisplay_frame_text_width_string (XFRAME (frame),
2218 query_string_font (Lisp_Object string, Lisp_Object face, Lisp_Object domain)
2220 unsigned char charsets[NUM_LEADING_BYTES];
2221 struct face_cachel frame_cachel;
2222 struct face_cachel *cachel;
2224 Lisp_Object frame = DOMAIN_FRAME (domain);
2226 /* Compute string font info */
2227 find_charsets_in_bufbyte_string (charsets,
2228 XSTRING_DATA (string),
2229 XSTRING_LENGTH (string));
2231 reset_face_cachel (&frame_cachel);
2232 update_face_cachel_data (&frame_cachel, frame, face);
2233 cachel = &frame_cachel;
2235 ensure_face_cachel_complete (cachel, domain, charsets);
2237 for (i = 0; i < NUM_LEADING_BYTES; i++)
2241 return FACE_CACHEL_FONT (cachel,
2242 CHARSET_BY_LEADING_BYTE (i +
2248 return Qnil; /* NOT REACHED */
2252 text_query_geometry (Lisp_Object image_instance,
2253 unsigned int* width, unsigned int* height,
2254 enum image_instance_geometry disp, Lisp_Object domain)
2256 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2257 unsigned int descent = 0;
2259 query_string_geometry (IMAGE_INSTANCE_TEXT_STRING (ii),
2260 IMAGE_INSTANCE_FACE (ii),
2261 width, height, &descent, domain);
2263 /* The descent gets set as a side effect of querying the
2265 IMAGE_INSTANCE_TEXT_DESCENT (ii) = descent;
2268 /* set the properties of a string */
2270 text_set_property (Lisp_Object image_instance, Lisp_Object prop,
2273 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2275 if (EQ (prop, Q_data))
2278 IMAGE_INSTANCE_TEXT_STRING (ii) = val;
2286 /****************************************************************************
2287 * formatted-string *
2288 ****************************************************************************/
2291 formatted_string_validate (Lisp_Object instantiator)
2293 data_must_be_present (instantiator);
2297 formatted_string_possible_dest_types (void)
2299 return IMAGE_TEXT_MASK;
2303 formatted_string_instantiate (Lisp_Object image_instance,
2304 Lisp_Object instantiator,
2305 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2306 int dest_mask, Lisp_Object domain)
2308 /* #### implement this */
2309 warn_when_safe (Qunimplemented, Qnotice,
2310 "`formatted-string' not yet implemented; assuming `string'");
2312 string_instantiate (image_instance, instantiator,
2313 pointer_fg, pointer_bg, dest_mask, domain);
2317 /************************************************************************/
2318 /* pixmap file functions */
2319 /************************************************************************/
2321 /* If INSTANTIATOR refers to inline data, return Qnil.
2322 If INSTANTIATOR refers to data in a file, return the full filename
2323 if it exists; otherwise, return a cons of (filename).
2325 FILE_KEYWORD and DATA_KEYWORD are symbols specifying the
2326 keywords used to look up the file and inline data,
2327 respectively, in the instantiator. Normally these would
2328 be Q_file and Q_data, but might be different for mask data. */
2331 potential_pixmap_file_instantiator (Lisp_Object instantiator,
2332 Lisp_Object file_keyword,
2333 Lisp_Object data_keyword,
2334 Lisp_Object console_type)
2339 assert (VECTORP (instantiator));
2341 data = find_keyword_in_vector (instantiator, data_keyword);
2342 file = find_keyword_in_vector (instantiator, file_keyword);
2344 if (!NILP (file) && NILP (data))
2346 Lisp_Object retval = MAYBE_LISP_CONTYPE_METH
2347 (decode_console_type(console_type, ERROR_ME),
2348 locate_pixmap_file, (file));
2353 return Fcons (file, Qnil); /* should have been file */
2360 simple_image_type_normalize (Lisp_Object inst, Lisp_Object console_type,
2361 Lisp_Object image_type_tag)
2363 /* This function can call lisp */
2364 Lisp_Object file = Qnil;
2365 struct gcpro gcpro1, gcpro2;
2366 Lisp_Object alist = Qnil;
2368 GCPRO2 (file, alist);
2370 /* Now, convert any file data into inline data. At the end of this,
2371 `data' will contain the inline data (if any) or Qnil, and `file'
2372 will contain the name this data was derived from (if known) or
2375 Note that if we cannot generate any regular inline data, we
2378 file = potential_pixmap_file_instantiator (inst, Q_file, Q_data,
2381 if (CONSP (file)) /* failure locating filename */
2382 signal_double_file_error ("Opening pixmap file",
2383 "no such file or directory",
2386 if (NILP (file)) /* no conversion necessary */
2387 RETURN_UNGCPRO (inst);
2389 alist = tagged_vector_to_alist (inst);
2392 Lisp_Object data = make_string_from_file (file);
2393 alist = remassq_no_quit (Q_file, alist);
2394 /* there can't be a :data at this point. */
2395 alist = Fcons (Fcons (Q_file, file),
2396 Fcons (Fcons (Q_data, data), alist));
2400 Lisp_Object result = alist_to_tagged_vector (image_type_tag, alist);
2402 RETURN_UNGCPRO (result);
2407 #ifdef HAVE_WINDOW_SYSTEM
2408 /**********************************************************************
2410 **********************************************************************/
2412 /* Check if DATA represents a valid inline XBM spec (i.e. a list
2413 of (width height bits), with checking done on the dimensions).
2414 If not, signal an error. */
2417 check_valid_xbm_inline (Lisp_Object data)
2419 Lisp_Object width, height, bits;
2421 if (!CONSP (data) ||
2422 !CONSP (XCDR (data)) ||
2423 !CONSP (XCDR (XCDR (data))) ||
2424 !NILP (XCDR (XCDR (XCDR (data)))))
2425 signal_simple_error ("Must be list of 3 elements", data);
2427 width = XCAR (data);
2428 height = XCAR (XCDR (data));
2429 bits = XCAR (XCDR (XCDR (data)));
2431 CHECK_STRING (bits);
2433 if (!NATNUMP (width))
2434 signal_simple_error ("Width must be a natural number", width);
2436 if (!NATNUMP (height))
2437 signal_simple_error ("Height must be a natural number", height);
2439 if (((XINT (width) * XINT (height)) / 8) > XSTRING_CHAR_LENGTH (bits))
2440 signal_simple_error ("data is too short for width and height",
2441 vector3 (width, height, bits));
2444 /* Validate method for XBM's. */
2447 xbm_validate (Lisp_Object instantiator)
2449 file_or_data_must_be_present (instantiator);
2452 /* Given a filename that is supposed to contain XBM data, return
2453 the inline representation of it as (width height bits). Return
2454 the hotspot through XHOT and YHOT, if those pointers are not 0.
2455 If there is no hotspot, XHOT and YHOT will contain -1.
2457 If the function fails:
2459 -- if OK_IF_DATA_INVALID is set and the data was invalid,
2461 -- maybe return an error, or return Qnil.
2464 #ifdef HAVE_X_WINDOWS
2465 #include <X11/Xlib.h>
2467 #define XFree(data) free(data)
2471 bitmap_to_lisp_data (Lisp_Object name, int *xhot, int *yhot,
2472 int ok_if_data_invalid)
2477 const char *filename_ext;
2479 TO_EXTERNAL_FORMAT (LISP_STRING, name,
2480 C_STRING_ALLOCA, filename_ext,
2482 result = read_bitmap_data_from_file (filename_ext, &w, &h,
2485 if (result == BitmapSuccess)
2488 int len = (w + 7) / 8 * h;
2490 retval = list3 (make_int (w), make_int (h),
2491 make_ext_string (data, len, Qbinary));
2492 XFree ((char *) data);
2498 case BitmapOpenFailed:
2500 /* should never happen */
2501 signal_double_file_error ("Opening bitmap file",
2502 "no such file or directory",
2505 case BitmapFileInvalid:
2507 if (ok_if_data_invalid)
2509 signal_double_file_error ("Reading bitmap file",
2510 "invalid data in file",
2513 case BitmapNoMemory:
2515 signal_double_file_error ("Reading bitmap file",
2521 signal_double_file_error_2 ("Reading bitmap file",
2522 "unknown error code",
2523 make_int (result), name);
2527 return Qnil; /* not reached */
2531 xbm_mask_file_munging (Lisp_Object alist, Lisp_Object file,
2532 Lisp_Object mask_file, Lisp_Object console_type)
2534 /* This is unclean but it's fairly standard -- a number of the
2535 bitmaps in /usr/include/X11/bitmaps use it -- so we support
2537 if (NILP (mask_file)
2538 /* don't override explicitly specified mask data. */
2539 && NILP (assq_no_quit (Q_mask_data, alist))
2542 mask_file = MAYBE_LISP_CONTYPE_METH
2543 (decode_console_type(console_type, ERROR_ME),
2544 locate_pixmap_file, (concat2 (file, build_string ("Mask"))));
2545 if (NILP (mask_file))
2546 mask_file = MAYBE_LISP_CONTYPE_METH
2547 (decode_console_type(console_type, ERROR_ME),
2548 locate_pixmap_file, (concat2 (file, build_string ("msk"))));
2551 if (!NILP (mask_file))
2553 Lisp_Object mask_data =
2554 bitmap_to_lisp_data (mask_file, 0, 0, 0);
2555 alist = remassq_no_quit (Q_mask_file, alist);
2556 /* there can't be a :mask-data at this point. */
2557 alist = Fcons (Fcons (Q_mask_file, mask_file),
2558 Fcons (Fcons (Q_mask_data, mask_data), alist));
2564 /* Normalize method for XBM's. */
2567 xbm_normalize (Lisp_Object inst, Lisp_Object console_type)
2569 Lisp_Object file = Qnil, mask_file = Qnil;
2570 struct gcpro gcpro1, gcpro2, gcpro3;
2571 Lisp_Object alist = Qnil;
2573 GCPRO3 (file, mask_file, alist);
2575 /* Now, convert any file data into inline data for both the regular
2576 data and the mask data. At the end of this, `data' will contain
2577 the inline data (if any) or Qnil, and `file' will contain
2578 the name this data was derived from (if known) or Qnil.
2579 Likewise for `mask_file' and `mask_data'.
2581 Note that if we cannot generate any regular inline data, we
2584 file = potential_pixmap_file_instantiator (inst, Q_file, Q_data,
2586 mask_file = potential_pixmap_file_instantiator (inst, Q_mask_file,
2587 Q_mask_data, console_type);
2589 if (CONSP (file)) /* failure locating filename */
2590 signal_double_file_error ("Opening bitmap file",
2591 "no such file or directory",
2594 if (NILP (file) && NILP (mask_file)) /* no conversion necessary */
2595 RETURN_UNGCPRO (inst);
2597 alist = tagged_vector_to_alist (inst);
2602 Lisp_Object data = bitmap_to_lisp_data (file, &xhot, &yhot, 0);
2603 alist = remassq_no_quit (Q_file, alist);
2604 /* there can't be a :data at this point. */
2605 alist = Fcons (Fcons (Q_file, file),
2606 Fcons (Fcons (Q_data, data), alist));
2608 if (xhot != -1 && NILP (assq_no_quit (Q_hotspot_x, alist)))
2609 alist = Fcons (Fcons (Q_hotspot_x, make_int (xhot)),
2611 if (yhot != -1 && NILP (assq_no_quit (Q_hotspot_y, alist)))
2612 alist = Fcons (Fcons (Q_hotspot_y, make_int (yhot)),
2616 alist = xbm_mask_file_munging (alist, file, mask_file, console_type);
2619 Lisp_Object result = alist_to_tagged_vector (Qxbm, alist);
2621 RETURN_UNGCPRO (result);
2627 xbm_possible_dest_types (void)
2630 IMAGE_MONO_PIXMAP_MASK |
2631 IMAGE_COLOR_PIXMAP_MASK |
2639 /**********************************************************************
2641 **********************************************************************/
2644 xface_validate (Lisp_Object instantiator)
2646 file_or_data_must_be_present (instantiator);
2650 xface_normalize (Lisp_Object inst, Lisp_Object console_type)
2652 /* This function can call lisp */
2653 Lisp_Object file = Qnil, mask_file = Qnil;
2654 struct gcpro gcpro1, gcpro2, gcpro3;
2655 Lisp_Object alist = Qnil;
2657 GCPRO3 (file, mask_file, alist);
2659 /* Now, convert any file data into inline data for both the regular
2660 data and the mask data. At the end of this, `data' will contain
2661 the inline data (if any) or Qnil, and `file' will contain
2662 the name this data was derived from (if known) or Qnil.
2663 Likewise for `mask_file' and `mask_data'.
2665 Note that if we cannot generate any regular inline data, we
2668 file = potential_pixmap_file_instantiator (inst, Q_file, Q_data,
2670 mask_file = potential_pixmap_file_instantiator (inst, Q_mask_file,
2671 Q_mask_data, console_type);
2673 if (CONSP (file)) /* failure locating filename */
2674 signal_double_file_error ("Opening bitmap file",
2675 "no such file or directory",
2678 if (NILP (file) && NILP (mask_file)) /* no conversion necessary */
2679 RETURN_UNGCPRO (inst);
2681 alist = tagged_vector_to_alist (inst);
2684 Lisp_Object data = make_string_from_file (file);
2685 alist = remassq_no_quit (Q_file, alist);
2686 /* there can't be a :data at this point. */
2687 alist = Fcons (Fcons (Q_file, file),
2688 Fcons (Fcons (Q_data, data), alist));
2691 alist = xbm_mask_file_munging (alist, file, mask_file, console_type);
2694 Lisp_Object result = alist_to_tagged_vector (Qxface, alist);
2696 RETURN_UNGCPRO (result);
2701 xface_possible_dest_types (void)
2704 IMAGE_MONO_PIXMAP_MASK |
2705 IMAGE_COLOR_PIXMAP_MASK |
2709 #endif /* HAVE_XFACE */
2714 /**********************************************************************
2716 **********************************************************************/
2719 pixmap_to_lisp_data (Lisp_Object name, int ok_if_data_invalid)
2725 TO_EXTERNAL_FORMAT (LISP_STRING, name,
2726 C_STRING_ALLOCA, fname,
2728 result = XpmReadFileToData (fname, &data);
2730 if (result == XpmSuccess)
2732 Lisp_Object retval = Qnil;
2733 struct buffer *old_buffer = current_buffer;
2734 Lisp_Object temp_buffer =
2735 Fget_buffer_create (build_string (" *pixmap conversion*"));
2737 int height, width, ncolors;
2738 struct gcpro gcpro1, gcpro2, gcpro3;
2739 int speccount = specpdl_depth ();
2741 GCPRO3 (name, retval, temp_buffer);
2743 specbind (Qinhibit_quit, Qt);
2744 set_buffer_internal (XBUFFER (temp_buffer));
2745 Ferase_buffer (Qnil);
2747 buffer_insert_c_string (current_buffer, "/* XPM */\r");
2748 buffer_insert_c_string (current_buffer, "static char *pixmap[] = {\r");
2750 sscanf (data[0], "%d %d %d", &height, &width, &ncolors);
2751 for (elt = 0; elt <= width + ncolors; elt++)
2753 buffer_insert_c_string (current_buffer, "\"");
2754 buffer_insert_c_string (current_buffer, data[elt]);
2756 if (elt < width + ncolors)
2757 buffer_insert_c_string (current_buffer, "\",\r");
2759 buffer_insert_c_string (current_buffer, "\"};\r");
2762 retval = Fbuffer_substring (Qnil, Qnil, Qnil);
2765 set_buffer_internal (old_buffer);
2766 unbind_to (speccount, Qnil);
2768 RETURN_UNGCPRO (retval);
2773 case XpmFileInvalid:
2775 if (ok_if_data_invalid)
2777 signal_image_error ("invalid XPM data in file", name);
2781 signal_double_file_error ("Reading pixmap file",
2782 "out of memory", name);
2786 /* should never happen? */
2787 signal_double_file_error ("Opening pixmap file",
2788 "no such file or directory", name);
2792 signal_double_file_error_2 ("Parsing pixmap file",
2793 "unknown error code",
2794 make_int (result), name);
2799 return Qnil; /* not reached */
2803 check_valid_xpm_color_symbols (Lisp_Object data)
2807 for (rest = data; !NILP (rest); rest = XCDR (rest))
2809 if (!CONSP (rest) ||
2810 !CONSP (XCAR (rest)) ||
2811 !STRINGP (XCAR (XCAR (rest))) ||
2812 (!STRINGP (XCDR (XCAR (rest))) &&
2813 !COLOR_SPECIFIERP (XCDR (XCAR (rest)))))
2814 signal_simple_error ("Invalid color symbol alist", data);
2819 xpm_validate (Lisp_Object instantiator)
2821 file_or_data_must_be_present (instantiator);
2824 Lisp_Object Vxpm_color_symbols;
2827 evaluate_xpm_color_symbols (void)
2829 Lisp_Object rest, results = Qnil;
2830 struct gcpro gcpro1, gcpro2;
2832 GCPRO2 (rest, results);
2833 for (rest = Vxpm_color_symbols; !NILP (rest); rest = XCDR (rest))
2835 Lisp_Object name, value, cons;
2841 CHECK_STRING (name);
2842 value = XCDR (cons);
2844 value = XCAR (value);
2845 value = Feval (value);
2848 if (!STRINGP (value) && !COLOR_SPECIFIERP (value))
2850 ("Result from xpm-color-symbols eval must be nil, string, or color",
2852 results = Fcons (Fcons (name, value), results);
2854 UNGCPRO; /* no more evaluation */
2859 xpm_normalize (Lisp_Object inst, Lisp_Object console_type)
2861 Lisp_Object file = Qnil;
2862 Lisp_Object color_symbols;
2863 struct gcpro gcpro1, gcpro2;
2864 Lisp_Object alist = Qnil;
2866 GCPRO2 (file, alist);
2868 /* Now, convert any file data into inline data. At the end of this,
2869 `data' will contain the inline data (if any) or Qnil, and
2870 `file' will contain the name this data was derived from (if
2873 Note that if we cannot generate any regular inline data, we
2876 file = potential_pixmap_file_instantiator (inst, Q_file, Q_data,
2879 if (CONSP (file)) /* failure locating filename */
2880 signal_double_file_error ("Opening pixmap file",
2881 "no such file or directory",
2884 color_symbols = find_keyword_in_vector_or_given (inst, Q_color_symbols,
2887 if (NILP (file) && !UNBOUNDP (color_symbols))
2888 /* no conversion necessary */
2889 RETURN_UNGCPRO (inst);
2891 alist = tagged_vector_to_alist (inst);
2895 Lisp_Object data = pixmap_to_lisp_data (file, 0);
2896 alist = remassq_no_quit (Q_file, alist);
2897 /* there can't be a :data at this point. */
2898 alist = Fcons (Fcons (Q_file, file),
2899 Fcons (Fcons (Q_data, data), alist));
2902 if (UNBOUNDP (color_symbols))
2904 color_symbols = evaluate_xpm_color_symbols ();
2905 alist = Fcons (Fcons (Q_color_symbols, color_symbols),
2910 Lisp_Object result = alist_to_tagged_vector (Qxpm, alist);
2912 RETURN_UNGCPRO (result);
2917 xpm_possible_dest_types (void)
2920 IMAGE_MONO_PIXMAP_MASK |
2921 IMAGE_COLOR_PIXMAP_MASK |
2925 #endif /* HAVE_XPM */
2928 /****************************************************************************
2929 * Image Specifier Object *
2930 ****************************************************************************/
2932 DEFINE_SPECIFIER_TYPE (image);
2935 image_create (Lisp_Object obj)
2937 Lisp_Specifier *image = XIMAGE_SPECIFIER (obj);
2939 IMAGE_SPECIFIER_ALLOWED (image) = ~0; /* all are allowed */
2940 IMAGE_SPECIFIER_ATTACHEE (image) = Qnil;
2941 IMAGE_SPECIFIER_ATTACHEE_PROPERTY (image) = Qnil;
2945 image_mark (Lisp_Object obj)
2947 Lisp_Specifier *image = XIMAGE_SPECIFIER (obj);
2949 mark_object (IMAGE_SPECIFIER_ATTACHEE (image));
2950 mark_object (IMAGE_SPECIFIER_ATTACHEE_PROPERTY (image));
2954 image_instantiate_cache_result (Lisp_Object locative)
2956 /* locative = (instance instantiator . subtable)
2958 So we are using the instantiator as the key and the instance as
2959 the value. Since the hashtable is key-weak this means that the
2960 image instance will stay around as long as the instantiator stays
2961 around. The instantiator is stored in the `image' slot of the
2962 glyph, so as long as the glyph is marked the instantiator will be
2963 as well and hence the cached image instance also.*/
2964 Fputhash (XCAR (XCDR (locative)), XCAR (locative), XCDR (XCDR (locative)));
2965 free_cons (XCONS (XCDR (locative)));
2966 free_cons (XCONS (locative));
2970 /* Given a specification for an image, return an instance of
2971 the image which matches the given instantiator and which can be
2972 displayed in the given domain. */
2975 image_instantiate (Lisp_Object specifier, Lisp_Object matchspec,
2976 Lisp_Object domain, Lisp_Object instantiator,
2979 Lisp_Object glyph = IMAGE_SPECIFIER_ATTACHEE (XIMAGE_SPECIFIER (specifier));
2980 int dest_mask = XIMAGE_SPECIFIER_ALLOWED (specifier);
2981 int pointerp = dest_mask & image_instance_type_to_mask (IMAGE_POINTER);
2983 if (IMAGE_INSTANCEP (instantiator))
2985 /* make sure that the image instance's governing domain and type are
2987 Lisp_Object governing_domain = XIMAGE_INSTANCE_DOMAIN (instantiator);
2989 if ((DEVICEP (governing_domain)
2990 && EQ (governing_domain, DOMAIN_DEVICE (domain)))
2991 || (FRAMEP (governing_domain)
2992 && EQ (governing_domain, DOMAIN_FRAME (domain)))
2993 || (WINDOWP (governing_domain)
2994 && EQ (governing_domain, DOMAIN_WINDOW (domain))))
2997 image_instance_type_to_mask (XIMAGE_INSTANCE_TYPE (instantiator));
2998 if (mask & dest_mask)
2999 return instantiator;
3001 signal_simple_error ("Type of image instance not allowed here",
3005 signal_simple_error_2 ("Wrong domain for image instance",
3006 instantiator, domain);
3008 else if (VECTORP (instantiator)
3009 && EQ (XVECTOR_DATA (instantiator)[0], Qinherit))
3011 assert (XVECTOR_LENGTH (instantiator) == 3);
3012 return (FACE_PROPERTY_INSTANCE
3013 (Fget_face (XVECTOR_DATA (instantiator)[2]),
3014 Qbackground_pixmap, domain, 0, depth));
3018 Lisp_Object instance;
3019 Lisp_Object subtable;
3020 Lisp_Object ls3 = Qnil;
3021 Lisp_Object pointer_fg = Qnil;
3022 Lisp_Object pointer_bg = Qnil;
3023 Lisp_Object governing_domain =
3024 get_image_instantiator_governing_domain (instantiator, domain);
3026 /* We have to put subwindow, widget and text image instances in
3027 a per-window cache so that we can see the same glyph in
3028 different windows. We use governing_domain to determine the type
3029 of image_instance that will be created. */
3033 pointer_fg = FACE_FOREGROUND (Vpointer_face, domain);
3034 pointer_bg = FACE_BACKGROUND (Vpointer_face, domain);
3035 ls3 = list3 (instantiator, pointer_fg, pointer_bg);
3038 /* First look in the device cache. */
3039 if (DEVICEP (governing_domain))
3041 subtable = Fgethash (make_int (dest_mask),
3042 XDEVICE (governing_domain)->
3043 image_instance_cache,
3045 if (UNBOUNDP (subtable))
3047 /* For the image instance cache, we do comparisons with
3048 EQ rather than with EQUAL, as we do for color and
3049 font names. The reasons are:
3051 1) pixmap data can be very long, and thus the hashing
3052 and comparing will take awhile.
3054 2) It's not so likely that we'll run into things that
3055 are EQUAL but not EQ (that can happen a lot with
3056 faces, because their specifiers are copied around);
3057 but pixmaps tend not to be in faces.
3059 However, if the image-instance could be a pointer, we
3060 have to use EQUAL because we massaged the
3061 instantiator into a cons3 also containing the
3062 foreground and background of the pointer face. */
3064 subtable = make_lisp_hash_table
3065 (20, pointerp ? HASH_TABLE_KEY_CAR_WEAK
3066 : HASH_TABLE_KEY_WEAK,
3067 pointerp ? HASH_TABLE_EQUAL
3069 Fputhash (make_int (dest_mask), subtable,
3070 XDEVICE (governing_domain)->image_instance_cache);
3071 instance = Qunbound;
3075 instance = Fgethash (pointerp ? ls3 : instantiator,
3076 subtable, Qunbound);
3079 else if (WINDOWP (governing_domain))
3081 /* Subwindows have a per-window cache and have to be treated
3084 Fgethash (instantiator,
3085 XWINDOW (governing_domain)->subwindow_instance_cache,
3089 abort (); /* We're not allowed anything else currently. */
3091 /* If we don't have an instance at this point then create
3093 if (UNBOUNDP (instance))
3095 Lisp_Object locative =
3097 noseeum_cons (pointerp ? ls3 : instantiator,
3098 DEVICEP (governing_domain) ? subtable
3099 : XWINDOW (governing_domain)
3100 ->subwindow_instance_cache));
3101 int speccount = specpdl_depth ();
3103 /* Make sure we cache the failures, too. Use an
3104 unwind-protect to catch such errors. If we fail, the
3105 unwind-protect records nil in the hash table. If we
3106 succeed, we change the car of the locative to the
3107 resulting instance, which gets recorded instead. */
3108 record_unwind_protect (image_instantiate_cache_result,
3111 instantiate_image_instantiator (governing_domain,
3112 domain, instantiator,
3113 pointer_fg, pointer_bg,
3116 /* We need a per-frame cache for redisplay. */
3117 cache_subwindow_instance_in_frame_maybe (instance);
3119 Fsetcar (locative, instance);
3120 #ifdef ERROR_CHECK_GLYPHS
3121 if (image_instance_type_to_mask (XIMAGE_INSTANCE_TYPE (instance))
3122 & (IMAGE_SUBWINDOW_MASK | IMAGE_WIDGET_MASK))
3123 assert (EQ (XIMAGE_INSTANCE_FRAME (instance),
3124 DOMAIN_FRAME (domain)));
3126 unbind_to (speccount, Qnil);
3127 #ifdef ERROR_CHECK_GLYPHS
3128 if (image_instance_type_to_mask (XIMAGE_INSTANCE_TYPE (instance))
3129 & (IMAGE_SUBWINDOW_MASK | IMAGE_WIDGET_MASK))
3130 assert (EQ (Fgethash ((pointerp ? ls3 : instantiator),
3131 XWINDOW (governing_domain)
3132 ->subwindow_instance_cache,
3133 Qunbound), instance));
3139 if (NILP (instance))
3140 signal_simple_error ("Can't instantiate image (probably cached)",
3142 #ifdef ERROR_CHECK_GLYPHS
3143 if (image_instance_type_to_mask (XIMAGE_INSTANCE_TYPE (instance))
3144 & (IMAGE_SUBWINDOW_MASK | IMAGE_WIDGET_MASK))
3145 assert (EQ (XIMAGE_INSTANCE_FRAME (instance),
3146 DOMAIN_FRAME (domain)));
3148 ERROR_CHECK_IMAGE_INSTANCE (instance);
3153 return Qnil; /* not reached */
3156 /* Validate an image instantiator. */
3159 image_validate (Lisp_Object instantiator)
3161 if (IMAGE_INSTANCEP (instantiator) || STRINGP (instantiator))
3163 else if (VECTORP (instantiator))
3165 Lisp_Object *elt = XVECTOR_DATA (instantiator);
3166 int instantiator_len = XVECTOR_LENGTH (instantiator);
3167 struct image_instantiator_methods *meths;
3168 Lisp_Object already_seen = Qnil;
3169 struct gcpro gcpro1;
3172 if (instantiator_len < 1)
3173 signal_simple_error ("Vector length must be at least 1",
3176 meths = decode_image_instantiator_format (elt[0], ERROR_ME);
3177 if (!(instantiator_len & 1))
3179 ("Must have alternating keyword/value pairs", instantiator);
3181 GCPRO1 (already_seen);
3183 for (i = 1; i < instantiator_len; i += 2)
3185 Lisp_Object keyword = elt[i];
3186 Lisp_Object value = elt[i+1];
3189 CHECK_SYMBOL (keyword);
3190 if (!SYMBOL_IS_KEYWORD (keyword))
3191 signal_simple_error ("Symbol must begin with a colon", keyword);
3193 for (j = 0; j < Dynarr_length (meths->keywords); j++)
3194 if (EQ (keyword, Dynarr_at (meths->keywords, j).keyword))
3197 if (j == Dynarr_length (meths->keywords))
3198 signal_simple_error ("Unrecognized keyword", keyword);
3200 if (!Dynarr_at (meths->keywords, j).multiple_p)
3202 if (!NILP (memq_no_quit (keyword, already_seen)))
3204 ("Keyword may not appear more than once", keyword);
3205 already_seen = Fcons (keyword, already_seen);
3208 (Dynarr_at (meths->keywords, j).validate) (value);
3213 MAYBE_IIFORMAT_METH (meths, validate, (instantiator));
3216 signal_simple_error ("Must be string or vector", instantiator);
3220 image_after_change (Lisp_Object specifier, Lisp_Object locale)
3222 Lisp_Object attachee =
3223 IMAGE_SPECIFIER_ATTACHEE (XIMAGE_SPECIFIER (specifier));
3224 Lisp_Object property =
3225 IMAGE_SPECIFIER_ATTACHEE_PROPERTY (XIMAGE_SPECIFIER (specifier));
3226 if (FACEP (attachee))
3227 face_property_was_changed (attachee, property, locale);
3228 else if (GLYPHP (attachee))
3229 glyph_property_was_changed (attachee, property, locale);
3233 set_image_attached_to (Lisp_Object obj, Lisp_Object face_or_glyph,
3234 Lisp_Object property)
3236 Lisp_Specifier *image = XIMAGE_SPECIFIER (obj);
3238 IMAGE_SPECIFIER_ATTACHEE (image) = face_or_glyph;
3239 IMAGE_SPECIFIER_ATTACHEE_PROPERTY (image) = property;
3243 image_going_to_add (Lisp_Object specifier, Lisp_Object locale,
3244 Lisp_Object tag_set, Lisp_Object instantiator)
3246 Lisp_Object possible_console_types = Qnil;
3248 Lisp_Object retlist = Qnil;
3249 struct gcpro gcpro1, gcpro2;
3251 LIST_LOOP (rest, Vconsole_type_list)
3253 Lisp_Object contype = XCAR (rest);
3254 if (!NILP (memq_no_quit (contype, tag_set)))
3255 possible_console_types = Fcons (contype, possible_console_types);
3258 if (XINT (Flength (possible_console_types)) > 1)
3259 /* two conflicting console types specified */
3262 if (NILP (possible_console_types))
3263 possible_console_types = Vconsole_type_list;
3265 GCPRO2 (retlist, possible_console_types);
3267 LIST_LOOP (rest, possible_console_types)
3269 Lisp_Object contype = XCAR (rest);
3270 Lisp_Object newinst = call_with_suspended_errors
3271 ((lisp_fn_t) normalize_image_instantiator,
3272 Qnil, Qimage, ERROR_ME_NOT, 3, instantiator, contype,
3273 make_int (XIMAGE_SPECIFIER_ALLOWED (specifier)));
3275 if (!NILP (newinst))
3278 if (NILP (memq_no_quit (contype, tag_set)))
3279 newtag = Fcons (contype, tag_set);
3282 retlist = Fcons (Fcons (newtag, newinst), retlist);
3291 /* Copy an image instantiator. We can't use Fcopy_tree since widgets
3292 may contain circular references which would send Fcopy_tree into
3295 image_copy_vector_instantiator (Lisp_Object instantiator)
3298 struct image_instantiator_methods *meths;
3300 int instantiator_len;
3302 CHECK_VECTOR (instantiator);
3304 instantiator = Fcopy_sequence (instantiator);
3305 elt = XVECTOR_DATA (instantiator);
3306 instantiator_len = XVECTOR_LENGTH (instantiator);
3308 meths = decode_image_instantiator_format (elt[0], ERROR_ME);
3310 for (i = 1; i < instantiator_len; i += 2)
3313 Lisp_Object keyword = elt[i];
3314 Lisp_Object value = elt[i+1];
3316 /* Find the keyword entry. */
3317 for (j = 0; j < Dynarr_length (meths->keywords); j++)
3319 if (EQ (keyword, Dynarr_at (meths->keywords, j).keyword))
3323 /* Only copy keyword values that should be copied. */
3324 if (Dynarr_at (meths->keywords, j).copy_p
3326 (CONSP (value) || VECTORP (value)))
3328 elt [i+1] = Fcopy_tree (value, Qt);
3332 return instantiator;
3336 image_copy_instantiator (Lisp_Object arg)
3341 rest = arg = Fcopy_sequence (arg);
3342 while (CONSP (rest))
3344 Lisp_Object elt = XCAR (rest);
3346 XCAR (rest) = Fcopy_tree (elt, Qt);
3347 else if (VECTORP (elt))
3348 XCAR (rest) = image_copy_vector_instantiator (elt);
3349 if (VECTORP (XCDR (rest))) /* hack for (a b . [c d]) */
3350 XCDR (rest) = Fcopy_tree (XCDR (rest), Qt);
3354 else if (VECTORP (arg))
3356 arg = image_copy_vector_instantiator (arg);
3361 DEFUN ("image-specifier-p", Fimage_specifier_p, 1, 1, 0, /*
3362 Return non-nil if OBJECT is an image specifier.
3363 See `make-image-specifier' for a description of image instantiators.
3367 return IMAGE_SPECIFIERP (object) ? Qt : Qnil;
3371 /****************************************************************************
3373 ****************************************************************************/
3376 mark_glyph (Lisp_Object obj)
3378 Lisp_Glyph *glyph = XGLYPH (obj);
3380 mark_object (glyph->image);
3381 mark_object (glyph->contrib_p);
3382 mark_object (glyph->baseline);
3383 mark_object (glyph->face);
3385 return glyph->plist;
3389 print_glyph (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
3391 Lisp_Glyph *glyph = XGLYPH (obj);
3395 error ("printing unreadable object #<glyph 0x%x>", glyph->header.uid);
3397 write_c_string ("#<glyph (", printcharfun);
3398 print_internal (Fglyph_type (obj), printcharfun, 0);
3399 write_c_string (") ", printcharfun);
3400 print_internal (glyph->image, printcharfun, 1);
3401 sprintf (buf, "0x%x>", glyph->header.uid);
3402 write_c_string (buf, printcharfun);
3405 /* Glyphs are equal if all of their display attributes are equal. We
3406 don't compare names or doc-strings, because that would make equal
3409 This isn't concerned with "unspecified" attributes, that's what
3410 #'glyph-differs-from-default-p is for. */
3412 glyph_equal (Lisp_Object obj1, Lisp_Object obj2, int depth)
3414 Lisp_Glyph *g1 = XGLYPH (obj1);
3415 Lisp_Glyph *g2 = XGLYPH (obj2);
3419 return (internal_equal (g1->image, g2->image, depth) &&
3420 internal_equal (g1->contrib_p, g2->contrib_p, depth) &&
3421 internal_equal (g1->baseline, g2->baseline, depth) &&
3422 internal_equal (g1->face, g2->face, depth) &&
3423 !plists_differ (g1->plist, g2->plist, 0, 0, depth + 1));
3426 static unsigned long
3427 glyph_hash (Lisp_Object obj, int depth)
3431 /* No need to hash all of the elements; that would take too long.
3432 Just hash the most common ones. */
3433 return HASH2 (internal_hash (XGLYPH (obj)->image, depth),
3434 internal_hash (XGLYPH (obj)->face, depth));
3438 glyph_getprop (Lisp_Object obj, Lisp_Object prop)
3440 Lisp_Glyph *g = XGLYPH (obj);
3442 if (EQ (prop, Qimage)) return g->image;
3443 if (EQ (prop, Qcontrib_p)) return g->contrib_p;
3444 if (EQ (prop, Qbaseline)) return g->baseline;
3445 if (EQ (prop, Qface)) return g->face;
3447 return external_plist_get (&g->plist, prop, 0, ERROR_ME);
3451 glyph_putprop (Lisp_Object obj, Lisp_Object prop, Lisp_Object value)
3453 if (EQ (prop, Qimage) ||
3454 EQ (prop, Qcontrib_p) ||
3455 EQ (prop, Qbaseline))
3458 if (EQ (prop, Qface))
3460 XGLYPH (obj)->face = Fget_face (value);
3464 external_plist_put (&XGLYPH (obj)->plist, prop, value, 0, ERROR_ME);
3469 glyph_remprop (Lisp_Object obj, Lisp_Object prop)
3471 if (EQ (prop, Qimage) ||
3472 EQ (prop, Qcontrib_p) ||
3473 EQ (prop, Qbaseline))
3476 if (EQ (prop, Qface))
3478 XGLYPH (obj)->face = Qnil;
3482 return external_remprop (&XGLYPH (obj)->plist, prop, 0, ERROR_ME);
3486 glyph_plist (Lisp_Object obj)
3488 Lisp_Glyph *glyph = XGLYPH (obj);
3489 Lisp_Object result = glyph->plist;
3491 result = cons3 (Qface, glyph->face, result);
3492 result = cons3 (Qbaseline, glyph->baseline, result);
3493 result = cons3 (Qcontrib_p, glyph->contrib_p, result);
3494 result = cons3 (Qimage, glyph->image, result);
3499 static const struct lrecord_description glyph_description[] = {
3500 { XD_LISP_OBJECT, offsetof (Lisp_Glyph, image) },
3501 { XD_LISP_OBJECT, offsetof (Lisp_Glyph, contrib_p) },
3502 { XD_LISP_OBJECT, offsetof (Lisp_Glyph, baseline) },
3503 { XD_LISP_OBJECT, offsetof (Lisp_Glyph, face) },
3504 { XD_LISP_OBJECT, offsetof (Lisp_Glyph, plist) },
3508 DEFINE_LRECORD_IMPLEMENTATION_WITH_PROPS ("glyph", glyph,
3509 mark_glyph, print_glyph, 0,
3510 glyph_equal, glyph_hash, glyph_description,
3511 glyph_getprop, glyph_putprop,
3512 glyph_remprop, glyph_plist,
3516 allocate_glyph (enum glyph_type type,
3517 void (*after_change) (Lisp_Object glyph, Lisp_Object property,
3518 Lisp_Object locale))
3520 /* This function can GC */
3521 Lisp_Object obj = Qnil;
3522 Lisp_Glyph *g = alloc_lcrecord_type (Lisp_Glyph, &lrecord_glyph);
3525 g->image = Fmake_specifier (Qimage); /* This function can GC */
3530 XIMAGE_SPECIFIER_ALLOWED (g->image) =
3531 IMAGE_NOTHING_MASK | IMAGE_TEXT_MASK
3532 | IMAGE_MONO_PIXMAP_MASK | IMAGE_COLOR_PIXMAP_MASK
3533 | IMAGE_SUBWINDOW_MASK | IMAGE_WIDGET_MASK;
3536 XIMAGE_SPECIFIER_ALLOWED (g->image) =
3537 IMAGE_NOTHING_MASK | IMAGE_POINTER_MASK;
3540 XIMAGE_SPECIFIER_ALLOWED (g->image) =
3541 IMAGE_NOTHING_MASK | IMAGE_MONO_PIXMAP_MASK
3542 | IMAGE_COLOR_PIXMAP_MASK;
3548 /* I think Fmake_specifier can GC. I think set_specifier_fallback can GC. */
3549 /* We're getting enough reports of odd behavior in this area it seems */
3550 /* best to GCPRO everything. */
3552 Lisp_Object tem1 = list1 (Fcons (Qnil, Vthe_nothing_vector));
3553 Lisp_Object tem2 = list1 (Fcons (Qnil, Qt));
3554 Lisp_Object tem3 = list1 (Fcons (Qnil, Qnil));
3555 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
3557 GCPRO4 (obj, tem1, tem2, tem3);
3559 set_specifier_fallback (g->image, tem1);
3560 g->contrib_p = Fmake_specifier (Qboolean);
3561 set_specifier_fallback (g->contrib_p, tem2);
3562 /* #### should have a specifier for the following */
3563 g->baseline = Fmake_specifier (Qgeneric);
3564 set_specifier_fallback (g->baseline, tem3);
3567 g->after_change = after_change;
3570 set_image_attached_to (g->image, obj, Qimage);
3577 static enum glyph_type
3578 decode_glyph_type (Lisp_Object type, Error_behavior errb)
3581 return GLYPH_BUFFER;
3583 if (ERRB_EQ (errb, ERROR_ME))
3584 CHECK_SYMBOL (type);
3586 if (EQ (type, Qbuffer)) return GLYPH_BUFFER;
3587 if (EQ (type, Qpointer)) return GLYPH_POINTER;
3588 if (EQ (type, Qicon)) return GLYPH_ICON;
3590 maybe_signal_simple_error ("Invalid glyph type", type, Qimage, errb);
3592 return GLYPH_UNKNOWN;
3596 valid_glyph_type_p (Lisp_Object type)
3598 return !NILP (memq_no_quit (type, Vglyph_type_list));
3601 DEFUN ("valid-glyph-type-p", Fvalid_glyph_type_p, 1, 1, 0, /*
3602 Given a GLYPH-TYPE, return non-nil if it is valid.
3603 Valid types are `buffer', `pointer', and `icon'.
3607 return valid_glyph_type_p (glyph_type) ? Qt : Qnil;
3610 DEFUN ("glyph-type-list", Fglyph_type_list, 0, 0, 0, /*
3611 Return a list of valid glyph types.
3615 return Fcopy_sequence (Vglyph_type_list);
3618 DEFUN ("make-glyph-internal", Fmake_glyph_internal, 0, 1, 0, /*
3619 Create and return a new uninitialized glyph or type TYPE.
3621 TYPE specifies the type of the glyph; this should be one of `buffer',
3622 `pointer', or `icon', and defaults to `buffer'. The type of the glyph
3623 specifies in which contexts the glyph can be used, and controls the
3624 allowable image types into which the glyph's image can be
3627 `buffer' glyphs can be used as the begin-glyph or end-glyph of an
3628 extent, in the modeline, and in the toolbar. Their image can be
3629 instantiated as `nothing', `mono-pixmap', `color-pixmap', `text',
3632 `pointer' glyphs can be used to specify the mouse pointer. Their
3633 image can be instantiated as `pointer'.
3635 `icon' glyphs can be used to specify the icon used when a frame is
3636 iconified. Their image can be instantiated as `mono-pixmap' and
3641 enum glyph_type typeval = decode_glyph_type (type, ERROR_ME);
3642 return allocate_glyph (typeval, 0);
3645 DEFUN ("glyphp", Fglyphp, 1, 1, 0, /*
3646 Return non-nil if OBJECT is a glyph.
3648 A glyph is an object used for pixmaps, widgets and the like. It is used
3649 in begin-glyphs and end-glyphs attached to extents, in marginal and textual
3650 annotations, in overlay arrows (overlay-arrow-* variables), in toolbar
3651 buttons, and the like. Much more detailed information can be found at
3652 `make-glyph'. Its image is described using an image specifier --
3653 see `make-image-specifier'. See also `make-image-instance' for further
3658 return GLYPHP (object) ? Qt : Qnil;
3661 DEFUN ("glyph-type", Fglyph_type, 1, 1, 0, /*
3662 Return the type of the given glyph.
3663 The return value will be one of 'buffer, 'pointer, or 'icon.
3667 CHECK_GLYPH (glyph);
3668 switch (XGLYPH_TYPE (glyph))
3671 case GLYPH_BUFFER: return Qbuffer;
3672 case GLYPH_POINTER: return Qpointer;
3673 case GLYPH_ICON: return Qicon;
3678 glyph_image_instance (Lisp_Object glyph, Lisp_Object domain,
3679 Error_behavior errb, int no_quit)
3681 Lisp_Object specifier = GLYPH_IMAGE (XGLYPH (glyph));
3683 /* This can never return Qunbound. All glyphs have 'nothing as
3685 Lisp_Object image_instance = specifier_instance (specifier, Qunbound,
3686 domain, errb, no_quit, 0,
3688 assert (!UNBOUNDP (image_instance));
3689 ERROR_CHECK_IMAGE_INSTANCE (image_instance);
3691 return image_instance;
3695 glyph_image_instance_maybe (Lisp_Object glyph_or_image, Lisp_Object window)
3697 Lisp_Object instance = glyph_or_image;
3699 if (GLYPHP (glyph_or_image))
3700 instance = glyph_image_instance (glyph_or_image, window, ERROR_ME_NOT, 1);
3705 /*****************************************************************************
3708 Return the width of the given GLYPH on the given WINDOW.
3709 Calculations are done based on recursively querying the geometry of
3710 the associated image instances.
3711 ****************************************************************************/
3713 glyph_width (Lisp_Object glyph_or_image, Lisp_Object domain)
3715 Lisp_Object instance = glyph_image_instance_maybe (glyph_or_image,
3717 if (!IMAGE_INSTANCEP (instance))
3720 if (XIMAGE_INSTANCE_NEEDS_LAYOUT (instance))
3721 image_instance_layout (instance, IMAGE_UNSPECIFIED_GEOMETRY,
3722 IMAGE_UNSPECIFIED_GEOMETRY, domain);
3724 return XIMAGE_INSTANCE_WIDTH (instance);
3727 DEFUN ("glyph-width", Fglyph_width, 1, 2, 0, /*
3728 Return the width of GLYPH on WINDOW.
3729 This may not be exact as it does not take into account all of the context
3730 that redisplay will.
3734 XSETWINDOW (window, decode_window (window));
3735 CHECK_GLYPH (glyph);
3737 return make_int (glyph_width (glyph, window));
3741 glyph_ascent (Lisp_Object glyph_or_image, Lisp_Object domain)
3743 Lisp_Object instance = glyph_image_instance_maybe (glyph_or_image,
3745 if (!IMAGE_INSTANCEP (instance))
3748 if (XIMAGE_INSTANCE_NEEDS_LAYOUT (instance))
3749 image_instance_layout (instance, IMAGE_UNSPECIFIED_GEOMETRY,
3750 IMAGE_UNSPECIFIED_GEOMETRY, domain);
3752 if (XIMAGE_INSTANCE_TYPE (instance) == IMAGE_TEXT)
3753 return XIMAGE_INSTANCE_TEXT_ASCENT (instance);
3755 return XIMAGE_INSTANCE_HEIGHT (instance);
3759 glyph_descent (Lisp_Object glyph_or_image, Lisp_Object domain)
3761 Lisp_Object instance = glyph_image_instance_maybe (glyph_or_image,
3763 if (!IMAGE_INSTANCEP (instance))
3766 if (XIMAGE_INSTANCE_NEEDS_LAYOUT (instance))
3767 image_instance_layout (instance, IMAGE_UNSPECIFIED_GEOMETRY,
3768 IMAGE_UNSPECIFIED_GEOMETRY, domain);
3770 if (XIMAGE_INSTANCE_TYPE (instance) == IMAGE_TEXT)
3771 return XIMAGE_INSTANCE_TEXT_DESCENT (instance);
3776 /* strictly a convenience function. */
3778 glyph_height (Lisp_Object glyph_or_image, Lisp_Object domain)
3780 Lisp_Object instance = glyph_image_instance_maybe (glyph_or_image,
3783 if (!IMAGE_INSTANCEP (instance))
3786 if (XIMAGE_INSTANCE_NEEDS_LAYOUT (instance))
3787 image_instance_layout (instance, IMAGE_UNSPECIFIED_GEOMETRY,
3788 IMAGE_UNSPECIFIED_GEOMETRY, domain);
3790 return XIMAGE_INSTANCE_HEIGHT (instance);
3793 DEFUN ("glyph-ascent", Fglyph_ascent, 1, 2, 0, /*
3794 Return the ascent value of GLYPH on WINDOW.
3795 This may not be exact as it does not take into account all of the context
3796 that redisplay will.
3800 XSETWINDOW (window, decode_window (window));
3801 CHECK_GLYPH (glyph);
3803 return make_int (glyph_ascent (glyph, window));
3806 DEFUN ("glyph-descent", Fglyph_descent, 1, 2, 0, /*
3807 Return the descent value of GLYPH on WINDOW.
3808 This may not be exact as it does not take into account all of the context
3809 that redisplay will.
3813 XSETWINDOW (window, decode_window (window));
3814 CHECK_GLYPH (glyph);
3816 return make_int (glyph_descent (glyph, window));
3819 /* This is redundant but I bet a lot of people expect it to exist. */
3820 DEFUN ("glyph-height", Fglyph_height, 1, 2, 0, /*
3821 Return the height of GLYPH on WINDOW.
3822 This may not be exact as it does not take into account all of the context
3823 that redisplay will.
3827 XSETWINDOW (window, decode_window (window));
3828 CHECK_GLYPH (glyph);
3830 return make_int (glyph_height (glyph, window));
3834 set_glyph_dirty_p (Lisp_Object glyph_or_image, Lisp_Object window, int dirty)
3836 Lisp_Object instance = glyph_or_image;
3838 if (!NILP (glyph_or_image))
3840 if (GLYPHP (glyph_or_image))
3842 instance = glyph_image_instance (glyph_or_image, window,
3844 XGLYPH_DIRTYP (glyph_or_image) = dirty;
3847 if (!IMAGE_INSTANCEP (instance))
3850 XIMAGE_INSTANCE_DIRTYP (instance) = dirty;
3855 set_image_instance_dirty_p (Lisp_Object instance, int dirty)
3857 if (IMAGE_INSTANCEP (instance))
3859 XIMAGE_INSTANCE_DIRTYP (instance) = dirty;
3860 /* Now cascade up the hierarchy. */
3861 set_image_instance_dirty_p (XIMAGE_INSTANCE_PARENT (instance),
3864 else if (GLYPHP (instance))
3866 XGLYPH_DIRTYP (instance) = dirty;
3870 /* #### do we need to cache this info to speed things up? */
3873 glyph_baseline (Lisp_Object glyph, Lisp_Object domain)
3875 if (!GLYPHP (glyph))
3879 Lisp_Object retval =
3880 specifier_instance_no_quit (GLYPH_BASELINE (XGLYPH (glyph)),
3881 /* #### look into ERROR_ME_NOT */
3882 Qunbound, domain, ERROR_ME_NOT,
3884 if (!NILP (retval) && !INTP (retval))
3886 else if (INTP (retval))
3888 if (XINT (retval) < 0)
3890 if (XINT (retval) > 100)
3891 retval = make_int (100);
3898 glyph_face (Lisp_Object glyph, Lisp_Object domain)
3900 /* #### Domain parameter not currently used but it will be */
3901 return GLYPHP (glyph) ? GLYPH_FACE (XGLYPH (glyph)) : Qnil;
3905 glyph_contrib_p (Lisp_Object glyph, Lisp_Object domain)
3907 if (!GLYPHP (glyph))
3910 return !NILP (specifier_instance_no_quit
3911 (GLYPH_CONTRIB_P (XGLYPH (glyph)), Qunbound, domain,
3912 /* #### look into ERROR_ME_NOT */
3913 ERROR_ME_NOT, 0, Qzero));
3917 glyph_property_was_changed (Lisp_Object glyph, Lisp_Object property,
3920 if (XGLYPH (glyph)->after_change)
3921 (XGLYPH (glyph)->after_change) (glyph, property, locale);
3924 #if 0 /* Not used for now */
3926 glyph_query_geometry (Lisp_Object glyph_or_image, Lisp_Object window,
3927 unsigned int* width, unsigned int* height,
3928 enum image_instance_geometry disp, Lisp_Object domain)
3930 Lisp_Object instance = glyph_or_image;
3932 if (GLYPHP (glyph_or_image))
3933 instance = glyph_image_instance (glyph_or_image, window, ERROR_ME_NOT, 1);
3935 image_instance_query_geometry (instance, width, height, disp, domain);
3939 glyph_layout (Lisp_Object glyph_or_image, Lisp_Object window,
3940 unsigned int width, unsigned int height, Lisp_Object domain)
3942 Lisp_Object instance = glyph_or_image;
3944 if (GLYPHP (glyph_or_image))
3945 instance = glyph_image_instance (glyph_or_image, window, ERROR_ME_NOT, 1);
3947 image_instance_layout (instance, width, height, domain);
3952 /*****************************************************************************
3953 * glyph cachel functions *
3954 *****************************************************************************/
3956 /* #### All of this is 95% copied from face cachels. Consider
3959 Why do we need glyph_cachels? Simply because a glyph_cachel captures
3960 per-window information about a particular glyph. A glyph itself is
3961 not created in any particular context, so if we were to rely on a
3962 glyph to tell us about its dirtiness we would not be able to reset
3963 the dirty flag after redisplaying it as it may exist in other
3964 contexts. When we have redisplayed we need to know which glyphs to
3965 reset the dirty flags on - the glyph_cachels give us a nice list we
3966 can iterate through doing this. */
3968 mark_glyph_cachels (glyph_cachel_dynarr *elements)
3975 for (elt = 0; elt < Dynarr_length (elements); elt++)
3977 struct glyph_cachel *cachel = Dynarr_atp (elements, elt);
3978 mark_object (cachel->glyph);
3983 update_glyph_cachel_data (struct window *w, Lisp_Object glyph,
3984 struct glyph_cachel *cachel)
3986 if (!cachel->updated || NILP (cachel->glyph) || !EQ (cachel->glyph, glyph)
3987 || XGLYPH_DIRTYP (cachel->glyph)
3988 || XFRAME(WINDOW_FRAME(w))->faces_changed)
3990 Lisp_Object window, instance;
3992 XSETWINDOW (window, w);
3994 cachel->glyph = glyph;
3995 /* Speed things up slightly by grabbing the glyph instantiation
3996 and passing it to the size functions. */
3997 instance = glyph_image_instance (glyph, window, ERROR_ME_NOT, 1);
3999 if (!IMAGE_INSTANCEP (instance))
4002 /* Mark text instance of the glyph dirty if faces have changed,
4003 because its geometry might have changed. */
4004 invalidate_glyph_geometry_maybe (instance, w);
4006 /* #### Do the following 2 lines buy us anything? --kkm */
4007 XGLYPH_DIRTYP (glyph) = XIMAGE_INSTANCE_DIRTYP (instance);
4008 cachel->dirty = XGLYPH_DIRTYP (glyph);
4009 cachel->width = glyph_width (instance, window);
4010 cachel->ascent = glyph_ascent (instance, window);
4011 cachel->descent = glyph_descent (instance, window);
4014 cachel->updated = 1;
4018 add_glyph_cachel (struct window *w, Lisp_Object glyph)
4020 struct glyph_cachel new_cachel;
4023 new_cachel.glyph = Qnil;
4025 update_glyph_cachel_data (w, glyph, &new_cachel);
4026 Dynarr_add (w->glyph_cachels, new_cachel);
4030 get_glyph_cachel_index (struct window *w, Lisp_Object glyph)
4037 for (elt = 0; elt < Dynarr_length (w->glyph_cachels); elt++)
4039 struct glyph_cachel *cachel =
4040 Dynarr_atp (w->glyph_cachels, elt);
4042 if (EQ (cachel->glyph, glyph) && !NILP (glyph))
4044 update_glyph_cachel_data (w, glyph, cachel);
4049 /* If we didn't find the glyph, add it and then return its index. */
4050 add_glyph_cachel (w, glyph);
4055 reset_glyph_cachels (struct window *w)
4057 Dynarr_reset (w->glyph_cachels);
4058 get_glyph_cachel_index (w, Vcontinuation_glyph);
4059 get_glyph_cachel_index (w, Vtruncation_glyph);
4060 get_glyph_cachel_index (w, Vhscroll_glyph);
4061 get_glyph_cachel_index (w, Vcontrol_arrow_glyph);
4062 get_glyph_cachel_index (w, Voctal_escape_glyph);
4063 get_glyph_cachel_index (w, Vinvisible_text_glyph);
4067 mark_glyph_cachels_as_not_updated (struct window *w)
4071 /* We need to have a dirty flag to tell if the glyph has changed.
4072 We can check to see if each glyph variable is actually a
4073 completely different glyph, though. */
4074 #define FROB(glyph_obj, gindex) \
4075 update_glyph_cachel_data (w, glyph_obj, \
4076 Dynarr_atp (w->glyph_cachels, gindex))
4078 FROB (Vcontinuation_glyph, CONT_GLYPH_INDEX);
4079 FROB (Vtruncation_glyph, TRUN_GLYPH_INDEX);
4080 FROB (Vhscroll_glyph, HSCROLL_GLYPH_INDEX);
4081 FROB (Vcontrol_arrow_glyph, CONTROL_GLYPH_INDEX);
4082 FROB (Voctal_escape_glyph, OCT_ESC_GLYPH_INDEX);
4083 FROB (Vinvisible_text_glyph, INVIS_GLYPH_INDEX);
4086 for (elt = 0; elt < Dynarr_length (w->glyph_cachels); elt++)
4088 Dynarr_atp (w->glyph_cachels, elt)->updated = 0;
4092 /* Unset the dirty bit on all the glyph cachels that have it. */
4094 mark_glyph_cachels_as_clean (struct window* w)
4098 XSETWINDOW (window, w);
4099 for (elt = 0; elt < Dynarr_length (w->glyph_cachels); elt++)
4101 struct glyph_cachel *cachel = Dynarr_atp (w->glyph_cachels, elt);
4103 set_glyph_dirty_p (cachel->glyph, window, 0);
4107 #ifdef MEMORY_USAGE_STATS
4110 compute_glyph_cachel_usage (glyph_cachel_dynarr *glyph_cachels,
4111 struct overhead_stats *ovstats)
4116 total += Dynarr_memory_usage (glyph_cachels, ovstats);
4121 #endif /* MEMORY_USAGE_STATS */
4125 /*****************************************************************************
4126 * subwindow cachel functions *
4127 *****************************************************************************/
4128 /* Subwindows are curious in that you have to physically unmap them to
4129 not display them. It is problematic deciding what to do in
4130 redisplay. We have two caches - a per-window instance cache that
4131 keeps track of subwindows on a window, these are linked to their
4132 instantiator in the hashtable and when the instantiator goes away
4133 we want the instance to go away also. However we also have a
4134 per-frame instance cache that we use to determine if a subwindow is
4135 obscuring an area that we want to clear. We need to be able to flip
4136 through this quickly so a hashtable is not suitable hence the
4137 subwindow_cachels. This is a weak list so unreference instances
4138 will get deleted properly. */
4140 /* redisplay in general assumes that drawing something will erase
4141 what was there before. unfortunately this does not apply to
4142 subwindows that need to be specifically unmapped in order to
4143 disappear. we take a brute force approach - on the basis that its
4144 cheap - and unmap all subwindows in a display line */
4146 /* Put new instances in the frame subwindow cache. This is less costly than
4147 doing it every time something gets mapped, and deleted instances will be
4148 removed automatically. */
4150 cache_subwindow_instance_in_frame_maybe (Lisp_Object instance)
4152 Lisp_Image_Instance* ii = XIMAGE_INSTANCE (instance);
4153 if (image_instance_type_to_mask (IMAGE_INSTANCE_TYPE (ii))
4154 & (IMAGE_WIDGET_MASK | IMAGE_SUBWINDOW_MASK))
4156 struct frame* f = DOMAIN_XFRAME (IMAGE_INSTANCE_DOMAIN (ii));
4157 XWEAK_LIST_LIST (FRAME_SUBWINDOW_CACHE (f))
4158 = Fcons (instance, XWEAK_LIST_LIST (FRAME_SUBWINDOW_CACHE (f)));
4162 /* Unmap and finalize all subwindow instances in the frame cache. This
4163 is necessary because GC will not guarantee the order things get
4164 deleted in and moreover, frame finalization deletes the window
4165 system windows before deleting XEmacs windows, and hence
4168 free_frame_subwindow_instance_cache (struct frame* f)
4172 LIST_LOOP (rest, XWEAK_LIST_LIST (FRAME_SUBWINDOW_CACHE (f)))
4174 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (XCAR (rest));
4175 /* Make sure that the subwindow is unmapped so that window
4176 deletion will not try and do it again. */
4177 unmap_subwindow (XCAR (rest));
4178 finalize_image_instance (ii, 0);
4182 /* Unmap and remove all instances from the frame cache. */
4184 reset_frame_subwindow_instance_cache (struct frame* f)
4188 LIST_LOOP (rest, XWEAK_LIST_LIST (FRAME_SUBWINDOW_CACHE (f)))
4190 Lisp_Object value = XCAR (rest);
4191 /* Make sure that the subwindow is unmapped so that window
4192 deletion will not try and do it again. */
4193 unmap_subwindow (value);
4194 XWEAK_LIST_LIST (FRAME_SUBWINDOW_CACHE (f))
4195 = delq_no_quit (value, XWEAK_LIST_LIST (FRAME_SUBWINDOW_CACHE (f)));
4199 /*****************************************************************************
4200 * subwindow exposure ignorance *
4201 *****************************************************************************/
4202 /* when we unmap subwindows the associated window system will generate
4203 expose events. This we do not want as redisplay already copes with
4204 the repainting necessary. Worse, we can get in an endless cycle of
4205 redisplay if we are not careful. Thus we keep a per-frame list of
4206 expose events that are going to come and ignore them as
4209 struct expose_ignore_blocktype
4211 Blocktype_declare (struct expose_ignore);
4212 } *the_expose_ignore_blocktype;
4215 check_for_ignored_expose (struct frame* f, int x, int y, int width, int height)
4217 struct expose_ignore *ei, *prev;
4218 /* the ignore list is FIFO so we should generally get a match with
4219 the first element in the list */
4220 for (ei = f->subwindow_exposures, prev = 0; ei; ei = ei->next)
4222 /* Checking for exact matches just isn't good enough as we
4223 mighte get exposures for partially obscure subwindows, thus
4224 we have to check for overlaps. Being conservative we will
4225 check for exposures wholly contained by the subwindow, this
4226 might give us what we want.*/
4227 if (ei->x <= x && ei->y <= y
4228 && ei->x + ei->width >= x + width
4229 && ei->y + ei->height >= y + height)
4231 #ifdef DEBUG_WIDGETS
4232 stderr_out ("ignored %d+%d, %dx%d for exposure %d+%d, %dx%d\n",
4233 x, y, width, height, ei->x, ei->y, ei->width, ei->height);
4236 f->subwindow_exposures = ei->next;
4238 prev->next = ei->next;
4240 if (ei == f->subwindow_exposures_tail)
4241 f->subwindow_exposures_tail = prev;
4243 Blocktype_free (the_expose_ignore_blocktype, ei);
4252 register_ignored_expose (struct frame* f, int x, int y, int width, int height)
4254 if (!hold_ignored_expose_registration)
4256 struct expose_ignore *ei;
4258 ei = Blocktype_alloc (the_expose_ignore_blocktype);
4264 ei->height = height;
4266 /* we have to add the exposure to the end of the list, since we
4267 want to check the oldest events first. for speed we keep a record
4268 of the end so that we can add right to it. */
4269 if (f->subwindow_exposures_tail)
4271 f->subwindow_exposures_tail->next = ei;
4273 if (!f->subwindow_exposures)
4275 f->subwindow_exposures = ei;
4277 f->subwindow_exposures_tail = ei;
4281 /****************************************************************************
4282 find_matching_subwindow
4284 See if there is a subwindow that completely encloses the requested
4286 ****************************************************************************/
4287 int find_matching_subwindow (struct frame* f, int x, int y, int width, int height)
4291 LIST_LOOP (rest, XWEAK_LIST_LIST (FRAME_SUBWINDOW_CACHE (f)))
4293 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (XCAR (rest));
4295 if (IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (ii)
4297 IMAGE_INSTANCE_DISPLAY_X (ii) <= x
4299 IMAGE_INSTANCE_DISPLAY_Y (ii) <= y
4301 IMAGE_INSTANCE_DISPLAY_X (ii)
4302 + IMAGE_INSTANCE_DISPLAY_WIDTH (ii) >= x + width
4304 IMAGE_INSTANCE_DISPLAY_Y (ii)
4305 + IMAGE_INSTANCE_DISPLAY_HEIGHT (ii) >= y + height)
4314 /*****************************************************************************
4315 * subwindow functions *
4316 *****************************************************************************/
4318 /* Update the displayed characteristics of a subwindow. This function
4319 should generally only get called if the subwindow is actually
4322 update_subwindow (Lisp_Object subwindow)
4324 Lisp_Image_Instance* ii = XIMAGE_INSTANCE (subwindow);
4325 int count = specpdl_depth ();
4327 /* The update method is allowed to call eval. Since it is quite
4328 common for this function to get called from somewhere in
4329 redisplay we need to make sure that quits are ignored. Otherwise
4330 Fsignal will abort. */
4331 specbind (Qinhibit_quit, Qt);
4333 ERROR_CHECK_IMAGE_INSTANCE (subwindow);
4335 if (WIDGET_IMAGE_INSTANCEP (subwindow))
4337 if (image_instance_changed (subwindow))
4338 update_widget (subwindow);
4339 /* Reset the changed flags. */
4340 IMAGE_INSTANCE_WIDGET_FACE_CHANGED (ii) = 0;
4341 IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii) = 0;
4342 IMAGE_INSTANCE_TEXT_CHANGED (ii) = 0;
4344 else if (IMAGE_INSTANCE_TYPE (ii) == IMAGE_SUBWINDOW
4346 !NILP (IMAGE_INSTANCE_FRAME (ii)))
4348 MAYBE_DEVMETH (DOMAIN_XDEVICE (ii->domain),
4349 update_subwindow, (ii));
4352 IMAGE_INSTANCE_SIZE_CHANGED (ii) = 0;
4353 /* This function is typically called by redisplay just before
4354 outputting the information to the screen. Thus we record a hash
4355 of the output to determine whether on-screen is the same as
4356 recorded structure. This approach has limitations in there is a
4357 good chance that hash values will be different for the same
4358 visual appearance. However, we would rather that then the other
4359 way round - it simply means that we will get more displays than
4360 we might need. We can get better hashing by making the depth
4361 negative - currently it will recurse down 7 levels.*/
4362 IMAGE_INSTANCE_DISPLAY_HASH (ii) = internal_hash (subwindow,
4363 IMAGE_INSTANCE_HASH_DEPTH);
4365 unbind_to (count, Qnil);
4369 image_instance_changed (Lisp_Object subwindow)
4371 Lisp_Image_Instance* ii = XIMAGE_INSTANCE (subwindow);
4373 if (internal_hash (subwindow, IMAGE_INSTANCE_HASH_DEPTH) !=
4374 IMAGE_INSTANCE_DISPLAY_HASH (ii))
4376 /* #### I think there is probably a bug here. This gets called for
4377 layouts - and yet the pending items are always nil for
4378 layouts. We are saved by layout optimization, but I'm undecided
4379 as to what the correct fix is. */
4380 else if (WIDGET_IMAGE_INSTANCEP (subwindow)
4381 && (!internal_equal (IMAGE_INSTANCE_WIDGET_ITEMS (ii),
4382 IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii), 0)
4383 || !NILP (IMAGE_INSTANCE_LAYOUT_CHILDREN (ii))))
4389 /* Update all the subwindows on a frame. */
4391 update_widget_instances (Lisp_Object frame)
4396 /* Its possible for the preceeding callback to have deleted the
4397 frame, so cope with this. */
4398 if (!FRAMEP (frame) || !FRAME_LIVE_P (XFRAME (frame)))
4401 CHECK_FRAME (frame);
4404 /* If we get called we know something has changed. */
4405 LIST_LOOP (rest, XWEAK_LIST_LIST (FRAME_SUBWINDOW_CACHE (f)))
4407 Lisp_Object widget = XCAR (rest);
4409 if (XIMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (widget)
4411 image_instance_changed (widget))
4413 set_image_instance_dirty_p (widget, 1);
4414 MARK_FRAME_GLYPHS_CHANGED (f);
4419 /* remove a subwindow from its frame */
4420 void unmap_subwindow (Lisp_Object subwindow)
4422 Lisp_Image_Instance* ii = XIMAGE_INSTANCE (subwindow);
4425 ERROR_CHECK_IMAGE_INSTANCE (subwindow);
4427 if (!image_instance_type_to_mask (IMAGE_INSTANCE_TYPE (ii))
4428 & (IMAGE_WIDGET_MASK | IMAGE_SUBWINDOW_MASK)
4430 !IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (ii))
4433 #ifdef DEBUG_WIDGETS
4434 stderr_out ("unmapping subwindow %d\n", IMAGE_INSTANCE_SUBWINDOW_ID (ii));
4436 f = XFRAME (IMAGE_INSTANCE_FRAME (ii));
4438 /* make sure we don't get expose events */
4439 register_ignored_expose (f, IMAGE_INSTANCE_DISPLAY_X (ii),
4440 IMAGE_INSTANCE_DISPLAY_Y (ii),
4441 IMAGE_INSTANCE_DISPLAY_WIDTH (ii),
4442 IMAGE_INSTANCE_DISPLAY_HEIGHT (ii));
4443 IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (ii) = 0;
4445 MAYBE_DEVMETH (XDEVICE (IMAGE_INSTANCE_DEVICE (ii)),
4446 unmap_subwindow, (ii));
4449 /* show a subwindow in its frame */
4450 void map_subwindow (Lisp_Object subwindow, int x, int y,
4451 struct display_glyph_area *dga)
4453 Lisp_Image_Instance* ii = XIMAGE_INSTANCE (subwindow);
4456 ERROR_CHECK_IMAGE_INSTANCE (subwindow);
4458 if (!image_instance_type_to_mask (IMAGE_INSTANCE_TYPE (ii))
4459 & (IMAGE_WIDGET_MASK | IMAGE_SUBWINDOW_MASK))
4462 #ifdef DEBUG_WIDGETS
4463 stderr_out ("mapping subwindow %d, %dx%d@%d+%d\n",
4464 IMAGE_INSTANCE_SUBWINDOW_ID (ii),
4465 dga->width, dga->height, x, y);
4467 f = XFRAME (IMAGE_INSTANCE_FRAME (ii));
4468 IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (ii) = 1;
4469 IMAGE_INSTANCE_DISPLAY_X (ii) = x;
4470 IMAGE_INSTANCE_DISPLAY_Y (ii) = y;
4471 IMAGE_INSTANCE_DISPLAY_WIDTH (ii) = dga->width;
4472 IMAGE_INSTANCE_DISPLAY_HEIGHT (ii) = dga->height;
4474 MAYBE_DEVMETH (DOMAIN_XDEVICE (ii->domain),
4475 map_subwindow, (ii, x, y, dga));
4479 subwindow_possible_dest_types (void)
4481 return IMAGE_SUBWINDOW_MASK;
4485 subwindow_governing_domain (void)
4487 return GOVERNING_DOMAIN_WINDOW;
4490 /* Partially instantiate a subwindow. */
4492 subwindow_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
4493 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
4494 int dest_mask, Lisp_Object domain)
4496 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
4497 Lisp_Object device = image_instance_device (image_instance);
4498 Lisp_Object frame = DOMAIN_FRAME (domain);
4499 Lisp_Object width = find_keyword_in_vector (instantiator, Q_pixel_width);
4500 Lisp_Object height = find_keyword_in_vector (instantiator, Q_pixel_height);
4503 signal_simple_error ("No selected frame", device);
4505 if (!(dest_mask & IMAGE_SUBWINDOW_MASK))
4506 incompatible_image_types (instantiator, dest_mask, IMAGE_SUBWINDOW_MASK);
4509 IMAGE_INSTANCE_SUBWINDOW_ID (ii) = 0;
4510 IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (ii) = 0;
4515 if (XINT (width) > 1)
4517 IMAGE_INSTANCE_WIDTH (ii) = w;
4518 IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii) = 0;
4524 if (XINT (height) > 1)
4526 IMAGE_INSTANCE_HEIGHT (ii) = h;
4527 IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii) = 0;
4531 /* This is just a backup in case no-one has assigned a suitable geometry.
4532 #### It should really query the enclose window for geometry. */
4534 subwindow_query_geometry (Lisp_Object image_instance, unsigned int* width,
4535 unsigned int* height, enum image_instance_geometry disp,
4538 if (width) *width = 20;
4539 if (height) *height = 20;
4542 DEFUN ("subwindowp", Fsubwindowp, 1, 1, 0, /*
4543 Return non-nil if OBJECT is a subwindow.
4547 CHECK_IMAGE_INSTANCE (object);
4548 return (XIMAGE_INSTANCE_TYPE (object) == IMAGE_SUBWINDOW) ? Qt : Qnil;
4551 DEFUN ("image-instance-subwindow-id", Fimage_instance_subwindow_id, 1, 1, 0, /*
4552 Return the window id of SUBWINDOW as a number.
4556 CHECK_SUBWINDOW_IMAGE_INSTANCE (subwindow);
4557 return make_int ((int) XIMAGE_INSTANCE_SUBWINDOW_ID (subwindow));
4560 DEFUN ("resize-subwindow", Fresize_subwindow, 1, 3, 0, /*
4561 Resize SUBWINDOW to WIDTH x HEIGHT.
4562 If a value is nil that parameter is not changed.
4564 (subwindow, width, height))
4567 Lisp_Image_Instance* ii;
4569 CHECK_SUBWINDOW_IMAGE_INSTANCE (subwindow);
4570 ii = XIMAGE_INSTANCE (subwindow);
4573 neww = IMAGE_INSTANCE_WIDTH (ii);
4575 neww = XINT (width);
4578 newh = IMAGE_INSTANCE_HEIGHT (ii);
4580 newh = XINT (height);
4582 /* The actual resizing gets done asychronously by
4583 update_subwindow. */
4584 IMAGE_INSTANCE_HEIGHT (ii) = newh;
4585 IMAGE_INSTANCE_WIDTH (ii) = neww;
4586 IMAGE_INSTANCE_SIZE_CHANGED (ii) = 1;
4591 DEFUN ("force-subwindow-map", Fforce_subwindow_map, 1, 1, 0, /*
4592 Generate a Map event for SUBWINDOW.
4596 CHECK_SUBWINDOW_IMAGE_INSTANCE (subwindow);
4598 map_subwindow (subwindow, 0, 0);
4604 /*****************************************************************************
4606 *****************************************************************************/
4608 /* Get the display tables for use currently on window W with face
4609 FACE. #### This will have to be redone. */
4612 get_display_tables (struct window *w, face_index findex,
4613 Lisp_Object *face_table, Lisp_Object *window_table)
4616 tem = WINDOW_FACE_CACHEL_DISPLAY_TABLE (w, findex);
4620 tem = noseeum_cons (tem, Qnil);
4622 tem = w->display_table;
4626 tem = noseeum_cons (tem, Qnil);
4627 *window_table = tem;
4631 display_table_entry (Emchar ch, Lisp_Object face_table,
4632 Lisp_Object window_table)
4636 /* Loop over FACE_TABLE, and then over WINDOW_TABLE. */
4637 for (tail = face_table; 1; tail = XCDR (tail))
4642 if (!NILP (window_table))
4644 tail = window_table;
4645 window_table = Qnil;
4650 table = XCAR (tail);
4652 if (VECTORP (table))
4654 if (ch < XVECTOR_LENGTH (table) && !NILP (XVECTOR_DATA (table)[ch]))
4655 return XVECTOR_DATA (table)[ch];
4659 else if (CHAR_TABLEP (table)
4660 && XCHAR_TABLE_TYPE (table) == CHAR_TABLE_TYPE_CHAR)
4662 return get_char_table (ch, XCHAR_TABLE (table));
4664 else if (CHAR_TABLEP (table)
4665 && XCHAR_TABLE_TYPE (table) == CHAR_TABLE_TYPE_GENERIC)
4667 Lisp_Object gotit = get_char_table (ch, XCHAR_TABLE (table));
4673 else if (RANGE_TABLEP (table))
4675 Lisp_Object gotit = Fget_range_table (make_char (ch), table, Qnil);
4686 /*****************************************************************************
4687 * timeouts for animated glyphs *
4688 *****************************************************************************/
4689 static Lisp_Object Qglyph_animated_timeout_handler;
4691 DEFUN ("glyph-animated-timeout-handler", Fglyph_animated_timeout_handler, 1, 1, 0, /*
4692 Callback function for updating animated images.
4697 CHECK_WEAK_LIST (arg);
4699 if (!NILP (XWEAK_LIST_LIST (arg)) && !NILP (XCAR (XWEAK_LIST_LIST (arg))))
4701 Lisp_Object value = XCAR (XWEAK_LIST_LIST (arg));
4703 if (IMAGE_INSTANCEP (value))
4705 Lisp_Image_Instance* ii = XIMAGE_INSTANCE (value);
4707 if (COLOR_PIXMAP_IMAGE_INSTANCEP (value)
4709 IMAGE_INSTANCE_PIXMAP_MAXSLICE (ii) > 1
4711 !disable_animated_pixmaps)
4713 /* Increment the index of the image slice we are currently
4715 IMAGE_INSTANCE_PIXMAP_SLICE (ii) =
4716 (IMAGE_INSTANCE_PIXMAP_SLICE (ii) + 1)
4717 % IMAGE_INSTANCE_PIXMAP_MAXSLICE (ii);
4718 /* We might need to kick redisplay at this point - but we
4720 MARK_DEVICE_FRAMES_GLYPHS_CHANGED
4721 (XDEVICE (image_instance_device (value)));
4722 /* Cascade dirtiness so that we can have an animated glyph in a layout
4724 set_image_instance_dirty_p (value, 1);
4731 Lisp_Object add_glyph_animated_timeout (EMACS_INT tickms, Lisp_Object image)
4733 Lisp_Object ret = Qnil;
4735 if (tickms > 0 && IMAGE_INSTANCEP (image))
4737 double ms = ((double)tickms) / 1000.0;
4738 struct gcpro gcpro1;
4739 Lisp_Object holder = make_weak_list (WEAK_LIST_SIMPLE);
4742 XWEAK_LIST_LIST (holder) = Fcons (image, Qnil);
4744 ret = Fadd_timeout (make_float (ms),
4745 Qglyph_animated_timeout_handler,
4746 holder, make_float (ms));
4753 void disable_glyph_animated_timeout (int i)
4758 Fdisable_timeout (id);
4762 /*****************************************************************************
4764 *****************************************************************************/
4767 syms_of_glyphs (void)
4769 INIT_LRECORD_IMPLEMENTATION (glyph);
4770 INIT_LRECORD_IMPLEMENTATION (image_instance);
4772 /* image instantiators */
4774 DEFSUBR (Fimage_instantiator_format_list);
4775 DEFSUBR (Fvalid_image_instantiator_format_p);
4776 DEFSUBR (Fset_console_type_image_conversion_list);
4777 DEFSUBR (Fconsole_type_image_conversion_list);
4779 defkeyword (&Q_file, ":file");
4780 defkeyword (&Q_data, ":data");
4781 defkeyword (&Q_face, ":face");
4782 defkeyword (&Q_pixel_height, ":pixel-height");
4783 defkeyword (&Q_pixel_width, ":pixel-width");
4786 defkeyword (&Q_color_symbols, ":color-symbols");
4788 #ifdef HAVE_WINDOW_SYSTEM
4789 defkeyword (&Q_mask_file, ":mask-file");
4790 defkeyword (&Q_mask_data, ":mask-data");
4791 defkeyword (&Q_hotspot_x, ":hotspot-x");
4792 defkeyword (&Q_hotspot_y, ":hotspot-y");
4793 defkeyword (&Q_foreground, ":foreground");
4794 defkeyword (&Q_background, ":background");
4796 /* image specifiers */
4798 DEFSUBR (Fimage_specifier_p);
4799 /* Qimage in general.c */
4801 /* image instances */
4803 defsymbol (&Qimage_instancep, "image-instance-p");
4805 defsymbol (&Qnothing_image_instance_p, "nothing-image-instance-p");
4806 defsymbol (&Qtext_image_instance_p, "text-image-instance-p");
4807 defsymbol (&Qmono_pixmap_image_instance_p, "mono-pixmap-image-instance-p");
4808 defsymbol (&Qcolor_pixmap_image_instance_p, "color-pixmap-image-instance-p");
4809 defsymbol (&Qpointer_image_instance_p, "pointer-image-instance-p");
4810 defsymbol (&Qwidget_image_instance_p, "widget-image-instance-p");
4811 defsymbol (&Qsubwindow_image_instance_p, "subwindow-image-instance-p");
4813 DEFSUBR (Fmake_image_instance);
4814 DEFSUBR (Fimage_instance_p);
4815 DEFSUBR (Fimage_instance_type);
4816 DEFSUBR (Fvalid_image_instance_type_p);
4817 DEFSUBR (Fimage_instance_type_list);
4818 DEFSUBR (Fimage_instance_name);
4819 DEFSUBR (Fimage_instance_domain);
4820 DEFSUBR (Fimage_instance_string);
4821 DEFSUBR (Fimage_instance_file_name);
4822 DEFSUBR (Fimage_instance_mask_file_name);
4823 DEFSUBR (Fimage_instance_depth);
4824 DEFSUBR (Fimage_instance_height);
4825 DEFSUBR (Fimage_instance_width);
4826 DEFSUBR (Fimage_instance_hotspot_x);
4827 DEFSUBR (Fimage_instance_hotspot_y);
4828 DEFSUBR (Fimage_instance_foreground);
4829 DEFSUBR (Fimage_instance_background);
4830 DEFSUBR (Fimage_instance_property);
4831 DEFSUBR (Fset_image_instance_property);
4832 DEFSUBR (Fcolorize_image_instance);
4834 DEFSUBR (Fsubwindowp);
4835 DEFSUBR (Fimage_instance_subwindow_id);
4836 DEFSUBR (Fresize_subwindow);
4837 DEFSUBR (Fforce_subwindow_map);
4839 /* Qnothing defined as part of the "nothing" image-instantiator
4841 /* Qtext defined in general.c */
4842 defsymbol (&Qmono_pixmap, "mono-pixmap");
4843 defsymbol (&Qcolor_pixmap, "color-pixmap");
4844 /* Qpointer defined in general.c */
4848 defsymbol (&Qglyphp, "glyphp");
4849 defsymbol (&Qcontrib_p, "contrib-p");
4850 defsymbol (&Qbaseline, "baseline");
4852 defsymbol (&Qbuffer_glyph_p, "buffer-glyph-p");
4853 defsymbol (&Qpointer_glyph_p, "pointer-glyph-p");
4854 defsymbol (&Qicon_glyph_p, "icon-glyph-p");
4856 defsymbol (&Qconst_glyph_variable, "const-glyph-variable");
4858 DEFSUBR (Fglyph_type);
4859 DEFSUBR (Fvalid_glyph_type_p);
4860 DEFSUBR (Fglyph_type_list);
4862 DEFSUBR (Fmake_glyph_internal);
4863 DEFSUBR (Fglyph_width);
4864 DEFSUBR (Fglyph_ascent);
4865 DEFSUBR (Fglyph_descent);
4866 DEFSUBR (Fglyph_height);
4868 /* Qbuffer defined in general.c. */
4869 /* Qpointer defined above */
4871 /* Unfortunately, timeout handlers must be lisp functions. This is
4872 for animated glyphs. */
4873 defsymbol (&Qglyph_animated_timeout_handler,
4874 "glyph-animated-timeout-handler");
4875 DEFSUBR (Fglyph_animated_timeout_handler);
4878 deferror (&Qimage_conversion_error,
4879 "image-conversion-error",
4880 "image-conversion error", Qio_error);
4884 static const struct lrecord_description image_specifier_description[] = {
4885 { XD_LISP_OBJECT, specifier_data_offset + offsetof (struct image_specifier, attachee) },
4886 { XD_LISP_OBJECT, specifier_data_offset + offsetof (struct image_specifier, attachee_property) },
4891 specifier_type_create_image (void)
4893 /* image specifiers */
4895 INITIALIZE_SPECIFIER_TYPE_WITH_DATA (image, "image", "imagep");
4897 SPECIFIER_HAS_METHOD (image, create);
4898 SPECIFIER_HAS_METHOD (image, mark);
4899 SPECIFIER_HAS_METHOD (image, instantiate);
4900 SPECIFIER_HAS_METHOD (image, validate);
4901 SPECIFIER_HAS_METHOD (image, after_change);
4902 SPECIFIER_HAS_METHOD (image, going_to_add);
4903 SPECIFIER_HAS_METHOD (image, copy_instantiator);
4907 reinit_specifier_type_create_image (void)
4909 REINITIALIZE_SPECIFIER_TYPE (image);
4913 static const struct lrecord_description iike_description_1[] = {
4914 { XD_LISP_OBJECT, offsetof (ii_keyword_entry, keyword) },
4918 static const struct struct_description iike_description = {
4919 sizeof (ii_keyword_entry),
4923 static const struct lrecord_description iiked_description_1[] = {
4924 XD_DYNARR_DESC (ii_keyword_entry_dynarr, &iike_description),
4928 static const struct struct_description iiked_description = {
4929 sizeof (ii_keyword_entry_dynarr),
4933 static const struct lrecord_description iife_description_1[] = {
4934 { XD_LISP_OBJECT, offsetof (image_instantiator_format_entry, symbol) },
4935 { XD_LISP_OBJECT, offsetof (image_instantiator_format_entry, device) },
4936 { XD_STRUCT_PTR, offsetof (image_instantiator_format_entry, meths), 1, &iim_description },
4940 static const struct struct_description iife_description = {
4941 sizeof (image_instantiator_format_entry),
4945 static const struct lrecord_description iifed_description_1[] = {
4946 XD_DYNARR_DESC (image_instantiator_format_entry_dynarr, &iife_description),
4950 static const struct struct_description iifed_description = {
4951 sizeof (image_instantiator_format_entry_dynarr),
4955 static const struct lrecord_description iim_description_1[] = {
4956 { XD_LISP_OBJECT, offsetof (struct image_instantiator_methods, symbol) },
4957 { XD_LISP_OBJECT, offsetof (struct image_instantiator_methods, device) },
4958 { XD_STRUCT_PTR, offsetof (struct image_instantiator_methods, keywords), 1, &iiked_description },
4959 { XD_STRUCT_PTR, offsetof (struct image_instantiator_methods, consoles), 1, &cted_description },
4963 const struct struct_description iim_description = {
4964 sizeof(struct image_instantiator_methods),
4969 image_instantiator_format_create (void)
4971 /* image instantiators */
4973 the_image_instantiator_format_entry_dynarr =
4974 Dynarr_new (image_instantiator_format_entry);
4976 Vimage_instantiator_format_list = Qnil;
4977 staticpro (&Vimage_instantiator_format_list);
4979 dumpstruct (&the_image_instantiator_format_entry_dynarr, &iifed_description);
4981 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (nothing, "nothing");
4983 IIFORMAT_HAS_METHOD (nothing, possible_dest_types);
4984 IIFORMAT_HAS_METHOD (nothing, instantiate);
4986 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (inherit, "inherit");
4988 IIFORMAT_HAS_METHOD (inherit, validate);
4989 IIFORMAT_HAS_METHOD (inherit, normalize);
4990 IIFORMAT_HAS_METHOD (inherit, possible_dest_types);
4991 IIFORMAT_HAS_METHOD (inherit, instantiate);
4993 IIFORMAT_VALID_KEYWORD (inherit, Q_face, check_valid_face);
4995 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (string, "string");
4997 IIFORMAT_HAS_METHOD (string, validate);
4998 IIFORMAT_HAS_SHARED_METHOD (string, governing_domain, subwindow);
4999 IIFORMAT_HAS_METHOD (string, possible_dest_types);
5000 IIFORMAT_HAS_METHOD (string, instantiate);
5002 IIFORMAT_VALID_KEYWORD (string, Q_data, check_valid_string);
5003 /* Do this so we can set strings. */
5004 /* #### Andy, what is this? This is a bogus format and should not be
5005 visible to the user. */
5006 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (text, "text");
5007 IIFORMAT_HAS_METHOD (text, set_property);
5008 IIFORMAT_HAS_METHOD (text, query_geometry);
5010 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (formatted_string, "formatted-string");
5012 IIFORMAT_HAS_METHOD (formatted_string, validate);
5013 IIFORMAT_HAS_METHOD (formatted_string, possible_dest_types);
5014 IIFORMAT_HAS_METHOD (formatted_string, instantiate);
5015 IIFORMAT_VALID_KEYWORD (formatted_string, Q_data, check_valid_string);
5017 /* Do this so pointers have geometry. */
5018 /* #### Andy, what is this? This is a bogus format and should not be
5019 visible to the user. */
5020 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (pointer, "pointer");
5021 IIFORMAT_HAS_SHARED_METHOD (pointer, query_geometry, subwindow);
5024 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (subwindow, "subwindow");
5025 IIFORMAT_HAS_METHOD (subwindow, possible_dest_types);
5026 IIFORMAT_HAS_METHOD (subwindow, governing_domain);
5027 IIFORMAT_HAS_METHOD (subwindow, instantiate);
5028 IIFORMAT_HAS_METHOD (subwindow, query_geometry);
5029 IIFORMAT_VALID_KEYWORD (subwindow, Q_pixel_width, check_valid_int);
5030 IIFORMAT_VALID_KEYWORD (subwindow, Q_pixel_height, check_valid_int);
5032 #ifdef HAVE_WINDOW_SYSTEM
5033 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (xbm, "xbm");
5035 IIFORMAT_HAS_METHOD (xbm, validate);
5036 IIFORMAT_HAS_METHOD (xbm, normalize);
5037 IIFORMAT_HAS_METHOD (xbm, possible_dest_types);
5039 IIFORMAT_VALID_KEYWORD (xbm, Q_data, check_valid_xbm_inline);
5040 IIFORMAT_VALID_KEYWORD (xbm, Q_file, check_valid_string);
5041 IIFORMAT_VALID_KEYWORD (xbm, Q_mask_data, check_valid_xbm_inline);
5042 IIFORMAT_VALID_KEYWORD (xbm, Q_mask_file, check_valid_string);
5043 IIFORMAT_VALID_KEYWORD (xbm, Q_hotspot_x, check_valid_int);
5044 IIFORMAT_VALID_KEYWORD (xbm, Q_hotspot_y, check_valid_int);
5045 IIFORMAT_VALID_KEYWORD (xbm, Q_foreground, check_valid_string);
5046 IIFORMAT_VALID_KEYWORD (xbm, Q_background, check_valid_string);
5047 #endif /* HAVE_WINDOW_SYSTEM */
5050 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (xface, "xface");
5052 IIFORMAT_HAS_METHOD (xface, validate);
5053 IIFORMAT_HAS_METHOD (xface, normalize);
5054 IIFORMAT_HAS_METHOD (xface, possible_dest_types);
5056 IIFORMAT_VALID_KEYWORD (xface, Q_data, check_valid_string);
5057 IIFORMAT_VALID_KEYWORD (xface, Q_file, check_valid_string);
5058 IIFORMAT_VALID_KEYWORD (xface, Q_hotspot_x, check_valid_int);
5059 IIFORMAT_VALID_KEYWORD (xface, Q_hotspot_y, check_valid_int);
5060 IIFORMAT_VALID_KEYWORD (xface, Q_foreground, check_valid_string);
5061 IIFORMAT_VALID_KEYWORD (xface, Q_background, check_valid_string);
5065 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (xpm, "xpm");
5067 IIFORMAT_HAS_METHOD (xpm, validate);
5068 IIFORMAT_HAS_METHOD (xpm, normalize);
5069 IIFORMAT_HAS_METHOD (xpm, possible_dest_types);
5071 IIFORMAT_VALID_KEYWORD (xpm, Q_data, check_valid_string);
5072 IIFORMAT_VALID_KEYWORD (xpm, Q_file, check_valid_string);
5073 IIFORMAT_VALID_KEYWORD (xpm, Q_color_symbols, check_valid_xpm_color_symbols);
5074 #endif /* HAVE_XPM */
5078 reinit_vars_of_glyphs (void)
5080 the_expose_ignore_blocktype =
5081 Blocktype_new (struct expose_ignore_blocktype);
5083 hold_ignored_expose_registration = 0;
5088 vars_of_glyphs (void)
5090 reinit_vars_of_glyphs ();
5092 Vthe_nothing_vector = vector1 (Qnothing);
5093 staticpro (&Vthe_nothing_vector);
5095 /* image instances */
5097 Vimage_instance_type_list = Fcons (Qnothing,
5098 list6 (Qtext, Qmono_pixmap, Qcolor_pixmap,
5099 Qpointer, Qsubwindow, Qwidget));
5100 staticpro (&Vimage_instance_type_list);
5104 Vglyph_type_list = list3 (Qbuffer, Qpointer, Qicon);
5105 staticpro (&Vglyph_type_list);
5107 /* The octal-escape glyph, control-arrow-glyph and
5108 invisible-text-glyph are completely initialized in glyphs.el */
5110 DEFVAR_LISP ("octal-escape-glyph", &Voctal_escape_glyph /*
5111 What to prefix character codes displayed in octal with.
5113 Voctal_escape_glyph = allocate_glyph (GLYPH_BUFFER, redisplay_glyph_changed);
5115 DEFVAR_LISP ("control-arrow-glyph", &Vcontrol_arrow_glyph /*
5116 What to use as an arrow for control characters.
5118 Vcontrol_arrow_glyph = allocate_glyph (GLYPH_BUFFER,
5119 redisplay_glyph_changed);
5121 DEFVAR_LISP ("invisible-text-glyph", &Vinvisible_text_glyph /*
5122 What to use to indicate the presence of invisible text.
5123 This is the glyph that is displayed when an ellipsis is called for
5124 \(see `selective-display-ellipses' and `buffer-invisibility-spec').
5125 Normally this is three dots ("...").
5127 Vinvisible_text_glyph = allocate_glyph (GLYPH_BUFFER,
5128 redisplay_glyph_changed);
5130 /* Partially initialized in glyphs.el */
5131 DEFVAR_LISP ("hscroll-glyph", &Vhscroll_glyph /*
5132 What to display at the beginning of horizontally scrolled lines.
5134 Vhscroll_glyph = allocate_glyph (GLYPH_BUFFER, redisplay_glyph_changed);
5135 #ifdef HAVE_WINDOW_SYSTEM
5141 DEFVAR_LISP ("xpm-color-symbols", &Vxpm_color_symbols /*
5142 Definitions of logical color-names used when reading XPM files.
5143 Elements of this list should be of the form (COLOR-NAME FORM-TO-EVALUATE).
5144 The COLOR-NAME should be a string, which is the name of the color to define;
5145 the FORM should evaluate to a `color' specifier object, or a string to be
5146 passed to `make-color-instance'. If a loaded XPM file references a symbolic
5147 color called COLOR-NAME, it will display as the computed color instead.
5149 The default value of this variable defines the logical color names
5150 \"foreground\" and \"background\" to be the colors of the `default' face.
5152 Vxpm_color_symbols = Qnil; /* initialized in x-faces.el */
5153 #endif /* HAVE_XPM */
5158 DEFVAR_BOOL ("disable-animated-pixmaps", &disable_animated_pixmaps /*
5159 Whether animated pixmaps should be animated.
5162 disable_animated_pixmaps = 0;
5166 specifier_vars_of_glyphs (void)
5168 /* #### Can we GC here? The set_specifier_* calls definitely need */
5170 /* display tables */
5172 DEFVAR_SPECIFIER ("current-display-table", &Vcurrent_display_table /*
5173 *The display table currently in use.
5174 This is a specifier; use `set-specifier' to change it.
5176 Display tables are used to control how characters are displayed. Each
5177 time that redisplay processes a character, it is looked up in all the
5178 display tables that apply (obtained by calling `specifier-instance' on
5179 `current-display-table' and any overriding display tables specified in
5180 currently active faces). The first entry found that matches the
5181 character determines how the character is displayed. If there is no
5182 matching entry, the default display method is used. (Non-control
5183 characters are displayed as themselves and control characters are
5184 displayed according to the buffer-local variable `ctl-arrow'. Control
5185 characters are further affected by `control-arrow-glyph' and
5186 `octal-escape-glyph'.)
5188 Each instantiator in this specifier and the display-table specifiers
5189 in faces is a display table or a list of such tables. If a list, each
5190 table will be searched in turn for an entry matching a particular
5191 character. Each display table is one of
5193 -- a vector, specifying values for characters starting at 0
5194 -- a char table, either of type `char' or `generic'
5197 Each entry in a display table should be one of
5199 -- nil (this entry is ignored and the search continues)
5200 -- a character (use this character; if it happens to be the same as
5201 the original character, default processing happens, otherwise
5202 redisplay attempts to display this character directly;
5203 #### At some point recursive display-table lookup will be
5205 -- a string (display each character in the string directly;
5206 #### At some point recursive display-table lookup will be
5208 -- a glyph (display the glyph;
5209 #### At some point recursive display-table lookup will be
5210 implemented when a string glyph is being processed.)
5211 -- a cons of the form (format "STRING") where STRING is a printf-like
5212 spec used to process the character. #### Unfortunately no
5213 formatting directives other than %% are implemented.
5214 -- a vector (each element of the vector is processed recursively;
5215 in such a case, nil elements in the vector are simply ignored)
5217 #### At some point in the near future, display tables are likely to
5218 be expanded to include other features, such as referencing characters
5219 in particular fonts and allowing the character search to continue
5220 all the way up the chain of specifier instantiators. These features
5221 are necessary to properly display Unicode characters.
5223 Vcurrent_display_table = Fmake_specifier (Qdisplay_table);
5224 set_specifier_fallback (Vcurrent_display_table,
5225 list1 (Fcons (Qnil, Qnil)));
5226 set_specifier_caching (Vcurrent_display_table,
5227 offsetof (struct window, display_table),
5228 some_window_value_changed,
5233 complex_vars_of_glyphs (void)
5235 /* Partially initialized in glyphs-x.c, glyphs.el */
5236 DEFVAR_LISP ("truncation-glyph", &Vtruncation_glyph /*
5237 What to display at the end of truncated lines.
5239 Vtruncation_glyph = allocate_glyph (GLYPH_BUFFER, redisplay_glyph_changed);
5241 /* Partially initialized in glyphs-x.c, glyphs.el */
5242 DEFVAR_LISP ("continuation-glyph", &Vcontinuation_glyph /*
5243 What to display at the end of wrapped lines.
5245 Vcontinuation_glyph = allocate_glyph (GLYPH_BUFFER, redisplay_glyph_changed);
5247 /* Partially initialized in glyphs-x.c, glyphs.el */
5248 DEFVAR_LISP ("xemacs-logo", &Vxemacs_logo /*
5249 The glyph used to display the XEmacs logo at startup.
5251 Vxemacs_logo = allocate_glyph (GLYPH_BUFFER, 0);