Mercurial > hg > xemacs-beta
comparison src/glyphs.c @ 412:697ef44129c6 r21-2-14
Import from CVS: tag r21-2-14
author | cvs |
---|---|
date | Mon, 13 Aug 2007 11:20:41 +0200 |
parents | de805c49cfc1 |
children | e804706bfb8c |
comparison
equal
deleted
inserted
replaced
411:12e008d41344 | 412:697ef44129c6 |
---|---|
1 /* Generic glyph/image implementation + display tables | 1 /* Generic glyph/image implementation + display tables |
2 Copyright (C) 1994, 1995 Board of Trustees, University of Illinois. | 2 Copyright (C) 1994, 1995 Board of Trustees, University of Illinois. |
3 Copyright (C) 1995 Tinker Systems | 3 Copyright (C) 1995 Tinker Systems |
4 Copyright (C) 1995, 1996, 2000 Ben Wing | 4 Copyright (C) 1995, 1996 Ben Wing |
5 Copyright (C) 1995 Sun Microsystems | 5 Copyright (C) 1995 Sun Microsystems |
6 Copyright (C) 1998, 1999, 2000 Andy Piper | 6 Copyright (C) 1998 Andy Piper |
7 | 7 |
8 This file is part of XEmacs. | 8 This file is part of XEmacs. |
9 | 9 |
10 XEmacs is free software; you can redistribute it and/or modify it | 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 | 11 under the terms of the GNU General Public License as published by the |
22 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | 22 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
23 Boston, MA 02111-1307, USA. */ | 23 Boston, MA 02111-1307, USA. */ |
24 | 24 |
25 /* Synched up with: Not in FSF. */ | 25 /* Synched up with: Not in FSF. */ |
26 | 26 |
27 /* Written by Ben Wing and Chuck Thompson. Heavily modified / | 27 /* Written by Ben Wing and Chuck Thompson */ |
28 rewritten by Andy Piper. */ | |
29 | 28 |
30 #include <config.h> | 29 #include <config.h> |
31 #include "lisp.h" | 30 #include "lisp.h" |
32 | 31 |
33 #include "blocktype.h" | |
34 #include "buffer.h" | 32 #include "buffer.h" |
35 #include "chartab.h" | |
36 #include "device.h" | 33 #include "device.h" |
37 #include "elhash.h" | 34 #include "elhash.h" |
38 #include "faces.h" | 35 #include "faces.h" |
39 #include "frame.h" | 36 #include "frame.h" |
40 #include "glyphs.h" | |
41 #include "insdel.h" | 37 #include "insdel.h" |
38 #include "opaque.h" | |
42 #include "objects.h" | 39 #include "objects.h" |
43 #include "opaque.h" | 40 #include "redisplay.h" |
41 #include "window.h" | |
42 #include "frame.h" | |
43 #include "chartab.h" | |
44 #include "rangetab.h" | 44 #include "rangetab.h" |
45 #include "redisplay.h" | |
46 #include "specifier.h" | |
47 #include "window.h" | |
48 | 45 |
49 #ifdef HAVE_XPM | 46 #ifdef HAVE_XPM |
50 #include <X11/xpm.h> | 47 #include <X11/xpm.h> |
51 #endif | 48 #endif |
52 | 49 |
71 Lisp_Object Vthe_nothing_vector; | 68 Lisp_Object Vthe_nothing_vector; |
72 Lisp_Object Vimage_instantiator_format_list; | 69 Lisp_Object Vimage_instantiator_format_list; |
73 Lisp_Object Vimage_instance_type_list; | 70 Lisp_Object Vimage_instance_type_list; |
74 Lisp_Object Vglyph_type_list; | 71 Lisp_Object Vglyph_type_list; |
75 | 72 |
76 int disable_animated_pixmaps; | |
77 | |
78 DEFINE_IMAGE_INSTANTIATOR_FORMAT (nothing); | 73 DEFINE_IMAGE_INSTANTIATOR_FORMAT (nothing); |
79 DEFINE_IMAGE_INSTANTIATOR_FORMAT (inherit); | 74 DEFINE_IMAGE_INSTANTIATOR_FORMAT (inherit); |
80 DEFINE_IMAGE_INSTANTIATOR_FORMAT (string); | 75 DEFINE_IMAGE_INSTANTIATOR_FORMAT (string); |
81 DEFINE_IMAGE_INSTANTIATOR_FORMAT (formatted_string); | 76 DEFINE_IMAGE_INSTANTIATOR_FORMAT (formatted_string); |
82 DEFINE_IMAGE_INSTANTIATOR_FORMAT (subwindow); | 77 DEFINE_IMAGE_INSTANTIATOR_FORMAT (subwindow); |
83 DEFINE_IMAGE_INSTANTIATOR_FORMAT (text); | |
84 DEFINE_IMAGE_INSTANTIATOR_FORMAT (pointer); | |
85 | 78 |
86 #ifdef HAVE_WINDOW_SYSTEM | 79 #ifdef HAVE_WINDOW_SYSTEM |
87 DEFINE_IMAGE_INSTANTIATOR_FORMAT (xbm); | 80 DEFINE_IMAGE_INSTANTIATOR_FORMAT (xbm); |
88 Lisp_Object Qxbm; | 81 Lisp_Object Qxbm; |
89 | 82 |
119 typedef struct | 112 typedef struct |
120 { | 113 { |
121 Dynarr_declare (struct image_instantiator_format_entry); | 114 Dynarr_declare (struct image_instantiator_format_entry); |
122 } image_instantiator_format_entry_dynarr; | 115 } image_instantiator_format_entry_dynarr; |
123 | 116 |
124 /* This contains one entry per format, per device it's defined on. */ | |
125 image_instantiator_format_entry_dynarr * | 117 image_instantiator_format_entry_dynarr * |
126 the_image_instantiator_format_entry_dynarr; | 118 the_image_instantiator_format_entry_dynarr; |
127 | 119 |
128 static Lisp_Object allocate_image_instance (Lisp_Object governing_domain, | 120 static Lisp_Object allocate_image_instance (Lisp_Object device); |
129 Lisp_Object glyph); | |
130 static void image_validate (Lisp_Object instantiator); | 121 static void image_validate (Lisp_Object instantiator); |
131 static void glyph_property_was_changed (Lisp_Object glyph, | 122 static void glyph_property_was_changed (Lisp_Object glyph, |
132 Lisp_Object property, | 123 Lisp_Object property, |
133 Lisp_Object locale); | 124 Lisp_Object locale); |
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 | |
140 always occur. */ | |
141 int hold_ignored_expose_registration; | |
142 | |
143 EXFUN (Fimage_instance_type, 1); | 125 EXFUN (Fimage_instance_type, 1); |
144 EXFUN (Fglyph_type, 1); | 126 EXFUN (Fglyph_type, 1); |
145 EXFUN (Fnext_window, 4); | |
146 | 127 |
147 | 128 |
148 /**************************************************************************** | 129 /**************************************************************************** |
149 * Image Instantiators * | 130 * Image Instantiators * |
150 ****************************************************************************/ | 131 ****************************************************************************/ |
172 Lisp_Object d = Dynarr_at (the_image_instantiator_format_entry_dynarr, i). | 153 Lisp_Object d = Dynarr_at (the_image_instantiator_format_entry_dynarr, i). |
173 device; | 154 device; |
174 if ((NILP (d) && NILP (device)) | 155 if ((NILP (d) && NILP (device)) |
175 || | 156 || |
176 (!NILP (device) && | 157 (!NILP (device) && |
177 EQ (CONSOLE_TYPE (XCONSOLE | 158 EQ (CONSOLE_TYPE (XCONSOLE |
178 (DEVICE_CONSOLE (XDEVICE (device)))), d))) | 159 (DEVICE_CONSOLE (XDEVICE (device)))), d))) |
179 return Dynarr_at (the_image_instantiator_format_entry_dynarr, i).meths; | 160 return Dynarr_at (the_image_instantiator_format_entry_dynarr, i).meths; |
180 } | 161 } |
181 } | 162 } |
182 | 163 |
191 { | 172 { |
192 return decode_device_ii_format (Qnil, format, errb); | 173 return decode_device_ii_format (Qnil, format, errb); |
193 } | 174 } |
194 | 175 |
195 static int | 176 static int |
196 valid_image_instantiator_format_p (Lisp_Object format, Lisp_Object locale) | 177 valid_image_instantiator_format_p (Lisp_Object format) |
197 { | 178 { |
198 int i; | 179 return (decode_image_instantiator_format (format, ERROR_ME_NOT) != 0); |
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)) | |
204 contype = locale; | |
205 else | |
206 { | |
207 struct console* console = decode_console (locale); | |
208 contype = console ? CONSOLE_TYPE (console) : locale; | |
209 } | |
210 /* nothing is valid in all locales */ | |
211 if (EQ (format, Qnothing)) | |
212 return 1; | |
213 /* reject unknown formats */ | |
214 else if (NILP (contype) || !meths) | |
215 return 0; | |
216 | |
217 for (i = 0; i < Dynarr_length (meths->consoles); i++) | |
218 if (EQ (contype, Dynarr_at (meths->consoles, i).symbol)) | |
219 return 1; | |
220 return 0; | |
221 } | 180 } |
222 | 181 |
223 DEFUN ("valid-image-instantiator-format-p", Fvalid_image_instantiator_format_p, | 182 DEFUN ("valid-image-instantiator-format-p", Fvalid_image_instantiator_format_p, |
224 1, 2, 0, /* | 183 1, 1, 0, /* |
225 Given an IMAGE-INSTANTIATOR-FORMAT, return non-nil if it is valid. | 184 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. | |
228 | |
229 Valid formats are some subset of 'nothing, 'string, 'formatted-string, | 185 Valid formats are some subset of 'nothing, 'string, 'formatted-string, |
230 'xpm, 'xbm, 'xface, 'gif, 'jpeg, 'png, 'tiff, 'cursor-font, 'font, | 186 'xpm, 'xbm, 'xface, 'gif, 'jpeg, 'png, 'tiff, 'cursor-font, 'font, |
231 'autodetect, 'subwindow, 'inherit, 'mswindows-resource, 'bmp, | 187 'autodetect, 'widget and 'subwindow, depending on how XEmacs was compiled. |
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. | |
235 */ | 188 */ |
236 (image_instantiator_format, locale)) | 189 (image_instantiator_format)) |
237 { | 190 { |
238 return valid_image_instantiator_format_p (image_instantiator_format, | 191 return valid_image_instantiator_format_p (image_instantiator_format) ? |
239 locale) ? | |
240 Qt : Qnil; | 192 Qt : Qnil; |
241 } | 193 } |
242 | 194 |
243 DEFUN ("image-instantiator-format-list", Fimage_instantiator_format_list, | 195 DEFUN ("image-instantiator-format-list", Fimage_instantiator_format_list, |
244 0, 0, 0, /* | 196 0, 0, 0, /* |
257 | 209 |
258 entry.symbol = symbol; | 210 entry.symbol = symbol; |
259 entry.device = device; | 211 entry.device = device; |
260 entry.meths = meths; | 212 entry.meths = meths; |
261 Dynarr_add (the_image_instantiator_format_entry_dynarr, entry); | 213 Dynarr_add (the_image_instantiator_format_entry_dynarr, entry); |
262 if (NILP (memq_no_quit (symbol, Vimage_instantiator_format_list))) | 214 Vimage_instantiator_format_list = |
263 Vimage_instantiator_format_list = | 215 Fcons (symbol, Vimage_instantiator_format_list); |
264 Fcons (symbol, Vimage_instantiator_format_list); | |
265 } | 216 } |
266 | 217 |
267 void | 218 void |
268 add_entry_to_image_instantiator_format_list (Lisp_Object symbol, | 219 add_entry_to_image_instantiator_format_list (Lisp_Object symbol, |
269 struct | 220 struct |
549 } | 500 } |
550 | 501 |
551 return Fvector (len, elt); | 502 return Fvector (len, elt); |
552 } | 503 } |
553 | 504 |
554 #ifdef ERROR_CHECK_GLYPHS | |
555 static int | |
556 check_instance_cache_mapper (Lisp_Object key, Lisp_Object value, | |
557 void *flag_closure) | |
558 { | |
559 /* This function can GC */ | |
560 /* value can be nil; we cache failures as well as successes */ | |
561 if (!NILP (value)) | |
562 { | |
563 Lisp_Object window; | |
564 VOID_TO_LISP (window, flag_closure); | |
565 assert (EQ (XIMAGE_INSTANCE_DOMAIN (value), window)); | |
566 } | |
567 | |
568 return 0; | |
569 } | |
570 | |
571 void | |
572 check_window_subwindow_cache (struct window* w) | |
573 { | |
574 Lisp_Object window; | |
575 | |
576 XSETWINDOW (window, w); | |
577 | |
578 assert (!NILP (w->subwindow_instance_cache)); | |
579 elisp_maphash (check_instance_cache_mapper, | |
580 w->subwindow_instance_cache, | |
581 LISP_TO_VOID (window)); | |
582 } | |
583 | |
584 void | |
585 check_image_instance_structure (Lisp_Object instance) | |
586 { | |
587 /* Weird nothing images exist at startup when the console is | |
588 deleted. */ | |
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))); | |
594 } | |
595 #endif | |
596 | |
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. */ | |
600 static Lisp_Object | |
601 get_image_instantiator_governing_domain (Lisp_Object instantiator, | |
602 Lisp_Object domain) | |
603 { | |
604 int governing_domain; | |
605 | |
606 struct image_instantiator_methods *meths = | |
607 decode_image_instantiator_format (XVECTOR_DATA (instantiator)[0], | |
608 ERROR_ME); | |
609 governing_domain = IIFORMAT_METH_OR_GIVEN (meths, governing_domain, (), | |
610 GOVERNING_DOMAIN_DEVICE); | |
611 | |
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); | |
621 | |
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); | |
628 else | |
629 abort (); | |
630 | |
631 return domain; | |
632 } | |
633 | |
634 static Lisp_Object | 505 static Lisp_Object |
635 normalize_image_instantiator (Lisp_Object instantiator, | 506 normalize_image_instantiator (Lisp_Object instantiator, |
636 Lisp_Object contype, | 507 Lisp_Object contype, |
637 Lisp_Object dest_mask) | 508 Lisp_Object dest_mask) |
638 { | 509 { |
653 { | 524 { |
654 struct gcpro gcpro1; | 525 struct gcpro gcpro1; |
655 struct image_instantiator_methods *meths; | 526 struct image_instantiator_methods *meths; |
656 | 527 |
657 GCPRO1 (instantiator); | 528 GCPRO1 (instantiator); |
658 | 529 |
659 meths = decode_image_instantiator_format (XVECTOR_DATA (instantiator)[0], | 530 meths = decode_image_instantiator_format (XVECTOR_DATA (instantiator)[0], |
660 ERROR_ME); | 531 ERROR_ME); |
661 RETURN_UNGCPRO (IIFORMAT_METH_OR_GIVEN (meths, normalize, | 532 RETURN_UNGCPRO (IIFORMAT_METH_OR_GIVEN (meths, normalize, |
662 (instantiator, contype), | 533 (instantiator, contype), |
663 instantiator)); | 534 instantiator)); |
664 } | 535 } |
665 } | 536 } |
666 | 537 |
667 static Lisp_Object | 538 static Lisp_Object |
668 instantiate_image_instantiator (Lisp_Object governing_domain, | 539 instantiate_image_instantiator (Lisp_Object device, Lisp_Object domain, |
669 Lisp_Object domain, | |
670 Lisp_Object instantiator, | 540 Lisp_Object instantiator, |
671 Lisp_Object pointer_fg, Lisp_Object pointer_bg, | 541 Lisp_Object pointer_fg, Lisp_Object pointer_bg, |
672 int dest_mask, Lisp_Object glyph) | 542 int dest_mask) |
673 { | 543 { |
674 Lisp_Object ii = allocate_image_instance (governing_domain, glyph); | 544 Lisp_Object ii = allocate_image_instance (device); |
675 Lisp_Image_Instance* p = XIMAGE_INSTANCE (ii); | 545 struct image_instantiator_methods *meths; |
676 struct image_instantiator_methods *meths, *device_meths; | |
677 struct gcpro gcpro1; | 546 struct gcpro gcpro1; |
547 int methp = 0; | |
678 | 548 |
679 GCPRO1 (ii); | 549 GCPRO1 (ii); |
680 if (!valid_image_instantiator_format_p (XVECTOR_DATA (instantiator)[0], | |
681 DOMAIN_DEVICE (governing_domain))) | |
682 signal_simple_error | |
683 ("Image instantiator format is invalid in this locale.", | |
684 instantiator); | |
685 | |
686 meths = decode_image_instantiator_format (XVECTOR_DATA (instantiator)[0], | 550 meths = decode_image_instantiator_format (XVECTOR_DATA (instantiator)[0], |
687 ERROR_ME); | 551 ERROR_ME); |
552 methp = (int)HAS_IIFORMAT_METH_P (meths, instantiate); | |
688 MAYBE_IIFORMAT_METH (meths, instantiate, (ii, instantiator, pointer_fg, | 553 MAYBE_IIFORMAT_METH (meths, instantiate, (ii, instantiator, pointer_fg, |
689 pointer_bg, dest_mask, domain)); | 554 pointer_bg, dest_mask, domain)); |
690 | 555 |
691 /* Now do device specific instantiation. */ | 556 /* now do device specific instantiation */ |
692 device_meths = decode_device_ii_format (DOMAIN_DEVICE (governing_domain), | 557 meths = decode_device_ii_format (device, XVECTOR_DATA (instantiator)[0], |
693 XVECTOR_DATA (instantiator)[0], | 558 ERROR_ME_NOT); |
694 ERROR_ME_NOT); | 559 |
695 | 560 if (!methp && (!meths || !HAS_IIFORMAT_METH_P (meths, instantiate))) |
696 if (!HAS_IIFORMAT_METH_P (meths, instantiate) | |
697 && (!device_meths || !HAS_IIFORMAT_METH_P (device_meths, instantiate))) | |
698 signal_simple_error | 561 signal_simple_error |
699 ("Don't know how to instantiate this image instantiator?", | 562 ("Don't know how to instantiate this image instantiator?", |
700 instantiator); | 563 instantiator); |
701 | 564 MAYBE_IIFORMAT_METH (meths, instantiate, (ii, instantiator, pointer_fg, |
702 /* In general native window system methods will require sane | 565 pointer_bg, dest_mask, domain)); |
703 geometry values, thus the instance needs to have been laid-out | 566 UNGCPRO; |
704 before they get called. */ | 567 |
705 image_instance_layout (ii, XIMAGE_INSTANCE_WIDTH (ii), | 568 return ii; |
706 XIMAGE_INSTANCE_HEIGHT (ii), domain); | |
707 | |
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)); | |
713 | |
714 /* We're done. */ | |
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); | |
720 | |
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; | |
726 | |
727 assert ( XIMAGE_INSTANCE_HEIGHT (ii) >= 0 | |
728 && XIMAGE_INSTANCE_WIDTH (ii) >= 0 ); | |
729 | |
730 ERROR_CHECK_IMAGE_INSTANCE (ii); | |
731 | |
732 RETURN_UNGCPRO (ii); | |
733 } | 569 } |
734 | 570 |
735 | 571 |
736 /**************************************************************************** | 572 /**************************************************************************** |
737 * Image-Instance Object * | 573 * Image-Instance Object * |
738 ****************************************************************************/ | 574 ****************************************************************************/ |
739 | 575 |
740 Lisp_Object Qimage_instancep; | 576 Lisp_Object Qimage_instancep; |
741 | 577 |
742 static Lisp_Object | 578 static Lisp_Object |
743 mark_image_instance (Lisp_Object obj) | 579 mark_image_instance (Lisp_Object obj, void (*markobj) (Lisp_Object)) |
744 { | 580 { |
745 Lisp_Image_Instance *i = XIMAGE_INSTANCE (obj); | 581 struct Lisp_Image_Instance *i = XIMAGE_INSTANCE (obj); |
746 | 582 |
747 /* #### I want to check the instance here, but there are way too | 583 markobj (i->name); |
748 many instances of the instance being marked while the domain is | |
749 dead. For instance you can get marked through an event when using | |
750 callback_ex.*/ | |
751 #if 0 | |
752 ERROR_CHECK_IMAGE_INSTANCE (obj); | |
753 #endif | |
754 | |
755 mark_object (i->name); | |
756 /* Is this legal in marking? We may get in the situation where the | |
757 domain has been deleted - making the instance unusable. It seems | |
758 better to remove the domain so that it can be finalized. */ | |
759 if (!DOMAIN_LIVE_P (i->domain)) | |
760 i->domain = Qnil; | |
761 else | |
762 mark_object (i->domain); | |
763 | |
764 /* We don't mark the glyph reference since that would create a | |
765 circularity preventing GC. */ | |
766 switch (IMAGE_INSTANCE_TYPE (i)) | 584 switch (IMAGE_INSTANCE_TYPE (i)) |
767 { | 585 { |
768 case IMAGE_TEXT: | 586 case IMAGE_TEXT: |
769 mark_object (IMAGE_INSTANCE_TEXT_STRING (i)); | 587 markobj (IMAGE_INSTANCE_TEXT_STRING (i)); |
770 break; | 588 break; |
771 case IMAGE_MONO_PIXMAP: | 589 case IMAGE_MONO_PIXMAP: |
772 case IMAGE_COLOR_PIXMAP: | 590 case IMAGE_COLOR_PIXMAP: |
773 mark_object (IMAGE_INSTANCE_PIXMAP_FILENAME (i)); | 591 markobj (IMAGE_INSTANCE_PIXMAP_FILENAME (i)); |
774 mark_object (IMAGE_INSTANCE_PIXMAP_MASK_FILENAME (i)); | 592 markobj (IMAGE_INSTANCE_PIXMAP_MASK_FILENAME (i)); |
775 mark_object (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (i)); | 593 markobj (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (i)); |
776 mark_object (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (i)); | 594 markobj (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (i)); |
777 mark_object (IMAGE_INSTANCE_PIXMAP_FG (i)); | 595 markobj (IMAGE_INSTANCE_PIXMAP_FG (i)); |
778 mark_object (IMAGE_INSTANCE_PIXMAP_BG (i)); | 596 markobj (IMAGE_INSTANCE_PIXMAP_BG (i)); |
779 break; | 597 break; |
780 | 598 |
781 case IMAGE_WIDGET: | 599 case IMAGE_WIDGET: |
782 mark_object (IMAGE_INSTANCE_WIDGET_TYPE (i)); | 600 markobj (IMAGE_INSTANCE_WIDGET_TYPE (i)); |
783 mark_object (IMAGE_INSTANCE_WIDGET_PROPS (i)); | 601 markobj (IMAGE_INSTANCE_WIDGET_PROPS (i)); |
784 mark_object (IMAGE_INSTANCE_WIDGET_FACE (i)); | 602 markobj (IMAGE_INSTANCE_WIDGET_FACE (i)); |
785 mark_object (IMAGE_INSTANCE_WIDGET_ITEMS (i)); | 603 mark_gui_item (&IMAGE_INSTANCE_WIDGET_ITEM (i), markobj); |
786 mark_object (IMAGE_INSTANCE_LAYOUT_CHILDREN (i)); | |
787 mark_object (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (i)); | |
788 mark_object (IMAGE_INSTANCE_WIDGET_HEIGHT_SUBR (i)); | |
789 mark_object (IMAGE_INSTANCE_WIDGET_WIDTH_SUBR (i)); | |
790 case IMAGE_SUBWINDOW: | 604 case IMAGE_SUBWINDOW: |
605 markobj (IMAGE_INSTANCE_SUBWINDOW_FRAME (i)); | |
791 break; | 606 break; |
792 | 607 |
793 default: | 608 default: |
794 break; | 609 break; |
795 } | 610 } |
796 | 611 |
797 /* The image may have been previously finalized (yes that's wierd, | 612 MAYBE_DEVMETH (XDEVICE (i->device), mark_image_instance, (i, markobj)); |
798 see Fdelete_frame() and mark_window_as_deleted()), in which case | |
799 the domain will be nil, so cope with this. */ | |
800 if (!NILP (IMAGE_INSTANCE_DEVICE (i))) | |
801 MAYBE_DEVMETH (XDEVICE (IMAGE_INSTANCE_DEVICE (i)), | |
802 mark_image_instance, (i)); | |
803 | 613 |
804 return i->device; | 614 return i->device; |
805 } | 615 } |
806 | 616 |
807 static void | 617 static void |
808 print_image_instance (Lisp_Object obj, Lisp_Object printcharfun, | 618 print_image_instance (Lisp_Object obj, Lisp_Object printcharfun, |
809 int escapeflag) | 619 int escapeflag) |
810 { | 620 { |
811 char buf[100]; | 621 char buf[100]; |
812 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (obj); | 622 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (obj); |
813 | 623 |
814 if (print_readably) | 624 if (print_readably) |
815 error ("printing unreadable object #<image-instance 0x%x>", | 625 error ("printing unreadable object #<image-instance 0x%x>", |
816 ii->header.uid); | 626 ii->header.uid); |
817 write_c_string ("#<image-instance (", printcharfun); | 627 write_c_string ("#<image-instance (", printcharfun); |
821 { | 631 { |
822 print_internal (ii->name, printcharfun, 1); | 632 print_internal (ii->name, printcharfun, 1); |
823 write_c_string (" ", printcharfun); | 633 write_c_string (" ", printcharfun); |
824 } | 634 } |
825 write_c_string ("on ", printcharfun); | 635 write_c_string ("on ", printcharfun); |
826 print_internal (ii->domain, printcharfun, 0); | 636 print_internal (ii->device, printcharfun, 0); |
827 write_c_string (" ", printcharfun); | 637 write_c_string (" ", printcharfun); |
828 switch (IMAGE_INSTANCE_TYPE (ii)) | 638 switch (IMAGE_INSTANCE_TYPE (ii)) |
829 { | 639 { |
830 case IMAGE_NOTHING: | 640 case IMAGE_NOTHING: |
831 break; | 641 break; |
895 write_c_string (")", printcharfun); | 705 write_c_string (")", printcharfun); |
896 } | 706 } |
897 break; | 707 break; |
898 | 708 |
899 case IMAGE_WIDGET: | 709 case IMAGE_WIDGET: |
900 print_internal (IMAGE_INSTANCE_WIDGET_TYPE (ii), printcharfun, 0); | 710 if (!NILP (IMAGE_INSTANCE_WIDGET_CALLBACK (ii))) |
901 | |
902 if (GUI_ITEMP (IMAGE_INSTANCE_WIDGET_ITEM (ii))) | |
903 { | 711 { |
904 write_c_string (" ", printcharfun); | 712 print_internal (IMAGE_INSTANCE_WIDGET_CALLBACK (ii), printcharfun, 0); |
905 print_internal (IMAGE_INSTANCE_WIDGET_TEXT (ii), printcharfun, 1); | 713 write_c_string (", ", printcharfun); |
906 } | 714 } |
907 | |
908 if (!NILP (IMAGE_INSTANCE_WIDGET_FACE (ii))) | 715 if (!NILP (IMAGE_INSTANCE_WIDGET_FACE (ii))) |
909 { | 716 { |
910 write_c_string (" face=", printcharfun); | 717 write_c_string (" (", printcharfun); |
911 print_internal | 718 print_internal |
912 (IMAGE_INSTANCE_WIDGET_FACE (ii), printcharfun, 0); | 719 (IMAGE_INSTANCE_WIDGET_FACE (ii), printcharfun, 0); |
720 write_c_string (")", printcharfun); | |
913 } | 721 } |
914 | 722 |
723 if (!NILP (IMAGE_INSTANCE_WIDGET_TEXT (ii))) | |
724 print_internal (IMAGE_INSTANCE_WIDGET_TEXT (ii), printcharfun, 0); | |
915 | 725 |
916 case IMAGE_SUBWINDOW: | 726 case IMAGE_SUBWINDOW: |
917 sprintf (buf, " %dx%d", IMAGE_INSTANCE_WIDTH (ii), | 727 sprintf (buf, " %dx%d", IMAGE_INSTANCE_SUBWINDOW_WIDTH (ii), |
918 IMAGE_INSTANCE_HEIGHT (ii)); | 728 IMAGE_INSTANCE_SUBWINDOW_HEIGHT (ii)); |
919 write_c_string (buf, printcharfun); | 729 write_c_string (buf, printcharfun); |
920 | 730 |
921 /* This is stolen from frame.c. Subwindows are strange in that they | 731 /* This is stolen from frame.c. Subwindows are strange in that they |
922 are specific to a particular frame so we want to print in their | 732 are specific to a particular frame so we want to print in their |
923 description what that frame is. */ | 733 description what that frame is. */ |
924 | 734 |
925 write_c_string (" on #<", printcharfun); | 735 write_c_string (" on #<", printcharfun); |
926 { | 736 { |
927 struct frame* f = XFRAME (IMAGE_INSTANCE_FRAME (ii)); | 737 struct frame* f = XFRAME (IMAGE_INSTANCE_SUBWINDOW_FRAME (ii)); |
928 | 738 |
929 if (!FRAME_LIVE_P (f)) | 739 if (!FRAME_LIVE_P (f)) |
930 write_c_string ("dead", printcharfun); | 740 write_c_string ("dead", printcharfun); |
931 else | 741 else |
932 write_c_string (DEVICE_TYPE_NAME (XDEVICE (FRAME_DEVICE (f))), | 742 write_c_string (DEVICE_TYPE_NAME (XDEVICE (FRAME_DEVICE (f))), |
933 printcharfun); | 743 printcharfun); |
744 | |
745 write_c_string ("-frame ", printcharfun); | |
934 } | 746 } |
935 write_c_string ("-frame>", printcharfun); | 747 write_c_string (">", printcharfun); |
936 sprintf (buf, " 0x%p", IMAGE_INSTANCE_SUBWINDOW_ID (ii)); | 748 sprintf (buf, " 0x%p", IMAGE_INSTANCE_SUBWINDOW_ID (ii)); |
937 write_c_string (buf, printcharfun); | 749 write_c_string (buf, printcharfun); |
938 | 750 |
939 break; | 751 break; |
940 | 752 |
941 default: | 753 default: |
942 abort (); | 754 abort (); |
943 } | 755 } |
944 | 756 |
945 MAYBE_DEVMETH (DOMAIN_XDEVICE (ii->domain), print_image_instance, | 757 MAYBE_DEVMETH (XDEVICE (ii->device), print_image_instance, |
946 (ii, printcharfun, escapeflag)); | 758 (ii, printcharfun, escapeflag)); |
947 sprintf (buf, " 0x%x>", ii->header.uid); | 759 sprintf (buf, " 0x%x>", ii->header.uid); |
948 write_c_string (buf, printcharfun); | 760 write_c_string (buf, printcharfun); |
949 } | 761 } |
950 | 762 |
951 static void | 763 static void |
952 finalize_image_instance (void *header, int for_disksave) | 764 finalize_image_instance (void *header, int for_disksave) |
953 { | 765 { |
954 Lisp_Image_Instance *i = (Lisp_Image_Instance *) header; | 766 struct Lisp_Image_Instance *i = (struct Lisp_Image_Instance *) header; |
955 | 767 |
956 /* objects like this exist at dump time, so don't bomb out. */ | 768 if (IMAGE_INSTANCE_TYPE (i) == IMAGE_NOTHING) |
957 if (IMAGE_INSTANCE_TYPE (i) == IMAGE_NOTHING | 769 /* objects like this exist at dump time, so don't bomb out. */ |
958 || | |
959 NILP (IMAGE_INSTANCE_DEVICE (i))) | |
960 return; | 770 return; |
961 if (for_disksave) finalose (i); | 771 if (for_disksave) finalose (i); |
962 | 772 |
963 /* We can't use the domain here, because it might have | 773 /* do this so that the cachels get reset */ |
964 disappeared. */ | 774 if (IMAGE_INSTANCE_TYPE (i) == IMAGE_WIDGET |
965 MAYBE_DEVMETH (XDEVICE (IMAGE_INSTANCE_DEVICE (i)), | 775 || |
966 finalize_image_instance, (i)); | 776 IMAGE_INSTANCE_TYPE (i) == IMAGE_SUBWINDOW) |
967 | 777 { |
968 /* Make sure we don't try this twice. */ | 778 MARK_FRAME_GLYPHS_CHANGED |
969 IMAGE_INSTANCE_DEVICE (i) = Qnil; | 779 (XFRAME (IMAGE_INSTANCE_SUBWINDOW_FRAME (i))); |
780 } | |
781 | |
782 MAYBE_DEVMETH (XDEVICE (i->device), finalize_image_instance, (i)); | |
970 } | 783 } |
971 | 784 |
972 static int | 785 static int |
973 image_instance_equal (Lisp_Object obj1, Lisp_Object obj2, int depth) | 786 image_instance_equal (Lisp_Object obj1, Lisp_Object obj2, int depth) |
974 { | 787 { |
975 Lisp_Image_Instance *i1 = XIMAGE_INSTANCE (obj1); | 788 struct Lisp_Image_Instance *i1 = XIMAGE_INSTANCE (obj1); |
976 Lisp_Image_Instance *i2 = XIMAGE_INSTANCE (obj2); | 789 struct Lisp_Image_Instance *i2 = XIMAGE_INSTANCE (obj2); |
977 | 790 struct device *d1 = XDEVICE (i1->device); |
978 ERROR_CHECK_IMAGE_INSTANCE (obj1); | 791 struct device *d2 = XDEVICE (i2->device); |
979 ERROR_CHECK_IMAGE_INSTANCE (obj2); | 792 |
980 | 793 if (d1 != d2) |
981 if (!EQ (IMAGE_INSTANCE_DOMAIN (i1), | 794 return 0; |
982 IMAGE_INSTANCE_DOMAIN (i2)) | 795 if (IMAGE_INSTANCE_TYPE (i1) != IMAGE_INSTANCE_TYPE (i2)) |
983 || IMAGE_INSTANCE_TYPE (i1) != IMAGE_INSTANCE_TYPE (i2) | |
984 || IMAGE_INSTANCE_WIDTH (i1) != IMAGE_INSTANCE_WIDTH (i2) | |
985 || IMAGE_INSTANCE_MARGIN_WIDTH (i1) != | |
986 IMAGE_INSTANCE_MARGIN_WIDTH (i2) | |
987 || IMAGE_INSTANCE_HEIGHT (i1) != IMAGE_INSTANCE_HEIGHT (i2) | |
988 || IMAGE_INSTANCE_XOFFSET (i1) != IMAGE_INSTANCE_XOFFSET (i2) | |
989 || IMAGE_INSTANCE_YOFFSET (i1) != IMAGE_INSTANCE_YOFFSET (i2)) | |
990 return 0; | 796 return 0; |
991 if (!internal_equal (IMAGE_INSTANCE_NAME (i1), IMAGE_INSTANCE_NAME (i2), | 797 if (!internal_equal (IMAGE_INSTANCE_NAME (i1), IMAGE_INSTANCE_NAME (i2), |
992 depth + 1)) | 798 depth + 1)) |
993 return 0; | 799 return 0; |
994 | 800 |
1005 break; | 811 break; |
1006 | 812 |
1007 case IMAGE_MONO_PIXMAP: | 813 case IMAGE_MONO_PIXMAP: |
1008 case IMAGE_COLOR_PIXMAP: | 814 case IMAGE_COLOR_PIXMAP: |
1009 case IMAGE_POINTER: | 815 case IMAGE_POINTER: |
1010 if (!(IMAGE_INSTANCE_PIXMAP_DEPTH (i1) == | 816 if (!(IMAGE_INSTANCE_PIXMAP_WIDTH (i1) == |
817 IMAGE_INSTANCE_PIXMAP_WIDTH (i2) && | |
818 IMAGE_INSTANCE_PIXMAP_HEIGHT (i1) == | |
819 IMAGE_INSTANCE_PIXMAP_HEIGHT (i2) && | |
820 IMAGE_INSTANCE_PIXMAP_DEPTH (i1) == | |
1011 IMAGE_INSTANCE_PIXMAP_DEPTH (i2) && | 821 IMAGE_INSTANCE_PIXMAP_DEPTH (i2) && |
1012 IMAGE_INSTANCE_PIXMAP_SLICE (i1) == | |
1013 IMAGE_INSTANCE_PIXMAP_SLICE (i2) && | |
1014 EQ (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (i1), | 822 EQ (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (i1), |
1015 IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (i2)) && | 823 IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (i2)) && |
1016 EQ (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (i1), | 824 EQ (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (i1), |
1017 IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (i2)) && | 825 IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (i2)) && |
1018 internal_equal (IMAGE_INSTANCE_PIXMAP_FILENAME (i1), | 826 internal_equal (IMAGE_INSTANCE_PIXMAP_FILENAME (i1), |
1024 return 0; | 832 return 0; |
1025 break; | 833 break; |
1026 | 834 |
1027 case IMAGE_WIDGET: | 835 case IMAGE_WIDGET: |
1028 if (!(EQ (IMAGE_INSTANCE_WIDGET_TYPE (i1), | 836 if (!(EQ (IMAGE_INSTANCE_WIDGET_TYPE (i1), |
1029 IMAGE_INSTANCE_WIDGET_TYPE (i2)) | 837 IMAGE_INSTANCE_WIDGET_TYPE (i2)) && |
1030 && IMAGE_INSTANCE_SUBWINDOW_ID (i1) == | 838 EQ (IMAGE_INSTANCE_WIDGET_CALLBACK (i1), |
1031 IMAGE_INSTANCE_SUBWINDOW_ID (i2) | 839 IMAGE_INSTANCE_WIDGET_CALLBACK (i2)) |
1032 && | |
1033 EQ (IMAGE_INSTANCE_WIDGET_FACE (i1), | |
1034 IMAGE_INSTANCE_WIDGET_TYPE (i2)) | |
1035 && internal_equal (IMAGE_INSTANCE_WIDGET_ITEMS (i1), | |
1036 IMAGE_INSTANCE_WIDGET_ITEMS (i2), | |
1037 depth + 1) | |
1038 && internal_equal (IMAGE_INSTANCE_LAYOUT_CHILDREN (i1), | |
1039 IMAGE_INSTANCE_LAYOUT_CHILDREN (i2), | |
1040 depth + 1) | |
1041 && internal_equal (IMAGE_INSTANCE_WIDGET_PROPS (i1), | 840 && internal_equal (IMAGE_INSTANCE_WIDGET_PROPS (i1), |
1042 IMAGE_INSTANCE_WIDGET_PROPS (i2), | 841 IMAGE_INSTANCE_WIDGET_PROPS (i2), |
1043 depth + 1) | 842 depth + 1) |
1044 && internal_equal (IMAGE_INSTANCE_WIDGET_WIDTH_SUBR (i1), | 843 && internal_equal (IMAGE_INSTANCE_WIDGET_TEXT (i1), |
1045 IMAGE_INSTANCE_WIDGET_WIDTH_SUBR (i2), | 844 IMAGE_INSTANCE_WIDGET_TEXT (i2), |
1046 depth + 1) | 845 depth + 1))) |
1047 && internal_equal (IMAGE_INSTANCE_WIDGET_HEIGHT_SUBR (i1), | |
1048 IMAGE_INSTANCE_WIDGET_HEIGHT_SUBR (i2), | |
1049 depth + 1) | |
1050 )) | |
1051 return 0; | 846 return 0; |
1052 break; | |
1053 | |
1054 case IMAGE_SUBWINDOW: | 847 case IMAGE_SUBWINDOW: |
1055 if (!(IMAGE_INSTANCE_SUBWINDOW_ID (i1) == | 848 if (!(IMAGE_INSTANCE_SUBWINDOW_WIDTH (i1) == |
849 IMAGE_INSTANCE_SUBWINDOW_WIDTH (i2) && | |
850 IMAGE_INSTANCE_SUBWINDOW_HEIGHT (i1) == | |
851 IMAGE_INSTANCE_SUBWINDOW_HEIGHT (i2) && | |
852 IMAGE_INSTANCE_SUBWINDOW_ID (i1) == | |
1056 IMAGE_INSTANCE_SUBWINDOW_ID (i2))) | 853 IMAGE_INSTANCE_SUBWINDOW_ID (i2))) |
1057 return 0; | 854 return 0; |
1058 break; | 855 break; |
1059 | 856 |
1060 default: | 857 default: |
1061 abort (); | 858 abort (); |
1062 } | 859 } |
1063 | 860 |
1064 return DEVMETH_OR_GIVEN (DOMAIN_XDEVICE (i1->domain), | 861 return DEVMETH_OR_GIVEN (d1, image_instance_equal, (i1, i2, depth), 1); |
1065 image_instance_equal, (i1, i2, depth), 1); | |
1066 } | |
1067 | |
1068 /* Image instance domain manipulators. We can't error check in these | |
1069 otherwise we get into infinite recursion. */ | |
1070 Lisp_Object | |
1071 image_instance_device (Lisp_Object instance) | |
1072 { | |
1073 return XIMAGE_INSTANCE_DEVICE (instance); | |
1074 } | |
1075 | |
1076 Lisp_Object | |
1077 image_instance_frame (Lisp_Object instance) | |
1078 { | |
1079 return XIMAGE_INSTANCE_FRAME (instance); | |
1080 } | |
1081 | |
1082 Lisp_Object | |
1083 image_instance_window (Lisp_Object instance) | |
1084 { | |
1085 return DOMAIN_WINDOW (XIMAGE_INSTANCE_DOMAIN (instance)); | |
1086 } | |
1087 | |
1088 int | |
1089 image_instance_live_p (Lisp_Object instance) | |
1090 { | |
1091 return DOMAIN_LIVE_P (XIMAGE_INSTANCE_DOMAIN (instance)); | |
1092 } | 862 } |
1093 | 863 |
1094 static unsigned long | 864 static unsigned long |
1095 image_instance_hash (Lisp_Object obj, int depth) | 865 image_instance_hash (Lisp_Object obj, int depth) |
1096 { | 866 { |
1097 Lisp_Image_Instance *i = XIMAGE_INSTANCE (obj); | 867 struct Lisp_Image_Instance *i = XIMAGE_INSTANCE (obj); |
1098 unsigned long hash = HASH4 (LISP_HASH (IMAGE_INSTANCE_DOMAIN (i)), | 868 struct device *d = XDEVICE (i->device); |
1099 IMAGE_INSTANCE_WIDTH (i), | 869 unsigned long hash = (unsigned long) d; |
1100 IMAGE_INSTANCE_MARGIN_WIDTH (i), | |
1101 IMAGE_INSTANCE_HEIGHT (i)); | |
1102 | |
1103 ERROR_CHECK_IMAGE_INSTANCE (obj); | |
1104 | 870 |
1105 switch (IMAGE_INSTANCE_TYPE (i)) | 871 switch (IMAGE_INSTANCE_TYPE (i)) |
1106 { | 872 { |
1107 case IMAGE_NOTHING: | 873 case IMAGE_NOTHING: |
1108 break; | 874 break; |
1113 break; | 879 break; |
1114 | 880 |
1115 case IMAGE_MONO_PIXMAP: | 881 case IMAGE_MONO_PIXMAP: |
1116 case IMAGE_COLOR_PIXMAP: | 882 case IMAGE_COLOR_PIXMAP: |
1117 case IMAGE_POINTER: | 883 case IMAGE_POINTER: |
1118 hash = HASH4 (hash, IMAGE_INSTANCE_PIXMAP_DEPTH (i), | 884 hash = HASH5 (hash, IMAGE_INSTANCE_PIXMAP_WIDTH (i), |
1119 IMAGE_INSTANCE_PIXMAP_SLICE (i), | 885 IMAGE_INSTANCE_PIXMAP_HEIGHT (i), |
886 IMAGE_INSTANCE_PIXMAP_DEPTH (i), | |
1120 internal_hash (IMAGE_INSTANCE_PIXMAP_FILENAME (i), | 887 internal_hash (IMAGE_INSTANCE_PIXMAP_FILENAME (i), |
1121 depth + 1)); | 888 depth + 1)); |
1122 break; | 889 break; |
1123 | 890 |
1124 case IMAGE_WIDGET: | 891 case IMAGE_WIDGET: |
1125 /* We need the hash to be equivalent to what should be | 892 hash = HASH4 (hash, |
1126 displayed. */ | 893 internal_hash (IMAGE_INSTANCE_WIDGET_TYPE (i), depth + 1), |
1127 hash = HASH5 (hash, | |
1128 LISP_HASH (IMAGE_INSTANCE_WIDGET_TYPE (i)), | |
1129 internal_hash (IMAGE_INSTANCE_WIDGET_PROPS (i), depth + 1), | 894 internal_hash (IMAGE_INSTANCE_WIDGET_PROPS (i), depth + 1), |
1130 internal_hash (IMAGE_INSTANCE_WIDGET_ITEMS (i), depth + 1), | 895 internal_hash (IMAGE_INSTANCE_WIDGET_CALLBACK (i), depth + 1)); |
1131 internal_hash (IMAGE_INSTANCE_LAYOUT_CHILDREN (i), | |
1132 depth + 1)); | |
1133 case IMAGE_SUBWINDOW: | 896 case IMAGE_SUBWINDOW: |
1134 hash = HASH2 (hash, (int) IMAGE_INSTANCE_SUBWINDOW_ID (i)); | 897 hash = HASH4 (hash, IMAGE_INSTANCE_SUBWINDOW_WIDTH (i), |
898 IMAGE_INSTANCE_SUBWINDOW_HEIGHT (i), | |
899 (int) IMAGE_INSTANCE_SUBWINDOW_ID (i)); | |
1135 break; | 900 break; |
1136 | 901 |
1137 default: | 902 default: |
1138 abort (); | 903 abort (); |
1139 } | 904 } |
1140 | 905 |
1141 return HASH2 (hash, DEVMETH_OR_GIVEN | 906 return HASH2 (hash, DEVMETH_OR_GIVEN (d, image_instance_hash, (i, depth), |
1142 (XDEVICE (image_instance_device (obj)), | 907 0)); |
1143 image_instance_hash, (i, depth), | |
1144 0)); | |
1145 } | 908 } |
1146 | 909 |
1147 DEFINE_LRECORD_IMPLEMENTATION ("image-instance", image_instance, | 910 DEFINE_LRECORD_IMPLEMENTATION ("image-instance", image_instance, |
1148 mark_image_instance, print_image_instance, | 911 mark_image_instance, print_image_instance, |
1149 finalize_image_instance, image_instance_equal, | 912 finalize_image_instance, image_instance_equal, |
1150 image_instance_hash, 0, | 913 image_instance_hash, |
1151 Lisp_Image_Instance); | 914 struct Lisp_Image_Instance); |
1152 | 915 |
1153 static Lisp_Object | 916 static Lisp_Object |
1154 allocate_image_instance (Lisp_Object governing_domain, Lisp_Object glyph) | 917 allocate_image_instance (Lisp_Object device) |
1155 { | 918 { |
1156 Lisp_Image_Instance *lp = | 919 struct Lisp_Image_Instance *lp = |
1157 alloc_lcrecord_type (Lisp_Image_Instance, &lrecord_image_instance); | 920 alloc_lcrecord_type (struct Lisp_Image_Instance, &lrecord_image_instance); |
1158 Lisp_Object val; | 921 Lisp_Object val; |
1159 | 922 |
1160 zero_lcrecord (lp); | 923 zero_lcrecord (lp); |
1161 /* It's not possible to simply keep a record of the domain in which | 924 lp->device = device; |
1162 the instance was instantiated. This is because caching may mean | |
1163 that the domain becomes invalid but the instance remains | |
1164 valid. However, the only truly relevant domain is the domain in | |
1165 which the instance is cached since this is the one that will be | |
1166 common to the instances. */ | |
1167 lp->domain = governing_domain; | |
1168 /* The cache domain is not quite sufficient since the domain can get | |
1169 deleted before the image instance does. We need to know the | |
1170 domain device in order to finalize the image instance | |
1171 properly. We therefore record the device also. */ | |
1172 lp->device = DOMAIN_DEVICE (governing_domain); | |
1173 lp->type = IMAGE_NOTHING; | 925 lp->type = IMAGE_NOTHING; |
1174 lp->name = Qnil; | 926 lp->name = Qnil; |
1175 lp->x_offset = 0; | |
1176 lp->y_offset = 0; | |
1177 lp->width = IMAGE_UNSPECIFIED_GEOMETRY; | |
1178 lp->margin_width = 0; | |
1179 lp->height = IMAGE_UNSPECIFIED_GEOMETRY; | |
1180 lp->parent = glyph; | |
1181 /* So that layouts get done. */ | |
1182 lp->layout_changed = 1; | |
1183 lp->initialized = 0; | |
1184 | |
1185 XSETIMAGE_INSTANCE (val, lp); | 927 XSETIMAGE_INSTANCE (val, lp); |
1186 MARK_GLYPHS_CHANGED; | |
1187 | |
1188 return val; | 928 return val; |
1189 } | 929 } |
1190 | 930 |
1191 static enum image_instance_type | 931 static enum image_instance_type |
1192 decode_image_instance_type (Lisp_Object type, Error_behavior errb) | 932 decode_image_instance_type (Lisp_Object type, Error_behavior errb) |
1226 | 966 |
1227 return Qnil; /* not reached */ | 967 return Qnil; /* not reached */ |
1228 } | 968 } |
1229 | 969 |
1230 static int | 970 static int |
971 image_instance_type_to_mask (enum image_instance_type type) | |
972 { | |
973 /* This depends on the fact that enums are assigned consecutive | |
974 integers starting at 0. (Remember that IMAGE_UNKNOWN is the | |
975 first enum.) I'm fairly sure this behavior in ANSI-mandated, | |
976 so there should be no portability problems here. */ | |
977 return (1 << ((int) (type) - 1)); | |
978 } | |
979 | |
980 static int | |
1231 decode_image_instance_type_list (Lisp_Object list) | 981 decode_image_instance_type_list (Lisp_Object list) |
1232 { | 982 { |
1233 Lisp_Object rest; | 983 Lisp_Object rest; |
1234 int mask = 0; | 984 int mask = 0; |
1235 | 985 |
1277 { | 1027 { |
1278 signal_error | 1028 signal_error |
1279 (Qerror, | 1029 (Qerror, |
1280 list2 | 1030 list2 |
1281 (emacs_doprnt_string_lisp_2 | 1031 (emacs_doprnt_string_lisp_2 |
1282 ((const Bufbyte *) | 1032 ((CONST Bufbyte *) |
1283 "No compatible image-instance types given: wanted one of %s, got %s", | 1033 "No compatible image-instance types given: wanted one of %s, got %s", |
1284 Qnil, -1, 2, | 1034 Qnil, -1, 2, |
1285 encode_image_instance_type_list (desired_dest_mask), | 1035 encode_image_instance_type_list (desired_dest_mask), |
1286 encode_image_instance_type_list (given_dest_mask)), | 1036 encode_image_instance_type_list (given_dest_mask)), |
1287 instantiator)); | 1037 instantiator)); |
1294 } | 1044 } |
1295 | 1045 |
1296 DEFUN ("valid-image-instance-type-p", Fvalid_image_instance_type_p, 1, 1, 0, /* | 1046 DEFUN ("valid-image-instance-type-p", Fvalid_image_instance_type_p, 1, 1, 0, /* |
1297 Given an IMAGE-INSTANCE-TYPE, return non-nil if it is valid. | 1047 Given an IMAGE-INSTANCE-TYPE, return non-nil if it is valid. |
1298 Valid types are some subset of 'nothing, 'text, 'mono-pixmap, 'color-pixmap, | 1048 Valid types are some subset of 'nothing, 'text, 'mono-pixmap, 'color-pixmap, |
1299 'pointer, 'subwindow, and 'widget, depending on how XEmacs was compiled. | 1049 'pointer, and 'subwindow, depending on how XEmacs was compiled. |
1300 */ | 1050 */ |
1301 (image_instance_type)) | 1051 (image_instance_type)) |
1302 { | 1052 { |
1303 return valid_image_instance_type_p (image_instance_type) ? Qt : Qnil; | 1053 return valid_image_instance_type_p (image_instance_type) ? Qt : Qnil; |
1304 } | 1054 } |
1331 assert (ERRB_EQ (errb, ERROR_ME_WARN)); | 1081 assert (ERRB_EQ (errb, ERROR_ME_WARN)); |
1332 return Qwarning; | 1082 return Qwarning; |
1333 } | 1083 } |
1334 } | 1084 } |
1335 | 1085 |
1336 /* Recurse up the hierarchy looking for the topmost glyph. This means | |
1337 that instances in layouts will inherit face properties from their | |
1338 parent. */ | |
1339 Lisp_Object image_instance_parent_glyph (Lisp_Image_Instance* ii) | |
1340 { | |
1341 if (IMAGE_INSTANCEP (IMAGE_INSTANCE_PARENT (ii))) | |
1342 { | |
1343 return image_instance_parent_glyph | |
1344 (XIMAGE_INSTANCE (IMAGE_INSTANCE_PARENT (ii))); | |
1345 } | |
1346 return IMAGE_INSTANCE_PARENT (ii); | |
1347 } | |
1348 | |
1349 static Lisp_Object | 1086 static Lisp_Object |
1350 make_image_instance_1 (Lisp_Object data, Lisp_Object domain, | 1087 make_image_instance_1 (Lisp_Object data, Lisp_Object device, |
1351 Lisp_Object dest_types) | 1088 Lisp_Object dest_types) |
1352 { | 1089 { |
1353 Lisp_Object ii; | 1090 Lisp_Object ii; |
1354 struct gcpro gcpro1; | 1091 struct gcpro gcpro1; |
1355 int dest_mask; | 1092 int dest_mask; |
1356 Lisp_Object governing_domain; | 1093 |
1357 | 1094 XSETDEVICE (device, decode_device (device)); |
1095 /* instantiate_image_instantiator() will abort if given an | |
1096 image instance ... */ | |
1358 if (IMAGE_INSTANCEP (data)) | 1097 if (IMAGE_INSTANCEP (data)) |
1359 signal_simple_error ("Image instances not allowed here", data); | 1098 signal_simple_error ("Image instances not allowed here", data); |
1360 image_validate (data); | 1099 image_validate (data); |
1361 domain = decode_domain (domain); | |
1362 /* instantiate_image_instantiator() will abort if given an | |
1363 image instance ... */ | |
1364 dest_mask = decode_image_instance_type_list (dest_types); | 1100 dest_mask = decode_image_instance_type_list (dest_types); |
1365 data = normalize_image_instantiator (data, | 1101 data = normalize_image_instantiator (data, DEVICE_TYPE (XDEVICE (device)), |
1366 DEVICE_TYPE (DOMAIN_XDEVICE (domain)), | |
1367 make_int (dest_mask)); | 1102 make_int (dest_mask)); |
1368 GCPRO1 (data); | 1103 GCPRO1 (data); |
1369 /* After normalizing the data, it's always either an image instance (which | 1104 if (VECTORP (data) && EQ (XVECTOR_DATA (data)[0], Qinherit)) |
1370 we filtered out above) or a vector. */ | |
1371 if (EQ (XVECTOR_DATA (data)[0], Qinherit)) | |
1372 signal_simple_error ("Inheritance not allowed here", data); | 1105 signal_simple_error ("Inheritance not allowed here", data); |
1373 governing_domain = | 1106 ii = instantiate_image_instantiator (device, device, data, |
1374 get_image_instantiator_governing_domain (data, domain); | 1107 Qnil, Qnil, dest_mask); |
1375 ii = instantiate_image_instantiator (governing_domain, domain, data, | |
1376 Qnil, Qnil, dest_mask, Qnil); | |
1377 RETURN_UNGCPRO (ii); | 1108 RETURN_UNGCPRO (ii); |
1378 } | 1109 } |
1379 | 1110 |
1380 DEFUN ("make-image-instance", Fmake_image_instance, 1, 4, 0, /* | 1111 DEFUN ("make-image-instance", Fmake_image_instance, 1, 4, 0, /* |
1381 Return a new `image-instance' object. | 1112 Return a new `image-instance' object. |
1385 do not need to directly create image instances; use a glyph instead. | 1116 do not need to directly create image instances; use a glyph instead. |
1386 However, it may occasionally be useful to explicitly create image | 1117 However, it may occasionally be useful to explicitly create image |
1387 instances, if you want more control over the instantiation process. | 1118 instances, if you want more control over the instantiation process. |
1388 | 1119 |
1389 DATA is an image instantiator, which describes the image; see | 1120 DATA is an image instantiator, which describes the image; see |
1390 `make-image-specifier' for a description of the allowed values. | 1121 `image-specifier-p' for a description of the allowed values. |
1391 | 1122 |
1392 DEST-TYPES should be a list of allowed image instance types that can | 1123 DEST-TYPES should be a list of allowed image instance types that can |
1393 be generated. The recognized image instance types are | 1124 be generated. The recognized image instance types are |
1394 | 1125 |
1395 'nothing | 1126 'nothing |
1410 'pointer | 1141 'pointer |
1411 Used as the mouse pointer for a window. | 1142 Used as the mouse pointer for a window. |
1412 'subwindow | 1143 'subwindow |
1413 A child window that is treated as an image. This allows (e.g.) | 1144 A child window that is treated as an image. This allows (e.g.) |
1414 another program to be responsible for drawing into the window. | 1145 another program to be responsible for drawing into the window. |
1415 'widget | 1146 Not currently implemented. |
1416 A child window that contains a window-system widget, e.g. a push | 1147 |
1417 button, text field, or slider. | 1148 The DEST-TYPES list is unordered. If multiple destination types |
1418 | 1149 are possible for a given instantiator, the "most natural" type |
1419 The DEST-TYPES list is unordered. If multiple destination types are | 1150 for the instantiator's format is chosen. (For XBM, the most natural |
1420 possible for a given instantiator, the "most natural" type for the | 1151 types are `mono-pixmap', followed by `color-pixmap', followed by |
1421 instantiator's format is chosen. (For XBM, the most natural types are | 1152 `pointer'. For the other normal image formats, the most natural |
1422 `mono-pixmap', followed by `color-pixmap', followed by `pointer'. For | 1153 types are `color-pixmap', followed by `mono-pixmap', followed by |
1423 the other normal image formats, the most natural types are | 1154 `pointer'. For the string and formatted-string formats, the most |
1424 `color-pixmap', followed by `mono-pixmap', followed by `pointer'. For | 1155 natural types are `text', followed by `mono-pixmap' (not currently |
1425 the string and formatted-string formats, the most natural types are | 1156 implemented), followed by `color-pixmap' (not currently implemented). |
1426 `text', followed by `mono-pixmap' (not currently implemented), | 1157 The other formats can only be instantiated as one type. (If you |
1427 followed by `color-pixmap' (not currently implemented). For MS | 1158 want to control more specifically the order of the types into which |
1428 Windows resources, the most natural type for pointer resources is | 1159 an image is instantiated, just call `make-image-instance' repeatedly |
1429 `pointer', and for the others it's `color-pixmap'. The other formats | 1160 until it succeeds, passing less and less preferred destination types |
1430 can only be instantiated as one type. (If you want to control more | 1161 each time. |
1431 specifically the order of the types into which an image is | |
1432 instantiated, just call `make-image-instance' repeatedly until it | |
1433 succeeds, passing less and less preferred destination types each | |
1434 time.) | |
1435 | |
1436 See `make-image-specifier' for a description of the different image | |
1437 instantiator formats. | |
1438 | 1162 |
1439 If DEST-TYPES is omitted, all possible types are allowed. | 1163 If DEST-TYPES is omitted, all possible types are allowed. |
1440 | |
1441 DOMAIN specifies the domain to which the image instance will be attached. | |
1442 This domain is termed the \"governing domain\". The type of the governing | |
1443 domain depends on the image instantiator format. (Although, more correctly, | |
1444 it should probably depend on the image instance type.) For example, pixmap | |
1445 image instances are specific to a device, but widget image instances are | |
1446 specific to a particular XEmacs window because in order to display such a | |
1447 widget when two windows onto the same buffer want to display the widget, | |
1448 two separate underlying widgets must be created. (That's because a widget | |
1449 is actually a child window-system window, and all window-system windows have | |
1450 a unique existence on the screen.) This means that the governing domain for | |
1451 a pixmap image instance will be some device (most likely, the only existing | |
1452 device), whereas the governing domain for a widget image instance will be | |
1453 some XEmacs window. | |
1454 | |
1455 If you specify an overly general DOMAIN (e.g. a frame when a window was | |
1456 wanted), an error is signaled. If you specify an overly specific DOMAIN | |
1457 \(e.g. a window when a device was wanted), the corresponding general domain | |
1458 is fetched and used instead. For `make-image-instance', it makes no | |
1459 difference whether you specify an overly specific domain or the properly | |
1460 general domain derived from it. However, it does matter when creating an | |
1461 image instance by instantiating a specifier or glyph (e.g. with | |
1462 `glyph-image-instance'), because the more specific domain causes spec lookup | |
1463 to start there and proceed to more general domains. (It would also matter | |
1464 when creating an image instance with an instantiator format of `inherit', | |
1465 but we currently disallow this. #### We should fix this.) | |
1466 | |
1467 If omitted, DOMAIN defaults to the selected window. | |
1468 | 1164 |
1469 NO-ERROR controls what happens when the image cannot be generated. | 1165 NO-ERROR controls what happens when the image cannot be generated. |
1470 If nil, an error message is generated. If t, no messages are | 1166 If nil, an error message is generated. If t, no messages are |
1471 generated and this function returns nil. If anything else, a warning | 1167 generated and this function returns nil. If anything else, a warning |
1472 message is generated and this function returns nil. | 1168 message is generated and this function returns nil. |
1473 */ | 1169 */ |
1474 (data, domain, dest_types, no_error)) | 1170 (data, device, dest_types, no_error)) |
1475 { | 1171 { |
1476 Error_behavior errb = decode_error_behavior_flag (no_error); | 1172 Error_behavior errb = decode_error_behavior_flag (no_error); |
1477 | 1173 |
1478 return call_with_suspended_errors ((lisp_fn_t) make_image_instance_1, | 1174 return call_with_suspended_errors ((lisp_fn_t) make_image_instance_1, |
1479 Qnil, Qimage, errb, | 1175 Qnil, Qimage, errb, |
1480 3, data, domain, dest_types); | 1176 3, data, device, dest_types); |
1481 } | 1177 } |
1482 | 1178 |
1483 DEFUN ("image-instance-p", Fimage_instance_p, 1, 1, 0, /* | 1179 DEFUN ("image-instance-p", Fimage_instance_p, 1, 1, 0, /* |
1484 Return non-nil if OBJECT is an image instance. | 1180 Return non-nil if OBJECT is an image instance. |
1485 */ | 1181 */ |
1494 'color-pixmap, 'pointer, or 'subwindow. | 1190 'color-pixmap, 'pointer, or 'subwindow. |
1495 */ | 1191 */ |
1496 (image_instance)) | 1192 (image_instance)) |
1497 { | 1193 { |
1498 CHECK_IMAGE_INSTANCE (image_instance); | 1194 CHECK_IMAGE_INSTANCE (image_instance); |
1499 ERROR_CHECK_IMAGE_INSTANCE (image_instance); | |
1500 return encode_image_instance_type (XIMAGE_INSTANCE_TYPE (image_instance)); | 1195 return encode_image_instance_type (XIMAGE_INSTANCE_TYPE (image_instance)); |
1501 } | 1196 } |
1502 | 1197 |
1503 DEFUN ("image-instance-name", Fimage_instance_name, 1, 1, 0, /* | 1198 DEFUN ("image-instance-name", Fimage_instance_name, 1, 1, 0, /* |
1504 Return the name of the given image instance. | 1199 Return the name of the given image instance. |
1505 */ | 1200 */ |
1506 (image_instance)) | 1201 (image_instance)) |
1507 { | 1202 { |
1508 CHECK_IMAGE_INSTANCE (image_instance); | 1203 CHECK_IMAGE_INSTANCE (image_instance); |
1509 return XIMAGE_INSTANCE_NAME (image_instance); | 1204 return XIMAGE_INSTANCE_NAME (image_instance); |
1510 } | |
1511 | |
1512 DEFUN ("image-instance-domain", Fimage_instance_domain, 1, 1, 0, /* | |
1513 Return the governing domain of the given image instance. | |
1514 The governing domain of an image instance is the domain that the image | |
1515 instance is specific to. It is NOT necessarily the domain that was | |
1516 given to the call to `specifier-instance' that resulted in the creation | |
1517 of this image instance. See `make-image-instance' for more information | |
1518 on governing domains. | |
1519 */ | |
1520 (image_instance)) | |
1521 { | |
1522 CHECK_IMAGE_INSTANCE (image_instance); | |
1523 return XIMAGE_INSTANCE_DOMAIN (image_instance); | |
1524 } | 1205 } |
1525 | 1206 |
1526 DEFUN ("image-instance-string", Fimage_instance_string, 1, 1, 0, /* | 1207 DEFUN ("image-instance-string", Fimage_instance_string, 1, 1, 0, /* |
1527 Return the string of the given image instance. | 1208 Return the string of the given image instance. |
1528 This will only be non-nil for text image instances and widgets. | 1209 This will only be non-nil for text image instances and widgets. |
1537 else | 1218 else |
1538 return Qnil; | 1219 return Qnil; |
1539 } | 1220 } |
1540 | 1221 |
1541 DEFUN ("image-instance-property", Fimage_instance_property, 2, 2, 0, /* | 1222 DEFUN ("image-instance-property", Fimage_instance_property, 2, 2, 0, /* |
1542 Return the given property of the given image instance. | 1223 Return the given property of the given image instance. |
1543 Returns nil if the property or the property method do not exist for | 1224 Returns nil if the property or the property method do not exist for |
1544 the image instance in the domain. | 1225 the image instance in the domain. |
1545 */ | 1226 */ |
1546 (image_instance, prop)) | 1227 (image_instance, prop)) |
1547 { | 1228 { |
1548 Lisp_Image_Instance* ii; | 1229 struct Lisp_Image_Instance* ii; |
1549 Lisp_Object type, ret; | 1230 Lisp_Object type, ret; |
1550 struct image_instantiator_methods* meths; | 1231 struct image_instantiator_methods* meths; |
1551 | 1232 |
1552 CHECK_IMAGE_INSTANCE (image_instance); | 1233 CHECK_IMAGE_INSTANCE (image_instance); |
1553 ERROR_CHECK_IMAGE_INSTANCE (image_instance); | |
1554 CHECK_SYMBOL (prop); | 1234 CHECK_SYMBOL (prop); |
1555 ii = XIMAGE_INSTANCE (image_instance); | 1235 ii = XIMAGE_INSTANCE (image_instance); |
1556 | 1236 |
1557 /* ... then try device specific methods ... */ | 1237 /* ... then try device specific methods ... */ |
1558 type = encode_image_instance_type (IMAGE_INSTANCE_TYPE (ii)); | 1238 type = encode_image_instance_type (IMAGE_INSTANCE_TYPE (ii)); |
1559 meths = decode_device_ii_format (image_instance_device (image_instance), | 1239 meths = decode_device_ii_format (IMAGE_INSTANCE_DEVICE (ii), |
1560 type, ERROR_ME_NOT); | 1240 type, ERROR_ME_NOT); |
1561 if (meths && HAS_IIFORMAT_METH_P (meths, property) | 1241 if (meths && HAS_IIFORMAT_METH_P (meths, property) |
1562 && | 1242 && |
1563 !UNBOUNDP (ret = IIFORMAT_METH (meths, property, (image_instance, prop)))) | 1243 !UNBOUNDP (ret = IIFORMAT_METH (meths, property, (image_instance, prop)))) |
1564 { | 1244 { |
1565 return ret; | 1245 return ret; |
1566 } | 1246 } |
1567 /* ... then format specific methods ... */ | 1247 /* ... then format specific methods ... */ |
1575 /* ... then fail */ | 1255 /* ... then fail */ |
1576 return Qnil; | 1256 return Qnil; |
1577 } | 1257 } |
1578 | 1258 |
1579 DEFUN ("set-image-instance-property", Fset_image_instance_property, 3, 3, 0, /* | 1259 DEFUN ("set-image-instance-property", Fset_image_instance_property, 3, 3, 0, /* |
1580 Set the given property of the given image instance. | 1260 Set the given property of the given image instance. |
1581 Does nothing if the property or the property method do not exist for | 1261 Does nothing if the property or the property method do not exist for |
1582 the image instance in the domain. | 1262 the image instance in the domain. |
1583 | 1263 */ |
1584 WARNING: If you are thinking about using this function, think again. | |
1585 You probably want to be using `set-glyph-image' to change the glyph's | |
1586 specifier. Be especially wary if you are thinking of calling this | |
1587 function after having called `glyph-image-instance'. Unless you are | |
1588 absolutely sure what you're doing, pretty much the only legitimate | |
1589 uses for this function are setting user-specified info in a widget, | |
1590 such as text in a text field. */ | |
1591 (image_instance, prop, val)) | 1264 (image_instance, prop, val)) |
1592 { | 1265 { |
1593 Lisp_Image_Instance* ii; | 1266 struct Lisp_Image_Instance* ii; |
1594 Lisp_Object type, ret; | 1267 Lisp_Object type, ret; |
1595 struct image_instantiator_methods* meths; | 1268 struct image_instantiator_methods* meths; |
1596 | 1269 |
1597 CHECK_IMAGE_INSTANCE (image_instance); | 1270 CHECK_IMAGE_INSTANCE (image_instance); |
1598 ERROR_CHECK_IMAGE_INSTANCE (image_instance); | |
1599 CHECK_SYMBOL (prop); | 1271 CHECK_SYMBOL (prop); |
1600 ii = XIMAGE_INSTANCE (image_instance); | 1272 ii = XIMAGE_INSTANCE (image_instance); |
1601 type = encode_image_instance_type (IMAGE_INSTANCE_TYPE (ii)); | 1273 type = encode_image_instance_type (IMAGE_INSTANCE_TYPE (ii)); |
1602 /* try device specific methods first ... */ | 1274 /* try device specific methods first ... */ |
1603 meths = decode_device_ii_format (image_instance_device (image_instance), | 1275 meths = decode_device_ii_format (IMAGE_INSTANCE_DEVICE (ii), |
1604 type, ERROR_ME_NOT); | 1276 type, ERROR_ME_NOT); |
1605 if (meths && HAS_IIFORMAT_METH_P (meths, set_property) | 1277 if (meths && HAS_IIFORMAT_METH_P (meths, set_property) |
1606 && | 1278 && |
1607 !UNBOUNDP (ret = | 1279 !UNBOUNDP (ret = |
1608 IIFORMAT_METH (meths, set_property, (image_instance, prop, val)))) | 1280 IIFORMAT_METH (meths, set_property, (image_instance, prop, val)))) |
1609 { | 1281 { |
1610 val = ret; | 1282 return ret; |
1611 } | 1283 } |
1612 else | 1284 /* ... then format specific methods ... */ |
1613 { | 1285 meths = decode_device_ii_format (Qnil, type, ERROR_ME_NOT); |
1614 /* ... then format specific methods ... */ | 1286 if (meths && HAS_IIFORMAT_METH_P (meths, set_property) |
1615 meths = decode_device_ii_format (Qnil, type, ERROR_ME_NOT); | 1287 && |
1616 if (meths && HAS_IIFORMAT_METH_P (meths, set_property) | 1288 !UNBOUNDP (ret = |
1617 && | 1289 IIFORMAT_METH (meths, set_property, (image_instance, prop, val)))) |
1618 !UNBOUNDP (ret = | 1290 { |
1619 IIFORMAT_METH (meths, set_property, (image_instance, prop, val)))) | 1291 return ret; |
1620 { | 1292 } |
1621 val = ret; | |
1622 } | |
1623 else | |
1624 { | |
1625 val = Qnil; | |
1626 } | |
1627 } | |
1628 | |
1629 /* Make sure the image instance gets redisplayed. */ | |
1630 set_image_instance_dirty_p (image_instance, 1); | |
1631 /* Force the glyph to be laid out again. */ | |
1632 IMAGE_INSTANCE_LAYOUT_CHANGED (ii) = 1; | |
1633 | |
1634 MARK_SUBWINDOWS_STATE_CHANGED; | |
1635 MARK_GLYPHS_CHANGED; | |
1636 | 1293 |
1637 return val; | 1294 return val; |
1638 } | 1295 } |
1639 | 1296 |
1640 DEFUN ("image-instance-file-name", Fimage_instance_file_name, 1, 1, 0, /* | 1297 DEFUN ("image-instance-file-name", Fimage_instance_file_name, 1, 1, 0, /* |
1641 Return the file name from which IMAGE-INSTANCE was read, if known. | 1298 Return the file name from which IMAGE-INSTANCE was read, if known. |
1642 */ | 1299 */ |
1643 (image_instance)) | 1300 (image_instance)) |
1644 { | 1301 { |
1645 CHECK_IMAGE_INSTANCE (image_instance); | 1302 CHECK_IMAGE_INSTANCE (image_instance); |
1646 ERROR_CHECK_IMAGE_INSTANCE (image_instance); | |
1647 | 1303 |
1648 switch (XIMAGE_INSTANCE_TYPE (image_instance)) | 1304 switch (XIMAGE_INSTANCE_TYPE (image_instance)) |
1649 { | 1305 { |
1650 case IMAGE_MONO_PIXMAP: | 1306 case IMAGE_MONO_PIXMAP: |
1651 case IMAGE_COLOR_PIXMAP: | 1307 case IMAGE_COLOR_PIXMAP: |
1661 Return the file name from which IMAGE-INSTANCE's mask was read, if known. | 1317 Return the file name from which IMAGE-INSTANCE's mask was read, if known. |
1662 */ | 1318 */ |
1663 (image_instance)) | 1319 (image_instance)) |
1664 { | 1320 { |
1665 CHECK_IMAGE_INSTANCE (image_instance); | 1321 CHECK_IMAGE_INSTANCE (image_instance); |
1666 ERROR_CHECK_IMAGE_INSTANCE (image_instance); | |
1667 | 1322 |
1668 switch (XIMAGE_INSTANCE_TYPE (image_instance)) | 1323 switch (XIMAGE_INSTANCE_TYPE (image_instance)) |
1669 { | 1324 { |
1670 case IMAGE_MONO_PIXMAP: | 1325 case IMAGE_MONO_PIXMAP: |
1671 case IMAGE_COLOR_PIXMAP: | 1326 case IMAGE_COLOR_PIXMAP: |
1682 This is 0 for a bitmap, or a positive integer for a pixmap. | 1337 This is 0 for a bitmap, or a positive integer for a pixmap. |
1683 */ | 1338 */ |
1684 (image_instance)) | 1339 (image_instance)) |
1685 { | 1340 { |
1686 CHECK_IMAGE_INSTANCE (image_instance); | 1341 CHECK_IMAGE_INSTANCE (image_instance); |
1687 ERROR_CHECK_IMAGE_INSTANCE (image_instance); | |
1688 | 1342 |
1689 switch (XIMAGE_INSTANCE_TYPE (image_instance)) | 1343 switch (XIMAGE_INSTANCE_TYPE (image_instance)) |
1690 { | 1344 { |
1691 case IMAGE_MONO_PIXMAP: | 1345 case IMAGE_MONO_PIXMAP: |
1692 case IMAGE_COLOR_PIXMAP: | 1346 case IMAGE_COLOR_PIXMAP: |
1702 Return the height of the image instance, in pixels. | 1356 Return the height of the image instance, in pixels. |
1703 */ | 1357 */ |
1704 (image_instance)) | 1358 (image_instance)) |
1705 { | 1359 { |
1706 CHECK_IMAGE_INSTANCE (image_instance); | 1360 CHECK_IMAGE_INSTANCE (image_instance); |
1707 ERROR_CHECK_IMAGE_INSTANCE (image_instance); | |
1708 | 1361 |
1709 switch (XIMAGE_INSTANCE_TYPE (image_instance)) | 1362 switch (XIMAGE_INSTANCE_TYPE (image_instance)) |
1710 { | 1363 { |
1711 case IMAGE_MONO_PIXMAP: | 1364 case IMAGE_MONO_PIXMAP: |
1712 case IMAGE_COLOR_PIXMAP: | 1365 case IMAGE_COLOR_PIXMAP: |
1713 case IMAGE_POINTER: | 1366 case IMAGE_POINTER: |
1367 return make_int (XIMAGE_INSTANCE_PIXMAP_HEIGHT (image_instance)); | |
1368 | |
1714 case IMAGE_SUBWINDOW: | 1369 case IMAGE_SUBWINDOW: |
1715 case IMAGE_WIDGET: | 1370 case IMAGE_WIDGET: |
1716 return make_int (XIMAGE_INSTANCE_HEIGHT (image_instance)); | 1371 return make_int (XIMAGE_INSTANCE_SUBWINDOW_HEIGHT (image_instance)); |
1717 | 1372 |
1718 default: | 1373 default: |
1719 return Qnil; | 1374 return Qnil; |
1720 } | 1375 } |
1721 } | 1376 } |
1724 Return the width of the image instance, in pixels. | 1379 Return the width of the image instance, in pixels. |
1725 */ | 1380 */ |
1726 (image_instance)) | 1381 (image_instance)) |
1727 { | 1382 { |
1728 CHECK_IMAGE_INSTANCE (image_instance); | 1383 CHECK_IMAGE_INSTANCE (image_instance); |
1729 ERROR_CHECK_IMAGE_INSTANCE (image_instance); | |
1730 | 1384 |
1731 switch (XIMAGE_INSTANCE_TYPE (image_instance)) | 1385 switch (XIMAGE_INSTANCE_TYPE (image_instance)) |
1732 { | 1386 { |
1733 case IMAGE_MONO_PIXMAP: | 1387 case IMAGE_MONO_PIXMAP: |
1734 case IMAGE_COLOR_PIXMAP: | 1388 case IMAGE_COLOR_PIXMAP: |
1735 case IMAGE_POINTER: | 1389 case IMAGE_POINTER: |
1390 return make_int (XIMAGE_INSTANCE_PIXMAP_WIDTH (image_instance)); | |
1391 | |
1736 case IMAGE_SUBWINDOW: | 1392 case IMAGE_SUBWINDOW: |
1737 case IMAGE_WIDGET: | 1393 case IMAGE_WIDGET: |
1738 return make_int (XIMAGE_INSTANCE_WIDTH (image_instance)); | 1394 return make_int (XIMAGE_INSTANCE_SUBWINDOW_WIDTH (image_instance)); |
1739 | 1395 |
1740 default: | 1396 default: |
1741 return Qnil; | 1397 return Qnil; |
1742 } | 1398 } |
1743 } | 1399 } |
1751 This will always be nil for a non-pointer image instance. | 1407 This will always be nil for a non-pointer image instance. |
1752 */ | 1408 */ |
1753 (image_instance)) | 1409 (image_instance)) |
1754 { | 1410 { |
1755 CHECK_IMAGE_INSTANCE (image_instance); | 1411 CHECK_IMAGE_INSTANCE (image_instance); |
1756 ERROR_CHECK_IMAGE_INSTANCE (image_instance); | |
1757 | 1412 |
1758 switch (XIMAGE_INSTANCE_TYPE (image_instance)) | 1413 switch (XIMAGE_INSTANCE_TYPE (image_instance)) |
1759 { | 1414 { |
1760 case IMAGE_MONO_PIXMAP: | 1415 case IMAGE_MONO_PIXMAP: |
1761 case IMAGE_COLOR_PIXMAP: | 1416 case IMAGE_COLOR_PIXMAP: |
1776 This will always be nil for a non-pointer image instance. | 1431 This will always be nil for a non-pointer image instance. |
1777 */ | 1432 */ |
1778 (image_instance)) | 1433 (image_instance)) |
1779 { | 1434 { |
1780 CHECK_IMAGE_INSTANCE (image_instance); | 1435 CHECK_IMAGE_INSTANCE (image_instance); |
1781 ERROR_CHECK_IMAGE_INSTANCE (image_instance); | |
1782 | 1436 |
1783 switch (XIMAGE_INSTANCE_TYPE (image_instance)) | 1437 switch (XIMAGE_INSTANCE_TYPE (image_instance)) |
1784 { | 1438 { |
1785 case IMAGE_MONO_PIXMAP: | 1439 case IMAGE_MONO_PIXMAP: |
1786 case IMAGE_COLOR_PIXMAP: | 1440 case IMAGE_COLOR_PIXMAP: |
1798 colorized mono pixmaps and for pointers.) | 1452 colorized mono pixmaps and for pointers.) |
1799 */ | 1453 */ |
1800 (image_instance)) | 1454 (image_instance)) |
1801 { | 1455 { |
1802 CHECK_IMAGE_INSTANCE (image_instance); | 1456 CHECK_IMAGE_INSTANCE (image_instance); |
1803 ERROR_CHECK_IMAGE_INSTANCE (image_instance); | |
1804 | 1457 |
1805 switch (XIMAGE_INSTANCE_TYPE (image_instance)) | 1458 switch (XIMAGE_INSTANCE_TYPE (image_instance)) |
1806 { | 1459 { |
1807 case IMAGE_MONO_PIXMAP: | 1460 case IMAGE_MONO_PIXMAP: |
1808 case IMAGE_COLOR_PIXMAP: | 1461 case IMAGE_COLOR_PIXMAP: |
1810 return XIMAGE_INSTANCE_PIXMAP_FG (image_instance); | 1463 return XIMAGE_INSTANCE_PIXMAP_FG (image_instance); |
1811 | 1464 |
1812 case IMAGE_WIDGET: | 1465 case IMAGE_WIDGET: |
1813 return FACE_FOREGROUND ( | 1466 return FACE_FOREGROUND ( |
1814 XIMAGE_INSTANCE_WIDGET_FACE (image_instance), | 1467 XIMAGE_INSTANCE_WIDGET_FACE (image_instance), |
1815 XIMAGE_INSTANCE_FRAME | 1468 XIMAGE_INSTANCE_SUBWINDOW_FRAME |
1816 (image_instance)); | 1469 (image_instance)); |
1817 | 1470 |
1818 default: | 1471 default: |
1819 return Qnil; | 1472 return Qnil; |
1820 } | 1473 } |
1826 colorized mono pixmaps and for pointers.) | 1479 colorized mono pixmaps and for pointers.) |
1827 */ | 1480 */ |
1828 (image_instance)) | 1481 (image_instance)) |
1829 { | 1482 { |
1830 CHECK_IMAGE_INSTANCE (image_instance); | 1483 CHECK_IMAGE_INSTANCE (image_instance); |
1831 ERROR_CHECK_IMAGE_INSTANCE (image_instance); | |
1832 | 1484 |
1833 switch (XIMAGE_INSTANCE_TYPE (image_instance)) | 1485 switch (XIMAGE_INSTANCE_TYPE (image_instance)) |
1834 { | 1486 { |
1835 case IMAGE_MONO_PIXMAP: | 1487 case IMAGE_MONO_PIXMAP: |
1836 case IMAGE_COLOR_PIXMAP: | 1488 case IMAGE_COLOR_PIXMAP: |
1838 return XIMAGE_INSTANCE_PIXMAP_BG (image_instance); | 1490 return XIMAGE_INSTANCE_PIXMAP_BG (image_instance); |
1839 | 1491 |
1840 case IMAGE_WIDGET: | 1492 case IMAGE_WIDGET: |
1841 return FACE_BACKGROUND ( | 1493 return FACE_BACKGROUND ( |
1842 XIMAGE_INSTANCE_WIDGET_FACE (image_instance), | 1494 XIMAGE_INSTANCE_WIDGET_FACE (image_instance), |
1843 XIMAGE_INSTANCE_FRAME | 1495 XIMAGE_INSTANCE_SUBWINDOW_FRAME |
1844 (image_instance)); | 1496 (image_instance)); |
1845 | 1497 |
1846 default: | 1498 default: |
1847 return Qnil; | 1499 return Qnil; |
1848 } | 1500 } |
1860 { | 1512 { |
1861 Lisp_Object new; | 1513 Lisp_Object new; |
1862 Lisp_Object device; | 1514 Lisp_Object device; |
1863 | 1515 |
1864 CHECK_IMAGE_INSTANCE (image_instance); | 1516 CHECK_IMAGE_INSTANCE (image_instance); |
1865 ERROR_CHECK_IMAGE_INSTANCE (image_instance); | |
1866 CHECK_COLOR_INSTANCE (foreground); | 1517 CHECK_COLOR_INSTANCE (foreground); |
1867 CHECK_COLOR_INSTANCE (background); | 1518 CHECK_COLOR_INSTANCE (background); |
1868 | 1519 |
1869 device = image_instance_device (image_instance); | 1520 device = XIMAGE_INSTANCE_DEVICE (image_instance); |
1870 if (!HAS_DEVMETH_P (XDEVICE (device), colorize_image_instance)) | 1521 if (!HAS_DEVMETH_P (XDEVICE (device), colorize_image_instance)) |
1871 return image_instance; | 1522 return image_instance; |
1872 | 1523 |
1873 /* #### There should be a copy_image_instance(), which calls a | 1524 new = allocate_image_instance (device); |
1874 device-specific method to copy the window-system subobject. */ | |
1875 new = allocate_image_instance (XIMAGE_INSTANCE_DOMAIN (image_instance), | |
1876 Qnil); | |
1877 copy_lcrecord (XIMAGE_INSTANCE (new), XIMAGE_INSTANCE (image_instance)); | 1525 copy_lcrecord (XIMAGE_INSTANCE (new), XIMAGE_INSTANCE (image_instance)); |
1878 /* note that if this method returns non-zero, this method MUST | 1526 /* note that if this method returns non-zero, this method MUST |
1879 copy any window-system resources, so that when one image instance is | 1527 copy any window-system resources, so that when one image instance is |
1880 freed, the other one is not hosed. */ | 1528 freed, the other one is not hosed. */ |
1881 if (!DEVMETH (XDEVICE (device), colorize_image_instance, (new, foreground, | 1529 if (!DEVMETH (XDEVICE (device), colorize_image_instance, (new, foreground, |
1882 background))) | 1530 background))) |
1883 return image_instance; | 1531 return image_instance; |
1884 return new; | 1532 return new; |
1885 } | 1533 } |
1886 | 1534 |
1887 | |
1888 /************************************************************************/ | |
1889 /* Geometry calculations */ | |
1890 /************************************************************************/ | |
1891 | |
1892 /* Find out desired geometry of the image instance. If there is no | |
1893 special function then just return the width and / or height. */ | |
1894 void | |
1895 image_instance_query_geometry (Lisp_Object image_instance, | |
1896 int* width, int* height, | |
1897 enum image_instance_geometry disp, | |
1898 Lisp_Object domain) | |
1899 { | |
1900 Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance); | |
1901 Lisp_Object type; | |
1902 struct image_instantiator_methods* meths; | |
1903 ERROR_CHECK_IMAGE_INSTANCE (image_instance); | |
1904 | |
1905 type = encode_image_instance_type (IMAGE_INSTANCE_TYPE (ii)); | |
1906 meths = decode_device_ii_format (Qnil, type, ERROR_ME_NOT); | |
1907 | |
1908 if (meths && HAS_IIFORMAT_METH_P (meths, query_geometry)) | |
1909 { | |
1910 IIFORMAT_METH (meths, query_geometry, (image_instance, width, height, | |
1911 disp, domain)); | |
1912 } | |
1913 else | |
1914 { | |
1915 if (width) | |
1916 *width = IMAGE_INSTANCE_WIDTH (ii); | |
1917 if (height) | |
1918 *height = IMAGE_INSTANCE_HEIGHT (ii); | |
1919 } | |
1920 } | |
1921 | |
1922 /* Layout the image instance using the provided dimensions. Layout | |
1923 widgets are going to do different kinds of calculations to | |
1924 determine what size to give things so we could make the layout | |
1925 function relatively simple to take account of that. An alternative | |
1926 approach is to consider separately the two cases, one where you | |
1927 don't mind what size you have (normal widgets) and one where you | |
1928 want to specifiy something (layout widgets). */ | |
1929 void | |
1930 image_instance_layout (Lisp_Object image_instance, | |
1931 int width, int height, Lisp_Object domain) | |
1932 { | |
1933 Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance); | |
1934 Lisp_Object type; | |
1935 struct image_instantiator_methods* meths; | |
1936 | |
1937 ERROR_CHECK_IMAGE_INSTANCE (image_instance); | |
1938 | |
1939 /* Nothing is as nothing does. */ | |
1940 if (NOTHING_IMAGE_INSTANCEP (image_instance)) | |
1941 return; | |
1942 | |
1943 type = encode_image_instance_type (IMAGE_INSTANCE_TYPE (ii)); | |
1944 meths = decode_device_ii_format (Qnil, type, ERROR_ME_NOT); | |
1945 | |
1946 /* If geometry is unspecified then get some reasonable values for it. */ | |
1947 if (width == IMAGE_UNSPECIFIED_GEOMETRY | |
1948 || | |
1949 height == IMAGE_UNSPECIFIED_GEOMETRY) | |
1950 { | |
1951 int dwidth = IMAGE_UNSPECIFIED_GEOMETRY; | |
1952 int dheight = IMAGE_UNSPECIFIED_GEOMETRY; | |
1953 | |
1954 /* Get the desired geometry. */ | |
1955 if (meths && HAS_IIFORMAT_METH_P (meths, query_geometry)) | |
1956 { | |
1957 IIFORMAT_METH (meths, query_geometry, (image_instance, &dwidth, &dheight, | |
1958 IMAGE_DESIRED_GEOMETRY, | |
1959 domain)); | |
1960 } | |
1961 else | |
1962 { | |
1963 dwidth = IMAGE_INSTANCE_WIDTH (ii); | |
1964 dheight = IMAGE_INSTANCE_HEIGHT (ii); | |
1965 } | |
1966 | |
1967 /* Compare with allowed geometry. */ | |
1968 if (width == IMAGE_UNSPECIFIED_GEOMETRY) | |
1969 width = dwidth; | |
1970 if (height == IMAGE_UNSPECIFIED_GEOMETRY) | |
1971 height = dheight; | |
1972 } | |
1973 | |
1974 /* If we don't have sane values then we cannot layout at this point and | |
1975 must just return. */ | |
1976 if (width == IMAGE_UNSPECIFIED_GEOMETRY | |
1977 || | |
1978 height == IMAGE_UNSPECIFIED_GEOMETRY) | |
1979 return; | |
1980 | |
1981 /* At this point width and height should contain sane values. Thus | |
1982 we set the glyph geometry and lay it out. */ | |
1983 if (IMAGE_INSTANCE_WIDTH (ii) != width | |
1984 || | |
1985 IMAGE_INSTANCE_HEIGHT (ii) != height) | |
1986 { | |
1987 IMAGE_INSTANCE_SIZE_CHANGED (ii) = 1; | |
1988 } | |
1989 | |
1990 IMAGE_INSTANCE_WIDTH (ii) = width; | |
1991 IMAGE_INSTANCE_HEIGHT (ii) = height; | |
1992 | |
1993 if (IIFORMAT_METH_OR_GIVEN (meths, layout, | |
1994 (image_instance, width, height, domain), 1)) | |
1995 /* Do not clear the dirty flag here - redisplay will do this for | |
1996 us at the end. */ | |
1997 IMAGE_INSTANCE_LAYOUT_CHANGED (ii) = 0; | |
1998 } | |
1999 | |
2000 /* | |
2001 * Mark image instance in W as dirty if (a) W's faces have changed and | |
2002 * (b) GLYPH_OR_II instance in W is a string. | |
2003 * | |
2004 * Return non-zero if instance has been marked dirty. | |
2005 */ | |
2006 int | |
2007 invalidate_glyph_geometry_maybe (Lisp_Object glyph_or_ii, struct window* w) | |
2008 { | |
2009 if (XFRAME(WINDOW_FRAME(w))->faces_changed) | |
2010 { | |
2011 Lisp_Object image = glyph_or_ii; | |
2012 | |
2013 if (GLYPHP (glyph_or_ii)) | |
2014 { | |
2015 Lisp_Object window; | |
2016 XSETWINDOW (window, w); | |
2017 image = glyph_image_instance (glyph_or_ii, window, ERROR_ME_NOT, 1); | |
2018 } | |
2019 | |
2020 if (TEXT_IMAGE_INSTANCEP (image)) | |
2021 { | |
2022 Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image); | |
2023 IMAGE_INSTANCE_DIRTYP (ii) = 1; | |
2024 IMAGE_INSTANCE_LAYOUT_CHANGED (ii) = 1; | |
2025 if (GLYPHP (glyph_or_ii)) | |
2026 XGLYPH_DIRTYP (glyph_or_ii) = 1; | |
2027 return 1; | |
2028 } | |
2029 } | |
2030 | |
2031 return 0; | |
2032 } | |
2033 | |
2034 | 1535 |
2035 /************************************************************************/ | 1536 /************************************************************************/ |
2036 /* error helpers */ | 1537 /* error helpers */ |
2037 /************************************************************************/ | 1538 /************************************************************************/ |
2038 DOESNT_RETURN | 1539 DOESNT_RETURN |
2039 signal_image_error (const char *reason, Lisp_Object frob) | 1540 signal_image_error (CONST char *reason, Lisp_Object frob) |
2040 { | 1541 { |
2041 signal_error (Qimage_conversion_error, | 1542 signal_error (Qimage_conversion_error, |
2042 list2 (build_translated_string (reason), frob)); | 1543 list2 (build_translated_string (reason), frob)); |
2043 } | 1544 } |
2044 | 1545 |
2045 DOESNT_RETURN | 1546 DOESNT_RETURN |
2046 signal_image_error_2 (const char *reason, Lisp_Object frob0, Lisp_Object frob1) | 1547 signal_image_error_2 (CONST char *reason, Lisp_Object frob0, Lisp_Object frob1) |
2047 { | 1548 { |
2048 signal_error (Qimage_conversion_error, | 1549 signal_error (Qimage_conversion_error, |
2049 list3 (build_translated_string (reason), frob0, frob1)); | 1550 list3 (build_translated_string (reason), frob0, frob1)); |
2050 } | 1551 } |
2051 | 1552 |
2062 static void | 1563 static void |
2063 nothing_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, | 1564 nothing_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, |
2064 Lisp_Object pointer_fg, Lisp_Object pointer_bg, | 1565 Lisp_Object pointer_fg, Lisp_Object pointer_bg, |
2065 int dest_mask, Lisp_Object domain) | 1566 int dest_mask, Lisp_Object domain) |
2066 { | 1567 { |
2067 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); | 1568 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); |
2068 | 1569 |
2069 if (dest_mask & IMAGE_NOTHING_MASK) | 1570 if (dest_mask & IMAGE_NOTHING_MASK) |
2070 { | 1571 IMAGE_INSTANCE_TYPE (ii) = IMAGE_NOTHING; |
2071 IMAGE_INSTANCE_TYPE (ii) = IMAGE_NOTHING; | |
2072 IMAGE_INSTANCE_HEIGHT (ii) = 0; | |
2073 IMAGE_INSTANCE_WIDTH (ii) = 0; | |
2074 } | |
2075 else | 1572 else |
2076 incompatible_image_types (instantiator, dest_mask, IMAGE_NOTHING_MASK); | 1573 incompatible_image_types (instantiator, dest_mask, IMAGE_NOTHING_MASK); |
2077 } | 1574 } |
2078 | 1575 |
2079 | 1576 |
2129 string_possible_dest_types (void) | 1626 string_possible_dest_types (void) |
2130 { | 1627 { |
2131 return IMAGE_TEXT_MASK; | 1628 return IMAGE_TEXT_MASK; |
2132 } | 1629 } |
2133 | 1630 |
2134 /* Called from autodetect_instantiate() */ | 1631 /* called from autodetect_instantiate() */ |
2135 void | 1632 void |
2136 string_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, | 1633 string_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, |
2137 Lisp_Object pointer_fg, Lisp_Object pointer_bg, | 1634 Lisp_Object pointer_fg, Lisp_Object pointer_bg, |
2138 int dest_mask, Lisp_Object domain) | 1635 int dest_mask, Lisp_Object domain) |
2139 { | 1636 { |
2140 Lisp_Object string = find_keyword_in_vector (instantiator, Q_data); | 1637 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data); |
2141 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); | 1638 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); |
2142 | 1639 |
2143 /* Should never get here with a domain other than a window. */ | 1640 assert (!NILP (data)); |
2144 assert (!NILP (string) && WINDOWP (DOMAIN_WINDOW (domain))); | |
2145 if (dest_mask & IMAGE_TEXT_MASK) | 1641 if (dest_mask & IMAGE_TEXT_MASK) |
2146 { | 1642 { |
2147 IMAGE_INSTANCE_TYPE (ii) = IMAGE_TEXT; | 1643 IMAGE_INSTANCE_TYPE (ii) = IMAGE_TEXT; |
2148 IMAGE_INSTANCE_TEXT_STRING (ii) = string; | 1644 IMAGE_INSTANCE_TEXT_STRING (ii) = data; |
2149 } | 1645 } |
2150 else | 1646 else |
2151 incompatible_image_types (instantiator, dest_mask, IMAGE_TEXT_MASK); | 1647 incompatible_image_types (instantiator, dest_mask, IMAGE_TEXT_MASK); |
2152 } | |
2153 | |
2154 /* Sort out the size of the text that is being displayed. Calculating | |
2155 it dynamically allows us to change the text and still see | |
2156 everything. Note that the following methods are for text not string | |
2157 since that is what the instantiated type is. The first method is a | |
2158 helper that is used elsewhere for calculating text geometry. */ | |
2159 void | |
2160 query_string_geometry (Lisp_Object string, Lisp_Object face, | |
2161 int* width, int* height, int* descent, Lisp_Object domain) | |
2162 { | |
2163 struct font_metric_info fm; | |
2164 unsigned char charsets[NUM_LEADING_BYTES]; | |
2165 struct face_cachel frame_cachel; | |
2166 struct face_cachel *cachel; | |
2167 Lisp_Object frame = DOMAIN_FRAME (domain); | |
2168 | |
2169 /* Compute height */ | |
2170 if (height) | |
2171 { | |
2172 /* Compute string metric info */ | |
2173 find_charsets_in_bufbyte_string (charsets, | |
2174 XSTRING_DATA (string), | |
2175 XSTRING_LENGTH (string)); | |
2176 | |
2177 /* Fallback to the default face if none was provided. */ | |
2178 if (!NILP (face)) | |
2179 { | |
2180 reset_face_cachel (&frame_cachel); | |
2181 update_face_cachel_data (&frame_cachel, frame, face); | |
2182 cachel = &frame_cachel; | |
2183 } | |
2184 else | |
2185 { | |
2186 cachel = WINDOW_FACE_CACHEL (DOMAIN_XWINDOW (domain), | |
2187 DEFAULT_INDEX); | |
2188 } | |
2189 | |
2190 ensure_face_cachel_complete (cachel, domain, charsets); | |
2191 face_cachel_charset_font_metric_info (cachel, charsets, &fm); | |
2192 | |
2193 *height = fm.ascent + fm.descent; | |
2194 /* #### descent only gets set if we query the height as well. */ | |
2195 if (descent) | |
2196 *descent = fm.descent; | |
2197 } | |
2198 | |
2199 /* Compute width */ | |
2200 if (width) | |
2201 { | |
2202 if (!NILP (face)) | |
2203 *width = redisplay_frame_text_width_string (XFRAME (frame), | |
2204 face, | |
2205 0, string, 0, -1); | |
2206 else | |
2207 *width = redisplay_frame_text_width_string (XFRAME (frame), | |
2208 Vdefault_face, | |
2209 0, string, 0, -1); | |
2210 } | |
2211 } | |
2212 | |
2213 Lisp_Object | |
2214 query_string_font (Lisp_Object string, Lisp_Object face, Lisp_Object domain) | |
2215 { | |
2216 unsigned char charsets[NUM_LEADING_BYTES]; | |
2217 struct face_cachel frame_cachel; | |
2218 struct face_cachel *cachel; | |
2219 int i; | |
2220 Lisp_Object frame = DOMAIN_FRAME (domain); | |
2221 | |
2222 /* Compute string font info */ | |
2223 find_charsets_in_bufbyte_string (charsets, | |
2224 XSTRING_DATA (string), | |
2225 XSTRING_LENGTH (string)); | |
2226 | |
2227 reset_face_cachel (&frame_cachel); | |
2228 update_face_cachel_data (&frame_cachel, frame, face); | |
2229 cachel = &frame_cachel; | |
2230 | |
2231 ensure_face_cachel_complete (cachel, domain, charsets); | |
2232 | |
2233 for (i = 0; i < NUM_LEADING_BYTES; i++) | |
2234 { | |
2235 if (charsets[i]) | |
2236 { | |
2237 return FACE_CACHEL_FONT (cachel, | |
2238 CHARSET_BY_LEADING_BYTE (i + | |
2239 MIN_LEADING_BYTE)); | |
2240 | |
2241 } | |
2242 } | |
2243 | |
2244 return Qnil; /* NOT REACHED */ | |
2245 } | |
2246 | |
2247 static void | |
2248 text_query_geometry (Lisp_Object image_instance, | |
2249 int* width, int* height, | |
2250 enum image_instance_geometry disp, Lisp_Object domain) | |
2251 { | |
2252 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); | |
2253 int descent = 0; | |
2254 | |
2255 query_string_geometry (IMAGE_INSTANCE_TEXT_STRING (ii), | |
2256 IMAGE_INSTANCE_FACE (ii), | |
2257 width, height, &descent, domain); | |
2258 | |
2259 /* The descent gets set as a side effect of querying the | |
2260 geometry. */ | |
2261 IMAGE_INSTANCE_TEXT_DESCENT (ii) = descent; | |
2262 } | |
2263 | |
2264 /* set the properties of a string */ | |
2265 static Lisp_Object | |
2266 text_set_property (Lisp_Object image_instance, Lisp_Object prop, | |
2267 Lisp_Object val) | |
2268 { | |
2269 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); | |
2270 | |
2271 if (EQ (prop, Q_data)) | |
2272 { | |
2273 CHECK_STRING (val); | |
2274 IMAGE_INSTANCE_TEXT_STRING (ii) = val; | |
2275 | |
2276 return Qt; | |
2277 } | |
2278 return Qunbound; | |
2279 } | 1648 } |
2280 | 1649 |
2281 | 1650 |
2282 /**************************************************************************** | 1651 /**************************************************************************** |
2283 * formatted-string * | 1652 * formatted-string * |
2299 formatted_string_instantiate (Lisp_Object image_instance, | 1668 formatted_string_instantiate (Lisp_Object image_instance, |
2300 Lisp_Object instantiator, | 1669 Lisp_Object instantiator, |
2301 Lisp_Object pointer_fg, Lisp_Object pointer_bg, | 1670 Lisp_Object pointer_fg, Lisp_Object pointer_bg, |
2302 int dest_mask, Lisp_Object domain) | 1671 int dest_mask, Lisp_Object domain) |
2303 { | 1672 { |
1673 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data); | |
1674 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); | |
1675 | |
1676 assert (!NILP (data)); | |
2304 /* #### implement this */ | 1677 /* #### implement this */ |
2305 warn_when_safe (Qunimplemented, Qnotice, | 1678 warn_when_safe (Qunimplemented, Qnotice, |
2306 "`formatted-string' not yet implemented; assuming `string'"); | 1679 "`formatted-string' not yet implemented; assuming `string'"); |
2307 | 1680 if (dest_mask & IMAGE_TEXT_MASK) |
2308 string_instantiate (image_instance, instantiator, | 1681 { |
2309 pointer_fg, pointer_bg, dest_mask, domain); | 1682 IMAGE_INSTANCE_TYPE (ii) = IMAGE_TEXT; |
1683 IMAGE_INSTANCE_TEXT_STRING (ii) = data; | |
1684 } | |
1685 else | |
1686 incompatible_image_types (instantiator, dest_mask, IMAGE_TEXT_MASK); | |
2310 } | 1687 } |
2311 | 1688 |
2312 | 1689 |
2313 /************************************************************************/ | 1690 /************************************************************************/ |
2314 /* pixmap file functions */ | 1691 /* pixmap file functions */ |
2468 int ok_if_data_invalid) | 1845 int ok_if_data_invalid) |
2469 { | 1846 { |
2470 unsigned int w, h; | 1847 unsigned int w, h; |
2471 Extbyte *data; | 1848 Extbyte *data; |
2472 int result; | 1849 int result; |
2473 const char *filename_ext; | 1850 CONST char *filename_ext; |
2474 | 1851 |
2475 TO_EXTERNAL_FORMAT (LISP_STRING, name, | 1852 GET_C_STRING_FILENAME_DATA_ALLOCA (name, filename_ext); |
2476 C_STRING_ALLOCA, filename_ext, | |
2477 Qfile_name); | |
2478 result = read_bitmap_data_from_file (filename_ext, &w, &h, | 1853 result = read_bitmap_data_from_file (filename_ext, &w, &h, |
2479 &data, xhot, yhot); | 1854 &data, xhot, yhot); |
2480 | 1855 |
2481 if (result == BitmapSuccess) | 1856 if (result == BitmapSuccess) |
2482 { | 1857 { |
2483 Lisp_Object retval; | 1858 Lisp_Object retval; |
2484 int len = (w + 7) / 8 * h; | 1859 int len = (w + 7) / 8 * h; |
2485 | 1860 |
2486 retval = list3 (make_int (w), make_int (h), | 1861 retval = list3 (make_int (w), make_int (h), |
2487 make_ext_string (data, len, Qbinary)); | 1862 make_ext_string (data, len, FORMAT_BINARY)); |
2488 XFree ((char *) data); | 1863 XFree ((char *) data); |
2489 return retval; | 1864 return retval; |
2490 } | 1865 } |
2491 | 1866 |
2492 switch (result) | 1867 switch (result) |
2715 pixmap_to_lisp_data (Lisp_Object name, int ok_if_data_invalid) | 2090 pixmap_to_lisp_data (Lisp_Object name, int ok_if_data_invalid) |
2716 { | 2091 { |
2717 char **data; | 2092 char **data; |
2718 int result; | 2093 int result; |
2719 char *fname = 0; | 2094 char *fname = 0; |
2720 | 2095 |
2721 TO_EXTERNAL_FORMAT (LISP_STRING, name, | 2096 GET_C_STRING_FILENAME_DATA_ALLOCA (name, fname); |
2722 C_STRING_ALLOCA, fname, | |
2723 Qfile_name); | |
2724 result = XpmReadFileToData (fname, &data); | 2097 result = XpmReadFileToData (fname, &data); |
2725 | 2098 |
2726 if (result == XpmSuccess) | 2099 if (result == XpmSuccess) |
2727 { | 2100 { |
2728 Lisp_Object retval = Qnil; | 2101 Lisp_Object retval = Qnil; |
2928 DEFINE_SPECIFIER_TYPE (image); | 2301 DEFINE_SPECIFIER_TYPE (image); |
2929 | 2302 |
2930 static void | 2303 static void |
2931 image_create (Lisp_Object obj) | 2304 image_create (Lisp_Object obj) |
2932 { | 2305 { |
2933 Lisp_Specifier *image = XIMAGE_SPECIFIER (obj); | 2306 struct Lisp_Specifier *image = XIMAGE_SPECIFIER (obj); |
2934 | 2307 |
2935 IMAGE_SPECIFIER_ALLOWED (image) = ~0; /* all are allowed */ | 2308 IMAGE_SPECIFIER_ALLOWED (image) = ~0; /* all are allowed */ |
2936 IMAGE_SPECIFIER_ATTACHEE (image) = Qnil; | 2309 IMAGE_SPECIFIER_ATTACHEE (image) = Qnil; |
2937 IMAGE_SPECIFIER_ATTACHEE_PROPERTY (image) = Qnil; | 2310 IMAGE_SPECIFIER_ATTACHEE_PROPERTY (image) = Qnil; |
2938 } | 2311 } |
2939 | 2312 |
2940 static void | 2313 static void |
2941 image_mark (Lisp_Object obj) | 2314 image_mark (Lisp_Object obj, void (*markobj) (Lisp_Object)) |
2942 { | 2315 { |
2943 Lisp_Specifier *image = XIMAGE_SPECIFIER (obj); | 2316 struct Lisp_Specifier *image = XIMAGE_SPECIFIER (obj); |
2944 | 2317 |
2945 mark_object (IMAGE_SPECIFIER_ATTACHEE (image)); | 2318 markobj (IMAGE_SPECIFIER_ATTACHEE (image)); |
2946 mark_object (IMAGE_SPECIFIER_ATTACHEE_PROPERTY (image)); | 2319 markobj (IMAGE_SPECIFIER_ATTACHEE_PROPERTY (image)); |
2947 } | 2320 } |
2948 | 2321 |
2949 static Lisp_Object | 2322 static Lisp_Object |
2950 image_instantiate_cache_result (Lisp_Object locative) | 2323 image_instantiate_cache_result (Lisp_Object locative) |
2951 { | 2324 { |
2952 /* locative = (instance instantiator . subtable) | 2325 /* locative = (instance instantiator . subtable) */ |
2953 | |
2954 So we are using the instantiator as the key and the instance as | |
2955 the value. Since the hashtable is key-weak this means that the | |
2956 image instance will stay around as long as the instantiator stays | |
2957 around. The instantiator is stored in the `image' slot of the | |
2958 glyph, so as long as the glyph is marked the instantiator will be | |
2959 as well and hence the cached image instance also.*/ | |
2960 Fputhash (XCAR (XCDR (locative)), XCAR (locative), XCDR (XCDR (locative))); | 2326 Fputhash (XCAR (XCDR (locative)), XCAR (locative), XCDR (XCDR (locative))); |
2961 free_cons (XCONS (XCDR (locative))); | 2327 free_cons (XCONS (XCDR (locative))); |
2962 free_cons (XCONS (locative)); | 2328 free_cons (XCONS (locative)); |
2963 return Qnil; | 2329 return Qnil; |
2964 } | 2330 } |
2970 static Lisp_Object | 2336 static Lisp_Object |
2971 image_instantiate (Lisp_Object specifier, Lisp_Object matchspec, | 2337 image_instantiate (Lisp_Object specifier, Lisp_Object matchspec, |
2972 Lisp_Object domain, Lisp_Object instantiator, | 2338 Lisp_Object domain, Lisp_Object instantiator, |
2973 Lisp_Object depth) | 2339 Lisp_Object depth) |
2974 { | 2340 { |
2975 Lisp_Object glyph = IMAGE_SPECIFIER_ATTACHEE (XIMAGE_SPECIFIER (specifier)); | 2341 Lisp_Object device = DFW_DEVICE (domain); |
2342 struct device *d = XDEVICE (device); | |
2976 int dest_mask = XIMAGE_SPECIFIER_ALLOWED (specifier); | 2343 int dest_mask = XIMAGE_SPECIFIER_ALLOWED (specifier); |
2977 int pointerp = dest_mask & image_instance_type_to_mask (IMAGE_POINTER); | 2344 int pointerp = dest_mask & image_instance_type_to_mask (IMAGE_POINTER); |
2978 | 2345 |
2979 if (IMAGE_INSTANCEP (instantiator)) | 2346 if (IMAGE_INSTANCEP (instantiator)) |
2980 { | 2347 { |
2981 /* make sure that the image instance's governing domain and type are | 2348 /* make sure that the image instance's device and type are |
2982 matching. */ | 2349 matching. */ |
2983 Lisp_Object governing_domain = XIMAGE_INSTANCE_DOMAIN (instantiator); | 2350 |
2984 | 2351 if (EQ (device, XIMAGE_INSTANCE_DEVICE (instantiator))) |
2985 if ((DEVICEP (governing_domain) | |
2986 && EQ (governing_domain, DOMAIN_DEVICE (domain))) | |
2987 || (FRAMEP (governing_domain) | |
2988 && EQ (governing_domain, DOMAIN_FRAME (domain))) | |
2989 || (WINDOWP (governing_domain) | |
2990 && EQ (governing_domain, DOMAIN_WINDOW (domain)))) | |
2991 { | 2352 { |
2992 int mask = | 2353 int mask = |
2993 image_instance_type_to_mask (XIMAGE_INSTANCE_TYPE (instantiator)); | 2354 image_instance_type_to_mask (XIMAGE_INSTANCE_TYPE (instantiator)); |
2994 if (mask & dest_mask) | 2355 if (mask & dest_mask) |
2995 return instantiator; | 2356 return instantiator; |
2996 else | 2357 else |
2997 signal_simple_error ("Type of image instance not allowed here", | 2358 signal_simple_error ("Type of image instance not allowed here", |
2998 instantiator); | 2359 instantiator); |
2999 } | 2360 } |
3000 else | 2361 else |
3001 signal_simple_error_2 ("Wrong domain for image instance", | 2362 signal_simple_error_2 ("Wrong device for image instance", |
3002 instantiator, domain); | 2363 instantiator, device); |
3003 } | 2364 } |
3004 else if (VECTORP (instantiator) | 2365 else if (VECTORP (instantiator) |
3005 && EQ (XVECTOR_DATA (instantiator)[0], Qinherit)) | 2366 && EQ (XVECTOR_DATA (instantiator)[0], Qinherit)) |
3006 { | 2367 { |
3007 assert (XVECTOR_LENGTH (instantiator) == 3); | 2368 assert (XVECTOR_LENGTH (instantiator) == 3); |
3009 (Fget_face (XVECTOR_DATA (instantiator)[2]), | 2370 (Fget_face (XVECTOR_DATA (instantiator)[2]), |
3010 Qbackground_pixmap, domain, 0, depth)); | 2371 Qbackground_pixmap, domain, 0, depth)); |
3011 } | 2372 } |
3012 else | 2373 else |
3013 { | 2374 { |
3014 Lisp_Object instance = Qnil; | 2375 Lisp_Object instance; |
3015 Lisp_Object subtable = Qnil; | 2376 Lisp_Object subtable; |
3016 Lisp_Object ls3 = Qnil; | 2377 Lisp_Object ls3 = Qnil; |
3017 Lisp_Object pointer_fg = Qnil; | 2378 Lisp_Object pointer_fg = Qnil; |
3018 Lisp_Object pointer_bg = Qnil; | 2379 Lisp_Object pointer_bg = Qnil; |
3019 Lisp_Object governing_domain = | |
3020 get_image_instantiator_governing_domain (instantiator, domain); | |
3021 struct gcpro gcpro1; | |
3022 | |
3023 GCPRO1 (instance); | |
3024 | |
3025 /* We have to put subwindow, widget and text image instances in | |
3026 a per-window cache so that we can see the same glyph in | |
3027 different windows. We use governing_domain to determine the type | |
3028 of image_instance that will be created. */ | |
3029 | 2380 |
3030 if (pointerp) | 2381 if (pointerp) |
3031 { | 2382 { |
3032 pointer_fg = FACE_FOREGROUND (Vpointer_face, domain); | 2383 pointer_fg = FACE_FOREGROUND (Vpointer_face, domain); |
3033 pointer_bg = FACE_BACKGROUND (Vpointer_face, domain); | 2384 pointer_bg = FACE_BACKGROUND (Vpointer_face, domain); |
3034 ls3 = list3 (instantiator, pointer_fg, pointer_bg); | 2385 ls3 = list3 (instantiator, pointer_fg, pointer_bg); |
3035 } | 2386 } |
3036 | 2387 |
3037 /* First look in the device cache. */ | 2388 /* First look in the hash table. */ |
3038 if (DEVICEP (governing_domain)) | 2389 subtable = Fgethash (make_int (dest_mask), d->image_instance_cache, |
2390 Qunbound); | |
2391 if (UNBOUNDP (subtable)) | |
3039 { | 2392 { |
3040 subtable = Fgethash (make_int (dest_mask), | 2393 /* For the image instance cache, we do comparisons with EQ rather |
3041 XDEVICE (governing_domain)-> | 2394 than with EQUAL, as we do for color and font names. |
3042 image_instance_cache, | 2395 The reasons are: |
3043 Qunbound); | 2396 |
3044 if (UNBOUNDP (subtable)) | 2397 1) pixmap data can be very long, and thus the hashing and |
2398 comparing will take awhile. | |
2399 2) It's not so likely that we'll run into things that are EQUAL | |
2400 but not EQ (that can happen a lot with faces, because their | |
2401 specifiers are copied around); but pixmaps tend not to be | |
2402 in faces. | |
2403 | |
2404 However, if the image-instance could be a pointer, we have to | |
2405 use EQUAL because we massaged the instantiator into a cons3 | |
2406 also containing the foreground and background of the | |
2407 pointer face. | |
2408 */ | |
2409 | |
2410 subtable = make_lisp_hash_table (20, | |
2411 pointerp ? HASH_TABLE_KEY_CAR_WEAK | |
2412 : HASH_TABLE_KEY_WEAK, | |
2413 pointerp ? HASH_TABLE_EQUAL | |
2414 : HASH_TABLE_EQ); | |
2415 Fputhash (make_int (dest_mask), subtable, | |
2416 d->image_instance_cache); | |
2417 instance = Qunbound; | |
2418 } | |
2419 else | |
2420 { | |
2421 instance = Fgethash (pointerp ? ls3 : instantiator, | |
2422 subtable, Qunbound); | |
2423 /* subwindows have a per-window cache and have to be treated | |
2424 differently. dest_mask can be a bitwise OR of all image | |
2425 types so we will only catch someone possibly trying to | |
2426 instantiate a subwindow type thing. Unfortunately, this | |
2427 will occur most of the time so this probably slows things | |
2428 down. But with the current design I don't see anyway | |
2429 round it. */ | |
2430 if (UNBOUNDP (instance) | |
2431 && | |
2432 dest_mask & (IMAGE_SUBWINDOW_MASK | IMAGE_WIDGET_MASK)) | |
3045 { | 2433 { |
3046 /* For the image instance cache, we do comparisons with | 2434 if (!WINDOWP (domain)) |
3047 EQ rather than with EQUAL, as we do for color and | 2435 signal_simple_error ("Can't instantiate subwindow outside a window", |
3048 font names. The reasons are: | 2436 instantiator); |
3049 | 2437 instance = Fgethash (instantiator, |
3050 1) pixmap data can be very long, and thus the hashing | 2438 XWINDOW (domain)->subwindow_instance_cache, |
3051 and comparing will take awhile. | 2439 Qunbound); |
3052 | |
3053 2) It's not so likely that we'll run into things that | |
3054 are EQUAL but not EQ (that can happen a lot with | |
3055 faces, because their specifiers are copied around); | |
3056 but pixmaps tend not to be in faces. | |
3057 | |
3058 However, if the image-instance could be a pointer, we | |
3059 have to use EQUAL because we massaged the | |
3060 instantiator into a cons3 also containing the | |
3061 foreground and background of the pointer face. */ | |
3062 | |
3063 subtable = make_lisp_hash_table | |
3064 (20, pointerp ? HASH_TABLE_KEY_CAR_WEAK | |
3065 : HASH_TABLE_KEY_WEAK, | |
3066 pointerp ? HASH_TABLE_EQUAL | |
3067 : HASH_TABLE_EQ); | |
3068 Fputhash (make_int (dest_mask), subtable, | |
3069 XDEVICE (governing_domain)->image_instance_cache); | |
3070 instance = Qunbound; | |
3071 } | |
3072 else | |
3073 { | |
3074 instance = Fgethash (pointerp ? ls3 : instantiator, | |
3075 subtable, Qunbound); | |
3076 } | 2440 } |
3077 } | 2441 } |
3078 else if (WINDOWP (governing_domain)) | 2442 |
3079 { | |
3080 /* Subwindows have a per-window cache and have to be treated | |
3081 differently. */ | |
3082 instance = | |
3083 Fgethash (instantiator, | |
3084 XWINDOW (governing_domain)->subwindow_instance_cache, | |
3085 Qunbound); | |
3086 } | |
3087 else | |
3088 abort (); /* We're not allowed anything else currently. */ | |
3089 | |
3090 /* If we don't have an instance at this point then create | |
3091 one. */ | |
3092 if (UNBOUNDP (instance)) | 2443 if (UNBOUNDP (instance)) |
3093 { | 2444 { |
3094 Lisp_Object locative = | 2445 Lisp_Object locative = |
3095 noseeum_cons (Qnil, | 2446 noseeum_cons (Qnil, |
3096 noseeum_cons (pointerp ? ls3 : instantiator, | 2447 noseeum_cons (pointerp ? ls3 : instantiator, |
3097 DEVICEP (governing_domain) ? subtable | 2448 subtable)); |
3098 : XWINDOW (governing_domain) | |
3099 ->subwindow_instance_cache)); | |
3100 int speccount = specpdl_depth (); | 2449 int speccount = specpdl_depth (); |
3101 | 2450 |
3102 /* Make sure we cache the failures, too. Use an | 2451 /* make sure we cache the failures, too. |
3103 unwind-protect to catch such errors. If we fail, the | 2452 Use an unwind-protect to catch such errors. |
3104 unwind-protect records nil in the hash table. If we | 2453 If we fail, the unwind-protect records nil in |
3105 succeed, we change the car of the locative to the | 2454 the hash table. If we succeed, we change the |
3106 resulting instance, which gets recorded instead. */ | 2455 car of the locative to the resulting instance, |
2456 which gets recorded instead. */ | |
3107 record_unwind_protect (image_instantiate_cache_result, | 2457 record_unwind_protect (image_instantiate_cache_result, |
3108 locative); | 2458 locative); |
3109 instance = | 2459 instance = instantiate_image_instantiator (device, |
3110 instantiate_image_instantiator (governing_domain, | 2460 domain, |
3111 domain, instantiator, | 2461 instantiator, |
3112 pointer_fg, pointer_bg, | 2462 pointer_fg, pointer_bg, |
3113 dest_mask, glyph); | 2463 dest_mask); |
3114 | 2464 |
3115 /* We need a per-frame cache for redisplay. */ | |
3116 cache_subwindow_instance_in_frame_maybe (instance); | |
3117 | |
3118 Fsetcar (locative, instance); | 2465 Fsetcar (locative, instance); |
3119 #ifdef ERROR_CHECK_GLYPHS | 2466 /* only after the image has been instantiated do we know |
2467 whether we need to put it in the per-window image instance | |
2468 cache. */ | |
3120 if (image_instance_type_to_mask (XIMAGE_INSTANCE_TYPE (instance)) | 2469 if (image_instance_type_to_mask (XIMAGE_INSTANCE_TYPE (instance)) |
3121 & (IMAGE_SUBWINDOW_MASK | IMAGE_WIDGET_MASK)) | 2470 & |
3122 assert (EQ (XIMAGE_INSTANCE_FRAME (instance), | 2471 (IMAGE_SUBWINDOW_MASK | IMAGE_WIDGET_MASK)) |
3123 DOMAIN_FRAME (domain))); | 2472 { |
3124 #endif | 2473 if (!WINDOWP (domain)) |
2474 signal_simple_error ("Can't instantiate subwindow outside a window", | |
2475 instantiator); | |
2476 | |
2477 Fsetcdr (XCDR (locative), XWINDOW (domain)->subwindow_instance_cache ); | |
2478 } | |
3125 unbind_to (speccount, Qnil); | 2479 unbind_to (speccount, Qnil); |
3126 #ifdef ERROR_CHECK_GLYPHS | |
3127 if (image_instance_type_to_mask (XIMAGE_INSTANCE_TYPE (instance)) | |
3128 & (IMAGE_SUBWINDOW_MASK | IMAGE_WIDGET_MASK)) | |
3129 assert (EQ (Fgethash ((pointerp ? ls3 : instantiator), | |
3130 XWINDOW (governing_domain) | |
3131 ->subwindow_instance_cache, | |
3132 Qunbound), instance)); | |
3133 #endif | |
3134 } | 2480 } |
3135 else | 2481 else |
3136 free_list (ls3); | 2482 free_list (ls3); |
3137 | 2483 |
3138 if (NILP (instance)) | 2484 if (NILP (instance)) |
3139 signal_simple_error ("Can't instantiate image (probably cached)", | 2485 signal_simple_error ("Can't instantiate image (probably cached)", |
3140 instantiator); | 2486 instantiator); |
3141 #ifdef ERROR_CHECK_GLYPHS | 2487 return instance; |
3142 if (image_instance_type_to_mask (XIMAGE_INSTANCE_TYPE (instance)) | |
3143 & (IMAGE_SUBWINDOW_MASK | IMAGE_WIDGET_MASK)) | |
3144 assert (EQ (XIMAGE_INSTANCE_FRAME (instance), | |
3145 DOMAIN_FRAME (domain))); | |
3146 #endif | |
3147 ERROR_CHECK_IMAGE_INSTANCE (instance); | |
3148 RETURN_UNGCPRO (instance); | |
3149 } | 2488 } |
3150 | 2489 |
3151 abort (); | 2490 abort (); |
3152 return Qnil; /* not reached */ | 2491 return Qnil; /* not reached */ |
3153 } | 2492 } |
3230 | 2569 |
3231 void | 2570 void |
3232 set_image_attached_to (Lisp_Object obj, Lisp_Object face_or_glyph, | 2571 set_image_attached_to (Lisp_Object obj, Lisp_Object face_or_glyph, |
3233 Lisp_Object property) | 2572 Lisp_Object property) |
3234 { | 2573 { |
3235 Lisp_Specifier *image = XIMAGE_SPECIFIER (obj); | 2574 struct Lisp_Specifier *image = XIMAGE_SPECIFIER (obj); |
3236 | 2575 |
3237 IMAGE_SPECIFIER_ATTACHEE (image) = face_or_glyph; | 2576 IMAGE_SPECIFIER_ATTACHEE (image) = face_or_glyph; |
3238 IMAGE_SPECIFIER_ATTACHEE_PROPERTY (image) = property; | 2577 IMAGE_SPECIFIER_ATTACHEE_PROPERTY (image) = property; |
3239 } | 2578 } |
3240 | 2579 |
3285 UNGCPRO; | 2624 UNGCPRO; |
3286 | 2625 |
3287 return retlist; | 2626 return retlist; |
3288 } | 2627 } |
3289 | 2628 |
3290 /* Copy an image instantiator. We can't use Fcopy_tree since widgets | |
3291 may contain circular references which would send Fcopy_tree into | |
3292 infloop death. */ | |
3293 static Lisp_Object | |
3294 image_copy_vector_instantiator (Lisp_Object instantiator) | |
3295 { | |
3296 int i; | |
3297 struct image_instantiator_methods *meths; | |
3298 Lisp_Object *elt; | |
3299 int instantiator_len; | |
3300 | |
3301 CHECK_VECTOR (instantiator); | |
3302 | |
3303 instantiator = Fcopy_sequence (instantiator); | |
3304 elt = XVECTOR_DATA (instantiator); | |
3305 instantiator_len = XVECTOR_LENGTH (instantiator); | |
3306 | |
3307 meths = decode_image_instantiator_format (elt[0], ERROR_ME); | |
3308 | |
3309 for (i = 1; i < instantiator_len; i += 2) | |
3310 { | |
3311 int j; | |
3312 Lisp_Object keyword = elt[i]; | |
3313 Lisp_Object value = elt[i+1]; | |
3314 | |
3315 /* Find the keyword entry. */ | |
3316 for (j = 0; j < Dynarr_length (meths->keywords); j++) | |
3317 { | |
3318 if (EQ (keyword, Dynarr_at (meths->keywords, j).keyword)) | |
3319 break; | |
3320 } | |
3321 | |
3322 /* Only copy keyword values that should be copied. */ | |
3323 if (Dynarr_at (meths->keywords, j).copy_p | |
3324 && | |
3325 (CONSP (value) || VECTORP (value))) | |
3326 { | |
3327 elt [i+1] = Fcopy_tree (value, Qt); | |
3328 } | |
3329 } | |
3330 | |
3331 return instantiator; | |
3332 } | |
3333 | |
3334 static Lisp_Object | |
3335 image_copy_instantiator (Lisp_Object arg) | |
3336 { | |
3337 if (CONSP (arg)) | |
3338 { | |
3339 Lisp_Object rest; | |
3340 rest = arg = Fcopy_sequence (arg); | |
3341 while (CONSP (rest)) | |
3342 { | |
3343 Lisp_Object elt = XCAR (rest); | |
3344 if (CONSP (elt)) | |
3345 XCAR (rest) = Fcopy_tree (elt, Qt); | |
3346 else if (VECTORP (elt)) | |
3347 XCAR (rest) = image_copy_vector_instantiator (elt); | |
3348 if (VECTORP (XCDR (rest))) /* hack for (a b . [c d]) */ | |
3349 XCDR (rest) = Fcopy_tree (XCDR (rest), Qt); | |
3350 rest = XCDR (rest); | |
3351 } | |
3352 } | |
3353 else if (VECTORP (arg)) | |
3354 { | |
3355 arg = image_copy_vector_instantiator (arg); | |
3356 } | |
3357 return arg; | |
3358 } | |
3359 | |
3360 DEFUN ("image-specifier-p", Fimage_specifier_p, 1, 1, 0, /* | 2629 DEFUN ("image-specifier-p", Fimage_specifier_p, 1, 1, 0, /* |
3361 Return non-nil if OBJECT is an image specifier. | 2630 Return non-nil if OBJECT is an image specifier. |
3362 See `make-image-specifier' for a description of image instantiators. | 2631 |
2632 An image specifier is used for images (pixmaps and the like). It is used | |
2633 to describe the actual image in a glyph. It is instanced as an image- | |
2634 instance. | |
2635 | |
2636 Image instantiators come in many formats: `xbm', `xpm', `gif', `jpeg', | |
2637 etc. This describes the format of the data describing the image. The | |
2638 resulting image instances also come in many types -- `mono-pixmap', | |
2639 `color-pixmap', `text', `pointer', etc. This refers to the behavior of | |
2640 the image and the sorts of places it can appear. (For example, a | |
2641 color-pixmap image has fixed colors specified for it, while a | |
2642 mono-pixmap image comes in two unspecified shades "foreground" and | |
2643 "background" that are determined from the face of the glyph or | |
2644 surrounding text; a text image appears as a string of text and has an | |
2645 unspecified foreground, background, and font; a pointer image behaves | |
2646 like a mono-pixmap image but can only be used as a mouse pointer | |
2647 \[mono-pixmap images cannot be used as mouse pointers]; etc.) It is | |
2648 important to keep the distinction between image instantiator format and | |
2649 image instance type in mind. Typically, a given image instantiator | |
2650 format can result in many different image instance types (for example, | |
2651 `xpm' can be instanced as `color-pixmap', `mono-pixmap', or `pointer'; | |
2652 whereas `cursor-font' can be instanced only as `pointer'), and a | |
2653 particular image instance type can be generated by many different | |
2654 image instantiator formats (e.g. `color-pixmap' can be generated by `xpm', | |
2655 `gif', `jpeg', etc.). | |
2656 | |
2657 See `make-image-instance' for a more detailed discussion of image | |
2658 instance types. | |
2659 | |
2660 An image instantiator should be a string or a vector of the form | |
2661 | |
2662 [FORMAT :KEYWORD VALUE ...] | |
2663 | |
2664 i.e. a format symbol followed by zero or more alternating keyword-value | |
2665 pairs. FORMAT should be one of | |
2666 | |
2667 'nothing | |
2668 (Don't display anything; no keywords are valid for this. | |
2669 Can only be instanced as `nothing'.) | |
2670 'string | |
2671 (Display this image as a text string. Can only be instanced | |
2672 as `text', although support for instancing as `mono-pixmap' | |
2673 should be added.) | |
2674 'formatted-string | |
2675 (Display this image as a text string, with replaceable fields; | |
2676 not currently implemented.) | |
2677 'xbm | |
2678 (An X bitmap; only if X or Windows support was compiled into this XEmacs. | |
2679 Can be instanced as `mono-pixmap', `color-pixmap', or `pointer'.) | |
2680 'xpm | |
2681 (An XPM pixmap; only if XPM support was compiled into this XEmacs. | |
2682 Can be instanced as `color-pixmap', `mono-pixmap', or `pointer'.) | |
2683 'xface | |
2684 (An X-Face bitmap, used to encode people's faces in e-mail messages; | |
2685 only if X-Face support was compiled into this XEmacs. Can be | |
2686 instanced as `mono-pixmap', `color-pixmap', or `pointer'.) | |
2687 'gif | |
2688 (A GIF87 or GIF89 image; only if GIF support was compiled into this | |
2689 XEmacs. NOTE: only the first frame of animated gifs will be displayed. | |
2690 Can be instanced as `color-pixmap'.) | |
2691 'jpeg | |
2692 (A JPEG image; only if JPEG support was compiled into this XEmacs. | |
2693 Can be instanced as `color-pixmap'.) | |
2694 'png | |
2695 (A PNG image; only if PNG support was compiled into this XEmacs. | |
2696 Can be instanced as `color-pixmap'.) | |
2697 'tiff | |
2698 (A TIFF image; only if TIFF support was compiled into this XEmacs. | |
2699 Can be instanced as `color-pixmap'.) | |
2700 'cursor-font | |
2701 (One of the standard cursor-font names, such as "watch" or | |
2702 "right_ptr" under X. Under X, this is, more specifically, any | |
2703 of the standard cursor names from appendix B of the Xlib manual | |
2704 [also known as the file <X11/cursorfont.h>] minus the XC_ prefix. | |
2705 On other window systems, the valid names will be specific to the | |
2706 type of window system. Can only be instanced as `pointer'.) | |
2707 'font | |
2708 (A glyph from a font; i.e. the name of a font, and glyph index into it | |
2709 of the form "FONT fontname index [[mask-font] mask-index]". | |
2710 Currently can only be instanced as `pointer', although this should | |
2711 probably be fixed.) | |
2712 'subwindow | |
2713 (An embedded X window; not currently implemented.) | |
2714 'widget | |
2715 (A widget control, for instance text field or radio button.) | |
2716 'autodetect | |
2717 (XEmacs tries to guess what format the data is in. If X support | |
2718 exists, the data string will be checked to see if it names a filename. | |
2719 If so, and this filename contains XBM or XPM data, the appropriate | |
2720 sort of pixmap or pointer will be created. [This includes picking up | |
2721 any specified hotspot or associated mask file.] Otherwise, if `pointer' | |
2722 is one of the allowable image-instance types and the string names a | |
2723 valid cursor-font name, the image will be created as a pointer. | |
2724 Otherwise, the image will be displayed as text. If no X support | |
2725 exists, the image will always be displayed as text.) | |
2726 'inherit | |
2727 Inherit from the background-pixmap property of a face. | |
2728 | |
2729 The valid keywords are: | |
2730 | |
2731 :data | |
2732 (Inline data. For most formats above, this should be a string. For | |
2733 XBM images, this should be a list of three elements: width, height, and | |
2734 a string of bit data. This keyword is not valid for instantiator | |
2735 formats `nothing' and `inherit'.) | |
2736 :file | |
2737 (Data is contained in a file. The value is the name of this file. | |
2738 If both :data and :file are specified, the image is created from | |
2739 what is specified in :data and the string in :file becomes the | |
2740 value of the `image-instance-file-name' function when applied to | |
2741 the resulting image-instance. This keyword is not valid for | |
2742 instantiator formats `nothing', `string', `formatted-string', | |
2743 `cursor-font', `font', `autodetect', and `inherit'.) | |
2744 :foreground | |
2745 :background | |
2746 (For `xbm', `xface', `cursor-font', `widget' and `font'. These keywords | |
2747 allow you to explicitly specify foreground and background colors. | |
2748 The argument should be anything acceptable to `make-color-instance'. | |
2749 This will cause what would be a `mono-pixmap' to instead be colorized | |
2750 as a two-color color-pixmap, and specifies the foreground and/or | |
2751 background colors for a pointer instead of black and white.) | |
2752 :mask-data | |
2753 (For `xbm' and `xface'. This specifies a mask to be used with the | |
2754 bitmap. The format is a list of width, height, and bits, like for | |
2755 :data.) | |
2756 :mask-file | |
2757 (For `xbm' and `xface'. This specifies a file containing the mask data. | |
2758 If neither a mask file nor inline mask data is given for an XBM image, | |
2759 and the XBM image comes from a file, XEmacs will look for a mask file | |
2760 with the same name as the image file but with "Mask" or "msk" | |
2761 appended. For example, if you specify the XBM file "left_ptr" | |
2762 [usually located in "/usr/include/X11/bitmaps"], the associated | |
2763 mask file "left_ptrmsk" will automatically be picked up.) | |
2764 :hotspot-x | |
2765 :hotspot-y | |
2766 (For `xbm' and `xface'. These keywords specify a hotspot if the image | |
2767 is instantiated as a `pointer'. Note that if the XBM image file | |
2768 specifies a hotspot, it will automatically be picked up if no | |
2769 explicit hotspot is given.) | |
2770 :color-symbols | |
2771 (Only for `xpm'. This specifies an alist that maps strings | |
2772 that specify symbolic color names to the actual color to be used | |
2773 for that symbolic color (in the form of a string or a color-specifier | |
2774 object). If this is not specified, the contents of `xpm-color-symbols' | |
2775 are used to generate the alist.) | |
2776 :face | |
2777 (Only for `inherit'. This specifies the face to inherit from.) | |
2778 | |
2779 If instead of a vector, the instantiator is a string, it will be | |
2780 converted into a vector by looking it up according to the specs in the | |
2781 `console-type-image-conversion-list' (q.v.) for the console type of | |
2782 the domain (usually a window; sometimes a frame or device) over which | |
2783 the image is being instantiated. | |
2784 | |
2785 If the instantiator specifies data from a file, the data will be read | |
2786 in at the time that the instantiator is added to the image (which may | |
2787 be well before when the image is actually displayed), and the | |
2788 instantiator will be converted into one of the inline-data forms, with | |
2789 the filename retained using a :file keyword. This implies that the | |
2790 file must exist when the instantiator is added to the image, but does | |
2791 not need to exist at any other time (e.g. it may safely be a temporary | |
2792 file). | |
3363 */ | 2793 */ |
3364 (object)) | 2794 (object)) |
3365 { | 2795 { |
3366 return IMAGE_SPECIFIERP (object) ? Qt : Qnil; | 2796 return IMAGE_SPECIFIERP (object) ? Qt : Qnil; |
3367 } | 2797 } |
3370 /**************************************************************************** | 2800 /**************************************************************************** |
3371 * Glyph Object * | 2801 * Glyph Object * |
3372 ****************************************************************************/ | 2802 ****************************************************************************/ |
3373 | 2803 |
3374 static Lisp_Object | 2804 static Lisp_Object |
3375 mark_glyph (Lisp_Object obj) | 2805 mark_glyph (Lisp_Object obj, void (*markobj) (Lisp_Object)) |
3376 { | 2806 { |
3377 Lisp_Glyph *glyph = XGLYPH (obj); | 2807 struct Lisp_Glyph *glyph = XGLYPH (obj); |
3378 | 2808 |
3379 mark_object (glyph->image); | 2809 markobj (glyph->image); |
3380 mark_object (glyph->contrib_p); | 2810 markobj (glyph->contrib_p); |
3381 mark_object (glyph->baseline); | 2811 markobj (glyph->baseline); |
3382 mark_object (glyph->face); | 2812 markobj (glyph->face); |
3383 | 2813 |
3384 return glyph->plist; | 2814 return glyph->plist; |
3385 } | 2815 } |
3386 | 2816 |
3387 static void | 2817 static void |
3388 print_glyph (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag) | 2818 print_glyph (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag) |
3389 { | 2819 { |
3390 Lisp_Glyph *glyph = XGLYPH (obj); | 2820 struct Lisp_Glyph *glyph = XGLYPH (obj); |
3391 char buf[20]; | 2821 char buf[20]; |
3392 | 2822 |
3393 if (print_readably) | 2823 if (print_readably) |
3394 error ("printing unreadable object #<glyph 0x%x>", glyph->header.uid); | 2824 error ("printing unreadable object #<glyph 0x%x>", glyph->header.uid); |
3395 | 2825 |
3408 This isn't concerned with "unspecified" attributes, that's what | 2838 This isn't concerned with "unspecified" attributes, that's what |
3409 #'glyph-differs-from-default-p is for. */ | 2839 #'glyph-differs-from-default-p is for. */ |
3410 static int | 2840 static int |
3411 glyph_equal (Lisp_Object obj1, Lisp_Object obj2, int depth) | 2841 glyph_equal (Lisp_Object obj1, Lisp_Object obj2, int depth) |
3412 { | 2842 { |
3413 Lisp_Glyph *g1 = XGLYPH (obj1); | 2843 struct Lisp_Glyph *g1 = XGLYPH (obj1); |
3414 Lisp_Glyph *g2 = XGLYPH (obj2); | 2844 struct Lisp_Glyph *g2 = XGLYPH (obj2); |
3415 | 2845 |
3416 depth++; | 2846 depth++; |
3417 | 2847 |
3418 return (internal_equal (g1->image, g2->image, depth) && | 2848 return (internal_equal (g1->image, g2->image, depth) && |
3419 internal_equal (g1->contrib_p, g2->contrib_p, depth) && | 2849 internal_equal (g1->contrib_p, g2->contrib_p, depth) && |
3434 } | 2864 } |
3435 | 2865 |
3436 static Lisp_Object | 2866 static Lisp_Object |
3437 glyph_getprop (Lisp_Object obj, Lisp_Object prop) | 2867 glyph_getprop (Lisp_Object obj, Lisp_Object prop) |
3438 { | 2868 { |
3439 Lisp_Glyph *g = XGLYPH (obj); | 2869 struct Lisp_Glyph *g = XGLYPH (obj); |
3440 | 2870 |
3441 if (EQ (prop, Qimage)) return g->image; | 2871 if (EQ (prop, Qimage)) return g->image; |
3442 if (EQ (prop, Qcontrib_p)) return g->contrib_p; | 2872 if (EQ (prop, Qcontrib_p)) return g->contrib_p; |
3443 if (EQ (prop, Qbaseline)) return g->baseline; | 2873 if (EQ (prop, Qbaseline)) return g->baseline; |
3444 if (EQ (prop, Qface)) return g->face; | 2874 if (EQ (prop, Qface)) return g->face; |
3447 } | 2877 } |
3448 | 2878 |
3449 static int | 2879 static int |
3450 glyph_putprop (Lisp_Object obj, Lisp_Object prop, Lisp_Object value) | 2880 glyph_putprop (Lisp_Object obj, Lisp_Object prop, Lisp_Object value) |
3451 { | 2881 { |
3452 if (EQ (prop, Qimage) || | 2882 if ((EQ (prop, Qimage)) || |
3453 EQ (prop, Qcontrib_p) || | 2883 (EQ (prop, Qcontrib_p)) || |
3454 EQ (prop, Qbaseline)) | 2884 (EQ (prop, Qbaseline))) |
3455 return 0; | 2885 return 0; |
3456 | 2886 |
3457 if (EQ (prop, Qface)) | 2887 if (EQ (prop, Qface)) |
3458 { | 2888 { |
3459 XGLYPH (obj)->face = Fget_face (value); | 2889 XGLYPH (obj)->face = Fget_face (value); |
3465 } | 2895 } |
3466 | 2896 |
3467 static int | 2897 static int |
3468 glyph_remprop (Lisp_Object obj, Lisp_Object prop) | 2898 glyph_remprop (Lisp_Object obj, Lisp_Object prop) |
3469 { | 2899 { |
3470 if (EQ (prop, Qimage) || | 2900 if ((EQ (prop, Qimage)) || |
3471 EQ (prop, Qcontrib_p) || | 2901 (EQ (prop, Qcontrib_p)) || |
3472 EQ (prop, Qbaseline)) | 2902 (EQ (prop, Qbaseline))) |
3473 return -1; | 2903 return -1; |
3474 | 2904 |
3475 if (EQ (prop, Qface)) | 2905 if (EQ (prop, Qface)) |
3476 { | 2906 { |
3477 XGLYPH (obj)->face = Qnil; | 2907 XGLYPH (obj)->face = Qnil; |
3482 } | 2912 } |
3483 | 2913 |
3484 static Lisp_Object | 2914 static Lisp_Object |
3485 glyph_plist (Lisp_Object obj) | 2915 glyph_plist (Lisp_Object obj) |
3486 { | 2916 { |
3487 Lisp_Glyph *glyph = XGLYPH (obj); | 2917 struct Lisp_Glyph *glyph = XGLYPH (obj); |
3488 Lisp_Object result = glyph->plist; | 2918 Lisp_Object result = glyph->plist; |
3489 | 2919 |
3490 result = cons3 (Qface, glyph->face, result); | 2920 result = cons3 (Qface, glyph->face, result); |
3491 result = cons3 (Qbaseline, glyph->baseline, result); | 2921 result = cons3 (Qbaseline, glyph->baseline, result); |
3492 result = cons3 (Qcontrib_p, glyph->contrib_p, result); | 2922 result = cons3 (Qcontrib_p, glyph->contrib_p, result); |
3493 result = cons3 (Qimage, glyph->image, result); | 2923 result = cons3 (Qimage, glyph->image, result); |
3494 | 2924 |
3495 return result; | 2925 return result; |
3496 } | 2926 } |
3497 | 2927 |
3498 static const struct lrecord_description glyph_description[] = { | |
3499 { XD_LISP_OBJECT, offsetof (Lisp_Glyph, image) }, | |
3500 { XD_LISP_OBJECT, offsetof (Lisp_Glyph, contrib_p) }, | |
3501 { XD_LISP_OBJECT, offsetof (Lisp_Glyph, baseline) }, | |
3502 { XD_LISP_OBJECT, offsetof (Lisp_Glyph, face) }, | |
3503 { XD_LISP_OBJECT, offsetof (Lisp_Glyph, plist) }, | |
3504 { XD_END } | |
3505 }; | |
3506 | |
3507 DEFINE_LRECORD_IMPLEMENTATION_WITH_PROPS ("glyph", glyph, | 2928 DEFINE_LRECORD_IMPLEMENTATION_WITH_PROPS ("glyph", glyph, |
3508 mark_glyph, print_glyph, 0, | 2929 mark_glyph, print_glyph, 0, |
3509 glyph_equal, glyph_hash, glyph_description, | 2930 glyph_equal, glyph_hash, |
3510 glyph_getprop, glyph_putprop, | 2931 glyph_getprop, glyph_putprop, |
3511 glyph_remprop, glyph_plist, | 2932 glyph_remprop, glyph_plist, |
3512 Lisp_Glyph); | 2933 struct Lisp_Glyph); |
3513 | 2934 |
3514 Lisp_Object | 2935 Lisp_Object |
3515 allocate_glyph (enum glyph_type type, | 2936 allocate_glyph (enum glyph_type type, |
3516 void (*after_change) (Lisp_Object glyph, Lisp_Object property, | 2937 void (*after_change) (Lisp_Object glyph, Lisp_Object property, |
3517 Lisp_Object locale)) | 2938 Lisp_Object locale)) |
3518 { | 2939 { |
3519 /* This function can GC */ | 2940 /* This function can GC */ |
3520 Lisp_Object obj = Qnil; | 2941 Lisp_Object obj = Qnil; |
3521 Lisp_Glyph *g = alloc_lcrecord_type (Lisp_Glyph, &lrecord_glyph); | 2942 struct Lisp_Glyph *g = |
2943 alloc_lcrecord_type (struct Lisp_Glyph, &lrecord_glyph); | |
3522 | 2944 |
3523 g->type = type; | 2945 g->type = type; |
3524 g->image = Fmake_specifier (Qimage); /* This function can GC */ | 2946 g->image = Fmake_specifier (Qimage); /* This function can GC */ |
3525 g->dirty = 0; | |
3526 switch (g->type) | 2947 switch (g->type) |
3527 { | 2948 { |
3528 case GLYPH_BUFFER: | 2949 case GLYPH_BUFFER: |
3529 XIMAGE_SPECIFIER_ALLOWED (g->image) = | 2950 XIMAGE_SPECIFIER_ALLOWED (g->image) = |
3530 IMAGE_NOTHING_MASK | IMAGE_TEXT_MASK | 2951 IMAGE_NOTHING_MASK | IMAGE_TEXT_MASK |
3531 | IMAGE_MONO_PIXMAP_MASK | IMAGE_COLOR_PIXMAP_MASK | 2952 | IMAGE_MONO_PIXMAP_MASK | IMAGE_COLOR_PIXMAP_MASK |
3532 | IMAGE_SUBWINDOW_MASK | IMAGE_WIDGET_MASK; | 2953 | IMAGE_SUBWINDOW_MASK | IMAGE_WIDGET_MASK; |
3533 break; | 2954 break; |
3534 case GLYPH_POINTER: | 2955 case GLYPH_POINTER: |
3535 XIMAGE_SPECIFIER_ALLOWED (g->image) = | 2956 XIMAGE_SPECIFIER_ALLOWED (g->image) = |
3536 IMAGE_NOTHING_MASK | IMAGE_POINTER_MASK; | 2957 IMAGE_NOTHING_MASK | IMAGE_POINTER_MASK; |
3537 break; | 2958 break; |
3538 case GLYPH_ICON: | 2959 case GLYPH_ICON: |
3539 XIMAGE_SPECIFIER_ALLOWED (g->image) = | 2960 XIMAGE_SPECIFIER_ALLOWED (g->image) = |
3540 IMAGE_NOTHING_MASK | IMAGE_MONO_PIXMAP_MASK | 2961 IMAGE_NOTHING_MASK | IMAGE_MONO_PIXMAP_MASK | IMAGE_COLOR_PIXMAP_MASK; |
3541 | IMAGE_COLOR_PIXMAP_MASK; | |
3542 break; | 2962 break; |
3543 default: | 2963 default: |
3544 abort (); | 2964 abort (); |
3545 } | 2965 } |
3546 | 2966 |
3642 } | 3062 } |
3643 | 3063 |
3644 DEFUN ("glyphp", Fglyphp, 1, 1, 0, /* | 3064 DEFUN ("glyphp", Fglyphp, 1, 1, 0, /* |
3645 Return non-nil if OBJECT is a glyph. | 3065 Return non-nil if OBJECT is a glyph. |
3646 | 3066 |
3647 A glyph is an object used for pixmaps, widgets and the like. It is used | 3067 A glyph is an object used for pixmaps and the like. It is used |
3648 in begin-glyphs and end-glyphs attached to extents, in marginal and textual | 3068 in begin-glyphs and end-glyphs attached to extents, in marginal and textual |
3649 annotations, in overlay arrows (overlay-arrow-* variables), in toolbar | 3069 annotations, in overlay arrows (overlay-arrow-* variables), in toolbar |
3650 buttons, and the like. Much more detailed information can be found at | 3070 buttons, and the like. Its image is described using an image specifier -- |
3651 `make-glyph'. Its image is described using an image specifier -- | 3071 see `image-specifier-p'. |
3652 see `make-image-specifier'. See also `make-image-instance' for further | |
3653 information. | |
3654 */ | 3072 */ |
3655 (object)) | 3073 (object)) |
3656 { | 3074 { |
3657 return GLYPHP (object) ? Qt : Qnil; | 3075 return GLYPHP (object) ? Qt : Qnil; |
3658 } | 3076 } |
3671 case GLYPH_POINTER: return Qpointer; | 3089 case GLYPH_POINTER: return Qpointer; |
3672 case GLYPH_ICON: return Qicon; | 3090 case GLYPH_ICON: return Qicon; |
3673 } | 3091 } |
3674 } | 3092 } |
3675 | 3093 |
3676 Lisp_Object | |
3677 glyph_image_instance (Lisp_Object glyph, Lisp_Object domain, | |
3678 Error_behavior errb, int no_quit) | |
3679 { | |
3680 Lisp_Object specifier = GLYPH_IMAGE (XGLYPH (glyph)); | |
3681 | |
3682 /* This can never return Qunbound. All glyphs have 'nothing as | |
3683 a fallback. */ | |
3684 Lisp_Object image_instance = specifier_instance (specifier, Qunbound, | |
3685 domain, errb, no_quit, 0, | |
3686 Qzero); | |
3687 assert (!UNBOUNDP (image_instance)); | |
3688 ERROR_CHECK_IMAGE_INSTANCE (image_instance); | |
3689 | |
3690 return image_instance; | |
3691 } | |
3692 | |
3693 static Lisp_Object | |
3694 glyph_image_instance_maybe (Lisp_Object glyph_or_image, Lisp_Object window) | |
3695 { | |
3696 Lisp_Object instance = glyph_or_image; | |
3697 | |
3698 if (GLYPHP (glyph_or_image)) | |
3699 instance = glyph_image_instance (glyph_or_image, window, ERROR_ME_NOT, 1); | |
3700 | |
3701 return instance; | |
3702 } | |
3703 | |
3704 /***************************************************************************** | 3094 /***************************************************************************** |
3705 glyph_width | 3095 glyph_width |
3706 | 3096 |
3707 Return the width of the given GLYPH on the given WINDOW. | 3097 Return the width of the given GLYPH on the given WINDOW. If the |
3708 Calculations are done based on recursively querying the geometry of | 3098 instance is a string then the width is calculated using the font of |
3709 the associated image instances. | 3099 the given FACE, unless a face is defined by the glyph itself. |
3710 ****************************************************************************/ | 3100 ****************************************************************************/ |
3711 unsigned short | 3101 unsigned short |
3712 glyph_width (Lisp_Object glyph_or_image, Lisp_Object domain) | 3102 glyph_width (Lisp_Object glyph, Lisp_Object frame_face, |
3713 { | 3103 face_index window_findex, Lisp_Object window) |
3714 Lisp_Object instance = glyph_image_instance_maybe (glyph_or_image, | 3104 { |
3715 domain); | 3105 Lisp_Object instance; |
3106 Lisp_Object frame = XWINDOW (window)->frame; | |
3107 | |
3108 /* #### We somehow need to distinguish between the user causing this | |
3109 error condition and a bug causing it. */ | |
3110 if (!GLYPHP (glyph)) | |
3111 return 0; | |
3112 else | |
3113 instance = glyph_image_instance (glyph, window, ERROR_ME_NOT, 1); | |
3114 | |
3716 if (!IMAGE_INSTANCEP (instance)) | 3115 if (!IMAGE_INSTANCEP (instance)) |
3717 return 0; | 3116 return 0; |
3718 | 3117 |
3719 if (XIMAGE_INSTANCE_NEEDS_LAYOUT (instance)) | 3118 switch (XIMAGE_INSTANCE_TYPE (instance)) |
3720 image_instance_layout (instance, IMAGE_UNSPECIFIED_GEOMETRY, | 3119 { |
3721 IMAGE_UNSPECIFIED_GEOMETRY, domain); | 3120 case IMAGE_TEXT: |
3722 | 3121 { |
3723 return XIMAGE_INSTANCE_WIDTH (instance); | 3122 Lisp_Object str = XIMAGE_INSTANCE_TEXT_STRING (instance); |
3123 Lisp_Object private_face = XGLYPH_FACE(glyph); | |
3124 | |
3125 if (!NILP (private_face)) | |
3126 return redisplay_frame_text_width_string (XFRAME (frame), | |
3127 private_face, | |
3128 0, str, 0, -1); | |
3129 else | |
3130 if (!NILP (frame_face)) | |
3131 return redisplay_frame_text_width_string (XFRAME (frame), | |
3132 frame_face, | |
3133 0, str, 0, -1); | |
3134 else | |
3135 return redisplay_text_width_string (XWINDOW (window), | |
3136 window_findex, | |
3137 0, str, 0, -1); | |
3138 } | |
3139 | |
3140 case IMAGE_MONO_PIXMAP: | |
3141 case IMAGE_COLOR_PIXMAP: | |
3142 case IMAGE_POINTER: | |
3143 return XIMAGE_INSTANCE_PIXMAP_WIDTH (instance); | |
3144 | |
3145 case IMAGE_NOTHING: | |
3146 return 0; | |
3147 | |
3148 case IMAGE_SUBWINDOW: | |
3149 case IMAGE_WIDGET: | |
3150 return XIMAGE_INSTANCE_SUBWINDOW_WIDTH (instance); | |
3151 | |
3152 default: | |
3153 abort (); | |
3154 return 0; | |
3155 } | |
3724 } | 3156 } |
3725 | 3157 |
3726 DEFUN ("glyph-width", Fglyph_width, 1, 2, 0, /* | 3158 DEFUN ("glyph-width", Fglyph_width, 1, 2, 0, /* |
3727 Return the width of GLYPH on WINDOW. | 3159 Return the width of GLYPH on WINDOW. |
3728 This may not be exact as it does not take into account all of the context | 3160 This may not be exact as it does not take into account all of the context |
3731 (glyph, window)) | 3163 (glyph, window)) |
3732 { | 3164 { |
3733 XSETWINDOW (window, decode_window (window)); | 3165 XSETWINDOW (window, decode_window (window)); |
3734 CHECK_GLYPH (glyph); | 3166 CHECK_GLYPH (glyph); |
3735 | 3167 |
3736 return make_int (glyph_width (glyph, window)); | 3168 return make_int (glyph_width (glyph, Qnil, DEFAULT_INDEX, window)); |
3737 } | 3169 } |
3738 | 3170 |
3739 unsigned short | 3171 #define RETURN_ASCENT 0 |
3740 glyph_ascent (Lisp_Object glyph_or_image, Lisp_Object domain) | 3172 #define RETURN_DESCENT 1 |
3741 { | 3173 #define RETURN_HEIGHT 2 |
3742 Lisp_Object instance = glyph_image_instance_maybe (glyph_or_image, | 3174 |
3743 domain); | 3175 Lisp_Object |
3176 glyph_image_instance (Lisp_Object glyph, Lisp_Object domain, | |
3177 Error_behavior errb, int no_quit) | |
3178 { | |
3179 Lisp_Object specifier = GLYPH_IMAGE (XGLYPH (glyph)); | |
3180 | |
3181 /* This can never return Qunbound. All glyphs have 'nothing as | |
3182 a fallback. */ | |
3183 return specifier_instance (specifier, Qunbound, domain, errb, no_quit, 0, | |
3184 Qzero); | |
3185 } | |
3186 | |
3187 static unsigned short | |
3188 glyph_height_internal (Lisp_Object glyph, Lisp_Object frame_face, | |
3189 face_index window_findex, Lisp_Object window, | |
3190 int function) | |
3191 { | |
3192 Lisp_Object instance; | |
3193 Lisp_Object frame = XWINDOW (window)->frame; | |
3194 | |
3195 if (!GLYPHP (glyph)) | |
3196 return 0; | |
3197 else | |
3198 instance = glyph_image_instance (glyph, window, ERROR_ME_NOT, 1); | |
3199 | |
3744 if (!IMAGE_INSTANCEP (instance)) | 3200 if (!IMAGE_INSTANCEP (instance)) |
3745 return 0; | 3201 return 0; |
3746 | 3202 |
3747 if (XIMAGE_INSTANCE_NEEDS_LAYOUT (instance)) | 3203 switch (XIMAGE_INSTANCE_TYPE (instance)) |
3748 image_instance_layout (instance, IMAGE_UNSPECIFIED_GEOMETRY, | 3204 { |
3749 IMAGE_UNSPECIFIED_GEOMETRY, domain); | 3205 case IMAGE_TEXT: |
3750 | 3206 { |
3751 if (XIMAGE_INSTANCE_TYPE (instance) == IMAGE_TEXT) | 3207 struct font_metric_info fm; |
3752 return XIMAGE_INSTANCE_TEXT_ASCENT (instance); | 3208 Lisp_Object string = XIMAGE_INSTANCE_TEXT_STRING (instance); |
3753 else | 3209 unsigned char charsets[NUM_LEADING_BYTES]; |
3754 return XIMAGE_INSTANCE_HEIGHT (instance); | 3210 struct face_cachel frame_cachel; |
3211 struct face_cachel *cachel; | |
3212 | |
3213 find_charsets_in_bufbyte_string (charsets, | |
3214 XSTRING_DATA (string), | |
3215 XSTRING_LENGTH (string)); | |
3216 | |
3217 if (!NILP (frame_face)) | |
3218 { | |
3219 reset_face_cachel (&frame_cachel); | |
3220 update_face_cachel_data (&frame_cachel, frame, frame_face); | |
3221 cachel = &frame_cachel; | |
3222 } | |
3223 else | |
3224 cachel = WINDOW_FACE_CACHEL (XWINDOW (window), window_findex); | |
3225 ensure_face_cachel_complete (cachel, window, charsets); | |
3226 | |
3227 face_cachel_charset_font_metric_info (cachel, charsets, &fm); | |
3228 | |
3229 switch (function) | |
3230 { | |
3231 case RETURN_ASCENT: return fm.ascent; | |
3232 case RETURN_DESCENT: return fm.descent; | |
3233 case RETURN_HEIGHT: return fm.ascent + fm.descent; | |
3234 default: | |
3235 abort (); | |
3236 return 0; /* not reached */ | |
3237 } | |
3238 } | |
3239 | |
3240 case IMAGE_MONO_PIXMAP: | |
3241 case IMAGE_COLOR_PIXMAP: | |
3242 case IMAGE_POINTER: | |
3243 /* #### Ugh ugh ugh -- temporary crap */ | |
3244 if (function == RETURN_ASCENT || function == RETURN_HEIGHT) | |
3245 return XIMAGE_INSTANCE_PIXMAP_HEIGHT (instance); | |
3246 else | |
3247 return 0; | |
3248 | |
3249 case IMAGE_NOTHING: | |
3250 return 0; | |
3251 | |
3252 case IMAGE_SUBWINDOW: | |
3253 case IMAGE_WIDGET: | |
3254 /* #### Ugh ugh ugh -- temporary crap */ | |
3255 if (function == RETURN_ASCENT || function == RETURN_HEIGHT) | |
3256 return XIMAGE_INSTANCE_SUBWINDOW_HEIGHT (instance); | |
3257 else | |
3258 return 0; | |
3259 | |
3260 default: | |
3261 abort (); | |
3262 return 0; | |
3263 } | |
3755 } | 3264 } |
3756 | 3265 |
3757 unsigned short | 3266 unsigned short |
3758 glyph_descent (Lisp_Object glyph_or_image, Lisp_Object domain) | 3267 glyph_ascent (Lisp_Object glyph, Lisp_Object frame_face, |
3759 { | 3268 face_index window_findex, Lisp_Object window) |
3760 Lisp_Object instance = glyph_image_instance_maybe (glyph_or_image, | 3269 { |
3761 domain); | 3270 return glyph_height_internal (glyph, frame_face, window_findex, window, |
3762 if (!IMAGE_INSTANCEP (instance)) | 3271 RETURN_ASCENT); |
3763 return 0; | 3272 } |
3764 | 3273 |
3765 if (XIMAGE_INSTANCE_NEEDS_LAYOUT (instance)) | 3274 unsigned short |
3766 image_instance_layout (instance, IMAGE_UNSPECIFIED_GEOMETRY, | 3275 glyph_descent (Lisp_Object glyph, Lisp_Object frame_face, |
3767 IMAGE_UNSPECIFIED_GEOMETRY, domain); | 3276 face_index window_findex, Lisp_Object window) |
3768 | 3277 { |
3769 if (XIMAGE_INSTANCE_TYPE (instance) == IMAGE_TEXT) | 3278 return glyph_height_internal (glyph, frame_face, window_findex, window, |
3770 return XIMAGE_INSTANCE_TEXT_DESCENT (instance); | 3279 RETURN_DESCENT); |
3771 else | |
3772 return 0; | |
3773 } | 3280 } |
3774 | 3281 |
3775 /* strictly a convenience function. */ | 3282 /* strictly a convenience function. */ |
3776 unsigned short | 3283 unsigned short |
3777 glyph_height (Lisp_Object glyph_or_image, Lisp_Object domain) | 3284 glyph_height (Lisp_Object glyph, Lisp_Object frame_face, |
3778 { | 3285 face_index window_findex, Lisp_Object window) |
3779 Lisp_Object instance = glyph_image_instance_maybe (glyph_or_image, | 3286 { |
3780 domain); | 3287 return glyph_height_internal (glyph, frame_face, window_findex, window, |
3781 | 3288 RETURN_HEIGHT); |
3782 if (!IMAGE_INSTANCEP (instance)) | |
3783 return 0; | |
3784 | |
3785 if (XIMAGE_INSTANCE_NEEDS_LAYOUT (instance)) | |
3786 image_instance_layout (instance, IMAGE_UNSPECIFIED_GEOMETRY, | |
3787 IMAGE_UNSPECIFIED_GEOMETRY, domain); | |
3788 | |
3789 return XIMAGE_INSTANCE_HEIGHT (instance); | |
3790 } | 3289 } |
3791 | 3290 |
3792 DEFUN ("glyph-ascent", Fglyph_ascent, 1, 2, 0, /* | 3291 DEFUN ("glyph-ascent", Fglyph_ascent, 1, 2, 0, /* |
3793 Return the ascent value of GLYPH on WINDOW. | 3292 Return the ascent value of GLYPH on WINDOW. |
3794 This may not be exact as it does not take into account all of the context | 3293 This may not be exact as it does not take into account all of the context |
3797 (glyph, window)) | 3296 (glyph, window)) |
3798 { | 3297 { |
3799 XSETWINDOW (window, decode_window (window)); | 3298 XSETWINDOW (window, decode_window (window)); |
3800 CHECK_GLYPH (glyph); | 3299 CHECK_GLYPH (glyph); |
3801 | 3300 |
3802 return make_int (glyph_ascent (glyph, window)); | 3301 return make_int (glyph_ascent (glyph, Qnil, DEFAULT_INDEX, window)); |
3803 } | 3302 } |
3804 | 3303 |
3805 DEFUN ("glyph-descent", Fglyph_descent, 1, 2, 0, /* | 3304 DEFUN ("glyph-descent", Fglyph_descent, 1, 2, 0, /* |
3806 Return the descent value of GLYPH on WINDOW. | 3305 Return the descent value of GLYPH on WINDOW. |
3807 This may not be exact as it does not take into account all of the context | 3306 This may not be exact as it does not take into account all of the context |
3810 (glyph, window)) | 3309 (glyph, window)) |
3811 { | 3310 { |
3812 XSETWINDOW (window, decode_window (window)); | 3311 XSETWINDOW (window, decode_window (window)); |
3813 CHECK_GLYPH (glyph); | 3312 CHECK_GLYPH (glyph); |
3814 | 3313 |
3815 return make_int (glyph_descent (glyph, window)); | 3314 return make_int (glyph_descent (glyph, Qnil, DEFAULT_INDEX, window)); |
3816 } | 3315 } |
3817 | 3316 |
3818 /* This is redundant but I bet a lot of people expect it to exist. */ | 3317 /* This is redundant but I bet a lot of people expect it to exist. */ |
3819 DEFUN ("glyph-height", Fglyph_height, 1, 2, 0, /* | 3318 DEFUN ("glyph-height", Fglyph_height, 1, 2, 0, /* |
3820 Return the height of GLYPH on WINDOW. | 3319 Return the height of GLYPH on WINDOW. |
3824 (glyph, window)) | 3323 (glyph, window)) |
3825 { | 3324 { |
3826 XSETWINDOW (window, decode_window (window)); | 3325 XSETWINDOW (window, decode_window (window)); |
3827 CHECK_GLYPH (glyph); | 3326 CHECK_GLYPH (glyph); |
3828 | 3327 |
3829 return make_int (glyph_height (glyph, window)); | 3328 return make_int (glyph_height (glyph, Qnil, DEFAULT_INDEX, window)); |
3830 } | 3329 } |
3831 | 3330 |
3832 static void | 3331 #undef RETURN_ASCENT |
3833 set_glyph_dirty_p (Lisp_Object glyph_or_image, Lisp_Object window, int dirty) | 3332 #undef RETURN_DESCENT |
3834 { | 3333 #undef RETURN_HEIGHT |
3835 Lisp_Object instance = glyph_or_image; | |
3836 | |
3837 if (!NILP (glyph_or_image)) | |
3838 { | |
3839 if (GLYPHP (glyph_or_image)) | |
3840 { | |
3841 instance = glyph_image_instance (glyph_or_image, window, | |
3842 ERROR_ME_NOT, 1); | |
3843 XGLYPH_DIRTYP (glyph_or_image) = dirty; | |
3844 } | |
3845 | |
3846 if (!IMAGE_INSTANCEP (instance)) | |
3847 return; | |
3848 | |
3849 XIMAGE_INSTANCE_DIRTYP (instance) = dirty; | |
3850 } | |
3851 } | |
3852 | |
3853 static void | |
3854 set_image_instance_dirty_p (Lisp_Object instance, int dirty) | |
3855 { | |
3856 if (IMAGE_INSTANCEP (instance)) | |
3857 { | |
3858 XIMAGE_INSTANCE_DIRTYP (instance) = dirty; | |
3859 /* Now cascade up the hierarchy. */ | |
3860 set_image_instance_dirty_p (XIMAGE_INSTANCE_PARENT (instance), | |
3861 dirty); | |
3862 } | |
3863 else if (GLYPHP (instance)) | |
3864 { | |
3865 XGLYPH_DIRTYP (instance) = dirty; | |
3866 } | |
3867 } | |
3868 | 3334 |
3869 /* #### do we need to cache this info to speed things up? */ | 3335 /* #### do we need to cache this info to speed things up? */ |
3870 | 3336 |
3871 Lisp_Object | 3337 Lisp_Object |
3872 glyph_baseline (Lisp_Object glyph, Lisp_Object domain) | 3338 glyph_baseline (Lisp_Object glyph, Lisp_Object domain) |
3918 { | 3384 { |
3919 if (XGLYPH (glyph)->after_change) | 3385 if (XGLYPH (glyph)->after_change) |
3920 (XGLYPH (glyph)->after_change) (glyph, property, locale); | 3386 (XGLYPH (glyph)->after_change) (glyph, property, locale); |
3921 } | 3387 } |
3922 | 3388 |
3923 #if 0 /* Not used for now */ | |
3924 static void | |
3925 glyph_query_geometry (Lisp_Object glyph_or_image, Lisp_Object window, | |
3926 unsigned int* width, unsigned int* height, | |
3927 enum image_instance_geometry disp, Lisp_Object domain) | |
3928 { | |
3929 Lisp_Object instance = glyph_or_image; | |
3930 | |
3931 if (GLYPHP (glyph_or_image)) | |
3932 instance = glyph_image_instance (glyph_or_image, window, ERROR_ME_NOT, 1); | |
3933 | |
3934 image_instance_query_geometry (instance, width, height, disp, domain); | |
3935 } | |
3936 | |
3937 static void | |
3938 glyph_layout (Lisp_Object glyph_or_image, Lisp_Object window, | |
3939 unsigned int width, unsigned int height, Lisp_Object domain) | |
3940 { | |
3941 Lisp_Object instance = glyph_or_image; | |
3942 | |
3943 if (GLYPHP (glyph_or_image)) | |
3944 instance = glyph_image_instance (glyph_or_image, window, ERROR_ME_NOT, 1); | |
3945 | |
3946 image_instance_layout (instance, width, height, domain); | |
3947 } | |
3948 #endif | |
3949 | |
3950 | 3389 |
3951 /***************************************************************************** | 3390 /***************************************************************************** |
3952 * glyph cachel functions * | 3391 * glyph cachel functions * |
3953 *****************************************************************************/ | 3392 *****************************************************************************/ |
3954 | 3393 |
3955 /* #### All of this is 95% copied from face cachels. Consider | 3394 /* |
3956 consolidating. | 3395 #### All of this is 95% copied from face cachels. |
3957 | 3396 Consider consolidating. |
3958 Why do we need glyph_cachels? Simply because a glyph_cachel captures | 3397 #### We need to add a dirty flag to the glyphs. |
3959 per-window information about a particular glyph. A glyph itself is | 3398 */ |
3960 not created in any particular context, so if we were to rely on a | 3399 |
3961 glyph to tell us about its dirtiness we would not be able to reset | |
3962 the dirty flag after redisplaying it as it may exist in other | |
3963 contexts. When we have redisplayed we need to know which glyphs to | |
3964 reset the dirty flags on - the glyph_cachels give us a nice list we | |
3965 can iterate through doing this. */ | |
3966 void | 3400 void |
3967 mark_glyph_cachels (glyph_cachel_dynarr *elements) | 3401 mark_glyph_cachels (glyph_cachel_dynarr *elements, |
3402 void (*markobj) (Lisp_Object)) | |
3968 { | 3403 { |
3969 int elt; | 3404 int elt; |
3970 | 3405 |
3971 if (!elements) | 3406 if (!elements) |
3972 return; | 3407 return; |
3973 | 3408 |
3974 for (elt = 0; elt < Dynarr_length (elements); elt++) | 3409 for (elt = 0; elt < Dynarr_length (elements); elt++) |
3975 { | 3410 { |
3976 struct glyph_cachel *cachel = Dynarr_atp (elements, elt); | 3411 struct glyph_cachel *cachel = Dynarr_atp (elements, elt); |
3977 mark_object (cachel->glyph); | 3412 markobj (cachel->glyph); |
3978 } | 3413 } |
3979 } | 3414 } |
3980 | 3415 |
3981 static void | 3416 static void |
3982 update_glyph_cachel_data (struct window *w, Lisp_Object glyph, | 3417 update_glyph_cachel_data (struct window *w, Lisp_Object glyph, |
3983 struct glyph_cachel *cachel) | 3418 struct glyph_cachel *cachel) |
3984 { | 3419 { |
3985 if (!cachel->updated || NILP (cachel->glyph) || !EQ (cachel->glyph, glyph) | 3420 /* #### This should be || !cachel->updated */ |
3986 || XGLYPH_DIRTYP (cachel->glyph) | 3421 if (NILP (cachel->glyph) || !EQ (cachel->glyph, glyph)) |
3987 || XFRAME(WINDOW_FRAME(w))->faces_changed) | 3422 { |
3988 { | 3423 Lisp_Object window; |
3989 Lisp_Object window, instance; | |
3990 | 3424 |
3991 XSETWINDOW (window, w); | 3425 XSETWINDOW (window, w); |
3992 | 3426 |
3427 /* #### This could be sped up if we redid things to grab the glyph | |
3428 instantiation and passed it to the size functions. */ | |
3993 cachel->glyph = glyph; | 3429 cachel->glyph = glyph; |
3994 /* Speed things up slightly by grabbing the glyph instantiation | 3430 cachel->width = glyph_width (glyph, Qnil, DEFAULT_INDEX, window); |
3995 and passing it to the size functions. */ | 3431 cachel->ascent = glyph_ascent (glyph, Qnil, DEFAULT_INDEX, window); |
3996 instance = glyph_image_instance (glyph, window, ERROR_ME_NOT, 1); | 3432 cachel->descent = glyph_descent (glyph, Qnil, DEFAULT_INDEX, window); |
3997 | |
3998 if (!IMAGE_INSTANCEP (instance)) | |
3999 return; | |
4000 | |
4001 /* Mark text instance of the glyph dirty if faces have changed, | |
4002 because its geometry might have changed. */ | |
4003 invalidate_glyph_geometry_maybe (instance, w); | |
4004 | |
4005 /* #### Do the following 2 lines buy us anything? --kkm */ | |
4006 XGLYPH_DIRTYP (glyph) = XIMAGE_INSTANCE_DIRTYP (instance); | |
4007 cachel->dirty = XGLYPH_DIRTYP (glyph); | |
4008 cachel->width = glyph_width (instance, window); | |
4009 cachel->ascent = glyph_ascent (instance, window); | |
4010 cachel->descent = glyph_descent (instance, window); | |
4011 } | 3433 } |
4012 | 3434 |
4013 cachel->updated = 1; | 3435 cachel->updated = 1; |
4014 } | 3436 } |
4015 | 3437 |
4023 | 3445 |
4024 update_glyph_cachel_data (w, glyph, &new_cachel); | 3446 update_glyph_cachel_data (w, glyph, &new_cachel); |
4025 Dynarr_add (w->glyph_cachels, new_cachel); | 3447 Dynarr_add (w->glyph_cachels, new_cachel); |
4026 } | 3448 } |
4027 | 3449 |
4028 glyph_index | 3450 static glyph_index |
4029 get_glyph_cachel_index (struct window *w, Lisp_Object glyph) | 3451 get_glyph_cachel_index (struct window *w, Lisp_Object glyph) |
4030 { | 3452 { |
4031 int elt; | 3453 int elt; |
4032 | 3454 |
4033 if (noninteractive) | 3455 if (noninteractive) |
4038 struct glyph_cachel *cachel = | 3460 struct glyph_cachel *cachel = |
4039 Dynarr_atp (w->glyph_cachels, elt); | 3461 Dynarr_atp (w->glyph_cachels, elt); |
4040 | 3462 |
4041 if (EQ (cachel->glyph, glyph) && !NILP (glyph)) | 3463 if (EQ (cachel->glyph, glyph) && !NILP (glyph)) |
4042 { | 3464 { |
4043 update_glyph_cachel_data (w, glyph, cachel); | 3465 if (!cachel->updated) |
3466 update_glyph_cachel_data (w, glyph, cachel); | |
4044 return elt; | 3467 return elt; |
4045 } | 3468 } |
4046 } | 3469 } |
4047 | 3470 |
4048 /* If we didn't find the glyph, add it and then return its index. */ | 3471 /* If we didn't find the glyph, add it and then return its index. */ |
4081 FROB (Voctal_escape_glyph, OCT_ESC_GLYPH_INDEX); | 3504 FROB (Voctal_escape_glyph, OCT_ESC_GLYPH_INDEX); |
4082 FROB (Vinvisible_text_glyph, INVIS_GLYPH_INDEX); | 3505 FROB (Vinvisible_text_glyph, INVIS_GLYPH_INDEX); |
4083 #undef FROB | 3506 #undef FROB |
4084 | 3507 |
4085 for (elt = 0; elt < Dynarr_length (w->glyph_cachels); elt++) | 3508 for (elt = 0; elt < Dynarr_length (w->glyph_cachels); elt++) |
4086 { | 3509 Dynarr_atp (w->glyph_cachels, elt)->updated = 0; |
4087 Dynarr_atp (w->glyph_cachels, elt)->updated = 0; | |
4088 } | |
4089 } | |
4090 | |
4091 /* Unset the dirty bit on all the glyph cachels that have it. */ | |
4092 void | |
4093 mark_glyph_cachels_as_clean (struct window* w) | |
4094 { | |
4095 int elt; | |
4096 Lisp_Object window; | |
4097 XSETWINDOW (window, w); | |
4098 for (elt = 0; elt < Dynarr_length (w->glyph_cachels); elt++) | |
4099 { | |
4100 struct glyph_cachel *cachel = Dynarr_atp (w->glyph_cachels, elt); | |
4101 cachel->dirty = 0; | |
4102 set_glyph_dirty_p (cachel->glyph, window, 0); | |
4103 } | |
4104 } | 3510 } |
4105 | 3511 |
4106 #ifdef MEMORY_USAGE_STATS | 3512 #ifdef MEMORY_USAGE_STATS |
4107 | 3513 |
4108 int | 3514 int |
4122 | 3528 |
4123 | 3529 |
4124 /***************************************************************************** | 3530 /***************************************************************************** |
4125 * subwindow cachel functions * | 3531 * subwindow cachel functions * |
4126 *****************************************************************************/ | 3532 *****************************************************************************/ |
4127 /* Subwindows are curious in that you have to physically unmap them to | 3533 /* subwindows are curious in that you have to physically unmap them to |
4128 not display them. It is problematic deciding what to do in | 3534 not display them. It is problematic deciding what to do in |
4129 redisplay. We have two caches - a per-window instance cache that | 3535 redisplay. We have two caches - a per-window instance cache that |
4130 keeps track of subwindows on a window, these are linked to their | 3536 keeps track of subwindows on a window, these are linked to their |
4131 instantiator in the hashtable and when the instantiator goes away | 3537 instantiator in the hashtable and when the instantiator goes away |
4132 we want the instance to go away also. However we also have a | 3538 we want the instance to go away also. However we also have a |
4133 per-frame instance cache that we use to determine if a subwindow is | 3539 per-frame instance cache that we use to determine if a subwindow is |
4134 obscuring an area that we want to clear. We need to be able to flip | 3540 obscuring an area that we want to clear. We need to be able to flip |
4135 through this quickly so a hashtable is not suitable hence the | 3541 through this quickly so a hashtable is not suitable hence the |
4136 subwindow_cachels. This is a weak list so unreference instances | 3542 subwindow_cachels. The question is should we just not mark |
4137 will get deleted properly. */ | 3543 instances in the subwindow_cachelsnor should we try and invalidate |
3544 the cache at suitable points in redisplay? If we don't invalidate | |
3545 the cache it will fill up with crud that will only get removed when | |
3546 the frame is deleted. So invalidation is good, the question is when | |
3547 and whether we mark as well. Go for the simple option - don't mark, | |
3548 MARK_SUBWINDOWS_CHANGED when a subwindow gets deleted. */ | |
3549 | |
3550 void | |
3551 mark_subwindow_cachels (subwindow_cachel_dynarr *elements, | |
3552 void (*markobj) (Lisp_Object)) | |
3553 { | |
3554 int elt; | |
3555 | |
3556 if (!elements) | |
3557 return; | |
3558 | |
3559 for (elt = 0; elt < Dynarr_length (elements); elt++) | |
3560 { | |
3561 struct subwindow_cachel *cachel = Dynarr_atp (elements, elt); | |
3562 markobj (cachel->subwindow); | |
3563 } | |
3564 } | |
3565 | |
3566 static void | |
3567 update_subwindow_cachel_data (struct frame *f, Lisp_Object subwindow, | |
3568 struct subwindow_cachel *cachel) | |
3569 { | |
3570 if (NILP (cachel->subwindow) || !EQ (cachel->subwindow, subwindow)) | |
3571 { | |
3572 cachel->subwindow = subwindow; | |
3573 cachel->width = XIMAGE_INSTANCE_SUBWINDOW_WIDTH (subwindow); | |
3574 cachel->height = XIMAGE_INSTANCE_SUBWINDOW_HEIGHT (subwindow); | |
3575 } | |
3576 | |
3577 cachel->updated = 1; | |
3578 } | |
3579 | |
3580 static void | |
3581 add_subwindow_cachel (struct frame *f, Lisp_Object subwindow) | |
3582 { | |
3583 struct subwindow_cachel new_cachel; | |
3584 | |
3585 xzero (new_cachel); | |
3586 new_cachel.subwindow = Qnil; | |
3587 new_cachel.x=0; | |
3588 new_cachel.y=0; | |
3589 new_cachel.being_displayed=0; | |
3590 | |
3591 update_subwindow_cachel_data (f, subwindow, &new_cachel); | |
3592 Dynarr_add (f->subwindow_cachels, new_cachel); | |
3593 } | |
3594 | |
3595 static int | |
3596 get_subwindow_cachel_index (struct frame *f, Lisp_Object subwindow) | |
3597 { | |
3598 int elt; | |
3599 | |
3600 if (noninteractive) | |
3601 return 0; | |
3602 | |
3603 for (elt = 0; elt < Dynarr_length (f->subwindow_cachels); elt++) | |
3604 { | |
3605 struct subwindow_cachel *cachel = | |
3606 Dynarr_atp (f->subwindow_cachels, elt); | |
3607 | |
3608 if (EQ (cachel->subwindow, subwindow) && !NILP (subwindow)) | |
3609 { | |
3610 if (!cachel->updated) | |
3611 update_subwindow_cachel_data (f, subwindow, cachel); | |
3612 return elt; | |
3613 } | |
3614 } | |
3615 | |
3616 /* If we didn't find the glyph, add it and then return its index. */ | |
3617 add_subwindow_cachel (f, subwindow); | |
3618 return elt; | |
3619 } | |
4138 | 3620 |
4139 /* redisplay in general assumes that drawing something will erase | 3621 /* redisplay in general assumes that drawing something will erase |
4140 what was there before. unfortunately this does not apply to | 3622 what was there before. unfortunately this does not apply to |
4141 subwindows that need to be specifically unmapped in order to | 3623 subwindows that need to be specifically unmapped in order to |
4142 disappear. we take a brute force approach - on the basis that its | 3624 disappear. we take a brute force approach - on the basis that its |
4143 cheap - and unmap all subwindows in a display line */ | 3625 cheap - and unmap all subwindows in a display line */ |
4144 | |
4145 /* Put new instances in the frame subwindow cache. This is less costly than | |
4146 doing it every time something gets mapped, and deleted instances will be | |
4147 removed automatically. */ | |
4148 static void | |
4149 cache_subwindow_instance_in_frame_maybe (Lisp_Object instance) | |
4150 { | |
4151 Lisp_Image_Instance* ii = XIMAGE_INSTANCE (instance); | |
4152 if (!NILP (DOMAIN_FRAME (IMAGE_INSTANCE_DOMAIN (ii)))) | |
4153 { | |
4154 struct frame* f = DOMAIN_XFRAME (IMAGE_INSTANCE_DOMAIN (ii)); | |
4155 XWEAK_LIST_LIST (FRAME_SUBWINDOW_CACHE (f)) | |
4156 = Fcons (instance, XWEAK_LIST_LIST (FRAME_SUBWINDOW_CACHE (f))); | |
4157 } | |
4158 } | |
4159 | |
4160 /* Unmap and finalize all subwindow instances in the frame cache. This | |
4161 is necessary because GC will not guarantee the order things get | |
4162 deleted in and moreover, frame finalization deletes the window | |
4163 system windows before deleting XEmacs windows, and hence | |
4164 subwindows. */ | |
4165 void | 3626 void |
4166 free_frame_subwindow_instance_cache (struct frame* f) | 3627 reset_subwindow_cachels (struct frame *f) |
4167 { | 3628 { |
4168 Lisp_Object rest; | 3629 int elt; |
4169 | 3630 for (elt = 0; elt < Dynarr_length (f->subwindow_cachels); elt++) |
4170 LIST_LOOP (rest, XWEAK_LIST_LIST (FRAME_SUBWINDOW_CACHE (f))) | 3631 { |
4171 { | 3632 struct subwindow_cachel *cachel = |
4172 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (XCAR (rest)); | 3633 Dynarr_atp (f->subwindow_cachels, elt); |
4173 /* Make sure that the subwindow is unmapped so that window | 3634 |
4174 deletion will not try and do it again. */ | 3635 if (!NILP (cachel->subwindow) && cachel->being_displayed) |
4175 unmap_subwindow (XCAR (rest)); | 3636 { |
4176 finalize_image_instance (ii, 0); | 3637 struct Lisp_Image_Instance* ii = XIMAGE_INSTANCE (cachel->subwindow); |
4177 } | 3638 MAYBE_DEVMETH (XDEVICE (f->device), unmap_subwindow, (ii)); |
4178 } | 3639 } |
4179 | 3640 } |
4180 /* Unmap and remove all instances from the frame cache. */ | 3641 Dynarr_reset (f->subwindow_cachels); |
3642 } | |
3643 | |
4181 void | 3644 void |
4182 reset_frame_subwindow_instance_cache (struct frame* f) | 3645 mark_subwindow_cachels_as_not_updated (struct frame *f) |
4183 { | 3646 { |
4184 Lisp_Object rest; | 3647 int elt; |
4185 | 3648 |
4186 LIST_LOOP (rest, XWEAK_LIST_LIST (FRAME_SUBWINDOW_CACHE (f))) | 3649 for (elt = 0; elt < Dynarr_length (f->subwindow_cachels); elt++) |
4187 { | 3650 Dynarr_atp (f->subwindow_cachels, elt)->updated = 0; |
4188 Lisp_Object value = XCAR (rest); | |
4189 /* Make sure that the subwindow is unmapped so that window | |
4190 deletion will not try and do it again. */ | |
4191 unmap_subwindow (value); | |
4192 XWEAK_LIST_LIST (FRAME_SUBWINDOW_CACHE (f)) | |
4193 = delq_no_quit (value, XWEAK_LIST_LIST (FRAME_SUBWINDOW_CACHE (f))); | |
4194 } | |
4195 } | |
4196 | |
4197 /***************************************************************************** | |
4198 * subwindow exposure ignorance * | |
4199 *****************************************************************************/ | |
4200 /* when we unmap subwindows the associated window system will generate | |
4201 expose events. This we do not want as redisplay already copes with | |
4202 the repainting necessary. Worse, we can get in an endless cycle of | |
4203 redisplay if we are not careful. Thus we keep a per-frame list of | |
4204 expose events that are going to come and ignore them as | |
4205 required. */ | |
4206 | |
4207 struct expose_ignore_blocktype | |
4208 { | |
4209 Blocktype_declare (struct expose_ignore); | |
4210 } *the_expose_ignore_blocktype; | |
4211 | |
4212 int | |
4213 check_for_ignored_expose (struct frame* f, int x, int y, int width, int height) | |
4214 { | |
4215 struct expose_ignore *ei, *prev; | |
4216 /* the ignore list is FIFO so we should generally get a match with | |
4217 the first element in the list */ | |
4218 for (ei = f->subwindow_exposures, prev = 0; ei; ei = ei->next) | |
4219 { | |
4220 /* Checking for exact matches just isn't good enough as we | |
4221 mighte get exposures for partially obscure subwindows, thus | |
4222 we have to check for overlaps. Being conservative we will | |
4223 check for exposures wholly contained by the subwindow, this | |
4224 might give us what we want.*/ | |
4225 if (ei->x <= x && ei->y <= y | |
4226 && ei->x + ei->width >= x + width | |
4227 && ei->y + ei->height >= y + height) | |
4228 { | |
4229 #ifdef DEBUG_WIDGETS | |
4230 stderr_out ("ignored %d+%d, %dx%d for exposure %d+%d, %dx%d\n", | |
4231 x, y, width, height, ei->x, ei->y, ei->width, ei->height); | |
4232 #endif | |
4233 if (!prev) | |
4234 f->subwindow_exposures = ei->next; | |
4235 else | |
4236 prev->next = ei->next; | |
4237 | |
4238 if (ei == f->subwindow_exposures_tail) | |
4239 f->subwindow_exposures_tail = prev; | |
4240 | |
4241 Blocktype_free (the_expose_ignore_blocktype, ei); | |
4242 return 1; | |
4243 } | |
4244 prev = ei; | |
4245 } | |
4246 return 0; | |
4247 } | |
4248 | |
4249 static void | |
4250 register_ignored_expose (struct frame* f, int x, int y, int width, int height) | |
4251 { | |
4252 if (!hold_ignored_expose_registration) | |
4253 { | |
4254 struct expose_ignore *ei; | |
4255 | |
4256 ei = Blocktype_alloc (the_expose_ignore_blocktype); | |
4257 | |
4258 ei->next = NULL; | |
4259 ei->x = x; | |
4260 ei->y = y; | |
4261 ei->width = width; | |
4262 ei->height = height; | |
4263 | |
4264 /* we have to add the exposure to the end of the list, since we | |
4265 want to check the oldest events first. for speed we keep a record | |
4266 of the end so that we can add right to it. */ | |
4267 if (f->subwindow_exposures_tail) | |
4268 { | |
4269 f->subwindow_exposures_tail->next = ei; | |
4270 } | |
4271 if (!f->subwindow_exposures) | |
4272 { | |
4273 f->subwindow_exposures = ei; | |
4274 } | |
4275 f->subwindow_exposures_tail = ei; | |
4276 } | |
4277 } | |
4278 | |
4279 /**************************************************************************** | |
4280 find_matching_subwindow | |
4281 | |
4282 See if there is a subwindow that completely encloses the requested | |
4283 area. | |
4284 ****************************************************************************/ | |
4285 int find_matching_subwindow (struct frame* f, int x, int y, int width, int height) | |
4286 { | |
4287 Lisp_Object rest; | |
4288 | |
4289 LIST_LOOP (rest, XWEAK_LIST_LIST (FRAME_SUBWINDOW_CACHE (f))) | |
4290 { | |
4291 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (XCAR (rest)); | |
4292 | |
4293 if (IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (ii) | |
4294 && | |
4295 IMAGE_INSTANCE_DISPLAY_X (ii) <= x | |
4296 && | |
4297 IMAGE_INSTANCE_DISPLAY_Y (ii) <= y | |
4298 && | |
4299 IMAGE_INSTANCE_DISPLAY_X (ii) | |
4300 + IMAGE_INSTANCE_DISPLAY_WIDTH (ii) >= x + width | |
4301 && | |
4302 IMAGE_INSTANCE_DISPLAY_Y (ii) | |
4303 + IMAGE_INSTANCE_DISPLAY_HEIGHT (ii) >= y + height) | |
4304 { | |
4305 return 1; | |
4306 } | |
4307 } | |
4308 return 0; | |
4309 } | 3651 } |
4310 | 3652 |
4311 | 3653 |
4312 /***************************************************************************** | 3654 /***************************************************************************** |
4313 * subwindow functions * | 3655 * subwindow functions * |
4314 *****************************************************************************/ | 3656 *****************************************************************************/ |
4315 | 3657 |
4316 /* Update the displayed characteristics of a subwindow. This function | 3658 /* update the displayed characteristics of a subwindow */ |
4317 should generally only get called if the subwindow is actually | 3659 static void |
4318 dirty. */ | 3660 update_subwindow (Lisp_Object subwindow) |
3661 { | |
3662 struct Lisp_Image_Instance* ii = XIMAGE_INSTANCE (subwindow); | |
3663 | |
3664 if (!IMAGE_INSTANCE_TYPE (ii) == IMAGE_WIDGET | |
3665 || | |
3666 NILP (IMAGE_INSTANCE_SUBWINDOW_FRAME (ii))) | |
3667 return; | |
3668 | |
3669 MAYBE_DEVMETH (XDEVICE (ii->device), update_subwindow, (ii)); | |
3670 } | |
3671 | |
4319 void | 3672 void |
4320 update_subwindow (Lisp_Object subwindow) | 3673 update_frame_subwindows (struct frame *f) |
4321 { | 3674 { |
4322 Lisp_Image_Instance* ii = XIMAGE_INSTANCE (subwindow); | 3675 int elt; |
4323 int count = specpdl_depth (); | 3676 |
4324 | 3677 if (f->subwindows_changed || f->glyphs_changed) |
4325 /* The update method is allowed to call eval. Since it is quite | 3678 for (elt = 0; elt < Dynarr_length (f->subwindow_cachels); elt++) |
4326 common for this function to get called from somewhere in | 3679 { |
4327 redisplay we need to make sure that quits are ignored. Otherwise | 3680 struct subwindow_cachel *cachel = |
4328 Fsignal will abort. */ | 3681 Dynarr_atp (f->subwindow_cachels, elt); |
4329 specbind (Qinhibit_quit, Qt); | 3682 |
4330 | 3683 if (cachel->being_displayed) |
4331 ERROR_CHECK_IMAGE_INSTANCE (subwindow); | 3684 { |
4332 | 3685 update_subwindow (cachel->subwindow); |
4333 if (WIDGET_IMAGE_INSTANCEP (subwindow)) | 3686 } |
4334 { | 3687 } |
4335 if (image_instance_changed (subwindow)) | |
4336 update_widget (subwindow); | |
4337 /* Reset the changed flags. */ | |
4338 IMAGE_INSTANCE_WIDGET_FACE_CHANGED (ii) = 0; | |
4339 IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii) = 0; | |
4340 IMAGE_INSTANCE_TEXT_CHANGED (ii) = 0; | |
4341 } | |
4342 else if (IMAGE_INSTANCE_TYPE (ii) == IMAGE_SUBWINDOW | |
4343 && | |
4344 !NILP (IMAGE_INSTANCE_FRAME (ii))) | |
4345 { | |
4346 MAYBE_DEVMETH (DOMAIN_XDEVICE (ii->domain), | |
4347 update_subwindow, (ii)); | |
4348 } | |
4349 | |
4350 IMAGE_INSTANCE_SIZE_CHANGED (ii) = 0; | |
4351 /* This function is typically called by redisplay just before | |
4352 outputting the information to the screen. Thus we record a hash | |
4353 of the output to determine whether on-screen is the same as | |
4354 recorded structure. This approach has limitations in there is a | |
4355 good chance that hash values will be different for the same | |
4356 visual appearance. However, we would rather that then the other | |
4357 way round - it simply means that we will get more displays than | |
4358 we might need. We can get better hashing by making the depth | |
4359 negative - currently it will recurse down 7 levels.*/ | |
4360 IMAGE_INSTANCE_DISPLAY_HASH (ii) = internal_hash (subwindow, | |
4361 IMAGE_INSTANCE_HASH_DEPTH); | |
4362 | |
4363 unbind_to (count, Qnil); | |
4364 } | |
4365 | |
4366 int | |
4367 image_instance_changed (Lisp_Object subwindow) | |
4368 { | |
4369 Lisp_Image_Instance* ii = XIMAGE_INSTANCE (subwindow); | |
4370 | |
4371 if (internal_hash (subwindow, IMAGE_INSTANCE_HASH_DEPTH) != | |
4372 IMAGE_INSTANCE_DISPLAY_HASH (ii)) | |
4373 return 1; | |
4374 /* #### I think there is probably a bug here. This gets called for | |
4375 layouts - and yet the pending items are always nil for | |
4376 layouts. We are saved by layout optimization, but I'm undecided | |
4377 as to what the correct fix is. */ | |
4378 else if (WIDGET_IMAGE_INSTANCEP (subwindow) | |
4379 && (!internal_equal (IMAGE_INSTANCE_WIDGET_ITEMS (ii), | |
4380 IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii), 0) | |
4381 || !NILP (IMAGE_INSTANCE_LAYOUT_CHILDREN (ii)))) | |
4382 return 1; | |
4383 else | |
4384 return 0; | |
4385 } | |
4386 | |
4387 /* Update all the subwindows on a frame. */ | |
4388 void | |
4389 update_widget_instances (Lisp_Object frame) | |
4390 { | |
4391 struct frame* f; | |
4392 Lisp_Object rest; | |
4393 | |
4394 /* Its possible for the preceeding callback to have deleted the | |
4395 frame, so cope with this. */ | |
4396 if (!FRAMEP (frame) || !FRAME_LIVE_P (XFRAME (frame))) | |
4397 return; | |
4398 | |
4399 CHECK_FRAME (frame); | |
4400 f = XFRAME (frame); | |
4401 | |
4402 /* If we get called we know something has changed. */ | |
4403 LIST_LOOP (rest, XWEAK_LIST_LIST (FRAME_SUBWINDOW_CACHE (f))) | |
4404 { | |
4405 Lisp_Object widget = XCAR (rest); | |
4406 | |
4407 if (XIMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (widget) | |
4408 && | |
4409 image_instance_changed (widget)) | |
4410 { | |
4411 set_image_instance_dirty_p (widget, 1); | |
4412 MARK_FRAME_GLYPHS_CHANGED (f); | |
4413 } | |
4414 } | |
4415 } | 3688 } |
4416 | 3689 |
4417 /* remove a subwindow from its frame */ | 3690 /* remove a subwindow from its frame */ |
4418 void unmap_subwindow (Lisp_Object subwindow) | 3691 void unmap_subwindow (Lisp_Object subwindow) |
4419 { | 3692 { |
4420 Lisp_Image_Instance* ii = XIMAGE_INSTANCE (subwindow); | 3693 struct Lisp_Image_Instance* ii = XIMAGE_INSTANCE (subwindow); |
3694 int elt; | |
3695 struct subwindow_cachel* cachel; | |
4421 struct frame* f; | 3696 struct frame* f; |
4422 | 3697 |
4423 ERROR_CHECK_IMAGE_INSTANCE (subwindow); | 3698 if (!(IMAGE_INSTANCE_TYPE (ii) == IMAGE_WIDGET |
4424 | 3699 || |
4425 if (!image_instance_type_to_mask (IMAGE_INSTANCE_TYPE (ii)) | 3700 IMAGE_INSTANCE_TYPE (ii) == IMAGE_SUBWINDOW) |
4426 & (IMAGE_WIDGET_MASK | IMAGE_SUBWINDOW_MASK) | |
4427 || | 3701 || |
4428 !IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (ii)) | 3702 NILP (IMAGE_INSTANCE_SUBWINDOW_FRAME (ii))) |
4429 return; | 3703 return; |
4430 | 3704 |
4431 #ifdef DEBUG_WIDGETS | 3705 f = XFRAME (IMAGE_INSTANCE_SUBWINDOW_FRAME (ii)); |
4432 stderr_out ("unmapping subwindow %d\n", IMAGE_INSTANCE_SUBWINDOW_ID (ii)); | 3706 elt = get_subwindow_cachel_index (f, subwindow); |
4433 #endif | 3707 cachel = Dynarr_atp (f->subwindow_cachels, elt); |
4434 f = XFRAME (IMAGE_INSTANCE_FRAME (ii)); | 3708 |
4435 | 3709 cachel->x = -1; |
4436 /* make sure we don't get expose events */ | 3710 cachel->y = -1; |
4437 register_ignored_expose (f, IMAGE_INSTANCE_DISPLAY_X (ii), | 3711 cachel->being_displayed = 0; |
4438 IMAGE_INSTANCE_DISPLAY_Y (ii), | |
4439 IMAGE_INSTANCE_DISPLAY_WIDTH (ii), | |
4440 IMAGE_INSTANCE_DISPLAY_HEIGHT (ii)); | |
4441 IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (ii) = 0; | 3712 IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (ii) = 0; |
4442 | 3713 |
4443 MAYBE_DEVMETH (XDEVICE (IMAGE_INSTANCE_DEVICE (ii)), | 3714 MAYBE_DEVMETH (XDEVICE (ii->device), unmap_subwindow, (ii)); |
4444 unmap_subwindow, (ii)); | |
4445 } | 3715 } |
4446 | 3716 |
4447 /* show a subwindow in its frame */ | 3717 /* show a subwindow in its frame */ |
4448 void map_subwindow (Lisp_Object subwindow, int x, int y, | 3718 void map_subwindow (Lisp_Object subwindow, int x, int y) |
4449 struct display_glyph_area *dga) | 3719 { |
4450 { | 3720 struct Lisp_Image_Instance* ii = XIMAGE_INSTANCE (subwindow); |
4451 Lisp_Image_Instance* ii = XIMAGE_INSTANCE (subwindow); | 3721 int elt; |
3722 struct subwindow_cachel* cachel; | |
4452 struct frame* f; | 3723 struct frame* f; |
4453 | 3724 |
4454 ERROR_CHECK_IMAGE_INSTANCE (subwindow); | 3725 if (!(IMAGE_INSTANCE_TYPE (ii) == IMAGE_WIDGET |
4455 | 3726 || |
4456 if (!image_instance_type_to_mask (IMAGE_INSTANCE_TYPE (ii)) | 3727 IMAGE_INSTANCE_TYPE (ii) == IMAGE_SUBWINDOW) |
4457 & (IMAGE_WIDGET_MASK | IMAGE_SUBWINDOW_MASK)) | 3728 || |
3729 NILP (IMAGE_INSTANCE_SUBWINDOW_FRAME (ii))) | |
4458 return; | 3730 return; |
4459 | 3731 |
4460 #ifdef DEBUG_WIDGETS | 3732 f = XFRAME (IMAGE_INSTANCE_SUBWINDOW_FRAME (ii)); |
4461 stderr_out ("mapping subwindow %d, %dx%d@%d+%d\n", | |
4462 IMAGE_INSTANCE_SUBWINDOW_ID (ii), | |
4463 dga->width, dga->height, x, y); | |
4464 #endif | |
4465 f = XFRAME (IMAGE_INSTANCE_FRAME (ii)); | |
4466 IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (ii) = 1; | 3733 IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (ii) = 1; |
4467 IMAGE_INSTANCE_DISPLAY_X (ii) = x; | 3734 elt = get_subwindow_cachel_index (f, subwindow); |
4468 IMAGE_INSTANCE_DISPLAY_Y (ii) = y; | 3735 cachel = Dynarr_atp (f->subwindow_cachels, elt); |
4469 IMAGE_INSTANCE_DISPLAY_WIDTH (ii) = dga->width; | 3736 cachel->x = x; |
4470 IMAGE_INSTANCE_DISPLAY_HEIGHT (ii) = dga->height; | 3737 cachel->y = y; |
4471 | 3738 cachel->being_displayed = 1; |
4472 MAYBE_DEVMETH (DOMAIN_XDEVICE (ii->domain), | 3739 |
4473 map_subwindow, (ii, x, y, dga)); | 3740 MAYBE_DEVMETH (XDEVICE (ii->device), map_subwindow, (ii, x, y)); |
4474 } | 3741 } |
4475 | 3742 |
4476 static int | 3743 static int |
4477 subwindow_possible_dest_types (void) | 3744 subwindow_possible_dest_types (void) |
4478 { | 3745 { |
4479 return IMAGE_SUBWINDOW_MASK; | 3746 return IMAGE_SUBWINDOW_MASK; |
4480 } | |
4481 | |
4482 int | |
4483 subwindow_governing_domain (void) | |
4484 { | |
4485 return GOVERNING_DOMAIN_WINDOW; | |
4486 } | 3747 } |
4487 | 3748 |
4488 /* Partially instantiate a subwindow. */ | 3749 /* Partially instantiate a subwindow. */ |
4489 void | 3750 void |
4490 subwindow_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, | 3751 subwindow_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, |
4491 Lisp_Object pointer_fg, Lisp_Object pointer_bg, | 3752 Lisp_Object pointer_fg, Lisp_Object pointer_bg, |
4492 int dest_mask, Lisp_Object domain) | 3753 int dest_mask, Lisp_Object domain) |
4493 { | 3754 { |
4494 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); | 3755 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); |
4495 Lisp_Object device = image_instance_device (image_instance); | 3756 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii); |
4496 Lisp_Object frame = DOMAIN_FRAME (domain); | 3757 Lisp_Object frame = FW_FRAME (domain); |
4497 Lisp_Object width = find_keyword_in_vector (instantiator, Q_pixel_width); | 3758 Lisp_Object width = find_keyword_in_vector (instantiator, Q_pixel_width); |
4498 Lisp_Object height = find_keyword_in_vector (instantiator, Q_pixel_height); | 3759 Lisp_Object height = find_keyword_in_vector (instantiator, Q_pixel_height); |
4499 | 3760 |
4500 if (NILP (frame)) | 3761 if (NILP (frame)) |
4501 signal_simple_error ("No selected frame", device); | 3762 signal_simple_error ("No selected frame", device); |
4502 | 3763 |
4503 if (!(dest_mask & IMAGE_SUBWINDOW_MASK)) | 3764 if (!(dest_mask & IMAGE_SUBWINDOW_MASK)) |
4504 incompatible_image_types (instantiator, dest_mask, IMAGE_SUBWINDOW_MASK); | 3765 incompatible_image_types (instantiator, dest_mask, IMAGE_SUBWINDOW_MASK); |
4505 | 3766 |
4506 ii->data = 0; | 3767 ii->data = 0; |
4507 IMAGE_INSTANCE_SUBWINDOW_ID (ii) = 0; | 3768 IMAGE_INSTANCE_SUBWINDOW_ID (ii) = 0; |
3769 IMAGE_INSTANCE_SUBWINDOW_FRAME (ii) = Qnil; | |
4508 IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (ii) = 0; | 3770 IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (ii) = 0; |
4509 | 3771 IMAGE_INSTANCE_SUBWINDOW_FRAME (ii) = frame; |
4510 if (INTP (width)) | 3772 |
3773 /* this stuff may get overidden by the widget code */ | |
3774 if (NILP (width)) | |
3775 IMAGE_INSTANCE_SUBWINDOW_WIDTH (ii) = 20; | |
3776 else | |
4511 { | 3777 { |
4512 int w = 1; | 3778 int w = 1; |
3779 CHECK_INT (width); | |
4513 if (XINT (width) > 1) | 3780 if (XINT (width) > 1) |
4514 w = XINT (width); | 3781 w = XINT (width); |
4515 IMAGE_INSTANCE_WIDTH (ii) = w; | 3782 IMAGE_INSTANCE_SUBWINDOW_WIDTH (ii) = w; |
4516 IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii) = 0; | 3783 } |
4517 } | 3784 if (NILP (height)) |
4518 | 3785 IMAGE_INSTANCE_SUBWINDOW_HEIGHT (ii) = 20; |
4519 if (INTP (height)) | 3786 else |
4520 { | 3787 { |
4521 int h = 1; | 3788 int h = 1; |
3789 CHECK_INT (height); | |
4522 if (XINT (height) > 1) | 3790 if (XINT (height) > 1) |
4523 h = XINT (height); | 3791 h = XINT (height); |
4524 IMAGE_INSTANCE_HEIGHT (ii) = h; | 3792 IMAGE_INSTANCE_SUBWINDOW_HEIGHT (ii) = h; |
4525 IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii) = 0; | 3793 } |
4526 } | |
4527 } | |
4528 | |
4529 /* This is just a backup in case no-one has assigned a suitable geometry. | |
4530 #### It should really query the enclose window for geometry. */ | |
4531 static void | |
4532 subwindow_query_geometry (Lisp_Object image_instance, int* width, | |
4533 int* height, enum image_instance_geometry disp, | |
4534 Lisp_Object domain) | |
4535 { | |
4536 if (width) *width = 20; | |
4537 if (height) *height = 20; | |
4538 } | 3794 } |
4539 | 3795 |
4540 DEFUN ("subwindowp", Fsubwindowp, 1, 1, 0, /* | 3796 DEFUN ("subwindowp", Fsubwindowp, 1, 1, 0, /* |
4541 Return non-nil if OBJECT is a subwindow. | 3797 Return non-nil if OBJECT is a subwindow. |
4542 */ | 3798 */ |
4550 Return the window id of SUBWINDOW as a number. | 3806 Return the window id of SUBWINDOW as a number. |
4551 */ | 3807 */ |
4552 (subwindow)) | 3808 (subwindow)) |
4553 { | 3809 { |
4554 CHECK_SUBWINDOW_IMAGE_INSTANCE (subwindow); | 3810 CHECK_SUBWINDOW_IMAGE_INSTANCE (subwindow); |
4555 return make_int ((int) XIMAGE_INSTANCE_SUBWINDOW_ID (subwindow)); | 3811 return make_int ((int) (XIMAGE_INSTANCE_SUBWINDOW_ID (subwindow))); |
4556 } | 3812 } |
4557 | 3813 |
4558 DEFUN ("resize-subwindow", Fresize_subwindow, 1, 3, 0, /* | 3814 DEFUN ("resize-subwindow", Fresize_subwindow, 1, 3, 0, /* |
4559 Resize SUBWINDOW to WIDTH x HEIGHT. | 3815 Resize SUBWINDOW to WIDTH x HEIGHT. |
4560 If a value is nil that parameter is not changed. | 3816 If a value is nil that parameter is not changed. |
4561 */ | 3817 */ |
4562 (subwindow, width, height)) | 3818 (subwindow, width, height)) |
4563 { | 3819 { |
4564 int neww, newh; | 3820 int neww, newh; |
4565 Lisp_Image_Instance* ii; | |
4566 | 3821 |
4567 CHECK_SUBWINDOW_IMAGE_INSTANCE (subwindow); | 3822 CHECK_SUBWINDOW_IMAGE_INSTANCE (subwindow); |
4568 ii = XIMAGE_INSTANCE (subwindow); | |
4569 | 3823 |
4570 if (NILP (width)) | 3824 if (NILP (width)) |
4571 neww = IMAGE_INSTANCE_WIDTH (ii); | 3825 neww = XIMAGE_INSTANCE_SUBWINDOW_WIDTH (subwindow); |
4572 else | 3826 else |
4573 neww = XINT (width); | 3827 neww = XINT (width); |
4574 | 3828 |
4575 if (NILP (height)) | 3829 if (NILP (height)) |
4576 newh = IMAGE_INSTANCE_HEIGHT (ii); | 3830 newh = XIMAGE_INSTANCE_SUBWINDOW_HEIGHT (subwindow); |
4577 else | 3831 else |
4578 newh = XINT (height); | 3832 newh = XINT (height); |
4579 | 3833 |
4580 /* The actual resizing gets done asychronously by | 3834 |
4581 update_subwindow. */ | 3835 MAYBE_DEVMETH (XDEVICE (XIMAGE_INSTANCE_DEVICE (subwindow)), |
4582 IMAGE_INSTANCE_HEIGHT (ii) = newh; | 3836 resize_subwindow, (XIMAGE_INSTANCE (subwindow), neww, newh)); |
4583 IMAGE_INSTANCE_WIDTH (ii) = neww; | 3837 |
4584 IMAGE_INSTANCE_SIZE_CHANGED (ii) = 1; | 3838 XIMAGE_INSTANCE_SUBWINDOW_HEIGHT (subwindow) = newh; |
3839 XIMAGE_INSTANCE_SUBWINDOW_WIDTH (subwindow) = neww; | |
4585 | 3840 |
4586 return subwindow; | 3841 return subwindow; |
4587 } | 3842 } |
4588 | 3843 |
4589 DEFUN ("force-subwindow-map", Fforce_subwindow_map, 1, 1, 0, /* | 3844 DEFUN ("force-subwindow-map", Fforce_subwindow_map, 1, 1, 0, /* |
4590 Generate a Map event for SUBWINDOW. | 3845 Generate a Map event for SUBWINDOW. |
4591 */ | 3846 */ |
4592 (subwindow)) | 3847 (subwindow)) |
4593 { | 3848 { |
4594 CHECK_SUBWINDOW_IMAGE_INSTANCE (subwindow); | 3849 CHECK_SUBWINDOW_IMAGE_INSTANCE (subwindow); |
4595 #if 0 | 3850 |
4596 map_subwindow (subwindow, 0, 0); | 3851 map_subwindow (subwindow, 0, 0); |
4597 #endif | 3852 |
4598 return subwindow; | 3853 return subwindow; |
4599 } | 3854 } |
4600 | 3855 |
4601 | 3856 |
4602 /***************************************************************************** | 3857 /***************************************************************************** |
4678 } | 3933 } |
4679 else | 3934 else |
4680 abort (); | 3935 abort (); |
4681 } | 3936 } |
4682 } | 3937 } |
4683 | |
4684 /***************************************************************************** | |
4685 * timeouts for animated glyphs * | |
4686 *****************************************************************************/ | |
4687 static Lisp_Object Qglyph_animated_timeout_handler; | |
4688 | |
4689 DEFUN ("glyph-animated-timeout-handler", Fglyph_animated_timeout_handler, 1, 1, 0, /* | |
4690 Callback function for updating animated images. | |
4691 Don't use this. | |
4692 */ | |
4693 (arg)) | |
4694 { | |
4695 CHECK_WEAK_LIST (arg); | |
4696 | |
4697 if (!NILP (XWEAK_LIST_LIST (arg)) && !NILP (XCAR (XWEAK_LIST_LIST (arg)))) | |
4698 { | |
4699 Lisp_Object value = XCAR (XWEAK_LIST_LIST (arg)); | |
4700 | |
4701 if (IMAGE_INSTANCEP (value)) | |
4702 { | |
4703 Lisp_Image_Instance* ii = XIMAGE_INSTANCE (value); | |
4704 | |
4705 if (COLOR_PIXMAP_IMAGE_INSTANCEP (value) | |
4706 && | |
4707 IMAGE_INSTANCE_PIXMAP_MAXSLICE (ii) > 1 | |
4708 && | |
4709 !disable_animated_pixmaps) | |
4710 { | |
4711 /* Increment the index of the image slice we are currently | |
4712 viewing. */ | |
4713 IMAGE_INSTANCE_PIXMAP_SLICE (ii) = | |
4714 (IMAGE_INSTANCE_PIXMAP_SLICE (ii) + 1) | |
4715 % IMAGE_INSTANCE_PIXMAP_MAXSLICE (ii); | |
4716 /* We might need to kick redisplay at this point - but we | |
4717 also might not. */ | |
4718 MARK_DEVICE_FRAMES_GLYPHS_CHANGED | |
4719 (XDEVICE (image_instance_device (value))); | |
4720 /* Cascade dirtiness so that we can have an animated glyph in a layout | |
4721 for instance. */ | |
4722 set_image_instance_dirty_p (value, 1); | |
4723 } | |
4724 } | |
4725 } | |
4726 return Qnil; | |
4727 } | |
4728 | |
4729 Lisp_Object add_glyph_animated_timeout (EMACS_INT tickms, Lisp_Object image) | |
4730 { | |
4731 Lisp_Object ret = Qnil; | |
4732 | |
4733 if (tickms > 0 && IMAGE_INSTANCEP (image)) | |
4734 { | |
4735 double ms = ((double)tickms) / 1000.0; | |
4736 struct gcpro gcpro1; | |
4737 Lisp_Object holder = make_weak_list (WEAK_LIST_SIMPLE); | |
4738 | |
4739 GCPRO1 (holder); | |
4740 XWEAK_LIST_LIST (holder) = Fcons (image, Qnil); | |
4741 | |
4742 ret = Fadd_timeout (make_float (ms), | |
4743 Qglyph_animated_timeout_handler, | |
4744 holder, make_float (ms)); | |
4745 | |
4746 UNGCPRO; | |
4747 } | |
4748 return ret; | |
4749 } | |
4750 | |
4751 void disable_glyph_animated_timeout (int i) | |
4752 { | |
4753 Lisp_Object id; | |
4754 XSETINT (id, i); | |
4755 | |
4756 Fdisable_timeout (id); | |
4757 } | |
4758 | |
4759 | 3938 |
4760 /***************************************************************************** | 3939 /***************************************************************************** |
4761 * initialization * | 3940 * initialization * |
4762 *****************************************************************************/ | 3941 *****************************************************************************/ |
4763 | 3942 |
4764 void | 3943 void |
4765 syms_of_glyphs (void) | 3944 syms_of_glyphs (void) |
4766 { | 3945 { |
4767 INIT_LRECORD_IMPLEMENTATION (glyph); | |
4768 INIT_LRECORD_IMPLEMENTATION (image_instance); | |
4769 | |
4770 /* image instantiators */ | 3946 /* image instantiators */ |
4771 | 3947 |
4772 DEFSUBR (Fimage_instantiator_format_list); | 3948 DEFSUBR (Fimage_instantiator_format_list); |
4773 DEFSUBR (Fvalid_image_instantiator_format_p); | 3949 DEFSUBR (Fvalid_image_instantiator_format_p); |
4774 DEFSUBR (Fset_console_type_image_conversion_list); | 3950 DEFSUBR (Fset_console_type_image_conversion_list); |
4812 DEFSUBR (Fimage_instance_p); | 3988 DEFSUBR (Fimage_instance_p); |
4813 DEFSUBR (Fimage_instance_type); | 3989 DEFSUBR (Fimage_instance_type); |
4814 DEFSUBR (Fvalid_image_instance_type_p); | 3990 DEFSUBR (Fvalid_image_instance_type_p); |
4815 DEFSUBR (Fimage_instance_type_list); | 3991 DEFSUBR (Fimage_instance_type_list); |
4816 DEFSUBR (Fimage_instance_name); | 3992 DEFSUBR (Fimage_instance_name); |
4817 DEFSUBR (Fimage_instance_domain); | |
4818 DEFSUBR (Fimage_instance_string); | 3993 DEFSUBR (Fimage_instance_string); |
4819 DEFSUBR (Fimage_instance_file_name); | 3994 DEFSUBR (Fimage_instance_file_name); |
4820 DEFSUBR (Fimage_instance_mask_file_name); | 3995 DEFSUBR (Fimage_instance_mask_file_name); |
4821 DEFSUBR (Fimage_instance_depth); | 3996 DEFSUBR (Fimage_instance_depth); |
4822 DEFSUBR (Fimage_instance_height); | 3997 DEFSUBR (Fimage_instance_height); |
4864 DEFSUBR (Fglyph_height); | 4039 DEFSUBR (Fglyph_height); |
4865 | 4040 |
4866 /* Qbuffer defined in general.c. */ | 4041 /* Qbuffer defined in general.c. */ |
4867 /* Qpointer defined above */ | 4042 /* Qpointer defined above */ |
4868 | 4043 |
4869 /* Unfortunately, timeout handlers must be lisp functions. This is | |
4870 for animated glyphs. */ | |
4871 defsymbol (&Qglyph_animated_timeout_handler, | |
4872 "glyph-animated-timeout-handler"); | |
4873 DEFSUBR (Fglyph_animated_timeout_handler); | |
4874 | |
4875 /* Errors */ | 4044 /* Errors */ |
4876 deferror (&Qimage_conversion_error, | 4045 deferror (&Qimage_conversion_error, |
4877 "image-conversion-error", | 4046 "image-conversion-error", |
4878 "image-conversion error", Qio_error); | 4047 "image-conversion error", Qio_error); |
4879 | 4048 |
4880 } | 4049 } |
4881 | |
4882 static const struct lrecord_description image_specifier_description[] = { | |
4883 { XD_LISP_OBJECT, specifier_data_offset + offsetof (struct image_specifier, attachee) }, | |
4884 { XD_LISP_OBJECT, specifier_data_offset + offsetof (struct image_specifier, attachee_property) }, | |
4885 { XD_END } | |
4886 }; | |
4887 | 4050 |
4888 void | 4051 void |
4889 specifier_type_create_image (void) | 4052 specifier_type_create_image (void) |
4890 { | 4053 { |
4891 /* image specifiers */ | 4054 /* image specifiers */ |
4896 SPECIFIER_HAS_METHOD (image, mark); | 4059 SPECIFIER_HAS_METHOD (image, mark); |
4897 SPECIFIER_HAS_METHOD (image, instantiate); | 4060 SPECIFIER_HAS_METHOD (image, instantiate); |
4898 SPECIFIER_HAS_METHOD (image, validate); | 4061 SPECIFIER_HAS_METHOD (image, validate); |
4899 SPECIFIER_HAS_METHOD (image, after_change); | 4062 SPECIFIER_HAS_METHOD (image, after_change); |
4900 SPECIFIER_HAS_METHOD (image, going_to_add); | 4063 SPECIFIER_HAS_METHOD (image, going_to_add); |
4901 SPECIFIER_HAS_METHOD (image, copy_instantiator); | 4064 } |
4902 } | |
4903 | |
4904 void | |
4905 reinit_specifier_type_create_image (void) | |
4906 { | |
4907 REINITIALIZE_SPECIFIER_TYPE (image); | |
4908 } | |
4909 | |
4910 | |
4911 static const struct lrecord_description iike_description_1[] = { | |
4912 { XD_LISP_OBJECT, offsetof (ii_keyword_entry, keyword) }, | |
4913 { XD_END } | |
4914 }; | |
4915 | |
4916 static const struct struct_description iike_description = { | |
4917 sizeof (ii_keyword_entry), | |
4918 iike_description_1 | |
4919 }; | |
4920 | |
4921 static const struct lrecord_description iiked_description_1[] = { | |
4922 XD_DYNARR_DESC (ii_keyword_entry_dynarr, &iike_description), | |
4923 { XD_END } | |
4924 }; | |
4925 | |
4926 static const struct struct_description iiked_description = { | |
4927 sizeof (ii_keyword_entry_dynarr), | |
4928 iiked_description_1 | |
4929 }; | |
4930 | |
4931 static const struct lrecord_description iife_description_1[] = { | |
4932 { XD_LISP_OBJECT, offsetof (image_instantiator_format_entry, symbol) }, | |
4933 { XD_LISP_OBJECT, offsetof (image_instantiator_format_entry, device) }, | |
4934 { XD_STRUCT_PTR, offsetof (image_instantiator_format_entry, meths), 1, &iim_description }, | |
4935 { XD_END } | |
4936 }; | |
4937 | |
4938 static const struct struct_description iife_description = { | |
4939 sizeof (image_instantiator_format_entry), | |
4940 iife_description_1 | |
4941 }; | |
4942 | |
4943 static const struct lrecord_description iifed_description_1[] = { | |
4944 XD_DYNARR_DESC (image_instantiator_format_entry_dynarr, &iife_description), | |
4945 { XD_END } | |
4946 }; | |
4947 | |
4948 static const struct struct_description iifed_description = { | |
4949 sizeof (image_instantiator_format_entry_dynarr), | |
4950 iifed_description_1 | |
4951 }; | |
4952 | |
4953 static const struct lrecord_description iim_description_1[] = { | |
4954 { XD_LISP_OBJECT, offsetof (struct image_instantiator_methods, symbol) }, | |
4955 { XD_LISP_OBJECT, offsetof (struct image_instantiator_methods, device) }, | |
4956 { XD_STRUCT_PTR, offsetof (struct image_instantiator_methods, keywords), 1, &iiked_description }, | |
4957 { XD_STRUCT_PTR, offsetof (struct image_instantiator_methods, consoles), 1, &cted_description }, | |
4958 { XD_END } | |
4959 }; | |
4960 | |
4961 const struct struct_description iim_description = { | |
4962 sizeof(struct image_instantiator_methods), | |
4963 iim_description_1 | |
4964 }; | |
4965 | 4065 |
4966 void | 4066 void |
4967 image_instantiator_format_create (void) | 4067 image_instantiator_format_create (void) |
4968 { | 4068 { |
4969 /* image instantiators */ | 4069 /* image instantiators */ |
4971 the_image_instantiator_format_entry_dynarr = | 4071 the_image_instantiator_format_entry_dynarr = |
4972 Dynarr_new (image_instantiator_format_entry); | 4072 Dynarr_new (image_instantiator_format_entry); |
4973 | 4073 |
4974 Vimage_instantiator_format_list = Qnil; | 4074 Vimage_instantiator_format_list = Qnil; |
4975 staticpro (&Vimage_instantiator_format_list); | 4075 staticpro (&Vimage_instantiator_format_list); |
4976 | |
4977 dumpstruct (&the_image_instantiator_format_entry_dynarr, &iifed_description); | |
4978 | 4076 |
4979 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (nothing, "nothing"); | 4077 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (nothing, "nothing"); |
4980 | 4078 |
4981 IIFORMAT_HAS_METHOD (nothing, possible_dest_types); | 4079 IIFORMAT_HAS_METHOD (nothing, possible_dest_types); |
4982 IIFORMAT_HAS_METHOD (nothing, instantiate); | 4080 IIFORMAT_HAS_METHOD (nothing, instantiate); |
4991 IIFORMAT_VALID_KEYWORD (inherit, Q_face, check_valid_face); | 4089 IIFORMAT_VALID_KEYWORD (inherit, Q_face, check_valid_face); |
4992 | 4090 |
4993 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (string, "string"); | 4091 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (string, "string"); |
4994 | 4092 |
4995 IIFORMAT_HAS_METHOD (string, validate); | 4093 IIFORMAT_HAS_METHOD (string, validate); |
4996 IIFORMAT_HAS_SHARED_METHOD (string, governing_domain, subwindow); | |
4997 IIFORMAT_HAS_METHOD (string, possible_dest_types); | 4094 IIFORMAT_HAS_METHOD (string, possible_dest_types); |
4998 IIFORMAT_HAS_METHOD (string, instantiate); | 4095 IIFORMAT_HAS_METHOD (string, instantiate); |
4999 | 4096 |
5000 IIFORMAT_VALID_KEYWORD (string, Q_data, check_valid_string); | 4097 IIFORMAT_VALID_KEYWORD (string, Q_data, check_valid_string); |
5001 /* Do this so we can set strings. */ | |
5002 /* #### Andy, what is this? This is a bogus format and should not be | |
5003 visible to the user. */ | |
5004 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (text, "text"); | |
5005 IIFORMAT_HAS_METHOD (text, set_property); | |
5006 IIFORMAT_HAS_METHOD (text, query_geometry); | |
5007 | 4098 |
5008 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (formatted_string, "formatted-string"); | 4099 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (formatted_string, "formatted-string"); |
5009 | 4100 |
5010 IIFORMAT_HAS_METHOD (formatted_string, validate); | 4101 IIFORMAT_HAS_METHOD (formatted_string, validate); |
5011 IIFORMAT_HAS_METHOD (formatted_string, possible_dest_types); | 4102 IIFORMAT_HAS_METHOD (formatted_string, possible_dest_types); |
5012 IIFORMAT_HAS_METHOD (formatted_string, instantiate); | 4103 IIFORMAT_HAS_METHOD (formatted_string, instantiate); |
4104 | |
5013 IIFORMAT_VALID_KEYWORD (formatted_string, Q_data, check_valid_string); | 4105 IIFORMAT_VALID_KEYWORD (formatted_string, Q_data, check_valid_string); |
5014 | |
5015 /* Do this so pointers have geometry. */ | |
5016 /* #### Andy, what is this? This is a bogus format and should not be | |
5017 visible to the user. */ | |
5018 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (pointer, "pointer"); | |
5019 IIFORMAT_HAS_SHARED_METHOD (pointer, query_geometry, subwindow); | |
5020 | 4106 |
5021 /* subwindows */ | 4107 /* subwindows */ |
5022 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (subwindow, "subwindow"); | 4108 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (subwindow, "subwindow"); |
5023 IIFORMAT_HAS_METHOD (subwindow, possible_dest_types); | 4109 IIFORMAT_HAS_METHOD (subwindow, possible_dest_types); |
5024 IIFORMAT_HAS_METHOD (subwindow, governing_domain); | |
5025 IIFORMAT_HAS_METHOD (subwindow, instantiate); | 4110 IIFORMAT_HAS_METHOD (subwindow, instantiate); |
5026 IIFORMAT_HAS_METHOD (subwindow, query_geometry); | |
5027 IIFORMAT_VALID_KEYWORD (subwindow, Q_pixel_width, check_valid_int); | 4111 IIFORMAT_VALID_KEYWORD (subwindow, Q_pixel_width, check_valid_int); |
5028 IIFORMAT_VALID_KEYWORD (subwindow, Q_pixel_height, check_valid_int); | 4112 IIFORMAT_VALID_KEYWORD (subwindow, Q_pixel_height, check_valid_int); |
5029 | 4113 |
5030 #ifdef HAVE_WINDOW_SYSTEM | 4114 #ifdef HAVE_WINDOW_SYSTEM |
5031 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (xbm, "xbm"); | 4115 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (xbm, "xbm"); |
5071 IIFORMAT_VALID_KEYWORD (xpm, Q_color_symbols, check_valid_xpm_color_symbols); | 4155 IIFORMAT_VALID_KEYWORD (xpm, Q_color_symbols, check_valid_xpm_color_symbols); |
5072 #endif /* HAVE_XPM */ | 4156 #endif /* HAVE_XPM */ |
5073 } | 4157 } |
5074 | 4158 |
5075 void | 4159 void |
5076 reinit_vars_of_glyphs (void) | |
5077 { | |
5078 the_expose_ignore_blocktype = | |
5079 Blocktype_new (struct expose_ignore_blocktype); | |
5080 | |
5081 hold_ignored_expose_registration = 0; | |
5082 } | |
5083 | |
5084 | |
5085 void | |
5086 vars_of_glyphs (void) | 4160 vars_of_glyphs (void) |
5087 { | 4161 { |
5088 reinit_vars_of_glyphs (); | |
5089 | |
5090 Vthe_nothing_vector = vector1 (Qnothing); | 4162 Vthe_nothing_vector = vector1 (Qnothing); |
5091 staticpro (&Vthe_nothing_vector); | 4163 staticpro (&Vthe_nothing_vector); |
5092 | 4164 |
5093 /* image instances */ | 4165 /* image instances */ |
5094 | 4166 |
5095 Vimage_instance_type_list = Fcons (Qnothing, | 4167 Vimage_instance_type_list = Fcons (Qnothing, |
5096 list6 (Qtext, Qmono_pixmap, Qcolor_pixmap, | 4168 list6 (Qtext, Qmono_pixmap, Qcolor_pixmap, |
5097 Qpointer, Qsubwindow, Qwidget)); | 4169 Qpointer, Qsubwindow, Qwidget)); |
5098 staticpro (&Vimage_instance_type_list); | 4170 staticpro (&Vimage_instance_type_list); |
5099 | 4171 |
5100 /* glyphs */ | 4172 /* glyphs */ |
5101 | 4173 |
5150 Vxpm_color_symbols = Qnil; /* initialized in x-faces.el */ | 4222 Vxpm_color_symbols = Qnil; /* initialized in x-faces.el */ |
5151 #endif /* HAVE_XPM */ | 4223 #endif /* HAVE_XPM */ |
5152 #ifdef HAVE_XFACE | 4224 #ifdef HAVE_XFACE |
5153 Fprovide (Qxface); | 4225 Fprovide (Qxface); |
5154 #endif | 4226 #endif |
5155 | |
5156 DEFVAR_BOOL ("disable-animated-pixmaps", &disable_animated_pixmaps /* | |
5157 Whether animated pixmaps should be animated. | |
5158 Default is t. | |
5159 */); | |
5160 disable_animated_pixmaps = 0; | |
5161 } | 4227 } |
5162 | 4228 |
5163 void | 4229 void |
5164 specifier_vars_of_glyphs (void) | 4230 specifier_vars_of_glyphs (void) |
5165 { | 4231 { |
5168 /* display tables */ | 4234 /* display tables */ |
5169 | 4235 |
5170 DEFVAR_SPECIFIER ("current-display-table", &Vcurrent_display_table /* | 4236 DEFVAR_SPECIFIER ("current-display-table", &Vcurrent_display_table /* |
5171 *The display table currently in use. | 4237 *The display table currently in use. |
5172 This is a specifier; use `set-specifier' to change it. | 4238 This is a specifier; use `set-specifier' to change it. |
5173 | 4239 The display table is a vector created with `make-display-table'. |
5174 Display tables are used to control how characters are displayed. Each | 4240 The 256 elements control how to display each possible text character. |
5175 time that redisplay processes a character, it is looked up in all the | 4241 Each value should be a string, a glyph, a vector or nil. |
5176 display tables that apply (obtained by calling `specifier-instance' on | 4242 If a value is a vector it must be composed only of strings and glyphs. |
5177 `current-display-table' and any overriding display tables specified in | 4243 nil means display the character in the default fashion. |
5178 currently active faces). The first entry found that matches the | 4244 Faces can have their own, overriding display table. |
5179 character determines how the character is displayed. If there is no | |
5180 matching entry, the default display method is used. (Non-control | |
5181 characters are displayed as themselves and control characters are | |
5182 displayed according to the buffer-local variable `ctl-arrow'. Control | |
5183 characters are further affected by `control-arrow-glyph' and | |
5184 `octal-escape-glyph'.) | |
5185 | |
5186 Each instantiator in this specifier and the display-table specifiers | |
5187 in faces is a display table or a list of such tables. If a list, each | |
5188 table will be searched in turn for an entry matching a particular | |
5189 character. Each display table is one of | |
5190 | |
5191 -- a vector, specifying values for characters starting at 0 | |
5192 -- a char table, either of type `char' or `generic' | |
5193 -- a range table | |
5194 | |
5195 Each entry in a display table should be one of | |
5196 | |
5197 -- nil (this entry is ignored and the search continues) | |
5198 -- a character (use this character; if it happens to be the same as | |
5199 the original character, default processing happens, otherwise | |
5200 redisplay attempts to display this character directly; | |
5201 #### At some point recursive display-table lookup will be | |
5202 implemented.) | |
5203 -- a string (display each character in the string directly; | |
5204 #### At some point recursive display-table lookup will be | |
5205 implemented.) | |
5206 -- a glyph (display the glyph; | |
5207 #### At some point recursive display-table lookup will be | |
5208 implemented when a string glyph is being processed.) | |
5209 -- a cons of the form (format "STRING") where STRING is a printf-like | |
5210 spec used to process the character. #### Unfortunately no | |
5211 formatting directives other than %% are implemented. | |
5212 -- a vector (each element of the vector is processed recursively; | |
5213 in such a case, nil elements in the vector are simply ignored) | |
5214 | |
5215 #### At some point in the near future, display tables are likely to | |
5216 be expanded to include other features, such as referencing characters | |
5217 in particular fonts and allowing the character search to continue | |
5218 all the way up the chain of specifier instantiators. These features | |
5219 are necessary to properly display Unicode characters. | |
5220 */ ); | 4245 */ ); |
5221 Vcurrent_display_table = Fmake_specifier (Qdisplay_table); | 4246 Vcurrent_display_table = Fmake_specifier (Qdisplay_table); |
5222 set_specifier_fallback (Vcurrent_display_table, | 4247 set_specifier_fallback (Vcurrent_display_table, |
5223 list1 (Fcons (Qnil, Qnil))); | 4248 list1 (Fcons (Qnil, Qnil))); |
5224 set_specifier_caching (Vcurrent_display_table, | 4249 set_specifier_caching (Vcurrent_display_table, |
5225 offsetof (struct window, display_table), | 4250 slot_offset (struct window, |
4251 display_table), | |
5226 some_window_value_changed, | 4252 some_window_value_changed, |
5227 0, 0); | 4253 0, 0); |
5228 } | 4254 } |
5229 | 4255 |
5230 void | 4256 void |