comparison src/glyphs.c @ 398:74fd4e045ea6 r21-2-29

Import from CVS: tag r21-2-29
author cvs
date Mon, 13 Aug 2007 11:13:30 +0200
parents aabb7f5b1c81
children a86b2b5e0111
comparison
equal deleted inserted replaced
397:f4aeb21a5bad 398:74fd4e045ea6
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 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 Andy Piper 6 Copyright (C) 1998, 1999, 2000 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 */ 27 /* Written by Ben Wing and Chuck Thompson. Heavily modified /
28 rewritten by Andy Piper. */
28 29
29 #include <config.h> 30 #include <config.h>
30 #include "lisp.h" 31 #include "lisp.h"
31 32
32 #include "buffer.h" 33 #include "buffer.h"
40 #include "redisplay.h" 41 #include "redisplay.h"
41 #include "window.h" 42 #include "window.h"
42 #include "frame.h" 43 #include "frame.h"
43 #include "chartab.h" 44 #include "chartab.h"
44 #include "rangetab.h" 45 #include "rangetab.h"
46 #include "blocktype.h"
45 47
46 #ifdef HAVE_XPM 48 #ifdef HAVE_XPM
47 #include <X11/xpm.h> 49 #include <X11/xpm.h>
48 #endif 50 #endif
49 51
54 Lisp_Object Qnothing_image_instance_p, Qtext_image_instance_p; 56 Lisp_Object Qnothing_image_instance_p, Qtext_image_instance_p;
55 Lisp_Object Qmono_pixmap_image_instance_p; 57 Lisp_Object Qmono_pixmap_image_instance_p;
56 Lisp_Object Qcolor_pixmap_image_instance_p; 58 Lisp_Object Qcolor_pixmap_image_instance_p;
57 Lisp_Object Qpointer_image_instance_p; 59 Lisp_Object Qpointer_image_instance_p;
58 Lisp_Object Qsubwindow_image_instance_p; 60 Lisp_Object Qsubwindow_image_instance_p;
61 Lisp_Object Qlayout_image_instance_p;
59 Lisp_Object Qwidget_image_instance_p; 62 Lisp_Object Qwidget_image_instance_p;
60 Lisp_Object Qconst_glyph_variable; 63 Lisp_Object Qconst_glyph_variable;
61 Lisp_Object Qmono_pixmap, Qcolor_pixmap, Qsubwindow; 64 Lisp_Object Qmono_pixmap, Qcolor_pixmap, Qsubwindow;
62 Lisp_Object Q_file, Q_data, Q_face, Q_pixel_width, Q_pixel_height; 65 Lisp_Object Q_file, Q_data, Q_face, Q_pixel_width, Q_pixel_height;
63 Lisp_Object Qformatted_string; 66 Lisp_Object Qformatted_string;
68 Lisp_Object Vthe_nothing_vector; 71 Lisp_Object Vthe_nothing_vector;
69 Lisp_Object Vimage_instantiator_format_list; 72 Lisp_Object Vimage_instantiator_format_list;
70 Lisp_Object Vimage_instance_type_list; 73 Lisp_Object Vimage_instance_type_list;
71 Lisp_Object Vglyph_type_list; 74 Lisp_Object Vglyph_type_list;
72 75
76 int disable_animated_pixmaps;
77
73 DEFINE_IMAGE_INSTANTIATOR_FORMAT (nothing); 78 DEFINE_IMAGE_INSTANTIATOR_FORMAT (nothing);
74 DEFINE_IMAGE_INSTANTIATOR_FORMAT (inherit); 79 DEFINE_IMAGE_INSTANTIATOR_FORMAT (inherit);
75 DEFINE_IMAGE_INSTANTIATOR_FORMAT (string); 80 DEFINE_IMAGE_INSTANTIATOR_FORMAT (string);
76 DEFINE_IMAGE_INSTANTIATOR_FORMAT (formatted_string); 81 DEFINE_IMAGE_INSTANTIATOR_FORMAT (formatted_string);
77 DEFINE_IMAGE_INSTANTIATOR_FORMAT (subwindow); 82 DEFINE_IMAGE_INSTANTIATOR_FORMAT (subwindow);
83 DEFINE_IMAGE_INSTANTIATOR_FORMAT (text);
78 84
79 #ifdef HAVE_WINDOW_SYSTEM 85 #ifdef HAVE_WINDOW_SYSTEM
80 DEFINE_IMAGE_INSTANTIATOR_FORMAT (xbm); 86 DEFINE_IMAGE_INSTANTIATOR_FORMAT (xbm);
81 Lisp_Object Qxbm; 87 Lisp_Object Qxbm;
82 88
115 } image_instantiator_format_entry_dynarr; 121 } image_instantiator_format_entry_dynarr;
116 122
117 image_instantiator_format_entry_dynarr * 123 image_instantiator_format_entry_dynarr *
118 the_image_instantiator_format_entry_dynarr; 124 the_image_instantiator_format_entry_dynarr;
119 125
120 static Lisp_Object allocate_image_instance (Lisp_Object device); 126 static Lisp_Object allocate_image_instance (Lisp_Object device, Lisp_Object glyph);
121 static void image_validate (Lisp_Object instantiator); 127 static void image_validate (Lisp_Object instantiator);
122 static void glyph_property_was_changed (Lisp_Object glyph, 128 static void glyph_property_was_changed (Lisp_Object glyph,
123 Lisp_Object property, 129 Lisp_Object property,
124 Lisp_Object locale); 130 Lisp_Object locale);
131 static void set_image_instance_dirty_p (Lisp_Object instance, int dirty);
132 static void register_ignored_expose (struct frame* f, int x, int y, int width, int height);
133 /* Unfortunately windows and X are different. In windows BeginPaint()
134 will prevent WM_PAINT messages being generated so it is unnecessary
135 to register exposures as they will not occur. Under X they will
136 always occur. */
137 int hold_ignored_expose_registration;
138
125 EXFUN (Fimage_instance_type, 1); 139 EXFUN (Fimage_instance_type, 1);
126 EXFUN (Fglyph_type, 1); 140 EXFUN (Fglyph_type, 1);
127 141
128 142
129 /**************************************************************************** 143 /****************************************************************************
153 Lisp_Object d = Dynarr_at (the_image_instantiator_format_entry_dynarr, i). 167 Lisp_Object d = Dynarr_at (the_image_instantiator_format_entry_dynarr, i).
154 device; 168 device;
155 if ((NILP (d) && NILP (device)) 169 if ((NILP (d) && NILP (device))
156 || 170 ||
157 (!NILP (device) && 171 (!NILP (device) &&
158 EQ (CONSOLE_TYPE (XCONSOLE 172 EQ (CONSOLE_TYPE (XCONSOLE
159 (DEVICE_CONSOLE (XDEVICE (device)))), d))) 173 (DEVICE_CONSOLE (XDEVICE (device)))), d)))
160 return Dynarr_at (the_image_instantiator_format_entry_dynarr, i).meths; 174 return Dynarr_at (the_image_instantiator_format_entry_dynarr, i).meths;
161 } 175 }
162 } 176 }
163 177
172 { 186 {
173 return decode_device_ii_format (Qnil, format, errb); 187 return decode_device_ii_format (Qnil, format, errb);
174 } 188 }
175 189
176 static int 190 static int
177 valid_image_instantiator_format_p (Lisp_Object format) 191 valid_image_instantiator_format_p (Lisp_Object format, Lisp_Object locale)
178 { 192 {
179 return (decode_image_instantiator_format (format, ERROR_ME_NOT) != 0); 193 int i;
194 struct image_instantiator_methods* meths =
195 decode_image_instantiator_format (format, ERROR_ME_NOT);
196 Lisp_Object contype = Qnil;
197 /* mess with the locale */
198 if (!NILP (locale) && SYMBOLP (locale))
199 contype = locale;
200 else
201 {
202 struct console* console = decode_console (locale);
203 contype = console ? CONSOLE_TYPE (console) : locale;
204 }
205 /* nothing is valid in all locales */
206 if (EQ (format, Qnothing))
207 return 1;
208 /* reject unknown formats */
209 else if (NILP (contype) || !meths)
210 return 0;
211
212 for (i = 0; i < Dynarr_length (meths->consoles); i++)
213 if (EQ (contype, Dynarr_at (meths->consoles, i).symbol))
214 return 1;
215 return 0;
180 } 216 }
181 217
182 DEFUN ("valid-image-instantiator-format-p", Fvalid_image_instantiator_format_p, 218 DEFUN ("valid-image-instantiator-format-p", Fvalid_image_instantiator_format_p,
183 1, 1, 0, /* 219 1, 2, 0, /*
184 Given an IMAGE-INSTANTIATOR-FORMAT, return non-nil if it is valid. 220 Given an IMAGE-INSTANTIATOR-FORMAT, return non-nil if it is valid.
221 If LOCALE is non-nil then the format is checked in that domain.
222 If LOCALE is nil the current console is used.
185 Valid formats are some subset of 'nothing, 'string, 'formatted-string, 223 Valid formats are some subset of 'nothing, 'string, 'formatted-string,
186 'xpm, 'xbm, 'xface, 'gif, 'jpeg, 'png, 'tiff, 'cursor-font, 'font, 224 'xpm, 'xbm, 'xface, 'gif, 'jpeg, 'png, 'tiff, 'cursor-font, 'font,
187 'autodetect, 'widget and 'subwindow, depending on how XEmacs was compiled. 225 'autodetect, 'widget and 'subwindow, depending on how XEmacs was compiled.
188 */ 226 */
189 (image_instantiator_format)) 227 (image_instantiator_format, locale))
190 { 228 {
191 return valid_image_instantiator_format_p (image_instantiator_format) ? 229 return valid_image_instantiator_format_p (image_instantiator_format, locale) ?
192 Qt : Qnil; 230 Qt : Qnil;
193 } 231 }
194 232
195 DEFUN ("image-instantiator-format-list", Fimage_instantiator_format_list, 233 DEFUN ("image-instantiator-format-list", Fimage_instantiator_format_list,
196 0, 0, 0, /* 234 0, 0, 0, /*
524 { 562 {
525 struct gcpro gcpro1; 563 struct gcpro gcpro1;
526 struct image_instantiator_methods *meths; 564 struct image_instantiator_methods *meths;
527 565
528 GCPRO1 (instantiator); 566 GCPRO1 (instantiator);
529 567
530 meths = decode_image_instantiator_format (XVECTOR_DATA (instantiator)[0], 568 meths = decode_image_instantiator_format (XVECTOR_DATA (instantiator)[0],
531 ERROR_ME); 569 ERROR_ME);
532 RETURN_UNGCPRO (IIFORMAT_METH_OR_GIVEN (meths, normalize, 570 RETURN_UNGCPRO (IIFORMAT_METH_OR_GIVEN (meths, normalize,
533 (instantiator, contype), 571 (instantiator, contype),
534 instantiator)); 572 instantiator));
537 575
538 static Lisp_Object 576 static Lisp_Object
539 instantiate_image_instantiator (Lisp_Object device, Lisp_Object domain, 577 instantiate_image_instantiator (Lisp_Object device, Lisp_Object domain,
540 Lisp_Object instantiator, 578 Lisp_Object instantiator,
541 Lisp_Object pointer_fg, Lisp_Object pointer_bg, 579 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
542 int dest_mask) 580 int dest_mask, Lisp_Object glyph)
543 { 581 {
544 Lisp_Object ii = allocate_image_instance (device); 582 Lisp_Object ii = allocate_image_instance (device, glyph);
545 struct image_instantiator_methods *meths; 583 struct image_instantiator_methods *meths;
546 struct gcpro gcpro1; 584 struct gcpro gcpro1;
547 int methp = 0; 585 int methp = 0;
548 586
549 GCPRO1 (ii); 587 GCPRO1 (ii);
588 if (!valid_image_instantiator_format_p (XVECTOR_DATA (instantiator)[0], device))
589 signal_simple_error
590 ("Image instantiator format is invalid in this locale.",
591 instantiator);
592
550 meths = decode_image_instantiator_format (XVECTOR_DATA (instantiator)[0], 593 meths = decode_image_instantiator_format (XVECTOR_DATA (instantiator)[0],
551 ERROR_ME); 594 ERROR_ME);
552 methp = (int)HAS_IIFORMAT_METH_P (meths, instantiate); 595 methp = (int)HAS_IIFORMAT_METH_P (meths, instantiate);
553 MAYBE_IIFORMAT_METH (meths, instantiate, (ii, instantiator, pointer_fg, 596 MAYBE_IIFORMAT_METH (meths, instantiate, (ii, instantiator, pointer_fg,
554 pointer_bg, dest_mask, domain)); 597 pointer_bg, dest_mask, domain));
555 598
556 /* now do device specific instantiation */ 599 /* now do device specific instantiation */
557 meths = decode_device_ii_format (device, XVECTOR_DATA (instantiator)[0], 600 meths = decode_device_ii_format (device, XVECTOR_DATA (instantiator)[0],
558 ERROR_ME_NOT); 601 ERROR_ME_NOT);
559 602
560 if (!methp && (!meths || !HAS_IIFORMAT_METH_P (meths, instantiate))) 603 if (!methp && (!meths || !HAS_IIFORMAT_METH_P (meths, instantiate)))
574 ****************************************************************************/ 617 ****************************************************************************/
575 618
576 Lisp_Object Qimage_instancep; 619 Lisp_Object Qimage_instancep;
577 620
578 static Lisp_Object 621 static Lisp_Object
579 mark_image_instance (Lisp_Object obj, void (*markobj) (Lisp_Object)) 622 mark_image_instance (Lisp_Object obj)
580 { 623 {
581 struct Lisp_Image_Instance *i = XIMAGE_INSTANCE (obj); 624 Lisp_Image_Instance *i = XIMAGE_INSTANCE (obj);
582 625
583 markobj (i->name); 626 mark_object (i->name);
627 /* We don't mark the glyph reference since that would create a
628 circularity preventing GC. */
584 switch (IMAGE_INSTANCE_TYPE (i)) 629 switch (IMAGE_INSTANCE_TYPE (i))
585 { 630 {
586 case IMAGE_TEXT: 631 case IMAGE_TEXT:
587 markobj (IMAGE_INSTANCE_TEXT_STRING (i)); 632 mark_object (IMAGE_INSTANCE_TEXT_STRING (i));
588 break; 633 break;
589 case IMAGE_MONO_PIXMAP: 634 case IMAGE_MONO_PIXMAP:
590 case IMAGE_COLOR_PIXMAP: 635 case IMAGE_COLOR_PIXMAP:
591 markobj (IMAGE_INSTANCE_PIXMAP_FILENAME (i)); 636 mark_object (IMAGE_INSTANCE_PIXMAP_FILENAME (i));
592 markobj (IMAGE_INSTANCE_PIXMAP_MASK_FILENAME (i)); 637 mark_object (IMAGE_INSTANCE_PIXMAP_MASK_FILENAME (i));
593 markobj (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (i)); 638 mark_object (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (i));
594 markobj (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (i)); 639 mark_object (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (i));
595 markobj (IMAGE_INSTANCE_PIXMAP_FG (i)); 640 mark_object (IMAGE_INSTANCE_PIXMAP_FG (i));
596 markobj (IMAGE_INSTANCE_PIXMAP_BG (i)); 641 mark_object (IMAGE_INSTANCE_PIXMAP_BG (i));
597 break; 642 break;
598 643
599 case IMAGE_WIDGET: 644 case IMAGE_WIDGET:
600 markobj (IMAGE_INSTANCE_WIDGET_TYPE (i)); 645 case IMAGE_LAYOUT:
601 markobj (IMAGE_INSTANCE_WIDGET_PROPS (i)); 646 mark_object (IMAGE_INSTANCE_WIDGET_TYPE (i));
602 markobj (IMAGE_INSTANCE_WIDGET_FACE (i)); 647 mark_object (IMAGE_INSTANCE_WIDGET_PROPS (i));
603 mark_gui_item (&IMAGE_INSTANCE_WIDGET_ITEM (i), markobj); 648 mark_object (IMAGE_INSTANCE_WIDGET_FACE (i));
649 mark_object (IMAGE_INSTANCE_WIDGET_ITEMS (i));
604 case IMAGE_SUBWINDOW: 650 case IMAGE_SUBWINDOW:
605 markobj (IMAGE_INSTANCE_SUBWINDOW_FRAME (i)); 651 mark_object (IMAGE_INSTANCE_SUBWINDOW_FRAME (i));
606 break; 652 break;
607 653
608 default: 654 default:
609 break; 655 break;
610 } 656 }
611 657
612 MAYBE_DEVMETH (XDEVICE (i->device), mark_image_instance, (i, markobj)); 658 MAYBE_DEVMETH (XDEVICE (i->device), mark_image_instance, (i));
613 659
614 return i->device; 660 return i->device;
615 } 661 }
616 662
617 static void 663 static void
618 print_image_instance (Lisp_Object obj, Lisp_Object printcharfun, 664 print_image_instance (Lisp_Object obj, Lisp_Object printcharfun,
619 int escapeflag) 665 int escapeflag)
620 { 666 {
621 char buf[100]; 667 char buf[100];
622 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (obj); 668 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (obj);
623 669
624 if (print_readably) 670 if (print_readably)
625 error ("printing unreadable object #<image-instance 0x%x>", 671 error ("printing unreadable object #<image-instance 0x%x>",
626 ii->header.uid); 672 ii->header.uid);
627 write_c_string ("#<image-instance (", printcharfun); 673 write_c_string ("#<image-instance (", printcharfun);
705 write_c_string (")", printcharfun); 751 write_c_string (")", printcharfun);
706 } 752 }
707 break; 753 break;
708 754
709 case IMAGE_WIDGET: 755 case IMAGE_WIDGET:
710 if (!NILP (IMAGE_INSTANCE_WIDGET_CALLBACK (ii)))
711 {
712 print_internal (IMAGE_INSTANCE_WIDGET_CALLBACK (ii), printcharfun, 0);
713 write_c_string (", ", printcharfun);
714 }
715 if (!NILP (IMAGE_INSTANCE_WIDGET_FACE (ii))) 756 if (!NILP (IMAGE_INSTANCE_WIDGET_FACE (ii)))
716 { 757 {
717 write_c_string (" (", printcharfun); 758 write_c_string (" (", printcharfun);
718 print_internal 759 print_internal
719 (IMAGE_INSTANCE_WIDGET_FACE (ii), printcharfun, 0); 760 (IMAGE_INSTANCE_WIDGET_FACE (ii), printcharfun, 0);
722 763
723 if (!NILP (IMAGE_INSTANCE_WIDGET_TEXT (ii))) 764 if (!NILP (IMAGE_INSTANCE_WIDGET_TEXT (ii)))
724 print_internal (IMAGE_INSTANCE_WIDGET_TEXT (ii), printcharfun, 0); 765 print_internal (IMAGE_INSTANCE_WIDGET_TEXT (ii), printcharfun, 0);
725 766
726 case IMAGE_SUBWINDOW: 767 case IMAGE_SUBWINDOW:
768 case IMAGE_LAYOUT:
727 sprintf (buf, " %dx%d", IMAGE_INSTANCE_SUBWINDOW_WIDTH (ii), 769 sprintf (buf, " %dx%d", IMAGE_INSTANCE_SUBWINDOW_WIDTH (ii),
728 IMAGE_INSTANCE_SUBWINDOW_HEIGHT (ii)); 770 IMAGE_INSTANCE_SUBWINDOW_HEIGHT (ii));
729 write_c_string (buf, printcharfun); 771 write_c_string (buf, printcharfun);
730 772
731 /* This is stolen from frame.c. Subwindows are strange in that they 773 /* This is stolen from frame.c. Subwindows are strange in that they
733 description what that frame is. */ 775 description what that frame is. */
734 776
735 write_c_string (" on #<", printcharfun); 777 write_c_string (" on #<", printcharfun);
736 { 778 {
737 struct frame* f = XFRAME (IMAGE_INSTANCE_SUBWINDOW_FRAME (ii)); 779 struct frame* f = XFRAME (IMAGE_INSTANCE_SUBWINDOW_FRAME (ii));
738 780
739 if (!FRAME_LIVE_P (f)) 781 if (!FRAME_LIVE_P (f))
740 write_c_string ("dead", printcharfun); 782 write_c_string ("dead", printcharfun);
741 else 783 else
742 write_c_string (DEVICE_TYPE_NAME (XDEVICE (FRAME_DEVICE (f))), 784 write_c_string (DEVICE_TYPE_NAME (XDEVICE (FRAME_DEVICE (f))),
743 printcharfun); 785 printcharfun);
744 786
745 write_c_string ("-frame ", printcharfun); 787 write_c_string ("-frame ", printcharfun);
746 } 788 }
747 write_c_string (">", printcharfun); 789 write_c_string (">", printcharfun);
748 sprintf (buf, " 0x%p", IMAGE_INSTANCE_SUBWINDOW_ID (ii)); 790 sprintf (buf, " 0x%p", IMAGE_INSTANCE_SUBWINDOW_ID (ii));
749 write_c_string (buf, printcharfun); 791 write_c_string (buf, printcharfun);
750 792
751 break; 793 break;
752 794
753 default: 795 default:
754 abort (); 796 abort ();
755 } 797 }
761 } 803 }
762 804
763 static void 805 static void
764 finalize_image_instance (void *header, int for_disksave) 806 finalize_image_instance (void *header, int for_disksave)
765 { 807 {
766 struct Lisp_Image_Instance *i = (struct Lisp_Image_Instance *) header; 808 Lisp_Image_Instance *i = (Lisp_Image_Instance *) header;
767 809
768 if (IMAGE_INSTANCE_TYPE (i) == IMAGE_NOTHING) 810 if (IMAGE_INSTANCE_TYPE (i) == IMAGE_NOTHING)
769 /* objects like this exist at dump time, so don't bomb out. */ 811 /* objects like this exist at dump time, so don't bomb out. */
770 return; 812 return;
771 if (for_disksave) finalose (i); 813 if (for_disksave) finalose (i);
772 814
773 /* do this so that the cachels get reset */ 815 /* do this so that the cachels get reset */
774 if (IMAGE_INSTANCE_TYPE (i) == IMAGE_WIDGET 816 if (IMAGE_INSTANCE_TYPE (i) == IMAGE_WIDGET
775 || 817 ||
818 IMAGE_INSTANCE_TYPE (i) == IMAGE_SUBWINDOW
819 ||
776 IMAGE_INSTANCE_TYPE (i) == IMAGE_SUBWINDOW) 820 IMAGE_INSTANCE_TYPE (i) == IMAGE_SUBWINDOW)
777 { 821 {
778 MARK_FRAME_GLYPHS_CHANGED 822 MARK_FRAME_SUBWINDOWS_CHANGED
779 (XFRAME (IMAGE_INSTANCE_SUBWINDOW_FRAME (i))); 823 (XFRAME (IMAGE_INSTANCE_SUBWINDOW_FRAME (i)));
780 } 824 }
781 825
782 MAYBE_DEVMETH (XDEVICE (i->device), finalize_image_instance, (i)); 826 MAYBE_DEVMETH (XDEVICE (i->device), finalize_image_instance, (i));
783 } 827 }
784 828
785 static int 829 static int
786 image_instance_equal (Lisp_Object obj1, Lisp_Object obj2, int depth) 830 image_instance_equal (Lisp_Object obj1, Lisp_Object obj2, int depth)
787 { 831 {
788 struct Lisp_Image_Instance *i1 = XIMAGE_INSTANCE (obj1); 832 Lisp_Image_Instance *i1 = XIMAGE_INSTANCE (obj1);
789 struct Lisp_Image_Instance *i2 = XIMAGE_INSTANCE (obj2); 833 Lisp_Image_Instance *i2 = XIMAGE_INSTANCE (obj2);
790 struct device *d1 = XDEVICE (i1->device); 834 struct device *d1 = XDEVICE (i1->device);
791 struct device *d2 = XDEVICE (i2->device); 835 struct device *d2 = XDEVICE (i2->device);
792 836
793 if (d1 != d2) 837 if (d1 != d2)
794 return 0; 838 return 0;
795 if (IMAGE_INSTANCE_TYPE (i1) != IMAGE_INSTANCE_TYPE (i2)) 839 if (IMAGE_INSTANCE_TYPE (i1) != IMAGE_INSTANCE_TYPE (i2)
840 || IMAGE_INSTANCE_WIDTH (i1) != IMAGE_INSTANCE_WIDTH (i2)
841 || IMAGE_INSTANCE_HEIGHT (i1) != IMAGE_INSTANCE_HEIGHT (i2)
842 || IMAGE_INSTANCE_XOFFSET (i1) != IMAGE_INSTANCE_XOFFSET (i2)
843 || IMAGE_INSTANCE_YOFFSET (i1) != IMAGE_INSTANCE_YOFFSET (i2))
796 return 0; 844 return 0;
797 if (!internal_equal (IMAGE_INSTANCE_NAME (i1), IMAGE_INSTANCE_NAME (i2), 845 if (!internal_equal (IMAGE_INSTANCE_NAME (i1), IMAGE_INSTANCE_NAME (i2),
798 depth + 1)) 846 depth + 1))
799 return 0; 847 return 0;
800 848
811 break; 859 break;
812 860
813 case IMAGE_MONO_PIXMAP: 861 case IMAGE_MONO_PIXMAP:
814 case IMAGE_COLOR_PIXMAP: 862 case IMAGE_COLOR_PIXMAP:
815 case IMAGE_POINTER: 863 case IMAGE_POINTER:
816 if (!(IMAGE_INSTANCE_PIXMAP_WIDTH (i1) == 864 if (!(IMAGE_INSTANCE_PIXMAP_DEPTH (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) ==
821 IMAGE_INSTANCE_PIXMAP_DEPTH (i2) && 865 IMAGE_INSTANCE_PIXMAP_DEPTH (i2) &&
866 IMAGE_INSTANCE_PIXMAP_SLICE (i1) ==
867 IMAGE_INSTANCE_PIXMAP_SLICE (i2) &&
822 EQ (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (i1), 868 EQ (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (i1),
823 IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (i2)) && 869 IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (i2)) &&
824 EQ (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (i1), 870 EQ (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (i1),
825 IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (i2)) && 871 IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (i2)) &&
826 internal_equal (IMAGE_INSTANCE_PIXMAP_FILENAME (i1), 872 internal_equal (IMAGE_INSTANCE_PIXMAP_FILENAME (i1),
831 depth + 1))) 877 depth + 1)))
832 return 0; 878 return 0;
833 break; 879 break;
834 880
835 case IMAGE_WIDGET: 881 case IMAGE_WIDGET:
882 case IMAGE_LAYOUT:
836 if (!(EQ (IMAGE_INSTANCE_WIDGET_TYPE (i1), 883 if (!(EQ (IMAGE_INSTANCE_WIDGET_TYPE (i1),
837 IMAGE_INSTANCE_WIDGET_TYPE (i2)) && 884 IMAGE_INSTANCE_WIDGET_TYPE (i2))
838 EQ (IMAGE_INSTANCE_WIDGET_CALLBACK (i1), 885 && IMAGE_INSTANCE_SUBWINDOW_ID (i1) ==
839 IMAGE_INSTANCE_WIDGET_CALLBACK (i2)) 886 IMAGE_INSTANCE_SUBWINDOW_ID (i2)
887 && internal_equal (IMAGE_INSTANCE_WIDGET_ITEMS (i1),
888 IMAGE_INSTANCE_WIDGET_ITEMS (i2),
889 depth + 1)
840 && internal_equal (IMAGE_INSTANCE_WIDGET_PROPS (i1), 890 && internal_equal (IMAGE_INSTANCE_WIDGET_PROPS (i1),
841 IMAGE_INSTANCE_WIDGET_PROPS (i2), 891 IMAGE_INSTANCE_WIDGET_PROPS (i2),
842 depth + 1) 892 depth + 1)
843 && internal_equal (IMAGE_INSTANCE_WIDGET_TEXT (i1), 893 ))
844 IMAGE_INSTANCE_WIDGET_TEXT (i2),
845 depth + 1)))
846 return 0; 894 return 0;
895 break;
896
847 case IMAGE_SUBWINDOW: 897 case IMAGE_SUBWINDOW:
848 if (!(IMAGE_INSTANCE_SUBWINDOW_WIDTH (i1) == 898 if (!(IMAGE_INSTANCE_SUBWINDOW_ID (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) ==
853 IMAGE_INSTANCE_SUBWINDOW_ID (i2))) 899 IMAGE_INSTANCE_SUBWINDOW_ID (i2)))
854 return 0; 900 return 0;
855 break; 901 break;
856 902
857 default: 903 default:
862 } 908 }
863 909
864 static unsigned long 910 static unsigned long
865 image_instance_hash (Lisp_Object obj, int depth) 911 image_instance_hash (Lisp_Object obj, int depth)
866 { 912 {
867 struct Lisp_Image_Instance *i = XIMAGE_INSTANCE (obj); 913 Lisp_Image_Instance *i = XIMAGE_INSTANCE (obj);
868 struct device *d = XDEVICE (i->device); 914 struct device *d = XDEVICE (i->device);
869 unsigned long hash = (unsigned long) d; 915 unsigned long hash = HASH3 ((unsigned long) d,
916 IMAGE_INSTANCE_WIDTH (i),
917 IMAGE_INSTANCE_HEIGHT (i));
870 918
871 switch (IMAGE_INSTANCE_TYPE (i)) 919 switch (IMAGE_INSTANCE_TYPE (i))
872 { 920 {
873 case IMAGE_NOTHING: 921 case IMAGE_NOTHING:
874 break; 922 break;
879 break; 927 break;
880 928
881 case IMAGE_MONO_PIXMAP: 929 case IMAGE_MONO_PIXMAP:
882 case IMAGE_COLOR_PIXMAP: 930 case IMAGE_COLOR_PIXMAP:
883 case IMAGE_POINTER: 931 case IMAGE_POINTER:
884 hash = HASH5 (hash, IMAGE_INSTANCE_PIXMAP_WIDTH (i), 932 hash = HASH4 (hash, IMAGE_INSTANCE_PIXMAP_DEPTH (i),
885 IMAGE_INSTANCE_PIXMAP_HEIGHT (i), 933 IMAGE_INSTANCE_PIXMAP_SLICE (i),
886 IMAGE_INSTANCE_PIXMAP_DEPTH (i),
887 internal_hash (IMAGE_INSTANCE_PIXMAP_FILENAME (i), 934 internal_hash (IMAGE_INSTANCE_PIXMAP_FILENAME (i),
888 depth + 1)); 935 depth + 1));
889 break; 936 break;
890 937
891 case IMAGE_WIDGET: 938 case IMAGE_WIDGET:
892 hash = HASH4 (hash, 939 case IMAGE_LAYOUT:
940 hash = HASH4 (hash,
893 internal_hash (IMAGE_INSTANCE_WIDGET_TYPE (i), depth + 1), 941 internal_hash (IMAGE_INSTANCE_WIDGET_TYPE (i), depth + 1),
894 internal_hash (IMAGE_INSTANCE_WIDGET_PROPS (i), depth + 1), 942 internal_hash (IMAGE_INSTANCE_WIDGET_PROPS (i), depth + 1),
895 internal_hash (IMAGE_INSTANCE_WIDGET_CALLBACK (i), depth + 1)); 943 internal_hash (IMAGE_INSTANCE_WIDGET_ITEMS (i), depth + 1));
896 case IMAGE_SUBWINDOW: 944 case IMAGE_SUBWINDOW:
897 hash = HASH4 (hash, IMAGE_INSTANCE_SUBWINDOW_WIDTH (i), 945 hash = HASH2 (hash, (int) IMAGE_INSTANCE_SUBWINDOW_ID (i));
898 IMAGE_INSTANCE_SUBWINDOW_HEIGHT (i),
899 (int) IMAGE_INSTANCE_SUBWINDOW_ID (i));
900 break; 946 break;
901 947
902 default: 948 default:
903 abort (); 949 abort ();
904 } 950 }
908 } 954 }
909 955
910 DEFINE_LRECORD_IMPLEMENTATION ("image-instance", image_instance, 956 DEFINE_LRECORD_IMPLEMENTATION ("image-instance", image_instance,
911 mark_image_instance, print_image_instance, 957 mark_image_instance, print_image_instance,
912 finalize_image_instance, image_instance_equal, 958 finalize_image_instance, image_instance_equal,
913 image_instance_hash, 959 image_instance_hash, 0,
914 struct Lisp_Image_Instance); 960 Lisp_Image_Instance);
915 961
916 static Lisp_Object 962 static Lisp_Object
917 allocate_image_instance (Lisp_Object device) 963 allocate_image_instance (Lisp_Object device, Lisp_Object glyph)
918 { 964 {
919 struct Lisp_Image_Instance *lp = 965 Lisp_Image_Instance *lp =
920 alloc_lcrecord_type (struct Lisp_Image_Instance, lrecord_image_instance); 966 alloc_lcrecord_type (Lisp_Image_Instance, &lrecord_image_instance);
921 Lisp_Object val; 967 Lisp_Object val;
922 968
923 zero_lcrecord (lp); 969 zero_lcrecord (lp);
924 lp->device = device; 970 lp->device = device;
925 lp->type = IMAGE_NOTHING; 971 lp->type = IMAGE_NOTHING;
926 lp->name = Qnil; 972 lp->name = Qnil;
973 lp->x_offset = 0;
974 lp->y_offset = 0;
975 lp->width = 0;
976 lp->height = 0;
977 lp->parent = glyph;
978 /* So that layouts get done. */
979 lp->layout_changed = 1;
980 lp->dirty = 1;
981
927 XSETIMAGE_INSTANCE (val, lp); 982 XSETIMAGE_INSTANCE (val, lp);
983 MARK_GLYPHS_CHANGED;
984
928 return val; 985 return val;
929 } 986 }
930 987
931 static enum image_instance_type 988 static enum image_instance_type
932 decode_image_instance_type (Lisp_Object type, Error_behavior errb) 989 decode_image_instance_type (Lisp_Object type, Error_behavior errb)
939 if (EQ (type, Qmono_pixmap)) return IMAGE_MONO_PIXMAP; 996 if (EQ (type, Qmono_pixmap)) return IMAGE_MONO_PIXMAP;
940 if (EQ (type, Qcolor_pixmap)) return IMAGE_COLOR_PIXMAP; 997 if (EQ (type, Qcolor_pixmap)) return IMAGE_COLOR_PIXMAP;
941 if (EQ (type, Qpointer)) return IMAGE_POINTER; 998 if (EQ (type, Qpointer)) return IMAGE_POINTER;
942 if (EQ (type, Qsubwindow)) return IMAGE_SUBWINDOW; 999 if (EQ (type, Qsubwindow)) return IMAGE_SUBWINDOW;
943 if (EQ (type, Qwidget)) return IMAGE_WIDGET; 1000 if (EQ (type, Qwidget)) return IMAGE_WIDGET;
1001 if (EQ (type, Qlayout)) return IMAGE_LAYOUT;
944 1002
945 maybe_signal_simple_error ("Invalid image-instance type", type, 1003 maybe_signal_simple_error ("Invalid image-instance type", type,
946 Qimage, errb); 1004 Qimage, errb);
947 1005
948 return IMAGE_UNKNOWN; /* not reached */ 1006 return IMAGE_UNKNOWN; /* not reached */
958 case IMAGE_MONO_PIXMAP: return Qmono_pixmap; 1016 case IMAGE_MONO_PIXMAP: return Qmono_pixmap;
959 case IMAGE_COLOR_PIXMAP: return Qcolor_pixmap; 1017 case IMAGE_COLOR_PIXMAP: return Qcolor_pixmap;
960 case IMAGE_POINTER: return Qpointer; 1018 case IMAGE_POINTER: return Qpointer;
961 case IMAGE_SUBWINDOW: return Qsubwindow; 1019 case IMAGE_SUBWINDOW: return Qsubwindow;
962 case IMAGE_WIDGET: return Qwidget; 1020 case IMAGE_WIDGET: return Qwidget;
1021 case IMAGE_LAYOUT: return Qlayout;
963 default: 1022 default:
964 abort (); 1023 abort ();
965 } 1024 }
966 1025
967 return Qnil; /* not reached */ 1026 return Qnil; /* not reached */
970 static int 1029 static int
971 image_instance_type_to_mask (enum image_instance_type type) 1030 image_instance_type_to_mask (enum image_instance_type type)
972 { 1031 {
973 /* This depends on the fact that enums are assigned consecutive 1032 /* This depends on the fact that enums are assigned consecutive
974 integers starting at 0. (Remember that IMAGE_UNKNOWN is the 1033 integers starting at 0. (Remember that IMAGE_UNKNOWN is the
975 first enum.) I'm fairly sure this behavior in ANSI-mandated, 1034 first enum.) I'm fairly sure this behavior is ANSI-mandated,
976 so there should be no portability problems here. */ 1035 so there should be no portability problems here. */
977 return (1 << ((int) (type) - 1)); 1036 return (1 << ((int) (type) - 1));
978 } 1037 }
979 1038
980 static int 1039 static int
1027 { 1086 {
1028 signal_error 1087 signal_error
1029 (Qerror, 1088 (Qerror,
1030 list2 1089 list2
1031 (emacs_doprnt_string_lisp_2 1090 (emacs_doprnt_string_lisp_2
1032 ((CONST Bufbyte *) 1091 ((const Bufbyte *)
1033 "No compatible image-instance types given: wanted one of %s, got %s", 1092 "No compatible image-instance types given: wanted one of %s, got %s",
1034 Qnil, -1, 2, 1093 Qnil, -1, 2,
1035 encode_image_instance_type_list (desired_dest_mask), 1094 encode_image_instance_type_list (desired_dest_mask),
1036 encode_image_instance_type_list (given_dest_mask)), 1095 encode_image_instance_type_list (given_dest_mask)),
1037 instantiator)); 1096 instantiator));
1079 else 1138 else
1080 { 1139 {
1081 assert (ERRB_EQ (errb, ERROR_ME_WARN)); 1140 assert (ERRB_EQ (errb, ERROR_ME_WARN));
1082 return Qwarning; 1141 return Qwarning;
1083 } 1142 }
1143 }
1144
1145 /* Recurse up the hierarchy looking for the topmost glyph. This means
1146 that instances in layouts will inherit face properties from their
1147 parent. */
1148 Lisp_Object image_instance_parent_glyph (Lisp_Image_Instance* ii)
1149 {
1150 if (IMAGE_INSTANCEP (IMAGE_INSTANCE_PARENT (ii)))
1151 {
1152 return image_instance_parent_glyph
1153 (XIMAGE_INSTANCE (IMAGE_INSTANCE_PARENT (ii)));
1154 }
1155 return IMAGE_INSTANCE_PARENT (ii);
1084 } 1156 }
1085 1157
1086 static Lisp_Object 1158 static Lisp_Object
1087 make_image_instance_1 (Lisp_Object data, Lisp_Object device, 1159 make_image_instance_1 (Lisp_Object data, Lisp_Object device,
1088 Lisp_Object dest_types) 1160 Lisp_Object dest_types)
1102 make_int (dest_mask)); 1174 make_int (dest_mask));
1103 GCPRO1 (data); 1175 GCPRO1 (data);
1104 if (VECTORP (data) && EQ (XVECTOR_DATA (data)[0], Qinherit)) 1176 if (VECTORP (data) && EQ (XVECTOR_DATA (data)[0], Qinherit))
1105 signal_simple_error ("Inheritance not allowed here", data); 1177 signal_simple_error ("Inheritance not allowed here", data);
1106 ii = instantiate_image_instantiator (device, device, data, 1178 ii = instantiate_image_instantiator (device, device, data,
1107 Qnil, Qnil, dest_mask); 1179 Qnil, Qnil, dest_mask, Qnil);
1108 RETURN_UNGCPRO (ii); 1180 RETURN_UNGCPRO (ii);
1109 } 1181 }
1110 1182
1111 DEFUN ("make-image-instance", Fmake_image_instance, 1, 4, 0, /* 1183 DEFUN ("make-image-instance", Fmake_image_instance, 1, 4, 0, /*
1112 Return a new `image-instance' object. 1184 Return a new `image-instance' object.
1141 'pointer 1213 'pointer
1142 Used as the mouse pointer for a window. 1214 Used as the mouse pointer for a window.
1143 'subwindow 1215 'subwindow
1144 A child window that is treated as an image. This allows (e.g.) 1216 A child window that is treated as an image. This allows (e.g.)
1145 another program to be responsible for drawing into the window. 1217 another program to be responsible for drawing into the window.
1146 Not currently implemented. 1218 'widget
1219 A child window that contains a window-system widget, e.g. a push
1220 button.
1147 1221
1148 The DEST-TYPES list is unordered. If multiple destination types 1222 The DEST-TYPES list is unordered. If multiple destination types
1149 are possible for a given instantiator, the "most natural" type 1223 are possible for a given instantiator, the "most natural" type
1150 for the instantiator's format is chosen. (For XBM, the most natural 1224 for the instantiator's format is chosen. (For XBM, the most natural
1151 types are `mono-pixmap', followed by `color-pixmap', followed by 1225 types are `mono-pixmap', followed by `color-pixmap', followed by
1218 else 1292 else
1219 return Qnil; 1293 return Qnil;
1220 } 1294 }
1221 1295
1222 DEFUN ("image-instance-property", Fimage_instance_property, 2, 2, 0, /* 1296 DEFUN ("image-instance-property", Fimage_instance_property, 2, 2, 0, /*
1223 Return the given property of the given image instance. 1297 Return the given property of the given image instance.
1224 Returns nil if the property or the property method do not exist for 1298 Returns nil if the property or the property method do not exist for
1225 the image instance in the domain. 1299 the image instance in the domain.
1226 */ 1300 */
1227 (image_instance, prop)) 1301 (image_instance, prop))
1228 { 1302 {
1229 struct Lisp_Image_Instance* ii; 1303 Lisp_Image_Instance* ii;
1230 Lisp_Object type, ret; 1304 Lisp_Object type, ret;
1231 struct image_instantiator_methods* meths; 1305 struct image_instantiator_methods* meths;
1232 1306
1233 CHECK_IMAGE_INSTANCE (image_instance); 1307 CHECK_IMAGE_INSTANCE (image_instance);
1234 CHECK_SYMBOL (prop); 1308 CHECK_SYMBOL (prop);
1235 ii = XIMAGE_INSTANCE (image_instance); 1309 ii = XIMAGE_INSTANCE (image_instance);
1236 1310
1237 /* ... then try device specific methods ... */ 1311 /* ... then try device specific methods ... */
1238 type = encode_image_instance_type (IMAGE_INSTANCE_TYPE (ii)); 1312 type = encode_image_instance_type (IMAGE_INSTANCE_TYPE (ii));
1239 meths = decode_device_ii_format (IMAGE_INSTANCE_DEVICE (ii), 1313 meths = decode_device_ii_format (IMAGE_INSTANCE_DEVICE (ii),
1240 type, ERROR_ME_NOT); 1314 type, ERROR_ME_NOT);
1241 if (meths && HAS_IIFORMAT_METH_P (meths, property) 1315 if (meths && HAS_IIFORMAT_METH_P (meths, property)
1242 && 1316 &&
1243 !UNBOUNDP (ret = IIFORMAT_METH (meths, property, (image_instance, prop)))) 1317 !UNBOUNDP (ret = IIFORMAT_METH (meths, property, (image_instance, prop))))
1244 { 1318 {
1245 return ret; 1319 return ret;
1246 } 1320 }
1247 /* ... then format specific methods ... */ 1321 /* ... then format specific methods ... */
1255 /* ... then fail */ 1329 /* ... then fail */
1256 return Qnil; 1330 return Qnil;
1257 } 1331 }
1258 1332
1259 DEFUN ("set-image-instance-property", Fset_image_instance_property, 3, 3, 0, /* 1333 DEFUN ("set-image-instance-property", Fset_image_instance_property, 3, 3, 0, /*
1260 Set the given property of the given image instance. 1334 Set the given property of the given image instance.
1261 Does nothing if the property or the property method do not exist for 1335 Does nothing if the property or the property method do not exist for
1262 the image instance in the domain. 1336 the image instance in the domain.
1263 */ 1337 */
1264 (image_instance, prop, val)) 1338 (image_instance, prop, val))
1265 { 1339 {
1266 struct Lisp_Image_Instance* ii; 1340 Lisp_Image_Instance* ii;
1267 Lisp_Object type, ret; 1341 Lisp_Object type, ret;
1268 struct image_instantiator_methods* meths; 1342 struct image_instantiator_methods* meths;
1269 1343
1270 CHECK_IMAGE_INSTANCE (image_instance); 1344 CHECK_IMAGE_INSTANCE (image_instance);
1271 CHECK_SYMBOL (prop); 1345 CHECK_SYMBOL (prop);
1272 ii = XIMAGE_INSTANCE (image_instance); 1346 ii = XIMAGE_INSTANCE (image_instance);
1273 type = encode_image_instance_type (IMAGE_INSTANCE_TYPE (ii)); 1347 type = encode_image_instance_type (IMAGE_INSTANCE_TYPE (ii));
1274 /* try device specific methods first ... */ 1348 /* try device specific methods first ... */
1275 meths = decode_device_ii_format (IMAGE_INSTANCE_DEVICE (ii), 1349 meths = decode_device_ii_format (IMAGE_INSTANCE_DEVICE (ii),
1276 type, ERROR_ME_NOT); 1350 type, ERROR_ME_NOT);
1277 if (meths && HAS_IIFORMAT_METH_P (meths, set_property) 1351 if (meths && HAS_IIFORMAT_METH_P (meths, set_property)
1278 && 1352 &&
1279 !UNBOUNDP (ret = 1353 !UNBOUNDP (ret =
1280 IIFORMAT_METH (meths, set_property, (image_instance, prop, val)))) 1354 IIFORMAT_METH (meths, set_property, (image_instance, prop, val))))
1281 { 1355 {
1282 return ret; 1356 val = ret;
1283 } 1357 }
1284 /* ... then format specific methods ... */ 1358 else
1285 meths = decode_device_ii_format (Qnil, type, ERROR_ME_NOT); 1359 {
1286 if (meths && HAS_IIFORMAT_METH_P (meths, set_property) 1360 /* ... then format specific methods ... */
1287 && 1361 meths = decode_device_ii_format (Qnil, type, ERROR_ME_NOT);
1288 !UNBOUNDP (ret = 1362 if (meths && HAS_IIFORMAT_METH_P (meths, set_property)
1289 IIFORMAT_METH (meths, set_property, (image_instance, prop, val)))) 1363 &&
1290 { 1364 !UNBOUNDP (ret =
1291 return ret; 1365 IIFORMAT_METH (meths, set_property, (image_instance, prop, val))))
1292 } 1366 {
1367 val = ret;
1368 }
1369 else
1370 {
1371 val = Qnil;
1372 }
1373 }
1374
1375 /* Make sure the image instance gets redisplayed. */
1376 set_image_instance_dirty_p (image_instance, 1);
1377 /* Force the glyph to be laid out again. */
1378 IMAGE_INSTANCE_LAYOUT_CHANGED (ii) = 1;
1379
1380 MARK_SUBWINDOWS_STATE_CHANGED;
1381 MARK_GLYPHS_CHANGED;
1293 1382
1294 return val; 1383 return val;
1295 } 1384 }
1296 1385
1297 DEFUN ("image-instance-file-name", Fimage_instance_file_name, 1, 1, 0, /* 1386 DEFUN ("image-instance-file-name", Fimage_instance_file_name, 1, 1, 0, /*
1362 switch (XIMAGE_INSTANCE_TYPE (image_instance)) 1451 switch (XIMAGE_INSTANCE_TYPE (image_instance))
1363 { 1452 {
1364 case IMAGE_MONO_PIXMAP: 1453 case IMAGE_MONO_PIXMAP:
1365 case IMAGE_COLOR_PIXMAP: 1454 case IMAGE_COLOR_PIXMAP:
1366 case IMAGE_POINTER: 1455 case IMAGE_POINTER:
1367 return make_int (XIMAGE_INSTANCE_PIXMAP_HEIGHT (image_instance));
1368
1369 case IMAGE_SUBWINDOW: 1456 case IMAGE_SUBWINDOW:
1370 case IMAGE_WIDGET: 1457 case IMAGE_WIDGET:
1371 return make_int (XIMAGE_INSTANCE_SUBWINDOW_HEIGHT (image_instance)); 1458 case IMAGE_LAYOUT:
1459 return make_int (XIMAGE_INSTANCE_HEIGHT (image_instance));
1372 1460
1373 default: 1461 default:
1374 return Qnil; 1462 return Qnil;
1375 } 1463 }
1376 } 1464 }
1385 switch (XIMAGE_INSTANCE_TYPE (image_instance)) 1473 switch (XIMAGE_INSTANCE_TYPE (image_instance))
1386 { 1474 {
1387 case IMAGE_MONO_PIXMAP: 1475 case IMAGE_MONO_PIXMAP:
1388 case IMAGE_COLOR_PIXMAP: 1476 case IMAGE_COLOR_PIXMAP:
1389 case IMAGE_POINTER: 1477 case IMAGE_POINTER:
1390 return make_int (XIMAGE_INSTANCE_PIXMAP_WIDTH (image_instance));
1391
1392 case IMAGE_SUBWINDOW: 1478 case IMAGE_SUBWINDOW:
1393 case IMAGE_WIDGET: 1479 case IMAGE_WIDGET:
1394 return make_int (XIMAGE_INSTANCE_SUBWINDOW_WIDTH (image_instance)); 1480 case IMAGE_LAYOUT:
1481 return make_int (XIMAGE_INSTANCE_WIDTH (image_instance));
1395 1482
1396 default: 1483 default:
1397 return Qnil; 1484 return Qnil;
1398 } 1485 }
1399 } 1486 }
1463 return XIMAGE_INSTANCE_PIXMAP_FG (image_instance); 1550 return XIMAGE_INSTANCE_PIXMAP_FG (image_instance);
1464 1551
1465 case IMAGE_WIDGET: 1552 case IMAGE_WIDGET:
1466 return FACE_FOREGROUND ( 1553 return FACE_FOREGROUND (
1467 XIMAGE_INSTANCE_WIDGET_FACE (image_instance), 1554 XIMAGE_INSTANCE_WIDGET_FACE (image_instance),
1468 XIMAGE_INSTANCE_SUBWINDOW_FRAME 1555 XIMAGE_INSTANCE_SUBWINDOW_FRAME
1469 (image_instance)); 1556 (image_instance));
1470 1557
1471 default: 1558 default:
1472 return Qnil; 1559 return Qnil;
1473 } 1560 }
1490 return XIMAGE_INSTANCE_PIXMAP_BG (image_instance); 1577 return XIMAGE_INSTANCE_PIXMAP_BG (image_instance);
1491 1578
1492 case IMAGE_WIDGET: 1579 case IMAGE_WIDGET:
1493 return FACE_BACKGROUND ( 1580 return FACE_BACKGROUND (
1494 XIMAGE_INSTANCE_WIDGET_FACE (image_instance), 1581 XIMAGE_INSTANCE_WIDGET_FACE (image_instance),
1495 XIMAGE_INSTANCE_SUBWINDOW_FRAME 1582 XIMAGE_INSTANCE_SUBWINDOW_FRAME
1496 (image_instance)); 1583 (image_instance));
1497 1584
1498 default: 1585 default:
1499 return Qnil; 1586 return Qnil;
1500 } 1587 }
1519 1606
1520 device = XIMAGE_INSTANCE_DEVICE (image_instance); 1607 device = XIMAGE_INSTANCE_DEVICE (image_instance);
1521 if (!HAS_DEVMETH_P (XDEVICE (device), colorize_image_instance)) 1608 if (!HAS_DEVMETH_P (XDEVICE (device), colorize_image_instance))
1522 return image_instance; 1609 return image_instance;
1523 1610
1524 new = allocate_image_instance (device); 1611 /* #### There should be a copy_image_instance(), which calls a
1612 device-specific method to copy the window-system subobject. */
1613 new = allocate_image_instance (device, Qnil);
1525 copy_lcrecord (XIMAGE_INSTANCE (new), XIMAGE_INSTANCE (image_instance)); 1614 copy_lcrecord (XIMAGE_INSTANCE (new), XIMAGE_INSTANCE (image_instance));
1526 /* note that if this method returns non-zero, this method MUST 1615 /* note that if this method returns non-zero, this method MUST
1527 copy any window-system resources, so that when one image instance is 1616 copy any window-system resources, so that when one image instance is
1528 freed, the other one is not hosed. */ 1617 freed, the other one is not hosed. */
1529 if (!DEVMETH (XDEVICE (device), colorize_image_instance, (new, foreground, 1618 if (!DEVMETH (XDEVICE (device), colorize_image_instance, (new, foreground,
1530 background))) 1619 background)))
1531 return image_instance; 1620 return image_instance;
1532 return new; 1621 return new;
1533 } 1622 }
1534 1623
1624
1625 /************************************************************************/
1626 /* Geometry calculations */
1627 /************************************************************************/
1628
1629 /* Find out desired geometry of the image instance. If there is no
1630 special function then just return the width and / or height. */
1631 void
1632 image_instance_query_geometry (Lisp_Object image_instance,
1633 unsigned int* width, unsigned int* height,
1634 enum image_instance_geometry disp,
1635 Lisp_Object domain)
1636 {
1637 Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance);
1638 Lisp_Object type;
1639 struct image_instantiator_methods* meths;
1640
1641 type = encode_image_instance_type (IMAGE_INSTANCE_TYPE (ii));
1642 meths = decode_device_ii_format (Qnil, type, ERROR_ME_NOT);
1643
1644 if (meths && HAS_IIFORMAT_METH_P (meths, query_geometry))
1645 {
1646 IIFORMAT_METH (meths, query_geometry, (image_instance, width, height,
1647 disp, domain));
1648 }
1649 else
1650 {
1651 if (width)
1652 *width = IMAGE_INSTANCE_WIDTH (ii);
1653 if (height)
1654 *height = IMAGE_INSTANCE_HEIGHT (ii);
1655 }
1656 }
1657
1658 /* Layout the image instance using the provided dimensions. Layout
1659 widgets are going to do different kinds of calculations to
1660 determine what size to give things so we could make the layout
1661 function relatively simple to take account of that. An alternative
1662 approach is to consider separately the two cases, one where you
1663 don't mind what size you have (normal widgets) and one where you
1664 want to specifiy something (layout widgets). */
1665 void
1666 image_instance_layout (Lisp_Object image_instance,
1667 unsigned int width, unsigned int height,
1668 Lisp_Object domain)
1669 {
1670 Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance);
1671 Lisp_Object type;
1672 struct image_instantiator_methods* meths;
1673
1674 type = encode_image_instance_type (IMAGE_INSTANCE_TYPE (ii));
1675 meths = decode_device_ii_format (Qnil, type, ERROR_ME_NOT);
1676
1677 /* If geometry is unspecified then get some reasonable values for it. */
1678 if (width == IMAGE_UNSPECIFIED_GEOMETRY
1679 ||
1680 height == IMAGE_UNSPECIFIED_GEOMETRY)
1681 {
1682 unsigned int dwidth, dheight;
1683
1684 /* Get the desired geometry. */
1685 if (meths && HAS_IIFORMAT_METH_P (meths, query_geometry))
1686 {
1687 IIFORMAT_METH (meths, query_geometry, (image_instance, &dwidth, &dheight,
1688 IMAGE_DESIRED_GEOMETRY,
1689 domain));
1690 }
1691 else
1692 {
1693 dwidth = IMAGE_INSTANCE_WIDTH (ii);
1694 dheight = IMAGE_INSTANCE_HEIGHT (ii);
1695 }
1696
1697 /* Compare with allowed geometry. */
1698 if (width == IMAGE_UNSPECIFIED_GEOMETRY)
1699 width = dwidth;
1700 if (height == IMAGE_UNSPECIFIED_GEOMETRY)
1701 height = dheight;
1702 }
1703
1704 /* At this point width and height should contain sane values. Thus
1705 we set the glyph geometry and lay it out. */
1706 if (IMAGE_INSTANCE_WIDTH (ii) != width
1707 ||
1708 IMAGE_INSTANCE_HEIGHT (ii) != height)
1709 {
1710 IMAGE_INSTANCE_SIZE_CHANGED (ii) = 1;
1711 }
1712
1713 IMAGE_INSTANCE_WIDTH (ii) = width;
1714 IMAGE_INSTANCE_HEIGHT (ii) = height;
1715
1716 if (meths && HAS_IIFORMAT_METH_P (meths, layout))
1717 {
1718 IIFORMAT_METH (meths, layout, (image_instance, width, height, domain));
1719 }
1720 /* else no change to the geometry. */
1721
1722 /* Do not clear the dirty flag here - redisplay will do this for
1723 us at the end. */
1724 IMAGE_INSTANCE_LAYOUT_CHANGED (ii) = 0;
1725 }
1726
1727 /*
1728 * Mark image instance in W as dirty if (a) W's faces have changed and
1729 * (b) GLYPH_OR_II instance in W is a string.
1730 *
1731 * Return non-zero if instance has been marked dirty.
1732 */
1733 int
1734 invalidate_glyph_geometry_maybe (Lisp_Object glyph_or_ii, struct window* w)
1735 {
1736 if (XFRAME(WINDOW_FRAME(w))->faces_changed)
1737 {
1738 Lisp_Object image = glyph_or_ii;
1739
1740 if (GLYPHP (glyph_or_ii))
1741 {
1742 Lisp_Object window;
1743 XSETWINDOW (window, w);
1744 image = glyph_image_instance (glyph_or_ii, window, ERROR_ME_NOT, 1);
1745 }
1746
1747 if (TEXT_IMAGE_INSTANCEP (image))
1748 {
1749 Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image);
1750 IMAGE_INSTANCE_DIRTYP (ii) = 1;
1751 IMAGE_INSTANCE_LAYOUT_CHANGED (ii) = 1;
1752 if (GLYPHP (glyph_or_ii))
1753 XGLYPH_DIRTYP (glyph_or_ii) = 1;
1754 return 1;
1755 }
1756 }
1757
1758 return 0;
1759 }
1760
1535 1761
1536 /************************************************************************/ 1762 /************************************************************************/
1537 /* error helpers */ 1763 /* error helpers */
1538 /************************************************************************/ 1764 /************************************************************************/
1539 DOESNT_RETURN 1765 DOESNT_RETURN
1540 signal_image_error (CONST char *reason, Lisp_Object frob) 1766 signal_image_error (const char *reason, Lisp_Object frob)
1541 { 1767 {
1542 signal_error (Qimage_conversion_error, 1768 signal_error (Qimage_conversion_error,
1543 list2 (build_translated_string (reason), frob)); 1769 list2 (build_translated_string (reason), frob));
1544 } 1770 }
1545 1771
1546 DOESNT_RETURN 1772 DOESNT_RETURN
1547 signal_image_error_2 (CONST char *reason, Lisp_Object frob0, Lisp_Object frob1) 1773 signal_image_error_2 (const char *reason, Lisp_Object frob0, Lisp_Object frob1)
1548 { 1774 {
1549 signal_error (Qimage_conversion_error, 1775 signal_error (Qimage_conversion_error,
1550 list3 (build_translated_string (reason), frob0, frob1)); 1776 list3 (build_translated_string (reason), frob0, frob1));
1551 } 1777 }
1552 1778
1563 static void 1789 static void
1564 nothing_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, 1790 nothing_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1565 Lisp_Object pointer_fg, Lisp_Object pointer_bg, 1791 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1566 int dest_mask, Lisp_Object domain) 1792 int dest_mask, Lisp_Object domain)
1567 { 1793 {
1568 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); 1794 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1569 1795
1570 if (dest_mask & IMAGE_NOTHING_MASK) 1796 if (dest_mask & IMAGE_NOTHING_MASK)
1571 IMAGE_INSTANCE_TYPE (ii) = IMAGE_NOTHING; 1797 IMAGE_INSTANCE_TYPE (ii) = IMAGE_NOTHING;
1572 else 1798 else
1573 incompatible_image_types (instantiator, dest_mask, IMAGE_NOTHING_MASK); 1799 incompatible_image_types (instantiator, dest_mask, IMAGE_NOTHING_MASK);
1626 string_possible_dest_types (void) 1852 string_possible_dest_types (void)
1627 { 1853 {
1628 return IMAGE_TEXT_MASK; 1854 return IMAGE_TEXT_MASK;
1629 } 1855 }
1630 1856
1631 /* called from autodetect_instantiate() */ 1857 /* Called from autodetect_instantiate() */
1632 void 1858 void
1633 string_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, 1859 string_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1634 Lisp_Object pointer_fg, Lisp_Object pointer_bg, 1860 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1635 int dest_mask, Lisp_Object domain) 1861 int dest_mask, Lisp_Object domain)
1636 { 1862 {
1637 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data); 1863 Lisp_Object string = find_keyword_in_vector (instantiator, Q_data);
1638 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); 1864 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1639 1865
1640 assert (!NILP (data)); 1866 /* Should never get here with a domain other than a window. */
1867 assert (!NILP (string) && WINDOWP (domain));
1641 if (dest_mask & IMAGE_TEXT_MASK) 1868 if (dest_mask & IMAGE_TEXT_MASK)
1642 { 1869 {
1643 IMAGE_INSTANCE_TYPE (ii) = IMAGE_TEXT; 1870 IMAGE_INSTANCE_TYPE (ii) = IMAGE_TEXT;
1644 IMAGE_INSTANCE_TEXT_STRING (ii) = data; 1871 IMAGE_INSTANCE_TEXT_STRING (ii) = string;
1645 } 1872 }
1646 else 1873 else
1647 incompatible_image_types (instantiator, dest_mask, IMAGE_TEXT_MASK); 1874 incompatible_image_types (instantiator, dest_mask, IMAGE_TEXT_MASK);
1875 }
1876
1877 /* Sort out the size of the text that is being displayed. Calculating
1878 it dynamically allows us to change the text and still see
1879 everything. Note that the following methods are for text not string
1880 since that is what the instantiated type is. The first method is a
1881 helper that is used elsewhere for calculating text geometry. */
1882 void
1883 query_string_geometry (Lisp_Object string, Lisp_Object face,
1884 unsigned int* width, unsigned int* height,
1885 unsigned int* descent, Lisp_Object domain)
1886 {
1887 struct font_metric_info fm;
1888 unsigned char charsets[NUM_LEADING_BYTES];
1889 struct face_cachel frame_cachel;
1890 struct face_cachel *cachel;
1891 Lisp_Object frame = FW_FRAME (domain);
1892
1893 /* Compute height */
1894 if (height)
1895 {
1896 /* Compute string metric info */
1897 find_charsets_in_bufbyte_string (charsets,
1898 XSTRING_DATA (string),
1899 XSTRING_LENGTH (string));
1900
1901 /* Fallback to the default face if none was provided. */
1902 if (!NILP (face))
1903 {
1904 reset_face_cachel (&frame_cachel);
1905 update_face_cachel_data (&frame_cachel, frame, face);
1906 cachel = &frame_cachel;
1907 }
1908 else
1909 {
1910 cachel = WINDOW_FACE_CACHEL (XWINDOW (domain), DEFAULT_INDEX);
1911 }
1912
1913 ensure_face_cachel_complete (cachel, domain, charsets);
1914 face_cachel_charset_font_metric_info (cachel, charsets, &fm);
1915
1916 *height = fm.ascent + fm.descent;
1917 /* #### descent only gets set if we query the height as well. */
1918 if (descent)
1919 *descent = fm.descent;
1920 }
1921
1922 /* Compute width */
1923 if (width)
1924 {
1925 if (!NILP (face))
1926 *width = redisplay_frame_text_width_string (XFRAME (frame),
1927 face,
1928 0, string, 0, -1);
1929 else
1930 *width = redisplay_frame_text_width_string (XFRAME (frame),
1931 Vdefault_face,
1932 0, string, 0, -1);
1933 }
1934 }
1935
1936 Lisp_Object
1937 query_string_font (Lisp_Object string, Lisp_Object face, Lisp_Object domain)
1938 {
1939 unsigned char charsets[NUM_LEADING_BYTES];
1940 struct face_cachel frame_cachel;
1941 struct face_cachel *cachel;
1942 int i;
1943 Lisp_Object frame = FW_FRAME (domain);
1944
1945 /* Compute string font info */
1946 find_charsets_in_bufbyte_string (charsets,
1947 XSTRING_DATA (string),
1948 XSTRING_LENGTH (string));
1949
1950 reset_face_cachel (&frame_cachel);
1951 update_face_cachel_data (&frame_cachel, frame, face);
1952 cachel = &frame_cachel;
1953
1954 ensure_face_cachel_complete (cachel, domain, charsets);
1955
1956 for (i = 0; i < NUM_LEADING_BYTES; i++)
1957 {
1958 if (charsets[i])
1959 {
1960 return FACE_CACHEL_FONT (cachel,
1961 CHARSET_BY_LEADING_BYTE (i +
1962 MIN_LEADING_BYTE));
1963
1964 }
1965 }
1966
1967 return Qnil; /* NOT REACHED */
1968 }
1969
1970 static void
1971 text_query_geometry (Lisp_Object image_instance,
1972 unsigned int* width, unsigned int* height,
1973 enum image_instance_geometry disp, Lisp_Object domain)
1974 {
1975 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1976 unsigned int descent = 0;
1977
1978 query_string_geometry (IMAGE_INSTANCE_TEXT_STRING (ii),
1979 IMAGE_INSTANCE_FACE (ii),
1980 width, height, &descent, domain);
1981
1982 /* The descent gets set as a side effect of querying the
1983 geometry. */
1984 IMAGE_INSTANCE_TEXT_DESCENT (ii) = descent;
1985 }
1986
1987 /* set the properties of a string */
1988 static Lisp_Object
1989 text_set_property (Lisp_Object image_instance, Lisp_Object prop,
1990 Lisp_Object val)
1991 {
1992 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1993
1994 if (EQ (prop, Q_data))
1995 {
1996 CHECK_STRING (val);
1997 IMAGE_INSTANCE_TEXT_STRING (ii) = val;
1998
1999 return Qt;
2000 }
2001 return Qunbound;
1648 } 2002 }
1649 2003
1650 2004
1651 /**************************************************************************** 2005 /****************************************************************************
1652 * formatted-string * 2006 * formatted-string *
1668 formatted_string_instantiate (Lisp_Object image_instance, 2022 formatted_string_instantiate (Lisp_Object image_instance,
1669 Lisp_Object instantiator, 2023 Lisp_Object instantiator,
1670 Lisp_Object pointer_fg, Lisp_Object pointer_bg, 2024 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1671 int dest_mask, Lisp_Object domain) 2025 int dest_mask, Lisp_Object domain)
1672 { 2026 {
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));
1677 /* #### implement this */ 2027 /* #### implement this */
1678 warn_when_safe (Qunimplemented, Qnotice, 2028 warn_when_safe (Qunimplemented, Qnotice,
1679 "`formatted-string' not yet implemented; assuming `string'"); 2029 "`formatted-string' not yet implemented; assuming `string'");
1680 if (dest_mask & IMAGE_TEXT_MASK) 2030
1681 { 2031 string_instantiate (image_instance, instantiator,
1682 IMAGE_INSTANCE_TYPE (ii) = IMAGE_TEXT; 2032 pointer_fg, pointer_bg, dest_mask, domain);
1683 IMAGE_INSTANCE_TEXT_STRING (ii) = data;
1684 }
1685 else
1686 incompatible_image_types (instantiator, dest_mask, IMAGE_TEXT_MASK);
1687 } 2033 }
1688 2034
1689 2035
1690 /************************************************************************/ 2036 /************************************************************************/
1691 /* pixmap file functions */ 2037 /* pixmap file functions */
1845 int ok_if_data_invalid) 2191 int ok_if_data_invalid)
1846 { 2192 {
1847 unsigned int w, h; 2193 unsigned int w, h;
1848 Extbyte *data; 2194 Extbyte *data;
1849 int result; 2195 int result;
1850 CONST char *filename_ext; 2196 const char *filename_ext;
1851 2197
1852 GET_C_STRING_FILENAME_DATA_ALLOCA (name, filename_ext); 2198 TO_EXTERNAL_FORMAT (LISP_STRING, name,
2199 C_STRING_ALLOCA, filename_ext,
2200 Qfile_name);
1853 result = read_bitmap_data_from_file (filename_ext, &w, &h, 2201 result = read_bitmap_data_from_file (filename_ext, &w, &h,
1854 &data, xhot, yhot); 2202 &data, xhot, yhot);
1855 2203
1856 if (result == BitmapSuccess) 2204 if (result == BitmapSuccess)
1857 { 2205 {
1858 Lisp_Object retval; 2206 Lisp_Object retval;
1859 int len = (w + 7) / 8 * h; 2207 int len = (w + 7) / 8 * h;
1860 2208
1861 retval = list3 (make_int (w), make_int (h), 2209 retval = list3 (make_int (w), make_int (h),
1862 make_ext_string (data, len, FORMAT_BINARY)); 2210 make_ext_string (data, len, Qbinary));
1863 XFree ((char *) data); 2211 XFree ((char *) data);
1864 return retval; 2212 return retval;
1865 } 2213 }
1866 2214
1867 switch (result) 2215 switch (result)
2090 pixmap_to_lisp_data (Lisp_Object name, int ok_if_data_invalid) 2438 pixmap_to_lisp_data (Lisp_Object name, int ok_if_data_invalid)
2091 { 2439 {
2092 char **data; 2440 char **data;
2093 int result; 2441 int result;
2094 char *fname = 0; 2442 char *fname = 0;
2095 2443
2096 GET_C_STRING_FILENAME_DATA_ALLOCA (name, fname); 2444 TO_EXTERNAL_FORMAT (LISP_STRING, name,
2445 C_STRING_ALLOCA, fname,
2446 Qfile_name);
2097 result = XpmReadFileToData (fname, &data); 2447 result = XpmReadFileToData (fname, &data);
2098 2448
2099 if (result == XpmSuccess) 2449 if (result == XpmSuccess)
2100 { 2450 {
2101 Lisp_Object retval = Qnil; 2451 Lisp_Object retval = Qnil;
2301 DEFINE_SPECIFIER_TYPE (image); 2651 DEFINE_SPECIFIER_TYPE (image);
2302 2652
2303 static void 2653 static void
2304 image_create (Lisp_Object obj) 2654 image_create (Lisp_Object obj)
2305 { 2655 {
2306 struct Lisp_Specifier *image = XIMAGE_SPECIFIER (obj); 2656 Lisp_Specifier *image = XIMAGE_SPECIFIER (obj);
2307 2657
2308 IMAGE_SPECIFIER_ALLOWED (image) = ~0; /* all are allowed */ 2658 IMAGE_SPECIFIER_ALLOWED (image) = ~0; /* all are allowed */
2309 IMAGE_SPECIFIER_ATTACHEE (image) = Qnil; 2659 IMAGE_SPECIFIER_ATTACHEE (image) = Qnil;
2310 IMAGE_SPECIFIER_ATTACHEE_PROPERTY (image) = Qnil; 2660 IMAGE_SPECIFIER_ATTACHEE_PROPERTY (image) = Qnil;
2311 } 2661 }
2312 2662
2313 static void 2663 static void
2314 image_mark (Lisp_Object obj, void (*markobj) (Lisp_Object)) 2664 image_mark (Lisp_Object obj)
2315 { 2665 {
2316 struct Lisp_Specifier *image = XIMAGE_SPECIFIER (obj); 2666 Lisp_Specifier *image = XIMAGE_SPECIFIER (obj);
2317 2667
2318 markobj (IMAGE_SPECIFIER_ATTACHEE (image)); 2668 mark_object (IMAGE_SPECIFIER_ATTACHEE (image));
2319 markobj (IMAGE_SPECIFIER_ATTACHEE_PROPERTY (image)); 2669 mark_object (IMAGE_SPECIFIER_ATTACHEE_PROPERTY (image));
2320 } 2670 }
2321 2671
2322 static Lisp_Object 2672 static Lisp_Object
2323 image_instantiate_cache_result (Lisp_Object locative) 2673 image_instantiate_cache_result (Lisp_Object locative)
2324 { 2674 {
2338 Lisp_Object domain, Lisp_Object instantiator, 2688 Lisp_Object domain, Lisp_Object instantiator,
2339 Lisp_Object depth) 2689 Lisp_Object depth)
2340 { 2690 {
2341 Lisp_Object device = DFW_DEVICE (domain); 2691 Lisp_Object device = DFW_DEVICE (domain);
2342 struct device *d = XDEVICE (device); 2692 struct device *d = XDEVICE (device);
2693 Lisp_Object glyph = IMAGE_SPECIFIER_ATTACHEE (XIMAGE_SPECIFIER (specifier));
2343 int dest_mask = XIMAGE_SPECIFIER_ALLOWED (specifier); 2694 int dest_mask = XIMAGE_SPECIFIER_ALLOWED (specifier);
2344 int pointerp = dest_mask & image_instance_type_to_mask (IMAGE_POINTER); 2695 int pointerp = dest_mask & image_instance_type_to_mask (IMAGE_POINTER);
2345 2696
2346 if (IMAGE_INSTANCEP (instantiator)) 2697 if (IMAGE_INSTANCEP (instantiator))
2347 { 2698 {
2391 if (UNBOUNDP (subtable)) 2742 if (UNBOUNDP (subtable))
2392 { 2743 {
2393 /* For the image instance cache, we do comparisons with EQ rather 2744 /* For the image instance cache, we do comparisons with EQ rather
2394 than with EQUAL, as we do for color and font names. 2745 than with EQUAL, as we do for color and font names.
2395 The reasons are: 2746 The reasons are:
2396 2747
2397 1) pixmap data can be very long, and thus the hashing and 2748 1) pixmap data can be very long, and thus the hashing and
2398 comparing will take awhile. 2749 comparing will take awhile.
2399 2) It's not so likely that we'll run into things that are EQUAL 2750 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 2751 but not EQ (that can happen a lot with faces, because their
2401 specifiers are copied around); but pixmaps tend not to be 2752 specifiers are copied around); but pixmaps tend not to be
2427 will occur most of the time so this probably slows things 2778 will occur most of the time so this probably slows things
2428 down. But with the current design I don't see anyway 2779 down. But with the current design I don't see anyway
2429 round it. */ 2780 round it. */
2430 if (UNBOUNDP (instance) 2781 if (UNBOUNDP (instance)
2431 && 2782 &&
2432 dest_mask & (IMAGE_SUBWINDOW_MASK | IMAGE_WIDGET_MASK)) 2783 dest_mask & (IMAGE_SUBWINDOW_MASK
2784 | IMAGE_WIDGET_MASK
2785 | IMAGE_TEXT_MASK))
2433 { 2786 {
2434 if (!WINDOWP (domain)) 2787 if (!WINDOWP (domain))
2435 signal_simple_error ("Can't instantiate subwindow outside a window", 2788 signal_simple_error ("Can't instantiate text or subwindow outside a window",
2436 instantiator); 2789 instantiator);
2437 instance = Fgethash (instantiator, 2790 instance = Fgethash (instantiator,
2438 XWINDOW (domain)->subwindow_instance_cache, 2791 XWINDOW (domain)->subwindow_instance_cache,
2439 Qunbound); 2792 Qunbound);
2440 } 2793 }
2441 } 2794 }
2442 2795
2443 if (UNBOUNDP (instance)) 2796 if (UNBOUNDP (instance))
2445 Lisp_Object locative = 2798 Lisp_Object locative =
2446 noseeum_cons (Qnil, 2799 noseeum_cons (Qnil,
2447 noseeum_cons (pointerp ? ls3 : instantiator, 2800 noseeum_cons (pointerp ? ls3 : instantiator,
2448 subtable)); 2801 subtable));
2449 int speccount = specpdl_depth (); 2802 int speccount = specpdl_depth ();
2450 2803
2451 /* make sure we cache the failures, too. 2804 /* make sure we cache the failures, too.
2452 Use an unwind-protect to catch such errors. 2805 Use an unwind-protect to catch such errors.
2453 If we fail, the unwind-protect records nil in 2806 If we fail, the unwind-protect records nil in
2454 the hash table. If we succeed, we change the 2807 the hash table. If we succeed, we change the
2455 car of the locative to the resulting instance, 2808 car of the locative to the resulting instance,
2458 locative); 2811 locative);
2459 instance = instantiate_image_instantiator (device, 2812 instance = instantiate_image_instantiator (device,
2460 domain, 2813 domain,
2461 instantiator, 2814 instantiator,
2462 pointer_fg, pointer_bg, 2815 pointer_fg, pointer_bg,
2463 dest_mask); 2816 dest_mask,
2464 2817 glyph);
2818
2465 Fsetcar (locative, instance); 2819 Fsetcar (locative, instance);
2466 /* only after the image has been instantiated do we know 2820 /* only after the image has been instantiated do we know
2467 whether we need to put it in the per-window image instance 2821 whether we need to put it in the per-window image instance
2468 cache. */ 2822 cache. */
2469 if (image_instance_type_to_mask (XIMAGE_INSTANCE_TYPE (instance)) 2823 if (image_instance_type_to_mask (XIMAGE_INSTANCE_TYPE (instance))
2471 (IMAGE_SUBWINDOW_MASK | IMAGE_WIDGET_MASK)) 2825 (IMAGE_SUBWINDOW_MASK | IMAGE_WIDGET_MASK))
2472 { 2826 {
2473 if (!WINDOWP (domain)) 2827 if (!WINDOWP (domain))
2474 signal_simple_error ("Can't instantiate subwindow outside a window", 2828 signal_simple_error ("Can't instantiate subwindow outside a window",
2475 instantiator); 2829 instantiator);
2476 2830
2477 Fsetcdr (XCDR (locative), XWINDOW (domain)->subwindow_instance_cache ); 2831 Fsetcdr (XCDR (locative), XWINDOW (domain)->subwindow_instance_cache );
2478 } 2832 }
2479 unbind_to (speccount, Qnil); 2833 unbind_to (speccount, Qnil);
2480 } 2834 }
2481 else 2835 else
2569 2923
2570 void 2924 void
2571 set_image_attached_to (Lisp_Object obj, Lisp_Object face_or_glyph, 2925 set_image_attached_to (Lisp_Object obj, Lisp_Object face_or_glyph,
2572 Lisp_Object property) 2926 Lisp_Object property)
2573 { 2927 {
2574 struct Lisp_Specifier *image = XIMAGE_SPECIFIER (obj); 2928 Lisp_Specifier *image = XIMAGE_SPECIFIER (obj);
2575 2929
2576 IMAGE_SPECIFIER_ATTACHEE (image) = face_or_glyph; 2930 IMAGE_SPECIFIER_ATTACHEE (image) = face_or_glyph;
2577 IMAGE_SPECIFIER_ATTACHEE_PROPERTY (image) = property; 2931 IMAGE_SPECIFIER_ATTACHEE_PROPERTY (image) = property;
2578 } 2932 }
2579 2933
2622 } 2976 }
2623 2977
2624 UNGCPRO; 2978 UNGCPRO;
2625 2979
2626 return retlist; 2980 return retlist;
2981 }
2982
2983 /* Copy an image instantiator. We can't use Fcopy_tree since widgets
2984 may contain circular references which would send Fcopy_tree into
2985 infloop death. */
2986 static Lisp_Object
2987 image_copy_vector_instantiator (Lisp_Object instantiator)
2988 {
2989 int i;
2990 struct image_instantiator_methods *meths;
2991 Lisp_Object *elt;
2992 int instantiator_len;
2993
2994 CHECK_VECTOR (instantiator);
2995
2996 instantiator = Fcopy_sequence (instantiator);
2997 elt = XVECTOR_DATA (instantiator);
2998 instantiator_len = XVECTOR_LENGTH (instantiator);
2999
3000 meths = decode_image_instantiator_format (elt[0], ERROR_ME);
3001
3002 for (i = 1; i < instantiator_len; i += 2)
3003 {
3004 int j;
3005 Lisp_Object keyword = elt[i];
3006 Lisp_Object value = elt[i+1];
3007
3008 /* Find the keyword entry. */
3009 for (j = 0; j < Dynarr_length (meths->keywords); j++)
3010 {
3011 if (EQ (keyword, Dynarr_at (meths->keywords, j).keyword))
3012 break;
3013 }
3014
3015 /* Only copy keyword values that should be copied. */
3016 if (Dynarr_at (meths->keywords, j).copy_p
3017 &&
3018 (CONSP (value) || VECTORP (value)))
3019 {
3020 elt [i+1] = Fcopy_tree (value, Qt);
3021 }
3022 }
3023
3024 return instantiator;
3025 }
3026
3027 static Lisp_Object
3028 image_copy_instantiator (Lisp_Object arg)
3029 {
3030 if (CONSP (arg))
3031 {
3032 Lisp_Object rest;
3033 rest = arg = Fcopy_sequence (arg);
3034 while (CONSP (rest))
3035 {
3036 Lisp_Object elt = XCAR (rest);
3037 if (CONSP (elt))
3038 XCAR (rest) = Fcopy_tree (elt, Qt);
3039 else if (VECTORP (elt))
3040 XCAR (rest) = image_copy_vector_instantiator (elt);
3041 if (VECTORP (XCDR (rest))) /* hack for (a b . [c d]) */
3042 XCDR (rest) = Fcopy_tree (XCDR (rest), Qt);
3043 rest = XCDR (rest);
3044 }
3045 }
3046 else if (VECTORP (arg))
3047 {
3048 arg = image_copy_vector_instantiator (arg);
3049 }
3050 return arg;
2627 } 3051 }
2628 3052
2629 DEFUN ("image-specifier-p", Fimage_specifier_p, 1, 1, 0, /* 3053 DEFUN ("image-specifier-p", Fimage_specifier_p, 1, 1, 0, /*
2630 Return non-nil if OBJECT is an image specifier. 3054 Return non-nil if OBJECT is an image specifier.
2631 3055
2708 (A glyph from a font; i.e. the name of a font, and glyph index into it 3132 (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]". 3133 of the form "FONT fontname index [[mask-font] mask-index]".
2710 Currently can only be instanced as `pointer', although this should 3134 Currently can only be instanced as `pointer', although this should
2711 probably be fixed.) 3135 probably be fixed.)
2712 'subwindow 3136 'subwindow
2713 (An embedded X window; not currently implemented.) 3137 (An embedded windowing system window.)
2714 'widget 3138 'edit-field
2715 (A widget control, for instance text field or radio button.) 3139 (A text editing widget glyph.)
3140 'button
3141 (A button widget glyph; either a push button, radio button or toggle button.)
3142 'tab-control
3143 (A tab widget glyph; a series of user selectable tabs.)
3144 'progress-gauge
3145 (A sliding widget glyph, for showing progress.)
3146 'combo-box
3147 (A drop list of selectable items in a widget glyph, for editing text.)
3148 'label
3149 (A static, text-only, widget glyph; for displaying text.)
3150 'tree-view
3151 (A folding widget glyph.)
2716 'autodetect 3152 'autodetect
2717 (XEmacs tries to guess what format the data is in. If X support 3153 (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. 3154 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 3155 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 3156 sort of pixmap or pointer will be created. [This includes picking up
2772 that specify symbolic color names to the actual color to be used 3208 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 3209 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' 3210 object). If this is not specified, the contents of `xpm-color-symbols'
2775 are used to generate the alist.) 3211 are used to generate the alist.)
2776 :face 3212 :face
2777 (Only for `inherit'. This specifies the face to inherit from.) 3213 (Only for `inherit'. This specifies the face to inherit from.
3214 For widget glyphs this also specifies the face to use for
3215 display. It defaults to gui-element-face.)
3216
3217 Keywords accepted as menu item specs are also accepted by widget
3218 glyphs. These are `:selected', `:active', `:suffix', `:keys',
3219 `:style', `:filter', `:config', `:included', `:key-sequence',
3220 `:accelerator', `:label' and `:callback'.
2778 3221
2779 If instead of a vector, the instantiator is a string, it will be 3222 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 3223 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 3224 `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 3225 the domain (usually a window; sometimes a frame or device) over which
2800 /**************************************************************************** 3243 /****************************************************************************
2801 * Glyph Object * 3244 * Glyph Object *
2802 ****************************************************************************/ 3245 ****************************************************************************/
2803 3246
2804 static Lisp_Object 3247 static Lisp_Object
2805 mark_glyph (Lisp_Object obj, void (*markobj) (Lisp_Object)) 3248 mark_glyph (Lisp_Object obj)
2806 { 3249 {
2807 struct Lisp_Glyph *glyph = XGLYPH (obj); 3250 Lisp_Glyph *glyph = XGLYPH (obj);
2808 3251
2809 markobj (glyph->image); 3252 mark_object (glyph->image);
2810 markobj (glyph->contrib_p); 3253 mark_object (glyph->contrib_p);
2811 markobj (glyph->baseline); 3254 mark_object (glyph->baseline);
2812 markobj (glyph->face); 3255 mark_object (glyph->face);
2813 3256
2814 return glyph->plist; 3257 return glyph->plist;
2815 } 3258 }
2816 3259
2817 static void 3260 static void
2818 print_glyph (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag) 3261 print_glyph (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
2819 { 3262 {
2820 struct Lisp_Glyph *glyph = XGLYPH (obj); 3263 Lisp_Glyph *glyph = XGLYPH (obj);
2821 char buf[20]; 3264 char buf[20];
2822 3265
2823 if (print_readably) 3266 if (print_readably)
2824 error ("printing unreadable object #<glyph 0x%x>", glyph->header.uid); 3267 error ("printing unreadable object #<glyph 0x%x>", glyph->header.uid);
2825 3268
2838 This isn't concerned with "unspecified" attributes, that's what 3281 This isn't concerned with "unspecified" attributes, that's what
2839 #'glyph-differs-from-default-p is for. */ 3282 #'glyph-differs-from-default-p is for. */
2840 static int 3283 static int
2841 glyph_equal (Lisp_Object obj1, Lisp_Object obj2, int depth) 3284 glyph_equal (Lisp_Object obj1, Lisp_Object obj2, int depth)
2842 { 3285 {
2843 struct Lisp_Glyph *g1 = XGLYPH (obj1); 3286 Lisp_Glyph *g1 = XGLYPH (obj1);
2844 struct Lisp_Glyph *g2 = XGLYPH (obj2); 3287 Lisp_Glyph *g2 = XGLYPH (obj2);
2845 3288
2846 depth++; 3289 depth++;
2847 3290
2848 return (internal_equal (g1->image, g2->image, depth) && 3291 return (internal_equal (g1->image, g2->image, depth) &&
2849 internal_equal (g1->contrib_p, g2->contrib_p, depth) && 3292 internal_equal (g1->contrib_p, g2->contrib_p, depth) &&
2864 } 3307 }
2865 3308
2866 static Lisp_Object 3309 static Lisp_Object
2867 glyph_getprop (Lisp_Object obj, Lisp_Object prop) 3310 glyph_getprop (Lisp_Object obj, Lisp_Object prop)
2868 { 3311 {
2869 struct Lisp_Glyph *g = XGLYPH (obj); 3312 Lisp_Glyph *g = XGLYPH (obj);
2870 3313
2871 if (EQ (prop, Qimage)) return g->image; 3314 if (EQ (prop, Qimage)) return g->image;
2872 if (EQ (prop, Qcontrib_p)) return g->contrib_p; 3315 if (EQ (prop, Qcontrib_p)) return g->contrib_p;
2873 if (EQ (prop, Qbaseline)) return g->baseline; 3316 if (EQ (prop, Qbaseline)) return g->baseline;
2874 if (EQ (prop, Qface)) return g->face; 3317 if (EQ (prop, Qface)) return g->face;
2877 } 3320 }
2878 3321
2879 static int 3322 static int
2880 glyph_putprop (Lisp_Object obj, Lisp_Object prop, Lisp_Object value) 3323 glyph_putprop (Lisp_Object obj, Lisp_Object prop, Lisp_Object value)
2881 { 3324 {
2882 if ((EQ (prop, Qimage)) || 3325 if (EQ (prop, Qimage) ||
2883 (EQ (prop, Qcontrib_p)) || 3326 EQ (prop, Qcontrib_p) ||
2884 (EQ (prop, Qbaseline))) 3327 EQ (prop, Qbaseline))
2885 return 0; 3328 return 0;
2886 3329
2887 if (EQ (prop, Qface)) 3330 if (EQ (prop, Qface))
2888 { 3331 {
2889 XGLYPH (obj)->face = Fget_face (value); 3332 XGLYPH (obj)->face = Fget_face (value);
2895 } 3338 }
2896 3339
2897 static int 3340 static int
2898 glyph_remprop (Lisp_Object obj, Lisp_Object prop) 3341 glyph_remprop (Lisp_Object obj, Lisp_Object prop)
2899 { 3342 {
2900 if ((EQ (prop, Qimage)) || 3343 if (EQ (prop, Qimage) ||
2901 (EQ (prop, Qcontrib_p)) || 3344 EQ (prop, Qcontrib_p) ||
2902 (EQ (prop, Qbaseline))) 3345 EQ (prop, Qbaseline))
2903 return -1; 3346 return -1;
2904 3347
2905 if (EQ (prop, Qface)) 3348 if (EQ (prop, Qface))
2906 { 3349 {
2907 XGLYPH (obj)->face = Qnil; 3350 XGLYPH (obj)->face = Qnil;
2912 } 3355 }
2913 3356
2914 static Lisp_Object 3357 static Lisp_Object
2915 glyph_plist (Lisp_Object obj) 3358 glyph_plist (Lisp_Object obj)
2916 { 3359 {
2917 struct Lisp_Glyph *glyph = XGLYPH (obj); 3360 Lisp_Glyph *glyph = XGLYPH (obj);
2918 Lisp_Object result = glyph->plist; 3361 Lisp_Object result = glyph->plist;
2919 3362
2920 result = cons3 (Qface, glyph->face, result); 3363 result = cons3 (Qface, glyph->face, result);
2921 result = cons3 (Qbaseline, glyph->baseline, result); 3364 result = cons3 (Qbaseline, glyph->baseline, result);
2922 result = cons3 (Qcontrib_p, glyph->contrib_p, result); 3365 result = cons3 (Qcontrib_p, glyph->contrib_p, result);
2923 result = cons3 (Qimage, glyph->image, result); 3366 result = cons3 (Qimage, glyph->image, result);
2924 3367
2925 return result; 3368 return result;
2926 } 3369 }
2927 3370
3371 static const struct lrecord_description glyph_description[] = {
3372 { XD_LISP_OBJECT, offsetof (Lisp_Glyph, image) },
3373 { XD_LISP_OBJECT, offsetof (Lisp_Glyph, contrib_p) },
3374 { XD_LISP_OBJECT, offsetof (Lisp_Glyph, baseline) },
3375 { XD_LISP_OBJECT, offsetof (Lisp_Glyph, face) },
3376 { XD_LISP_OBJECT, offsetof (Lisp_Glyph, plist) },
3377 { XD_END }
3378 };
3379
2928 DEFINE_LRECORD_IMPLEMENTATION_WITH_PROPS ("glyph", glyph, 3380 DEFINE_LRECORD_IMPLEMENTATION_WITH_PROPS ("glyph", glyph,
2929 mark_glyph, print_glyph, 0, 3381 mark_glyph, print_glyph, 0,
2930 glyph_equal, glyph_hash, 3382 glyph_equal, glyph_hash, glyph_description,
2931 glyph_getprop, glyph_putprop, 3383 glyph_getprop, glyph_putprop,
2932 glyph_remprop, glyph_plist, 3384 glyph_remprop, glyph_plist,
2933 struct Lisp_Glyph); 3385 Lisp_Glyph);
2934 3386
2935 Lisp_Object 3387 Lisp_Object
2936 allocate_glyph (enum glyph_type type, 3388 allocate_glyph (enum glyph_type type,
2937 void (*after_change) (Lisp_Object glyph, Lisp_Object property, 3389 void (*after_change) (Lisp_Object glyph, Lisp_Object property,
2938 Lisp_Object locale)) 3390 Lisp_Object locale))
2939 { 3391 {
2940 /* This function can GC */ 3392 /* This function can GC */
2941 Lisp_Object obj = Qnil; 3393 Lisp_Object obj = Qnil;
2942 struct Lisp_Glyph *g = 3394 Lisp_Glyph *g = alloc_lcrecord_type (Lisp_Glyph, &lrecord_glyph);
2943 alloc_lcrecord_type (struct Lisp_Glyph, lrecord_glyph);
2944 3395
2945 g->type = type; 3396 g->type = type;
2946 g->image = Fmake_specifier (Qimage); /* This function can GC */ 3397 g->image = Fmake_specifier (Qimage); /* This function can GC */
3398 g->dirty = 0;
2947 switch (g->type) 3399 switch (g->type)
2948 { 3400 {
2949 case GLYPH_BUFFER: 3401 case GLYPH_BUFFER:
2950 XIMAGE_SPECIFIER_ALLOWED (g->image) = 3402 XIMAGE_SPECIFIER_ALLOWED (g->image) =
2951 IMAGE_NOTHING_MASK | IMAGE_TEXT_MASK 3403 IMAGE_NOTHING_MASK | IMAGE_TEXT_MASK
2952 | IMAGE_MONO_PIXMAP_MASK | IMAGE_COLOR_PIXMAP_MASK 3404 | IMAGE_MONO_PIXMAP_MASK | IMAGE_COLOR_PIXMAP_MASK
2953 | IMAGE_SUBWINDOW_MASK | IMAGE_WIDGET_MASK; 3405 | IMAGE_SUBWINDOW_MASK | IMAGE_WIDGET_MASK
3406 | IMAGE_LAYOUT_MASK;
2954 break; 3407 break;
2955 case GLYPH_POINTER: 3408 case GLYPH_POINTER:
2956 XIMAGE_SPECIFIER_ALLOWED (g->image) = 3409 XIMAGE_SPECIFIER_ALLOWED (g->image) =
2957 IMAGE_NOTHING_MASK | IMAGE_POINTER_MASK; 3410 IMAGE_NOTHING_MASK | IMAGE_POINTER_MASK;
2958 break; 3411 break;
2959 case GLYPH_ICON: 3412 case GLYPH_ICON:
2960 XIMAGE_SPECIFIER_ALLOWED (g->image) = 3413 XIMAGE_SPECIFIER_ALLOWED (g->image) =
2961 IMAGE_NOTHING_MASK | IMAGE_MONO_PIXMAP_MASK | IMAGE_COLOR_PIXMAP_MASK; 3414 IMAGE_NOTHING_MASK | IMAGE_MONO_PIXMAP_MASK
3415 | IMAGE_COLOR_PIXMAP_MASK;
2962 break; 3416 break;
2963 default: 3417 default:
2964 abort (); 3418 abort ();
2965 } 3419 }
2966 3420
3089 case GLYPH_POINTER: return Qpointer; 3543 case GLYPH_POINTER: return Qpointer;
3090 case GLYPH_ICON: return Qicon; 3544 case GLYPH_ICON: return Qicon;
3091 } 3545 }
3092 } 3546 }
3093 3547
3548 Lisp_Object
3549 glyph_image_instance (Lisp_Object glyph, Lisp_Object domain,
3550 Error_behavior errb, int no_quit)
3551 {
3552 Lisp_Object specifier = GLYPH_IMAGE (XGLYPH (glyph));
3553
3554 /* This can never return Qunbound. All glyphs have 'nothing as
3555 a fallback. */
3556 Lisp_Object image_instance = specifier_instance (specifier, Qunbound,
3557 domain, errb, no_quit, 0,
3558 Qzero);
3559 assert (!UNBOUNDP (image_instance));
3560
3561 return image_instance;
3562 }
3563
3564 static Lisp_Object
3565 glyph_image_instance_maybe (Lisp_Object glyph_or_image, Lisp_Object window)
3566 {
3567 Lisp_Object instance = glyph_or_image;
3568
3569 if (GLYPHP (glyph_or_image))
3570 instance = glyph_image_instance (glyph_or_image, window, ERROR_ME_NOT, 1);
3571
3572 return instance;
3573 }
3574
3094 /***************************************************************************** 3575 /*****************************************************************************
3095 glyph_width 3576 glyph_width
3096 3577
3097 Return the width of the given GLYPH on the given WINDOW. If the 3578 Return the width of the given GLYPH on the given WINDOW.
3098 instance is a string then the width is calculated using the font of 3579 Calculations are done based on recursively querying the geometry of
3099 the given FACE, unless a face is defined by the glyph itself. 3580 the associated image instances.
3100 ****************************************************************************/ 3581 ****************************************************************************/
3101 unsigned short 3582 unsigned short
3102 glyph_width (Lisp_Object glyph, Lisp_Object frame_face, 3583 glyph_width (Lisp_Object glyph_or_image, Lisp_Object domain)
3103 face_index window_findex, Lisp_Object window) 3584 {
3104 { 3585 Lisp_Object instance = glyph_image_instance_maybe (glyph_or_image,
3105 Lisp_Object instance; 3586 domain);
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
3115 if (!IMAGE_INSTANCEP (instance)) 3587 if (!IMAGE_INSTANCEP (instance))
3116 return 0; 3588 return 0;
3117 3589
3118 switch (XIMAGE_INSTANCE_TYPE (instance)) 3590 if (XIMAGE_INSTANCE_NEEDS_LAYOUT (instance))
3119 { 3591 image_instance_layout (instance, IMAGE_UNSPECIFIED_GEOMETRY,
3120 case IMAGE_TEXT: 3592 IMAGE_UNSPECIFIED_GEOMETRY, domain);
3121 { 3593
3122 Lisp_Object str = XIMAGE_INSTANCE_TEXT_STRING (instance); 3594 return XIMAGE_INSTANCE_WIDTH (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 }
3156 } 3595 }
3157 3596
3158 DEFUN ("glyph-width", Fglyph_width, 1, 2, 0, /* 3597 DEFUN ("glyph-width", Fglyph_width, 1, 2, 0, /*
3159 Return the width of GLYPH on WINDOW. 3598 Return the width of GLYPH on WINDOW.
3160 This may not be exact as it does not take into account all of the context 3599 This may not be exact as it does not take into account all of the context
3163 (glyph, window)) 3602 (glyph, window))
3164 { 3603 {
3165 XSETWINDOW (window, decode_window (window)); 3604 XSETWINDOW (window, decode_window (window));
3166 CHECK_GLYPH (glyph); 3605 CHECK_GLYPH (glyph);
3167 3606
3168 return make_int (glyph_width (glyph, Qnil, DEFAULT_INDEX, window)); 3607 return make_int (glyph_width (glyph, window));
3169 } 3608 }
3170 3609
3171 #define RETURN_ASCENT 0 3610 unsigned short
3172 #define RETURN_DESCENT 1 3611 glyph_ascent (Lisp_Object glyph_or_image, Lisp_Object domain)
3173 #define RETURN_HEIGHT 2 3612 {
3174 3613 Lisp_Object instance = glyph_image_instance_maybe (glyph_or_image,
3175 Lisp_Object 3614 domain);
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
3200 if (!IMAGE_INSTANCEP (instance)) 3615 if (!IMAGE_INSTANCEP (instance))
3201 return 0; 3616 return 0;
3202 3617
3203 switch (XIMAGE_INSTANCE_TYPE (instance)) 3618 if (XIMAGE_INSTANCE_NEEDS_LAYOUT (instance))
3204 { 3619 image_instance_layout (instance, IMAGE_UNSPECIFIED_GEOMETRY,
3205 case IMAGE_TEXT: 3620 IMAGE_UNSPECIFIED_GEOMETRY, domain);
3206 { 3621
3207 struct font_metric_info fm; 3622 if (XIMAGE_INSTANCE_TYPE (instance) == IMAGE_TEXT)
3208 Lisp_Object string = XIMAGE_INSTANCE_TEXT_STRING (instance); 3623 return XIMAGE_INSTANCE_TEXT_ASCENT (instance);
3209 unsigned char charsets[NUM_LEADING_BYTES]; 3624 else
3210 struct face_cachel frame_cachel; 3625 return XIMAGE_INSTANCE_HEIGHT (instance);
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 }
3264 } 3626 }
3265 3627
3266 unsigned short 3628 unsigned short
3267 glyph_ascent (Lisp_Object glyph, Lisp_Object frame_face, 3629 glyph_descent (Lisp_Object glyph_or_image, Lisp_Object domain)
3268 face_index window_findex, Lisp_Object window) 3630 {
3269 { 3631 Lisp_Object instance = glyph_image_instance_maybe (glyph_or_image,
3270 return glyph_height_internal (glyph, frame_face, window_findex, window, 3632 domain);
3271 RETURN_ASCENT); 3633 if (!IMAGE_INSTANCEP (instance))
3272 } 3634 return 0;
3273 3635
3274 unsigned short 3636 if (XIMAGE_INSTANCE_NEEDS_LAYOUT (instance))
3275 glyph_descent (Lisp_Object glyph, Lisp_Object frame_face, 3637 image_instance_layout (instance, IMAGE_UNSPECIFIED_GEOMETRY,
3276 face_index window_findex, Lisp_Object window) 3638 IMAGE_UNSPECIFIED_GEOMETRY, domain);
3277 { 3639
3278 return glyph_height_internal (glyph, frame_face, window_findex, window, 3640 if (XIMAGE_INSTANCE_TYPE (instance) == IMAGE_TEXT)
3279 RETURN_DESCENT); 3641 return XIMAGE_INSTANCE_TEXT_DESCENT (instance);
3642 else
3643 return 0;
3280 } 3644 }
3281 3645
3282 /* strictly a convenience function. */ 3646 /* strictly a convenience function. */
3283 unsigned short 3647 unsigned short
3284 glyph_height (Lisp_Object glyph, Lisp_Object frame_face, 3648 glyph_height (Lisp_Object glyph_or_image, Lisp_Object domain)
3285 face_index window_findex, Lisp_Object window) 3649 {
3286 { 3650 Lisp_Object instance = glyph_image_instance_maybe (glyph_or_image,
3287 return glyph_height_internal (glyph, frame_face, window_findex, window, 3651 domain);
3288 RETURN_HEIGHT); 3652
3653 if (!IMAGE_INSTANCEP (instance))
3654 return 0;
3655
3656 if (XIMAGE_INSTANCE_NEEDS_LAYOUT (instance))
3657 image_instance_layout (instance, IMAGE_UNSPECIFIED_GEOMETRY,
3658 IMAGE_UNSPECIFIED_GEOMETRY, domain);
3659
3660 return XIMAGE_INSTANCE_HEIGHT (instance);
3289 } 3661 }
3290 3662
3291 DEFUN ("glyph-ascent", Fglyph_ascent, 1, 2, 0, /* 3663 DEFUN ("glyph-ascent", Fglyph_ascent, 1, 2, 0, /*
3292 Return the ascent value of GLYPH on WINDOW. 3664 Return the ascent value of GLYPH on WINDOW.
3293 This may not be exact as it does not take into account all of the context 3665 This may not be exact as it does not take into account all of the context
3296 (glyph, window)) 3668 (glyph, window))
3297 { 3669 {
3298 XSETWINDOW (window, decode_window (window)); 3670 XSETWINDOW (window, decode_window (window));
3299 CHECK_GLYPH (glyph); 3671 CHECK_GLYPH (glyph);
3300 3672
3301 return make_int (glyph_ascent (glyph, Qnil, DEFAULT_INDEX, window)); 3673 return make_int (glyph_ascent (glyph, window));
3302 } 3674 }
3303 3675
3304 DEFUN ("glyph-descent", Fglyph_descent, 1, 2, 0, /* 3676 DEFUN ("glyph-descent", Fglyph_descent, 1, 2, 0, /*
3305 Return the descent value of GLYPH on WINDOW. 3677 Return the descent value of GLYPH on WINDOW.
3306 This may not be exact as it does not take into account all of the context 3678 This may not be exact as it does not take into account all of the context
3309 (glyph, window)) 3681 (glyph, window))
3310 { 3682 {
3311 XSETWINDOW (window, decode_window (window)); 3683 XSETWINDOW (window, decode_window (window));
3312 CHECK_GLYPH (glyph); 3684 CHECK_GLYPH (glyph);
3313 3685
3314 return make_int (glyph_descent (glyph, Qnil, DEFAULT_INDEX, window)); 3686 return make_int (glyph_descent (glyph, window));
3315 } 3687 }
3316 3688
3317 /* This is redundant but I bet a lot of people expect it to exist. */ 3689 /* This is redundant but I bet a lot of people expect it to exist. */
3318 DEFUN ("glyph-height", Fglyph_height, 1, 2, 0, /* 3690 DEFUN ("glyph-height", Fglyph_height, 1, 2, 0, /*
3319 Return the height of GLYPH on WINDOW. 3691 Return the height of GLYPH on WINDOW.
3323 (glyph, window)) 3695 (glyph, window))
3324 { 3696 {
3325 XSETWINDOW (window, decode_window (window)); 3697 XSETWINDOW (window, decode_window (window));
3326 CHECK_GLYPH (glyph); 3698 CHECK_GLYPH (glyph);
3327 3699
3328 return make_int (glyph_height (glyph, Qnil, DEFAULT_INDEX, window)); 3700 return make_int (glyph_height (glyph, window));
3329 } 3701 }
3330 3702
3331 #undef RETURN_ASCENT 3703 static void
3332 #undef RETURN_DESCENT 3704 set_glyph_dirty_p (Lisp_Object glyph_or_image, Lisp_Object window, int dirty)
3333 #undef RETURN_HEIGHT 3705 {
3706 Lisp_Object instance = glyph_or_image;
3707
3708 if (!NILP (glyph_or_image))
3709 {
3710 if (GLYPHP (glyph_or_image))
3711 {
3712 instance = glyph_image_instance (glyph_or_image, window,
3713 ERROR_ME_NOT, 1);
3714 XGLYPH_DIRTYP (glyph_or_image) = dirty;
3715 }
3716
3717 XIMAGE_INSTANCE_DIRTYP (instance) = dirty;
3718 }
3719 }
3720
3721 static void
3722 set_image_instance_dirty_p (Lisp_Object instance, int dirty)
3723 {
3724 if (IMAGE_INSTANCEP (instance))
3725 {
3726 XIMAGE_INSTANCE_DIRTYP (instance) = dirty;
3727 /* Now cascade up the hierarchy. */
3728 set_image_instance_dirty_p (XIMAGE_INSTANCE_PARENT (instance),
3729 dirty);
3730 }
3731 else if (GLYPHP (instance))
3732 {
3733 XGLYPH_DIRTYP (instance) = dirty;
3734 }
3735 }
3334 3736
3335 /* #### do we need to cache this info to speed things up? */ 3737 /* #### do we need to cache this info to speed things up? */
3336 3738
3337 Lisp_Object 3739 Lisp_Object
3338 glyph_baseline (Lisp_Object glyph, Lisp_Object domain) 3740 glyph_baseline (Lisp_Object glyph, Lisp_Object domain)
3384 { 3786 {
3385 if (XGLYPH (glyph)->after_change) 3787 if (XGLYPH (glyph)->after_change)
3386 (XGLYPH (glyph)->after_change) (glyph, property, locale); 3788 (XGLYPH (glyph)->after_change) (glyph, property, locale);
3387 } 3789 }
3388 3790
3791 #if 0 /* Not used for now */
3792 static void
3793 glyph_query_geometry (Lisp_Object glyph_or_image, Lisp_Object window,
3794 unsigned int* width, unsigned int* height,
3795 enum image_instance_geometry disp, Lisp_Object domain)
3796 {
3797 Lisp_Object instance = glyph_or_image;
3798
3799 if (GLYPHP (glyph_or_image))
3800 instance = glyph_image_instance (glyph_or_image, window, ERROR_ME_NOT, 1);
3801
3802 image_instance_query_geometry (instance, width, height, disp, domain);
3803 }
3804
3805 static void
3806 glyph_layout (Lisp_Object glyph_or_image, Lisp_Object window,
3807 unsigned int width, unsigned int height, Lisp_Object domain)
3808 {
3809 Lisp_Object instance = glyph_or_image;
3810
3811 if (GLYPHP (glyph_or_image))
3812 instance = glyph_image_instance (glyph_or_image, window, ERROR_ME_NOT, 1);
3813
3814 image_instance_layout (instance, width, height, domain);
3815 }
3816 #endif
3817
3389 3818
3390 /***************************************************************************** 3819 /*****************************************************************************
3391 * glyph cachel functions * 3820 * glyph cachel functions *
3392 *****************************************************************************/ 3821 *****************************************************************************/
3393 3822
3394 /* 3823 /* #### All of this is 95% copied from face cachels. Consider
3395 #### All of this is 95% copied from face cachels. 3824 consolidating.
3396 Consider consolidating. 3825
3397 #### We need to add a dirty flag to the glyphs. 3826 Why do we need glyph_cachels? Simply because a glyph_cachel captures
3398 */ 3827 per-window information about a particular glyph. A glyph itself is
3399 3828 not created in any particular context, so if we were to rely on a
3829 glyph to tell us about its dirtiness we would not be able to reset
3830 the dirty flag after redisplaying it as it may exist in other
3831 contexts. When we have redisplayed we need to know which glyphs to
3832 reset the dirty flags on - the glyph_cachels give us a nice list we
3833 can iterate through doing this. */
3400 void 3834 void
3401 mark_glyph_cachels (glyph_cachel_dynarr *elements, 3835 mark_glyph_cachels (glyph_cachel_dynarr *elements)
3402 void (*markobj) (Lisp_Object))
3403 { 3836 {
3404 int elt; 3837 int elt;
3405 3838
3406 if (!elements) 3839 if (!elements)
3407 return; 3840 return;
3408 3841
3409 for (elt = 0; elt < Dynarr_length (elements); elt++) 3842 for (elt = 0; elt < Dynarr_length (elements); elt++)
3410 { 3843 {
3411 struct glyph_cachel *cachel = Dynarr_atp (elements, elt); 3844 struct glyph_cachel *cachel = Dynarr_atp (elements, elt);
3412 markobj (cachel->glyph); 3845 mark_object (cachel->glyph);
3413 } 3846 }
3414 } 3847 }
3415 3848
3416 static void 3849 static void
3417 update_glyph_cachel_data (struct window *w, Lisp_Object glyph, 3850 update_glyph_cachel_data (struct window *w, Lisp_Object glyph,
3418 struct glyph_cachel *cachel) 3851 struct glyph_cachel *cachel)
3419 { 3852 {
3420 /* #### This should be || !cachel->updated */ 3853 if (!cachel->updated || NILP (cachel->glyph) || !EQ (cachel->glyph, glyph)
3421 if (NILP (cachel->glyph) || !EQ (cachel->glyph, glyph)) 3854 || XGLYPH_DIRTYP (cachel->glyph)
3422 { 3855 || XFRAME(WINDOW_FRAME(w))->faces_changed)
3423 Lisp_Object window; 3856 {
3857 Lisp_Object window, instance;
3424 3858
3425 XSETWINDOW (window, w); 3859 XSETWINDOW (window, w);
3426 3860
3427 /* #### This could be sped up if we redid things to grab the glyph
3428 instantiation and passed it to the size functions. */
3429 cachel->glyph = glyph; 3861 cachel->glyph = glyph;
3430 cachel->width = glyph_width (glyph, Qnil, DEFAULT_INDEX, window); 3862 /* Speed things up slightly by grabbing the glyph instantiation
3431 cachel->ascent = glyph_ascent (glyph, Qnil, DEFAULT_INDEX, window); 3863 and passing it to the size functions. */
3432 cachel->descent = glyph_descent (glyph, Qnil, DEFAULT_INDEX, window); 3864 instance = glyph_image_instance (glyph, window, ERROR_ME_NOT, 1);
3865
3866 /* Mark text instance of the glyph dirty if faces have changed,
3867 because its geometry might have changed. */
3868 invalidate_glyph_geometry_maybe (instance, w);
3869
3870 /* #### Do the following 2 lines buy us anything? --kkm */
3871 XGLYPH_DIRTYP (glyph) = XIMAGE_INSTANCE_DIRTYP (instance);
3872 cachel->dirty = XGLYPH_DIRTYP (glyph);
3873 cachel->width = glyph_width (instance, window);
3874 cachel->ascent = glyph_ascent (instance, window);
3875 cachel->descent = glyph_descent (instance, window);
3433 } 3876 }
3434 3877
3435 cachel->updated = 1; 3878 cachel->updated = 1;
3436 } 3879 }
3437 3880
3445 3888
3446 update_glyph_cachel_data (w, glyph, &new_cachel); 3889 update_glyph_cachel_data (w, glyph, &new_cachel);
3447 Dynarr_add (w->glyph_cachels, new_cachel); 3890 Dynarr_add (w->glyph_cachels, new_cachel);
3448 } 3891 }
3449 3892
3450 static glyph_index 3893 glyph_index
3451 get_glyph_cachel_index (struct window *w, Lisp_Object glyph) 3894 get_glyph_cachel_index (struct window *w, Lisp_Object glyph)
3452 { 3895 {
3453 int elt; 3896 int elt;
3454 3897
3455 if (noninteractive) 3898 if (noninteractive)
3460 struct glyph_cachel *cachel = 3903 struct glyph_cachel *cachel =
3461 Dynarr_atp (w->glyph_cachels, elt); 3904 Dynarr_atp (w->glyph_cachels, elt);
3462 3905
3463 if (EQ (cachel->glyph, glyph) && !NILP (glyph)) 3906 if (EQ (cachel->glyph, glyph) && !NILP (glyph))
3464 { 3907 {
3465 if (!cachel->updated) 3908 update_glyph_cachel_data (w, glyph, cachel);
3466 update_glyph_cachel_data (w, glyph, cachel);
3467 return elt; 3909 return elt;
3468 } 3910 }
3469 } 3911 }
3470 3912
3471 /* If we didn't find the glyph, add it and then return its index. */ 3913 /* If we didn't find the glyph, add it and then return its index. */
3504 FROB (Voctal_escape_glyph, OCT_ESC_GLYPH_INDEX); 3946 FROB (Voctal_escape_glyph, OCT_ESC_GLYPH_INDEX);
3505 FROB (Vinvisible_text_glyph, INVIS_GLYPH_INDEX); 3947 FROB (Vinvisible_text_glyph, INVIS_GLYPH_INDEX);
3506 #undef FROB 3948 #undef FROB
3507 3949
3508 for (elt = 0; elt < Dynarr_length (w->glyph_cachels); elt++) 3950 for (elt = 0; elt < Dynarr_length (w->glyph_cachels); elt++)
3509 Dynarr_atp (w->glyph_cachels, elt)->updated = 0; 3951 {
3952 Dynarr_atp (w->glyph_cachels, elt)->updated = 0;
3953 }
3954 }
3955
3956 /* Unset the dirty bit on all the glyph cachels that have it. */
3957 void
3958 mark_glyph_cachels_as_clean (struct window* w)
3959 {
3960 int elt;
3961 Lisp_Object window;
3962 XSETWINDOW (window, w);
3963 for (elt = 0; elt < Dynarr_length (w->glyph_cachels); elt++)
3964 {
3965 struct glyph_cachel *cachel = Dynarr_atp (w->glyph_cachels, elt);
3966 cachel->dirty = 0;
3967 set_glyph_dirty_p (cachel->glyph, window, 0);
3968 }
3510 } 3969 }
3511 3970
3512 #ifdef MEMORY_USAGE_STATS 3971 #ifdef MEMORY_USAGE_STATS
3513 3972
3514 int 3973 int
3528 3987
3529 3988
3530 /***************************************************************************** 3989 /*****************************************************************************
3531 * subwindow cachel functions * 3990 * subwindow cachel functions *
3532 *****************************************************************************/ 3991 *****************************************************************************/
3533 /* subwindows are curious in that you have to physically unmap them to 3992 /* Subwindows are curious in that you have to physically unmap them to
3534 not display them. It is problematic deciding what to do in 3993 not display them. It is problematic deciding what to do in
3535 redisplay. We have two caches - a per-window instance cache that 3994 redisplay. We have two caches - a per-window instance cache that
3536 keeps track of subwindows on a window, these are linked to their 3995 keeps track of subwindows on a window, these are linked to their
3537 instantiator in the hashtable and when the instantiator goes away 3996 instantiator in the hashtable and when the instantiator goes away
3538 we want the instance to go away also. However we also have a 3997 we want the instance to go away also. However we also have a
3539 per-frame instance cache that we use to determine if a subwindow is 3998 per-frame instance cache that we use to determine if a subwindow is
3540 obscuring an area that we want to clear. We need to be able to flip 3999 obscuring an area that we want to clear. We need to be able to flip
3541 through this quickly so a hashtable is not suitable hence the 4000 through this quickly so a hashtable is not suitable hence the
3542 subwindow_cachels. The question is should we just not mark 4001 subwindow_cachels. The question is should we just not mark
3543 instances in the subwindow_cachelsnor should we try and invalidate 4002 instances in the subwindow_cachels or should we try and invalidate
3544 the cache at suitable points in redisplay? If we don't invalidate 4003 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 4004 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 4005 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, 4006 and whether we mark as well. Go for the simple option - don't mark,
3548 MARK_SUBWINDOWS_CHANGED when a subwindow gets deleted. */ 4007 MARK_SUBWINDOWS_CHANGED when a subwindow gets deleted. */
3549 4008
3550 void 4009 void
3551 mark_subwindow_cachels (subwindow_cachel_dynarr *elements, 4010 mark_subwindow_cachels (subwindow_cachel_dynarr *elements)
3552 void (*markobj) (Lisp_Object))
3553 { 4011 {
3554 int elt; 4012 int elt;
3555 4013
3556 if (!elements) 4014 if (!elements)
3557 return; 4015 return;
3558 4016
3559 for (elt = 0; elt < Dynarr_length (elements); elt++) 4017 for (elt = 0; elt < Dynarr_length (elements); elt++)
3560 { 4018 {
3561 struct subwindow_cachel *cachel = Dynarr_atp (elements, elt); 4019 struct subwindow_cachel *cachel = Dynarr_atp (elements, elt);
3562 markobj (cachel->subwindow); 4020 mark_object (cachel->subwindow);
3563 } 4021 }
3564 } 4022 }
3565 4023
3566 static void 4024 static void
3567 update_subwindow_cachel_data (struct frame *f, Lisp_Object subwindow, 4025 update_subwindow_cachel_data (struct frame *f, Lisp_Object subwindow,
3568 struct subwindow_cachel *cachel) 4026 struct subwindow_cachel *cachel)
3569 { 4027 {
3570 if (NILP (cachel->subwindow) || !EQ (cachel->subwindow, subwindow)) 4028 cachel->subwindow = subwindow;
3571 { 4029 cachel->width = XIMAGE_INSTANCE_SUBWINDOW_WIDTH (subwindow);
3572 cachel->subwindow = subwindow; 4030 cachel->height = XIMAGE_INSTANCE_SUBWINDOW_HEIGHT (subwindow);
3573 cachel->width = XIMAGE_INSTANCE_SUBWINDOW_WIDTH (subwindow);
3574 cachel->height = XIMAGE_INSTANCE_SUBWINDOW_HEIGHT (subwindow);
3575 }
3576
3577 cachel->updated = 1; 4031 cachel->updated = 1;
3578 } 4032 }
3579 4033
3580 static void 4034 static void
3581 add_subwindow_cachel (struct frame *f, Lisp_Object subwindow) 4035 add_subwindow_cachel (struct frame *f, Lisp_Object subwindow)
3614 } 4068 }
3615 4069
3616 /* If we didn't find the glyph, add it and then return its index. */ 4070 /* If we didn't find the glyph, add it and then return its index. */
3617 add_subwindow_cachel (f, subwindow); 4071 add_subwindow_cachel (f, subwindow);
3618 return elt; 4072 return elt;
4073 }
4074
4075 static void
4076 update_subwindow_cachel (Lisp_Object subwindow)
4077 {
4078 struct frame* f;
4079 int elt;
4080
4081 if (NILP (subwindow))
4082 return;
4083
4084 f = XFRAME ( XIMAGE_INSTANCE_SUBWINDOW_FRAME (subwindow));
4085
4086 for (elt = 0; elt < Dynarr_length (f->subwindow_cachels); elt++)
4087 {
4088 struct subwindow_cachel *cachel =
4089 Dynarr_atp (f->subwindow_cachels, elt);
4090
4091 if (EQ (cachel->subwindow, subwindow) && !NILP (subwindow))
4092 {
4093 update_subwindow_cachel_data (f, subwindow, cachel);
4094 }
4095 }
3619 } 4096 }
3620 4097
3621 /* redisplay in general assumes that drawing something will erase 4098 /* redisplay in general assumes that drawing something will erase
3622 what was there before. unfortunately this does not apply to 4099 what was there before. unfortunately this does not apply to
3623 subwindows that need to be specifically unmapped in order to 4100 subwindows that need to be specifically unmapped in order to
3632 struct subwindow_cachel *cachel = 4109 struct subwindow_cachel *cachel =
3633 Dynarr_atp (f->subwindow_cachels, elt); 4110 Dynarr_atp (f->subwindow_cachels, elt);
3634 4111
3635 if (!NILP (cachel->subwindow) && cachel->being_displayed) 4112 if (!NILP (cachel->subwindow) && cachel->being_displayed)
3636 { 4113 {
3637 struct Lisp_Image_Instance* ii = XIMAGE_INSTANCE (cachel->subwindow); 4114 cachel->updated = 1;
3638 MAYBE_DEVMETH (XDEVICE (f->device), unmap_subwindow, (ii)); 4115 /* #### This is not optimal as update_subwindow will search
4116 the cachels for ourselves as well. We could easily optimize. */
4117 unmap_subwindow (cachel->subwindow);
3639 } 4118 }
3640 } 4119 }
3641 Dynarr_reset (f->subwindow_cachels); 4120 Dynarr_reset (f->subwindow_cachels);
3642 } 4121 }
3643 4122
3646 { 4125 {
3647 int elt; 4126 int elt;
3648 4127
3649 for (elt = 0; elt < Dynarr_length (f->subwindow_cachels); elt++) 4128 for (elt = 0; elt < Dynarr_length (f->subwindow_cachels); elt++)
3650 Dynarr_atp (f->subwindow_cachels, elt)->updated = 0; 4129 Dynarr_atp (f->subwindow_cachels, elt)->updated = 0;
4130 }
4131
4132
4133
4134 /*****************************************************************************
4135 * subwindow exposure ignorance *
4136 *****************************************************************************/
4137 /* when we unmap subwindows the associated window system will generate
4138 expose events. This we do not want as redisplay already copes with
4139 the repainting necessary. Worse, we can get in an endless cycle of
4140 redisplay if we are not careful. Thus we keep a per-frame list of
4141 expose events that are going to come and ignore them as
4142 required. */
4143
4144 struct expose_ignore_blocktype
4145 {
4146 Blocktype_declare (struct expose_ignore);
4147 } *the_expose_ignore_blocktype;
4148
4149 int
4150 check_for_ignored_expose (struct frame* f, int x, int y, int width, int height)
4151 {
4152 struct expose_ignore *ei, *prev;
4153 /* the ignore list is FIFO so we should generally get a match with
4154 the first element in the list */
4155 for (ei = f->subwindow_exposures, prev = 0; ei; ei = ei->next)
4156 {
4157 /* Checking for exact matches just isn't good enough as we
4158 mighte get exposures for partially obscure subwindows, thus
4159 we have to check for overlaps. Being conservative we will
4160 check for exposures wholly contained by the subwindow, this
4161 might give us what we want.*/
4162 if (ei->x <= x && ei->y <= y
4163 && ei->x + ei->width >= x + width
4164 && ei->y + ei->height >= y + height)
4165 {
4166 #ifdef DEBUG_WIDGETS
4167 stderr_out ("ignored %d+%d, %dx%d for exposure %d+%d, %dx%d\n",
4168 x, y, width, height, ei->x, ei->y, ei->width, ei->height);
4169 #endif
4170 if (!prev)
4171 f->subwindow_exposures = ei->next;
4172 else
4173 prev->next = ei->next;
4174
4175 if (ei == f->subwindow_exposures_tail)
4176 f->subwindow_exposures_tail = prev;
4177
4178 Blocktype_free (the_expose_ignore_blocktype, ei);
4179 return 1;
4180 }
4181 prev = ei;
4182 }
4183 return 0;
4184 }
4185
4186 static void
4187 register_ignored_expose (struct frame* f, int x, int y, int width, int height)
4188 {
4189 if (!hold_ignored_expose_registration)
4190 {
4191 struct expose_ignore *ei;
4192
4193 ei = Blocktype_alloc (the_expose_ignore_blocktype);
4194
4195 ei->next = NULL;
4196 ei->x = x;
4197 ei->y = y;
4198 ei->width = width;
4199 ei->height = height;
4200
4201 /* we have to add the exposure to the end of the list, since we
4202 want to check the oldest events first. for speed we keep a record
4203 of the end so that we can add right to it. */
4204 if (f->subwindow_exposures_tail)
4205 {
4206 f->subwindow_exposures_tail->next = ei;
4207 }
4208 if (!f->subwindow_exposures)
4209 {
4210 f->subwindow_exposures = ei;
4211 }
4212 f->subwindow_exposures_tail = ei;
4213 }
4214 }
4215
4216 /****************************************************************************
4217 find_matching_subwindow
4218
4219 See if there is a subwindow that completely encloses the requested
4220 area.
4221 ****************************************************************************/
4222 int find_matching_subwindow (struct frame* f, int x, int y, int width, int height)
4223 {
4224 int elt;
4225
4226 for (elt = 0; elt < Dynarr_length (f->subwindow_cachels); elt++)
4227 {
4228 struct subwindow_cachel *cachel =
4229 Dynarr_atp (f->subwindow_cachels, elt);
4230
4231 if (cachel->being_displayed
4232 &&
4233 cachel->x <= x && cachel->y <= y
4234 &&
4235 cachel->x + cachel->width >= x + width
4236 &&
4237 cachel->y + cachel->height >= y + height)
4238 {
4239 return 1;
4240 }
4241 }
4242 return 0;
3651 } 4243 }
3652 4244
3653 4245
3654 /***************************************************************************** 4246 /*****************************************************************************
3655 * subwindow functions * 4247 * subwindow functions *
3656 *****************************************************************************/ 4248 *****************************************************************************/
3657 4249
3658 /* update the displayed characteristics of a subwindow */ 4250 /* update the displayed characteristics of a subwindow */
3659 static void 4251 void
3660 update_subwindow (Lisp_Object subwindow) 4252 update_subwindow (Lisp_Object subwindow)
3661 { 4253 {
3662 struct Lisp_Image_Instance* ii = XIMAGE_INSTANCE (subwindow); 4254 Lisp_Image_Instance* ii = XIMAGE_INSTANCE (subwindow);
3663 4255
3664 if (!IMAGE_INSTANCE_TYPE (ii) == IMAGE_WIDGET 4256 if (IMAGE_INSTANCE_TYPE (ii) == IMAGE_WIDGET
3665 || 4257 ||
3666 NILP (IMAGE_INSTANCE_SUBWINDOW_FRAME (ii))) 4258 IMAGE_INSTANCE_TYPE (ii) == IMAGE_LAYOUT)
3667 return; 4259 {
3668 4260 if (IMAGE_INSTANCE_TYPE (ii) == IMAGE_WIDGET)
3669 MAYBE_DEVMETH (XDEVICE (ii->device), update_subwindow, (ii)); 4261 update_widget (subwindow);
3670 } 4262 /* Reset the changed flags. */
3671 4263 IMAGE_INSTANCE_WIDGET_FACE_CHANGED (ii) = 0;
4264 IMAGE_INSTANCE_WIDGET_PERCENT_CHANGED (ii) = 0;
4265 IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii) = 0;
4266 IMAGE_INSTANCE_TEXT_CHANGED (ii) = 0;
4267 }
4268 else if (IMAGE_INSTANCE_TYPE (ii) == IMAGE_SUBWINDOW
4269 &&
4270 !NILP (IMAGE_INSTANCE_SUBWINDOW_FRAME (ii)))
4271 {
4272 MAYBE_DEVMETH (XDEVICE (ii->device), update_subwindow, (ii));
4273 }
4274
4275 IMAGE_INSTANCE_SIZE_CHANGED (ii) = 0;
4276 }
4277
4278 /* Update all the subwindows on a frame. */
3672 void 4279 void
3673 update_frame_subwindows (struct frame *f) 4280 update_frame_subwindows (struct frame *f)
3674 { 4281 {
3675 int elt; 4282 int elt;
3676 4283
3677 if (f->subwindows_changed || f->glyphs_changed) 4284 /* #### Checking all of these might be overkill now that we update
4285 subwindows in the actual redisplay code. */
4286 if (f->subwindows_changed || f->subwindows_state_changed || f->faces_changed)
3678 for (elt = 0; elt < Dynarr_length (f->subwindow_cachels); elt++) 4287 for (elt = 0; elt < Dynarr_length (f->subwindow_cachels); elt++)
3679 { 4288 {
3680 struct subwindow_cachel *cachel = 4289 struct subwindow_cachel *cachel =
3681 Dynarr_atp (f->subwindow_cachels, elt); 4290 Dynarr_atp (f->subwindow_cachels, elt);
3682 4291
3683 if (cachel->being_displayed) 4292 if (cachel->being_displayed)
3684 { 4293 {
3685 update_subwindow (cachel->subwindow); 4294 update_subwindow (cachel->subwindow);
3686 } 4295 }
3687 } 4296 }
3688 } 4297 }
3689 4298
3690 /* remove a subwindow from its frame */ 4299 /* remove a subwindow from its frame */
3691 void unmap_subwindow (Lisp_Object subwindow) 4300 void unmap_subwindow (Lisp_Object subwindow)
3692 { 4301 {
3693 struct Lisp_Image_Instance* ii = XIMAGE_INSTANCE (subwindow); 4302 Lisp_Image_Instance* ii = XIMAGE_INSTANCE (subwindow);
3694 int elt; 4303 int elt;
3695 struct subwindow_cachel* cachel; 4304 struct subwindow_cachel* cachel;
3696 struct frame* f; 4305 struct frame* f;
3697 4306
3698 if (!(IMAGE_INSTANCE_TYPE (ii) == IMAGE_WIDGET 4307 if (!(IMAGE_INSTANCE_TYPE (ii) == IMAGE_WIDGET
3699 || 4308 ||
3700 IMAGE_INSTANCE_TYPE (ii) == IMAGE_SUBWINDOW) 4309 IMAGE_INSTANCE_TYPE (ii) == IMAGE_SUBWINDOW)
3701 || 4310 ||
3702 NILP (IMAGE_INSTANCE_SUBWINDOW_FRAME (ii))) 4311 NILP (IMAGE_INSTANCE_SUBWINDOW_FRAME (ii)))
3703 return; 4312 return;
3704 4313 #ifdef DEBUG_WIDGETS
4314 stderr_out ("unmapping subwindow %d\n", IMAGE_INSTANCE_SUBWINDOW_ID (ii));
4315 #endif
3705 f = XFRAME (IMAGE_INSTANCE_SUBWINDOW_FRAME (ii)); 4316 f = XFRAME (IMAGE_INSTANCE_SUBWINDOW_FRAME (ii));
3706 elt = get_subwindow_cachel_index (f, subwindow); 4317 elt = get_subwindow_cachel_index (f, subwindow);
3707 cachel = Dynarr_atp (f->subwindow_cachels, elt); 4318 cachel = Dynarr_atp (f->subwindow_cachels, elt);
3708 4319
3709 cachel->x = -1; 4320 /* make sure we don't get expose events */
3710 cachel->y = -1; 4321 register_ignored_expose (f, cachel->x, cachel->y, cachel->width, cachel->height);
4322 cachel->x = ~0;
4323 cachel->y = ~0;
3711 cachel->being_displayed = 0; 4324 cachel->being_displayed = 0;
3712 IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (ii) = 0; 4325 IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (ii) = 0;
3713 4326
3714 MAYBE_DEVMETH (XDEVICE (ii->device), unmap_subwindow, (ii)); 4327 MAYBE_DEVMETH (XDEVICE (ii->device), unmap_subwindow, (ii));
3715 } 4328 }
3716 4329
3717 /* show a subwindow in its frame */ 4330 /* show a subwindow in its frame */
3718 void map_subwindow (Lisp_Object subwindow, int x, int y) 4331 void map_subwindow (Lisp_Object subwindow, int x, int y,
3719 { 4332 struct display_glyph_area *dga)
3720 struct Lisp_Image_Instance* ii = XIMAGE_INSTANCE (subwindow); 4333 {
3721 int elt; 4334 Lisp_Image_Instance* ii = XIMAGE_INSTANCE (subwindow);
4335 int elt;
3722 struct subwindow_cachel* cachel; 4336 struct subwindow_cachel* cachel;
3723 struct frame* f; 4337 struct frame* f;
3724 4338
3725 if (!(IMAGE_INSTANCE_TYPE (ii) == IMAGE_WIDGET 4339 if (!(IMAGE_INSTANCE_TYPE (ii) == IMAGE_WIDGET
3726 || 4340 ||
3727 IMAGE_INSTANCE_TYPE (ii) == IMAGE_SUBWINDOW) 4341 IMAGE_INSTANCE_TYPE (ii) == IMAGE_SUBWINDOW)
3728 || 4342 ||
3729 NILP (IMAGE_INSTANCE_SUBWINDOW_FRAME (ii))) 4343 NILP (IMAGE_INSTANCE_SUBWINDOW_FRAME (ii)))
3730 return; 4344 return;
3731 4345
4346 #ifdef DEBUG_WIDGETS
4347 stderr_out ("mapping subwindow %d, %dx%d@%d+%d\n",
4348 IMAGE_INSTANCE_SUBWINDOW_ID (ii),
4349 dga->width, dga->height, x, y);
4350 #endif
3732 f = XFRAME (IMAGE_INSTANCE_SUBWINDOW_FRAME (ii)); 4351 f = XFRAME (IMAGE_INSTANCE_SUBWINDOW_FRAME (ii));
3733 IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (ii) = 1; 4352 IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (ii) = 1;
3734 elt = get_subwindow_cachel_index (f, subwindow); 4353 elt = get_subwindow_cachel_index (f, subwindow);
3735 cachel = Dynarr_atp (f->subwindow_cachels, elt); 4354 cachel = Dynarr_atp (f->subwindow_cachels, elt);
3736 cachel->x = x; 4355 cachel->x = x;
3737 cachel->y = y; 4356 cachel->y = y;
4357 cachel->width = dga->width;
4358 cachel->height = dga->height;
3738 cachel->being_displayed = 1; 4359 cachel->being_displayed = 1;
3739 4360
3740 MAYBE_DEVMETH (XDEVICE (ii->device), map_subwindow, (ii, x, y)); 4361 #if 0
4362 /* This forces any pending display changes to happen to the image
4363 before we show it. I'm not sure whether or not we need mark as
4364 clean here, but for now we will. */
4365 if (IMAGE_INSTANCE_DIRTYP (ii))
4366 {
4367 update_subwindow (subwindow);
4368 IMAGE_INSTANCE_DIRTYP (ii) = 0;
4369 }
4370 #endif
4371
4372 MAYBE_DEVMETH (XDEVICE (ii->device), map_subwindow, (ii, x, y, dga));
3741 } 4373 }
3742 4374
3743 static int 4375 static int
3744 subwindow_possible_dest_types (void) 4376 subwindow_possible_dest_types (void)
3745 { 4377 {
3750 void 4382 void
3751 subwindow_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, 4383 subwindow_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
3752 Lisp_Object pointer_fg, Lisp_Object pointer_bg, 4384 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
3753 int dest_mask, Lisp_Object domain) 4385 int dest_mask, Lisp_Object domain)
3754 { 4386 {
3755 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); 4387 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
3756 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii); 4388 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
3757 Lisp_Object frame = FW_FRAME (domain); 4389 Lisp_Object frame = FW_FRAME (domain);
3758 Lisp_Object width = find_keyword_in_vector (instantiator, Q_pixel_width); 4390 Lisp_Object width = find_keyword_in_vector (instantiator, Q_pixel_width);
3759 Lisp_Object height = find_keyword_in_vector (instantiator, Q_pixel_height); 4391 Lisp_Object height = find_keyword_in_vector (instantiator, Q_pixel_height);
3760 4392
3761 if (NILP (frame)) 4393 if (NILP (frame))
3762 signal_simple_error ("No selected frame", device); 4394 signal_simple_error ("No selected frame", device);
3763 4395
3764 if (!(dest_mask & IMAGE_SUBWINDOW_MASK)) 4396 if (!(dest_mask & IMAGE_SUBWINDOW_MASK))
3765 incompatible_image_types (instantiator, dest_mask, IMAGE_SUBWINDOW_MASK); 4397 incompatible_image_types (instantiator, dest_mask, IMAGE_SUBWINDOW_MASK);
3766 4398
3767 ii->data = 0; 4399 ii->data = 0;
3768 IMAGE_INSTANCE_SUBWINDOW_ID (ii) = 0; 4400 IMAGE_INSTANCE_SUBWINDOW_ID (ii) = 0;
3769 IMAGE_INSTANCE_SUBWINDOW_FRAME (ii) = Qnil;
3770 IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (ii) = 0; 4401 IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (ii) = 0;
3771 IMAGE_INSTANCE_SUBWINDOW_FRAME (ii) = frame; 4402 IMAGE_INSTANCE_SUBWINDOW_FRAME (ii) = frame;
3772 4403
3773 /* this stuff may get overidden by the widget code */ 4404 /* #### This stuff may get overidden by the widget code and is
4405 actually really dumb now that we have dynamic geometry
4406 calculations. What should really happen is that the subwindow
4407 should query its child for an appropriate geometry. */
3774 if (NILP (width)) 4408 if (NILP (width))
3775 IMAGE_INSTANCE_SUBWINDOW_WIDTH (ii) = 20; 4409 IMAGE_INSTANCE_SUBWINDOW_WIDTH (ii) = 20;
3776 else 4410 else
3777 { 4411 {
3778 int w = 1; 4412 int w = 1;
3806 Return the window id of SUBWINDOW as a number. 4440 Return the window id of SUBWINDOW as a number.
3807 */ 4441 */
3808 (subwindow)) 4442 (subwindow))
3809 { 4443 {
3810 CHECK_SUBWINDOW_IMAGE_INSTANCE (subwindow); 4444 CHECK_SUBWINDOW_IMAGE_INSTANCE (subwindow);
3811 return make_int ((int) (XIMAGE_INSTANCE_SUBWINDOW_ID (subwindow))); 4445 return make_int ((int) XIMAGE_INSTANCE_SUBWINDOW_ID (subwindow));
3812 } 4446 }
3813 4447
3814 DEFUN ("resize-subwindow", Fresize_subwindow, 1, 3, 0, /* 4448 DEFUN ("resize-subwindow", Fresize_subwindow, 1, 3, 0, /*
3815 Resize SUBWINDOW to WIDTH x HEIGHT. 4449 Resize SUBWINDOW to WIDTH x HEIGHT.
3816 If a value is nil that parameter is not changed. 4450 If a value is nil that parameter is not changed.
3817 */ 4451 */
3818 (subwindow, width, height)) 4452 (subwindow, width, height))
3819 { 4453 {
3820 int neww, newh; 4454 int neww, newh;
4455 Lisp_Image_Instance* ii;
3821 4456
3822 CHECK_SUBWINDOW_IMAGE_INSTANCE (subwindow); 4457 CHECK_SUBWINDOW_IMAGE_INSTANCE (subwindow);
4458 ii = XIMAGE_INSTANCE (subwindow);
3823 4459
3824 if (NILP (width)) 4460 if (NILP (width))
3825 neww = XIMAGE_INSTANCE_SUBWINDOW_WIDTH (subwindow); 4461 neww = IMAGE_INSTANCE_WIDTH (ii);
3826 else 4462 else
3827 neww = XINT (width); 4463 neww = XINT (width);
3828 4464
3829 if (NILP (height)) 4465 if (NILP (height))
3830 newh = XIMAGE_INSTANCE_SUBWINDOW_HEIGHT (subwindow); 4466 newh = IMAGE_INSTANCE_HEIGHT (ii);
3831 else 4467 else
3832 newh = XINT (height); 4468 newh = XINT (height);
3833 4469
3834 4470 /* The actual resizing gets done asychronously by
3835 MAYBE_DEVMETH (XDEVICE (XIMAGE_INSTANCE_DEVICE (subwindow)), 4471 update_subwindow. */
3836 resize_subwindow, (XIMAGE_INSTANCE (subwindow), neww, newh)); 4472 IMAGE_INSTANCE_HEIGHT (ii) = newh;
3837 4473 IMAGE_INSTANCE_WIDTH (ii) = neww;
3838 XIMAGE_INSTANCE_SUBWINDOW_HEIGHT (subwindow) = newh; 4474 IMAGE_INSTANCE_SIZE_CHANGED (ii) = 1;
3839 XIMAGE_INSTANCE_SUBWINDOW_WIDTH (subwindow) = neww; 4475
4476 /* need to update the cachels as redisplay will not do this */
4477 update_subwindow_cachel (subwindow);
3840 4478
3841 return subwindow; 4479 return subwindow;
3842 } 4480 }
3843 4481
3844 DEFUN ("force-subwindow-map", Fforce_subwindow_map, 1, 1, 0, /* 4482 DEFUN ("force-subwindow-map", Fforce_subwindow_map, 1, 1, 0, /*
3845 Generate a Map event for SUBWINDOW. 4483 Generate a Map event for SUBWINDOW.
3846 */ 4484 */
3847 (subwindow)) 4485 (subwindow))
3848 { 4486 {
3849 CHECK_SUBWINDOW_IMAGE_INSTANCE (subwindow); 4487 CHECK_SUBWINDOW_IMAGE_INSTANCE (subwindow);
3850 4488 #if 0
3851 map_subwindow (subwindow, 0, 0); 4489 map_subwindow (subwindow, 0, 0);
3852 4490 #endif
3853 return subwindow; 4491 return subwindow;
3854 } 4492 }
3855 4493
3856 4494
3857 /***************************************************************************** 4495 /*****************************************************************************
3933 } 4571 }
3934 else 4572 else
3935 abort (); 4573 abort ();
3936 } 4574 }
3937 } 4575 }
4576
4577 /*****************************************************************************
4578 * timeouts for animated glyphs *
4579 *****************************************************************************/
4580 static Lisp_Object Qglyph_animated_timeout_handler;
4581
4582 DEFUN ("glyph-animated-timeout-handler", Fglyph_animated_timeout_handler, 1, 1, 0, /*
4583 Callback function for updating animated images.
4584 Don't use this.
4585 */
4586 (arg))
4587 {
4588 CHECK_WEAK_LIST (arg);
4589
4590 if (!NILP (XWEAK_LIST_LIST (arg)) && !NILP (XCAR (XWEAK_LIST_LIST (arg))))
4591 {
4592 Lisp_Object value = XCAR (XWEAK_LIST_LIST (arg));
4593
4594 if (IMAGE_INSTANCEP (value))
4595 {
4596 Lisp_Image_Instance* ii = XIMAGE_INSTANCE (value);
4597
4598 if (COLOR_PIXMAP_IMAGE_INSTANCEP (value)
4599 &&
4600 IMAGE_INSTANCE_PIXMAP_MAXSLICE (ii) > 1
4601 &&
4602 !disable_animated_pixmaps)
4603 {
4604 /* Increment the index of the image slice we are currently
4605 viewing. */
4606 IMAGE_INSTANCE_PIXMAP_SLICE (ii) =
4607 (IMAGE_INSTANCE_PIXMAP_SLICE (ii) + 1)
4608 % IMAGE_INSTANCE_PIXMAP_MAXSLICE (ii);
4609 /* We might need to kick redisplay at this point - but we
4610 also might not. */
4611 MARK_DEVICE_FRAMES_GLYPHS_CHANGED
4612 (XDEVICE (IMAGE_INSTANCE_DEVICE (ii)));
4613 /* Cascade dirtiness so that we can have an animated glyph in a layout
4614 for instance. */
4615 set_image_instance_dirty_p (value, 1);
4616 }
4617 }
4618 }
4619 return Qnil;
4620 }
4621
4622 Lisp_Object add_glyph_animated_timeout (EMACS_INT tickms, Lisp_Object image)
4623 {
4624 Lisp_Object ret = Qnil;
4625
4626 if (tickms > 0 && IMAGE_INSTANCEP (image))
4627 {
4628 double ms = ((double)tickms) / 1000.0;
4629 struct gcpro gcpro1;
4630 Lisp_Object holder = make_weak_list (WEAK_LIST_SIMPLE);
4631
4632 GCPRO1 (holder);
4633 XWEAK_LIST_LIST (holder) = Fcons (image, Qnil);
4634
4635 ret = Fadd_timeout (make_float (ms),
4636 Qglyph_animated_timeout_handler,
4637 holder, make_float (ms));
4638
4639 UNGCPRO;
4640 }
4641 return ret;
4642 }
4643
4644 void disable_glyph_animated_timeout (int i)
4645 {
4646 Lisp_Object id;
4647 XSETINT (id, i);
4648
4649 Fdisable_timeout (id);
4650 }
4651
3938 4652
3939 /***************************************************************************** 4653 /*****************************************************************************
3940 * initialization * 4654 * initialization *
3941 *****************************************************************************/ 4655 *****************************************************************************/
3942 4656
3981 defsymbol (&Qmono_pixmap_image_instance_p, "mono-pixmap-image-instance-p"); 4695 defsymbol (&Qmono_pixmap_image_instance_p, "mono-pixmap-image-instance-p");
3982 defsymbol (&Qcolor_pixmap_image_instance_p, "color-pixmap-image-instance-p"); 4696 defsymbol (&Qcolor_pixmap_image_instance_p, "color-pixmap-image-instance-p");
3983 defsymbol (&Qpointer_image_instance_p, "pointer-image-instance-p"); 4697 defsymbol (&Qpointer_image_instance_p, "pointer-image-instance-p");
3984 defsymbol (&Qwidget_image_instance_p, "widget-image-instance-p"); 4698 defsymbol (&Qwidget_image_instance_p, "widget-image-instance-p");
3985 defsymbol (&Qsubwindow_image_instance_p, "subwindow-image-instance-p"); 4699 defsymbol (&Qsubwindow_image_instance_p, "subwindow-image-instance-p");
4700 defsymbol (&Qlayout_image_instance_p, "layout-image-instance-p");
3986 4701
3987 DEFSUBR (Fmake_image_instance); 4702 DEFSUBR (Fmake_image_instance);
3988 DEFSUBR (Fimage_instance_p); 4703 DEFSUBR (Fimage_instance_p);
3989 DEFSUBR (Fimage_instance_type); 4704 DEFSUBR (Fimage_instance_type);
3990 DEFSUBR (Fvalid_image_instance_type_p); 4705 DEFSUBR (Fvalid_image_instance_type_p);
4039 DEFSUBR (Fglyph_height); 4754 DEFSUBR (Fglyph_height);
4040 4755
4041 /* Qbuffer defined in general.c. */ 4756 /* Qbuffer defined in general.c. */
4042 /* Qpointer defined above */ 4757 /* Qpointer defined above */
4043 4758
4759 /* Unfortunately, timeout handlers must be lisp functions. This is
4760 for animated glyphs. */
4761 defsymbol (&Qglyph_animated_timeout_handler,
4762 "glyph-animated-timeout-handler");
4763 DEFSUBR (Fglyph_animated_timeout_handler);
4764
4044 /* Errors */ 4765 /* Errors */
4045 deferror (&Qimage_conversion_error, 4766 deferror (&Qimage_conversion_error,
4046 "image-conversion-error", 4767 "image-conversion-error",
4047 "image-conversion error", Qio_error); 4768 "image-conversion error", Qio_error);
4048 4769
4049 } 4770 }
4771
4772 static const struct lrecord_description image_specifier_description[] = {
4773 { XD_LISP_OBJECT, specifier_data_offset + offsetof (struct image_specifier, attachee) },
4774 { XD_LISP_OBJECT, specifier_data_offset + offsetof (struct image_specifier, attachee_property) },
4775 { XD_END }
4776 };
4050 4777
4051 void 4778 void
4052 specifier_type_create_image (void) 4779 specifier_type_create_image (void)
4053 { 4780 {
4054 /* image specifiers */ 4781 /* image specifiers */
4059 SPECIFIER_HAS_METHOD (image, mark); 4786 SPECIFIER_HAS_METHOD (image, mark);
4060 SPECIFIER_HAS_METHOD (image, instantiate); 4787 SPECIFIER_HAS_METHOD (image, instantiate);
4061 SPECIFIER_HAS_METHOD (image, validate); 4788 SPECIFIER_HAS_METHOD (image, validate);
4062 SPECIFIER_HAS_METHOD (image, after_change); 4789 SPECIFIER_HAS_METHOD (image, after_change);
4063 SPECIFIER_HAS_METHOD (image, going_to_add); 4790 SPECIFIER_HAS_METHOD (image, going_to_add);
4064 } 4791 SPECIFIER_HAS_METHOD (image, copy_instantiator);
4792 }
4793
4794 void
4795 reinit_specifier_type_create_image (void)
4796 {
4797 REINITIALIZE_SPECIFIER_TYPE (image);
4798 }
4799
4800
4801 static const struct lrecord_description iike_description_1[] = {
4802 { XD_LISP_OBJECT, offsetof (ii_keyword_entry, keyword) },
4803 { XD_END }
4804 };
4805
4806 static const struct struct_description iike_description = {
4807 sizeof (ii_keyword_entry),
4808 iike_description_1
4809 };
4810
4811 static const struct lrecord_description iiked_description_1[] = {
4812 XD_DYNARR_DESC (ii_keyword_entry_dynarr, &iike_description),
4813 { XD_END }
4814 };
4815
4816 static const struct struct_description iiked_description = {
4817 sizeof (ii_keyword_entry_dynarr),
4818 iiked_description_1
4819 };
4820
4821 static const struct lrecord_description iife_description_1[] = {
4822 { XD_LISP_OBJECT, offsetof (image_instantiator_format_entry, symbol) },
4823 { XD_LISP_OBJECT, offsetof (image_instantiator_format_entry, device) },
4824 { XD_STRUCT_PTR, offsetof (image_instantiator_format_entry, meths), 1, &iim_description },
4825 { XD_END }
4826 };
4827
4828 static const struct struct_description iife_description = {
4829 sizeof (image_instantiator_format_entry),
4830 iife_description_1
4831 };
4832
4833 static const struct lrecord_description iifed_description_1[] = {
4834 XD_DYNARR_DESC (image_instantiator_format_entry_dynarr, &iife_description),
4835 { XD_END }
4836 };
4837
4838 static const struct struct_description iifed_description = {
4839 sizeof (image_instantiator_format_entry_dynarr),
4840 iifed_description_1
4841 };
4842
4843 static const struct lrecord_description iim_description_1[] = {
4844 { XD_LISP_OBJECT, offsetof (struct image_instantiator_methods, symbol) },
4845 { XD_LISP_OBJECT, offsetof (struct image_instantiator_methods, device) },
4846 { XD_STRUCT_PTR, offsetof (struct image_instantiator_methods, keywords), 1, &iiked_description },
4847 { XD_STRUCT_PTR, offsetof (struct image_instantiator_methods, consoles), 1, &cted_description },
4848 { XD_END }
4849 };
4850
4851 const struct struct_description iim_description = {
4852 sizeof(struct image_instantiator_methods),
4853 iim_description_1
4854 };
4065 4855
4066 void 4856 void
4067 image_instantiator_format_create (void) 4857 image_instantiator_format_create (void)
4068 { 4858 {
4069 /* image instantiators */ 4859 /* image instantiators */
4071 the_image_instantiator_format_entry_dynarr = 4861 the_image_instantiator_format_entry_dynarr =
4072 Dynarr_new (image_instantiator_format_entry); 4862 Dynarr_new (image_instantiator_format_entry);
4073 4863
4074 Vimage_instantiator_format_list = Qnil; 4864 Vimage_instantiator_format_list = Qnil;
4075 staticpro (&Vimage_instantiator_format_list); 4865 staticpro (&Vimage_instantiator_format_list);
4866
4867 dumpstruct (&the_image_instantiator_format_entry_dynarr, &iifed_description);
4076 4868
4077 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (nothing, "nothing"); 4869 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (nothing, "nothing");
4078 4870
4079 IIFORMAT_HAS_METHOD (nothing, possible_dest_types); 4871 IIFORMAT_HAS_METHOD (nothing, possible_dest_types);
4080 IIFORMAT_HAS_METHOD (nothing, instantiate); 4872 IIFORMAT_HAS_METHOD (nothing, instantiate);
4093 IIFORMAT_HAS_METHOD (string, validate); 4885 IIFORMAT_HAS_METHOD (string, validate);
4094 IIFORMAT_HAS_METHOD (string, possible_dest_types); 4886 IIFORMAT_HAS_METHOD (string, possible_dest_types);
4095 IIFORMAT_HAS_METHOD (string, instantiate); 4887 IIFORMAT_HAS_METHOD (string, instantiate);
4096 4888
4097 IIFORMAT_VALID_KEYWORD (string, Q_data, check_valid_string); 4889 IIFORMAT_VALID_KEYWORD (string, Q_data, check_valid_string);
4890 /* Do this so we can set strings. */
4891 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (text, "text");
4892 IIFORMAT_HAS_METHOD (text, set_property);
4893 IIFORMAT_HAS_METHOD (text, query_geometry);
4098 4894
4099 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (formatted_string, "formatted-string"); 4895 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (formatted_string, "formatted-string");
4100 4896
4101 IIFORMAT_HAS_METHOD (formatted_string, validate); 4897 IIFORMAT_HAS_METHOD (formatted_string, validate);
4102 IIFORMAT_HAS_METHOD (formatted_string, possible_dest_types); 4898 IIFORMAT_HAS_METHOD (formatted_string, possible_dest_types);
4103 IIFORMAT_HAS_METHOD (formatted_string, instantiate); 4899 IIFORMAT_HAS_METHOD (formatted_string, instantiate);
4104
4105 IIFORMAT_VALID_KEYWORD (formatted_string, Q_data, check_valid_string); 4900 IIFORMAT_VALID_KEYWORD (formatted_string, Q_data, check_valid_string);
4106 4901
4107 /* subwindows */ 4902 /* subwindows */
4108 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (subwindow, "subwindow"); 4903 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (subwindow, "subwindow");
4109 IIFORMAT_HAS_METHOD (subwindow, possible_dest_types); 4904 IIFORMAT_HAS_METHOD (subwindow, possible_dest_types);
4155 IIFORMAT_VALID_KEYWORD (xpm, Q_color_symbols, check_valid_xpm_color_symbols); 4950 IIFORMAT_VALID_KEYWORD (xpm, Q_color_symbols, check_valid_xpm_color_symbols);
4156 #endif /* HAVE_XPM */ 4951 #endif /* HAVE_XPM */
4157 } 4952 }
4158 4953
4159 void 4954 void
4955 reinit_vars_of_glyphs (void)
4956 {
4957 the_expose_ignore_blocktype =
4958 Blocktype_new (struct expose_ignore_blocktype);
4959
4960 hold_ignored_expose_registration = 0;
4961 }
4962
4963
4964 void
4160 vars_of_glyphs (void) 4965 vars_of_glyphs (void)
4161 { 4966 {
4967 reinit_vars_of_glyphs ();
4968
4162 Vthe_nothing_vector = vector1 (Qnothing); 4969 Vthe_nothing_vector = vector1 (Qnothing);
4163 staticpro (&Vthe_nothing_vector); 4970 staticpro (&Vthe_nothing_vector);
4164 4971
4165 /* image instances */ 4972 /* image instances */
4166 4973
4167 Vimage_instance_type_list = Fcons (Qnothing, 4974 Vimage_instance_type_list = Fcons (Qnothing,
4168 list6 (Qtext, Qmono_pixmap, Qcolor_pixmap, 4975 list6 (Qtext, Qmono_pixmap, Qcolor_pixmap,
4169 Qpointer, Qsubwindow, Qwidget)); 4976 Qpointer, Qsubwindow, Qwidget));
4170 staticpro (&Vimage_instance_type_list); 4977 staticpro (&Vimage_instance_type_list);
4171 4978
4172 /* glyphs */ 4979 /* glyphs */
4173 4980
4222 Vxpm_color_symbols = Qnil; /* initialized in x-faces.el */ 5029 Vxpm_color_symbols = Qnil; /* initialized in x-faces.el */
4223 #endif /* HAVE_XPM */ 5030 #endif /* HAVE_XPM */
4224 #ifdef HAVE_XFACE 5031 #ifdef HAVE_XFACE
4225 Fprovide (Qxface); 5032 Fprovide (Qxface);
4226 #endif 5033 #endif
5034
5035 DEFVAR_BOOL ("disable-animated-pixmaps", &disable_animated_pixmaps /*
5036 Whether animated pixmaps should be animated.
5037 Default is t.
5038 */);
5039 disable_animated_pixmaps = 0;
4227 } 5040 }
4228 5041
4229 void 5042 void
4230 specifier_vars_of_glyphs (void) 5043 specifier_vars_of_glyphs (void)
4231 { 5044 {
4245 */ ); 5058 */ );
4246 Vcurrent_display_table = Fmake_specifier (Qdisplay_table); 5059 Vcurrent_display_table = Fmake_specifier (Qdisplay_table);
4247 set_specifier_fallback (Vcurrent_display_table, 5060 set_specifier_fallback (Vcurrent_display_table,
4248 list1 (Fcons (Qnil, Qnil))); 5061 list1 (Fcons (Qnil, Qnil)));
4249 set_specifier_caching (Vcurrent_display_table, 5062 set_specifier_caching (Vcurrent_display_table,
4250 slot_offset (struct window, 5063 offsetof (struct window, display_table),
4251 display_table),
4252 some_window_value_changed, 5064 some_window_value_changed,
4253 0, 0); 5065 0, 0);
4254 } 5066 }
4255 5067
4256 void 5068 void