import -ko -b 1.1.3 XEmacs XEmacs-21_2 r21-2-35
[chise/xemacs-chise.git.1] / src / glyphs.c
1 /* Generic glyph/image implementation + display tables
2    Copyright (C) 1994, 1995 Board of Trustees, University of Illinois.
3    Copyright (C) 1995 Tinker Systems
4    Copyright (C) 1995, 1996, 2000 Ben Wing
5    Copyright (C) 1995 Sun Microsystems
6    Copyright (C) 1998, 1999, 2000 Andy Piper
7
8 This file is part of XEmacs.
9
10 XEmacs is free software; you can redistribute it and/or modify it
11 under the terms of the GNU General Public License as published by the
12 Free Software Foundation; either version 2, or (at your option) any
13 later version.
14
15 XEmacs is distributed in the hope that it will be useful, but WITHOUT
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
18 for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with XEmacs; see the file COPYING.  If not, write to
22 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23 Boston, MA 02111-1307, USA.  */
24
25 /* Synched up with: Not in FSF. */
26
27 /* Written by Ben Wing and Chuck Thompson. Heavily modified /
28    rewritten by Andy Piper. */
29
30 #include <config.h>
31 #include "lisp.h"
32
33 #include "blocktype.h"
34 #include "buffer.h"
35 #include "chartab.h"
36 #include "device.h"
37 #include "elhash.h"
38 #include "faces.h"
39 #include "frame.h"
40 #include "glyphs.h"
41 #include "insdel.h"
42 #include "objects.h"
43 #include "opaque.h"
44 #include "rangetab.h"
45 #include "redisplay.h"
46 #include "specifier.h"
47 #include "window.h"
48
49 #ifdef HAVE_XPM
50 #include <X11/xpm.h>
51 #endif
52
53 Lisp_Object Qimage_conversion_error;
54
55 Lisp_Object Qglyphp, Qcontrib_p, Qbaseline;
56 Lisp_Object Qbuffer_glyph_p, Qpointer_glyph_p, Qicon_glyph_p;
57 Lisp_Object Qnothing_image_instance_p, Qtext_image_instance_p;
58 Lisp_Object Qmono_pixmap_image_instance_p;
59 Lisp_Object Qcolor_pixmap_image_instance_p;
60 Lisp_Object Qpointer_image_instance_p;
61 Lisp_Object Qsubwindow_image_instance_p;
62 Lisp_Object Qwidget_image_instance_p;
63 Lisp_Object Qconst_glyph_variable;
64 Lisp_Object Qmono_pixmap, Qcolor_pixmap, Qsubwindow;
65 Lisp_Object Q_file, Q_data, Q_face, Q_pixel_width, Q_pixel_height;
66 Lisp_Object Qformatted_string;
67 Lisp_Object Vcurrent_display_table;
68 Lisp_Object Vtruncation_glyph, Vcontinuation_glyph, Voctal_escape_glyph;
69 Lisp_Object Vcontrol_arrow_glyph, Vinvisible_text_glyph, Vhscroll_glyph;
70 Lisp_Object Vxemacs_logo;
71 Lisp_Object Vthe_nothing_vector;
72 Lisp_Object Vimage_instantiator_format_list;
73 Lisp_Object Vimage_instance_type_list;
74 Lisp_Object Vglyph_type_list;
75
76 int disable_animated_pixmaps;
77
78 DEFINE_IMAGE_INSTANTIATOR_FORMAT (nothing);
79 DEFINE_IMAGE_INSTANTIATOR_FORMAT (inherit);
80 DEFINE_IMAGE_INSTANTIATOR_FORMAT (string);
81 DEFINE_IMAGE_INSTANTIATOR_FORMAT (formatted_string);
82 DEFINE_IMAGE_INSTANTIATOR_FORMAT (subwindow);
83 DEFINE_IMAGE_INSTANTIATOR_FORMAT (text);
84 DEFINE_IMAGE_INSTANTIATOR_FORMAT (pointer);
85
86 #ifdef HAVE_WINDOW_SYSTEM
87 DEFINE_IMAGE_INSTANTIATOR_FORMAT (xbm);
88 Lisp_Object Qxbm;
89
90 Lisp_Object Q_mask_file, Q_mask_data, Q_hotspot_x, Q_hotspot_y;
91 Lisp_Object Q_foreground, Q_background;
92 #ifndef BitmapSuccess
93 #define BitmapSuccess           0
94 #define BitmapOpenFailed        1
95 #define BitmapFileInvalid       2
96 #define BitmapNoMemory          3
97 #endif
98 #endif
99
100 #ifdef HAVE_XFACE
101 DEFINE_IMAGE_INSTANTIATOR_FORMAT (xface);
102 Lisp_Object Qxface;
103 #endif
104
105 #ifdef HAVE_XPM
106 DEFINE_IMAGE_INSTANTIATOR_FORMAT (xpm);
107 Lisp_Object Qxpm;
108 Lisp_Object Q_color_symbols;
109 #endif
110
111 typedef struct image_instantiator_format_entry image_instantiator_format_entry;
112 struct image_instantiator_format_entry
113 {
114   Lisp_Object symbol;
115   Lisp_Object device;
116   struct image_instantiator_methods *meths;
117 };
118
119 typedef struct
120 {
121   Dynarr_declare (struct image_instantiator_format_entry);
122 } image_instantiator_format_entry_dynarr;
123
124 /* This contains one entry per format, per device it's defined on. */
125 image_instantiator_format_entry_dynarr *
126   the_image_instantiator_format_entry_dynarr;
127
128 static Lisp_Object allocate_image_instance (Lisp_Object governing_domain, 
129                                             Lisp_Object glyph);
130 static void image_validate (Lisp_Object instantiator);
131 static void glyph_property_was_changed (Lisp_Object glyph,
132                                         Lisp_Object property,
133                                         Lisp_Object locale);
134 static void set_image_instance_dirty_p (Lisp_Object instance, int dirty);
135 static void register_ignored_expose (struct frame* f, int x, int y, int width, int height);
136 static void cache_subwindow_instance_in_frame_maybe (Lisp_Object instance);
137 /* Unfortunately windows and X are different. In windows BeginPaint()
138    will prevent WM_PAINT messages being generated so it is unnecessary
139    to register exposures as they will not occur. Under X they will
140    always occur. */
141 int hold_ignored_expose_registration;
142
143 EXFUN (Fimage_instance_type, 1);
144 EXFUN (Fglyph_type, 1);
145 EXFUN (Fnext_window, 4);
146
147 \f
148 /****************************************************************************
149  *                          Image Instantiators                             *
150  ****************************************************************************/
151
152 struct image_instantiator_methods *
153 decode_device_ii_format (Lisp_Object device, Lisp_Object format,
154                          Error_behavior errb)
155 {
156   int i;
157
158   if (!SYMBOLP (format))
159     {
160       if (ERRB_EQ (errb, ERROR_ME))
161         CHECK_SYMBOL (format);
162       return 0;
163     }
164
165   for (i = 0; i < Dynarr_length (the_image_instantiator_format_entry_dynarr);
166        i++)
167     {
168       if ( EQ (format,
169                Dynarr_at (the_image_instantiator_format_entry_dynarr, i).
170                symbol) )
171         {
172           Lisp_Object d = Dynarr_at (the_image_instantiator_format_entry_dynarr, i).
173             device;
174           if ((NILP (d) && NILP (device))
175               ||
176               (!NILP (device) &&
177                EQ (CONSOLE_TYPE (XCONSOLE
178                                  (DEVICE_CONSOLE (XDEVICE (device)))), d)))
179             return Dynarr_at (the_image_instantiator_format_entry_dynarr, i).meths;
180         }
181     }
182
183   maybe_signal_simple_error ("Invalid image-instantiator format", format,
184                              Qimage, errb);
185
186   return 0;
187 }
188
189 struct image_instantiator_methods *
190 decode_image_instantiator_format (Lisp_Object format, Error_behavior errb)
191 {
192   return decode_device_ii_format (Qnil, format, errb);
193 }
194
195 static int
196 valid_image_instantiator_format_p (Lisp_Object format, Lisp_Object locale)
197 {
198   int i;
199   struct image_instantiator_methods* meths =
200     decode_image_instantiator_format (format, ERROR_ME_NOT);
201   Lisp_Object contype = Qnil;
202   /* mess with the locale */
203   if (!NILP (locale) && SYMBOLP (locale))
204     contype = locale;
205   else
206     {
207       struct console* console = decode_console (locale);
208       contype = console ? CONSOLE_TYPE (console) : locale;
209     }
210   /* nothing is valid in all locales */
211   if (EQ (format, Qnothing))
212     return 1;
213   /* reject unknown formats */
214   else if (NILP (contype) || !meths)
215     return 0;
216
217   for (i = 0; i < Dynarr_length (meths->consoles); i++)
218     if (EQ (contype, Dynarr_at (meths->consoles, i).symbol))
219       return 1;
220   return 0;
221 }
222
223 DEFUN ("valid-image-instantiator-format-p", Fvalid_image_instantiator_format_p,
224        1, 2, 0, /*
225 Given an IMAGE-INSTANTIATOR-FORMAT, return non-nil if it is valid.
226 If LOCALE is non-nil then the format is checked in that domain.
227 If LOCALE is nil the current console is used.
228
229 Valid formats are some subset of 'nothing, 'string, 'formatted-string,
230 'xpm, 'xbm, 'xface, 'gif, 'jpeg, 'png, 'tiff, 'cursor-font, 'font,
231 'autodetect, 'subwindow, 'inherit, 'mswindows-resource, 'bmp,
232 'native-layout, 'layout, 'label, 'tab-control, 'tree-view,
233 'progress-gauge, 'scrollbar, 'combo-box, 'edit-field, 'button,
234 'widget, 'pointer, and 'text, depending on how XEmacs was compiled.
235 */
236        (image_instantiator_format, locale))
237 {
238   return valid_image_instantiator_format_p (image_instantiator_format,
239                                             locale) ?
240     Qt : Qnil;
241 }
242
243 DEFUN ("image-instantiator-format-list", Fimage_instantiator_format_list,
244        0, 0, 0, /*
245 Return a list of valid image-instantiator formats.
246 */
247        ())
248 {
249   return Fcopy_sequence (Vimage_instantiator_format_list);
250 }
251
252 void
253 add_entry_to_device_ii_format_list (Lisp_Object device, Lisp_Object symbol,
254                                     struct image_instantiator_methods *meths)
255 {
256   struct image_instantiator_format_entry entry;
257
258   entry.symbol = symbol;
259   entry.device = device;
260   entry.meths = meths;
261   Dynarr_add (the_image_instantiator_format_entry_dynarr, entry);
262   if (NILP (memq_no_quit (symbol, Vimage_instantiator_format_list)))
263     Vimage_instantiator_format_list =
264       Fcons (symbol, Vimage_instantiator_format_list);
265 }
266
267 void
268 add_entry_to_image_instantiator_format_list (Lisp_Object symbol,
269                                              struct
270                                              image_instantiator_methods *meths)
271 {
272   add_entry_to_device_ii_format_list (Qnil, symbol, meths);
273 }
274
275 static Lisp_Object *
276 get_image_conversion_list (Lisp_Object console_type)
277 {
278   return &decode_console_type (console_type, ERROR_ME)->image_conversion_list;
279 }
280
281 DEFUN ("set-console-type-image-conversion-list", Fset_console_type_image_conversion_list,
282        2, 2, 0, /*
283 Set the image-conversion-list for consoles of the given TYPE.
284 The image-conversion-list specifies how image instantiators that
285 are strings should be interpreted.  Each element of the list should be
286 a list of two elements (a regular expression string and a vector) or
287 a list of three elements (the preceding two plus an integer index into
288 the vector).  The string is converted to the vector associated with the
289 first matching regular expression.  If a vector index is specified, the
290 string itself is substituted into that position in the vector.
291
292 Note: The conversion above is applied when the image instantiator is
293 added to an image specifier, not when the specifier is actually
294 instantiated.  Therefore, changing the image-conversion-list only affects
295 newly-added instantiators.  Existing instantiators in glyphs and image
296 specifiers will not be affected.
297 */
298        (console_type, list))
299 {
300   Lisp_Object tail;
301   Lisp_Object *imlist = get_image_conversion_list (console_type);
302
303   /* Check the list to make sure that it only has valid entries. */
304
305   EXTERNAL_LIST_LOOP (tail, list)
306     {
307       Lisp_Object mapping = XCAR (tail);
308
309       /* Mapping form should be (STRING VECTOR) or (STRING VECTOR INTEGER) */
310       if (!CONSP (mapping) ||
311           !CONSP (XCDR (mapping)) ||
312           (!NILP (XCDR (XCDR (mapping))) &&
313            (!CONSP (XCDR (XCDR (mapping))) ||
314             !NILP (XCDR (XCDR (XCDR (mapping)))))))
315         signal_simple_error ("Invalid mapping form", mapping);
316       else
317         {
318           Lisp_Object exp = XCAR (mapping);
319           Lisp_Object typevec = XCAR (XCDR (mapping));
320           Lisp_Object pos = Qnil;
321           Lisp_Object newvec;
322           struct gcpro gcpro1;
323
324           CHECK_STRING (exp);
325           CHECK_VECTOR (typevec);
326           if (!NILP (XCDR (XCDR (mapping))))
327             {
328               pos = XCAR (XCDR (XCDR (mapping)));
329               CHECK_INT (pos);
330               if (XINT (pos) < 0 ||
331                   XINT (pos) >= XVECTOR_LENGTH (typevec))
332                 args_out_of_range_3
333                   (pos, Qzero, make_int (XVECTOR_LENGTH (typevec) - 1));
334             }
335
336           newvec = Fcopy_sequence (typevec);
337           if (INTP (pos))
338             XVECTOR_DATA (newvec)[XINT (pos)] = exp;
339           GCPRO1 (newvec);
340           image_validate (newvec);
341           UNGCPRO;
342         }
343     }
344
345   *imlist = Fcopy_tree (list, Qt);
346   return list;
347 }
348
349 DEFUN ("console-type-image-conversion-list", Fconsole_type_image_conversion_list,
350        1, 1, 0, /*
351 Return the image-conversion-list for devices of the given TYPE.
352 The image-conversion-list specifies how to interpret image string
353 instantiators for the specified console type.  See
354 `set-console-type-image-conversion-list' for a description of its syntax.
355 */
356        (console_type))
357 {
358   return Fcopy_tree (*get_image_conversion_list (console_type), Qt);
359 }
360
361 /* Process a string instantiator according to the image-conversion-list for
362    CONSOLE_TYPE.  Returns a vector. */
363
364 static Lisp_Object
365 process_image_string_instantiator (Lisp_Object data,
366                                    Lisp_Object console_type,
367                                    int dest_mask)
368 {
369   Lisp_Object tail;
370
371   LIST_LOOP (tail, *get_image_conversion_list (console_type))
372     {
373       Lisp_Object mapping = XCAR (tail);
374       Lisp_Object exp = XCAR (mapping);
375       Lisp_Object typevec = XCAR (XCDR (mapping));
376
377       /* if the result is of a type that can't be instantiated
378          (e.g. a string when we're dealing with a pointer glyph),
379          skip it. */
380       if (!(dest_mask &
381             IIFORMAT_METH (decode_image_instantiator_format
382                            (XVECTOR_DATA (typevec)[0], ERROR_ME),
383                            possible_dest_types, ())))
384         continue;
385       if (fast_string_match (exp, 0, data, 0, -1, 0, ERROR_ME, 0) >= 0)
386         {
387           if (!NILP (XCDR (XCDR (mapping))))
388             {
389               int pos = XINT (XCAR (XCDR (XCDR (mapping))));
390               Lisp_Object newvec = Fcopy_sequence (typevec);
391               XVECTOR_DATA (newvec)[pos] = data;
392               return newvec;
393             }
394           else
395             return typevec;
396         }
397     }
398
399   /* Oh well. */
400   signal_simple_error ("Unable to interpret glyph instantiator",
401                        data);
402
403   return Qnil;
404 }
405
406 Lisp_Object
407 find_keyword_in_vector_or_given (Lisp_Object vector, Lisp_Object keyword,
408                                  Lisp_Object default_)
409 {
410   Lisp_Object *elt;
411   int instantiator_len;
412
413   elt = XVECTOR_DATA (vector);
414   instantiator_len = XVECTOR_LENGTH (vector);
415
416   elt++;
417   instantiator_len--;
418
419   while (instantiator_len > 0)
420     {
421       if (EQ (elt[0], keyword))
422         return elt[1];
423       elt += 2;
424       instantiator_len -= 2;
425     }
426
427   return default_;
428 }
429
430 Lisp_Object
431 find_keyword_in_vector (Lisp_Object vector, Lisp_Object keyword)
432 {
433   return find_keyword_in_vector_or_given (vector, keyword, Qnil);
434 }
435
436 void
437 check_valid_string (Lisp_Object data)
438 {
439   CHECK_STRING (data);
440 }
441
442 void
443 check_valid_vector (Lisp_Object data)
444 {
445   CHECK_VECTOR (data);
446 }
447
448 void
449 check_valid_face (Lisp_Object data)
450 {
451   Fget_face (data);
452 }
453
454 void
455 check_valid_int (Lisp_Object data)
456 {
457   CHECK_INT (data);
458 }
459
460 void
461 file_or_data_must_be_present (Lisp_Object instantiator)
462 {
463   if (NILP (find_keyword_in_vector (instantiator, Q_file)) &&
464       NILP (find_keyword_in_vector (instantiator, Q_data)))
465     signal_simple_error ("Must supply either :file or :data",
466                          instantiator);
467 }
468
469 void
470 data_must_be_present (Lisp_Object instantiator)
471 {
472   if (NILP (find_keyword_in_vector (instantiator, Q_data)))
473     signal_simple_error ("Must supply :data", instantiator);
474 }
475
476 static void
477 face_must_be_present (Lisp_Object instantiator)
478 {
479   if (NILP (find_keyword_in_vector (instantiator, Q_face)))
480     signal_simple_error ("Must supply :face", instantiator);
481 }
482
483 /* utility function useful in retrieving data from a file. */
484
485 Lisp_Object
486 make_string_from_file (Lisp_Object file)
487 {
488   /* This function can call lisp */
489   int count = specpdl_depth ();
490   Lisp_Object temp_buffer;
491   struct gcpro gcpro1;
492   Lisp_Object data;
493
494   specbind (Qinhibit_quit, Qt);
495   record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
496   temp_buffer = Fget_buffer_create (build_string (" *pixmap conversion*"));
497   GCPRO1 (temp_buffer);
498   set_buffer_internal (XBUFFER (temp_buffer));
499   Ferase_buffer (Qnil);
500   specbind (intern ("format-alist"), Qnil);
501   Finsert_file_contents_internal (file, Qnil, Qnil, Qnil, Qnil, Qnil, Qnil);
502   data = Fbuffer_substring (Qnil, Qnil, Qnil);
503   unbind_to (count, Qnil);
504   UNGCPRO;
505   return data;
506 }
507
508 /* The following two functions are provided to make it easier for
509    the normalize methods to work with keyword-value vectors.
510    Hash tables are kind of heavyweight for this purpose.
511    (If vectors were resizable, we could avoid this problem;
512    but they're not.) An alternative approach that might be
513    more efficient but require more work is to use a type of
514    assoc-Dynarr and provide primitives for deleting elements out
515    of it. (However, you'd also have to add an unwind-protect
516    to make sure the Dynarr got freed in case of an error in
517    the normalization process.) */
518
519 Lisp_Object
520 tagged_vector_to_alist (Lisp_Object vector)
521 {
522   Lisp_Object *elt = XVECTOR_DATA (vector);
523   int len = XVECTOR_LENGTH (vector);
524   Lisp_Object result = Qnil;
525
526   assert (len & 1);
527   for (len -= 2; len >= 1; len -= 2)
528     result = Fcons (Fcons (elt[len], elt[len+1]), result);
529
530   return result;
531 }
532
533 Lisp_Object
534 alist_to_tagged_vector (Lisp_Object tag, Lisp_Object alist)
535 {
536   int len = 1 + 2 * XINT (Flength (alist));
537   Lisp_Object *elt = alloca_array (Lisp_Object, len);
538   int i;
539   Lisp_Object rest;
540
541   i = 0;
542   elt[i++] = tag;
543   LIST_LOOP (rest, alist)
544     {
545       Lisp_Object pair = XCAR (rest);
546       elt[i] = XCAR (pair);
547       elt[i+1] = XCDR (pair);
548       i += 2;
549     }
550
551   return Fvector (len, elt);
552 }
553
554 #ifdef ERROR_CHECK_GLYPHS
555 static int
556 check_instance_cache_mapper (Lisp_Object key, Lisp_Object value,
557                              void *flag_closure)
558 {
559   /* This function can GC */
560   /* value can be nil; we cache failures as well as successes */
561   if (!NILP (value))
562     {
563       Lisp_Object window;
564       VOID_TO_LISP (window, flag_closure);
565       assert (EQ (XIMAGE_INSTANCE_DOMAIN (value), window));
566     }
567
568   return 0;
569 }
570
571 void
572 check_window_subwindow_cache (struct window* w)
573 {
574   Lisp_Object window;
575   
576   XSETWINDOW (window, w);
577
578   assert (!NILP (w->subwindow_instance_cache));
579   elisp_maphash (check_instance_cache_mapper,
580                  w->subwindow_instance_cache,
581                  LISP_TO_VOID (window));
582 }
583
584 void
585 check_image_instance_structure (Lisp_Object instance)
586 {
587   /* Weird nothing images exist at startup when the console is
588      deleted. */
589   if (!NOTHING_IMAGE_INSTANCEP (instance))
590     assert (DOMAIN_LIVE_P (instance));
591   if (WINDOWP (XIMAGE_INSTANCE_DOMAIN (instance)))
592     check_window_subwindow_cache 
593       (XWINDOW (XIMAGE_INSTANCE_DOMAIN (instance)));
594 }
595 #endif
596
597 /* Determine what kind of domain governs the image instance.
598    Verify that the given domain is at least as specific, and extract
599    the governing domain from it. */
600 static Lisp_Object
601 get_image_instantiator_governing_domain (Lisp_Object instantiator,
602                                          Lisp_Object domain)
603 {
604   int governing_domain;
605
606   struct image_instantiator_methods *meths = 
607     decode_image_instantiator_format (XVECTOR_DATA (instantiator)[0],
608                                       ERROR_ME);
609   governing_domain = IIFORMAT_METH_OR_GIVEN (meths, governing_domain, (),
610                                              GOVERNING_DOMAIN_DEVICE);
611
612   if (governing_domain == GOVERNING_DOMAIN_WINDOW
613       && NILP (DOMAIN_WINDOW (domain)))
614     signal_simple_error_2 ("Domain for this instantiator must be resolvable to a window",
615                            instantiator, domain);
616   else if (governing_domain == GOVERNING_DOMAIN_FRAME
617            && NILP (DOMAIN_FRAME (domain)))
618     signal_simple_error_2
619       ("Domain for this instantiator must be resolvable to a frame",
620        instantiator, domain);
621
622   if (governing_domain == GOVERNING_DOMAIN_WINDOW)
623     domain = DOMAIN_WINDOW (domain);
624   else if (governing_domain == GOVERNING_DOMAIN_FRAME)
625     domain = DOMAIN_FRAME (domain);
626   else if (governing_domain == GOVERNING_DOMAIN_DEVICE)
627     domain = DOMAIN_DEVICE (domain);
628   else
629     abort ();
630
631   return domain;
632 }
633
634 static Lisp_Object
635 normalize_image_instantiator (Lisp_Object instantiator,
636                               Lisp_Object contype,
637                               Lisp_Object dest_mask)
638 {
639   if (IMAGE_INSTANCEP (instantiator))
640     return instantiator;
641
642   if (STRINGP (instantiator))
643     instantiator = process_image_string_instantiator (instantiator, contype,
644                                                       XINT (dest_mask));
645
646   assert (VECTORP (instantiator));
647   /* We have to always store the actual pixmap data and not the
648      filename even though this is a potential memory pig.  We have to
649      do this because it is quite possible that we will need to
650      instantiate a new instance of the pixmap and the file will no
651      longer exist (e.g. w3 pixmaps are almost always from temporary
652      files). */
653   {
654     struct gcpro gcpro1;
655     struct image_instantiator_methods *meths;
656
657     GCPRO1 (instantiator);
658
659     meths = decode_image_instantiator_format (XVECTOR_DATA (instantiator)[0],
660                                               ERROR_ME);
661     RETURN_UNGCPRO (IIFORMAT_METH_OR_GIVEN (meths, normalize,
662                                             (instantiator, contype),
663                                             instantiator));
664   }
665 }
666
667 static Lisp_Object
668 instantiate_image_instantiator (Lisp_Object governing_domain,
669                                 Lisp_Object domain,
670                                 Lisp_Object instantiator,
671                                 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
672                                 int dest_mask, Lisp_Object glyph)
673 {
674   Lisp_Object ii = allocate_image_instance (governing_domain, glyph);
675   Lisp_Image_Instance* p = XIMAGE_INSTANCE (ii);
676   struct image_instantiator_methods *meths, *device_meths;
677   struct gcpro gcpro1;
678
679   GCPRO1 (ii);
680   if (!valid_image_instantiator_format_p (XVECTOR_DATA (instantiator)[0], 
681                                           DOMAIN_DEVICE (governing_domain)))
682     signal_simple_error
683       ("Image instantiator format is invalid in this locale.",
684        instantiator);
685
686   meths = decode_image_instantiator_format (XVECTOR_DATA (instantiator)[0],
687                                             ERROR_ME);
688   MAYBE_IIFORMAT_METH (meths, instantiate, (ii, instantiator, pointer_fg,
689                                             pointer_bg, dest_mask, domain));
690
691   /* Now do device specific instantiation. */
692   device_meths = decode_device_ii_format (DOMAIN_DEVICE (governing_domain), 
693                                           XVECTOR_DATA (instantiator)[0],
694                                           ERROR_ME_NOT);
695
696   if (!HAS_IIFORMAT_METH_P (meths, instantiate)
697       && (!device_meths || !HAS_IIFORMAT_METH_P (device_meths, instantiate)))
698     signal_simple_error
699       ("Don't know how to instantiate this image instantiator?",
700        instantiator);
701
702   /* In general native window system methods will require sane
703      geometry values, thus the instance needs to have been laid-out
704      before they get called. */
705   image_instance_layout (ii, XIMAGE_INSTANCE_WIDTH (ii),
706                          XIMAGE_INSTANCE_HEIGHT (ii), domain);
707
708   MAYBE_IIFORMAT_METH (device_meths, instantiate, (ii, instantiator, pointer_fg,
709                                                    pointer_bg, dest_mask, domain));
710   /* Do post instantiation. */
711   MAYBE_IIFORMAT_METH (meths, post_instantiate, (ii, instantiator, domain));
712   MAYBE_IIFORMAT_METH (device_meths, post_instantiate, (ii, instantiator, domain));
713
714   /* We're done. */
715   IMAGE_INSTANCE_INITIALIZED (p) = 1;
716   /* Now that we're done verify that we really are laid out. */
717   if (IMAGE_INSTANCE_LAYOUT_CHANGED (p))
718       image_instance_layout (ii, XIMAGE_INSTANCE_WIDTH (ii),
719                              XIMAGE_INSTANCE_HEIGHT (ii), domain);
720   
721   /* We *must* have a clean image at this point. */
722   IMAGE_INSTANCE_TEXT_CHANGED (p) = 0;
723   IMAGE_INSTANCE_SIZE_CHANGED (p) = 0;
724   IMAGE_INSTANCE_LAYOUT_CHANGED (p) = 0;
725   IMAGE_INSTANCE_DIRTYP (p) = 0;
726
727   assert ( XIMAGE_INSTANCE_HEIGHT (ii) >= 0 
728            && XIMAGE_INSTANCE_WIDTH (ii) >= 0 );
729
730   ERROR_CHECK_IMAGE_INSTANCE (ii);
731
732   RETURN_UNGCPRO (ii);
733 }
734
735 \f
736 /****************************************************************************
737  *                          Image-Instance Object                           *
738  ****************************************************************************/
739
740 Lisp_Object Qimage_instancep;
741
742 static Lisp_Object
743 mark_image_instance (Lisp_Object obj)
744 {
745   Lisp_Image_Instance *i = XIMAGE_INSTANCE (obj);
746
747   /* #### I want to check the instance here, but there are way too
748      many instances of the instance being marked while the domain is
749      dead. For instance you can get marked through an event when using
750      callback_ex.*/
751 #if 0
752   ERROR_CHECK_IMAGE_INSTANCE (obj);
753 #endif
754
755   mark_object (i->name);
756   /* Is this legal in marking? We may get in the situation where the
757      domain has been deleted - making the instance unusable. It seems
758      better to remove the domain so that it can be finalized. */
759   if (!DOMAIN_LIVE_P (i->domain))
760     i->domain = Qnil;
761   else
762     mark_object (i->domain);
763
764   /* We don't mark the glyph reference since that would create a
765      circularity preventing GC. */
766   switch (IMAGE_INSTANCE_TYPE (i))
767     {
768     case IMAGE_TEXT:
769       mark_object (IMAGE_INSTANCE_TEXT_STRING (i));
770       break;
771     case IMAGE_MONO_PIXMAP:
772     case IMAGE_COLOR_PIXMAP:
773       mark_object (IMAGE_INSTANCE_PIXMAP_FILENAME (i));
774       mark_object (IMAGE_INSTANCE_PIXMAP_MASK_FILENAME (i));
775       mark_object (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (i));
776       mark_object (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (i));
777       mark_object (IMAGE_INSTANCE_PIXMAP_FG (i));
778       mark_object (IMAGE_INSTANCE_PIXMAP_BG (i));
779       break;
780
781     case IMAGE_WIDGET:
782       mark_object (IMAGE_INSTANCE_WIDGET_TYPE (i));
783       mark_object (IMAGE_INSTANCE_WIDGET_PROPS (i));
784       mark_object (IMAGE_INSTANCE_WIDGET_FACE (i));
785       mark_object (IMAGE_INSTANCE_WIDGET_ITEMS (i));
786       mark_object (IMAGE_INSTANCE_LAYOUT_CHILDREN (i));
787       mark_object (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (i));
788       mark_object (IMAGE_INSTANCE_WIDGET_HEIGHT_SUBR (i));
789       mark_object (IMAGE_INSTANCE_WIDGET_WIDTH_SUBR (i));
790     case IMAGE_SUBWINDOW:
791       break;
792
793     default:
794       break;
795     }
796
797   /* The image may have been previously finalized (yes that's wierd,
798      see Fdelete_frame() and mark_window_as_deleted()), in which case
799      the domain will be nil, so cope with this. */
800   if (!NILP (IMAGE_INSTANCE_DEVICE (i)))
801     MAYBE_DEVMETH (XDEVICE (IMAGE_INSTANCE_DEVICE (i)), 
802                    mark_image_instance, (i));
803
804   return i->device;
805 }
806
807 static void
808 print_image_instance (Lisp_Object obj, Lisp_Object printcharfun,
809                       int escapeflag)
810 {
811   char buf[100];
812   Lisp_Image_Instance *ii = XIMAGE_INSTANCE (obj);
813
814   if (print_readably)
815     error ("printing unreadable object #<image-instance 0x%x>",
816            ii->header.uid);
817   write_c_string ("#<image-instance (", printcharfun);
818   print_internal (Fimage_instance_type (obj), printcharfun, 0);
819   write_c_string (") ", printcharfun);
820   if (!NILP (ii->name))
821     {
822       print_internal (ii->name, printcharfun, 1);
823       write_c_string (" ", printcharfun);
824     }
825   write_c_string ("on ", printcharfun);
826   print_internal (ii->domain, printcharfun, 0);
827   write_c_string (" ", printcharfun);
828   switch (IMAGE_INSTANCE_TYPE (ii))
829     {
830     case IMAGE_NOTHING:
831       break;
832
833     case IMAGE_TEXT:
834       print_internal (IMAGE_INSTANCE_TEXT_STRING (ii), printcharfun, 1);
835       break;
836
837     case IMAGE_MONO_PIXMAP:
838     case IMAGE_COLOR_PIXMAP:
839     case IMAGE_POINTER:
840       if (STRINGP (IMAGE_INSTANCE_PIXMAP_FILENAME (ii)))
841         {
842           char *s;
843           Lisp_Object filename = IMAGE_INSTANCE_PIXMAP_FILENAME (ii);
844           s = strrchr ((char *) XSTRING_DATA (filename), '/');
845           if (s)
846             print_internal (build_string (s + 1), printcharfun, 1);
847           else
848             print_internal (filename, printcharfun, 1);
849         }
850       if (IMAGE_INSTANCE_PIXMAP_DEPTH (ii) > 1)
851         sprintf (buf, " %dx%dx%d", IMAGE_INSTANCE_PIXMAP_WIDTH (ii),
852                  IMAGE_INSTANCE_PIXMAP_HEIGHT (ii),
853                  IMAGE_INSTANCE_PIXMAP_DEPTH (ii));
854       else
855         sprintf (buf, " %dx%d", IMAGE_INSTANCE_PIXMAP_WIDTH (ii),
856                  IMAGE_INSTANCE_PIXMAP_HEIGHT (ii));
857       write_c_string (buf, printcharfun);
858       if (!NILP (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii)) ||
859           !NILP (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii)))
860         {
861           write_c_string (" @", printcharfun);
862           if (!NILP (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii)))
863             {
864               long_to_string (buf, XINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (ii)));
865               write_c_string (buf, printcharfun);
866             }
867           else
868             write_c_string ("??", printcharfun);
869           write_c_string (",", printcharfun);
870           if (!NILP (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii)))
871             {
872               long_to_string (buf, XINT (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii)));
873               write_c_string (buf, printcharfun);
874             }
875           else
876             write_c_string ("??", printcharfun);
877         }
878       if (!NILP (IMAGE_INSTANCE_PIXMAP_FG (ii)) ||
879           !NILP (IMAGE_INSTANCE_PIXMAP_BG (ii)))
880         {
881           write_c_string (" (", printcharfun);
882           if (!NILP (IMAGE_INSTANCE_PIXMAP_FG (ii)))
883             {
884               print_internal
885                 (XCOLOR_INSTANCE
886                  (IMAGE_INSTANCE_PIXMAP_FG (ii))->name, printcharfun, 0);
887             }
888           write_c_string ("/", printcharfun);
889           if (!NILP (IMAGE_INSTANCE_PIXMAP_BG (ii)))
890             {
891               print_internal
892                 (XCOLOR_INSTANCE
893                  (IMAGE_INSTANCE_PIXMAP_BG (ii))->name, printcharfun, 0);
894             }
895           write_c_string (")", printcharfun);
896         }
897       break;
898
899     case IMAGE_WIDGET:
900       print_internal (IMAGE_INSTANCE_WIDGET_TYPE (ii), printcharfun, 0);
901
902       if (GUI_ITEMP (IMAGE_INSTANCE_WIDGET_ITEM (ii)))
903         {
904           write_c_string (" ", printcharfun);
905           print_internal (IMAGE_INSTANCE_WIDGET_TEXT (ii), printcharfun, 1);
906         }
907
908       if (!NILP (IMAGE_INSTANCE_WIDGET_FACE (ii)))
909         {
910           write_c_string (" face=", printcharfun);
911           print_internal
912             (IMAGE_INSTANCE_WIDGET_FACE (ii), printcharfun, 0);
913         }
914
915
916     case IMAGE_SUBWINDOW:
917       sprintf (buf, " %dx%d", IMAGE_INSTANCE_WIDTH (ii),
918                IMAGE_INSTANCE_HEIGHT (ii));
919       write_c_string (buf, printcharfun);
920
921       /* This is stolen from frame.c.  Subwindows are strange in that they
922          are specific to a particular frame so we want to print in their
923          description what that frame is. */
924
925       write_c_string (" on #<", printcharfun);
926       {
927         struct frame* f  = XFRAME (IMAGE_INSTANCE_FRAME (ii));
928
929         if (!FRAME_LIVE_P (f))
930           write_c_string ("dead", printcharfun);
931         else
932           write_c_string (DEVICE_TYPE_NAME (XDEVICE (FRAME_DEVICE (f))),
933                           printcharfun);
934       }
935       write_c_string ("-frame>", printcharfun);
936       sprintf (buf, " 0x%p", IMAGE_INSTANCE_SUBWINDOW_ID (ii));
937       write_c_string (buf, printcharfun);
938
939       break;
940
941     default:
942       abort ();
943     }
944
945   MAYBE_DEVMETH (DOMAIN_XDEVICE (ii->domain), print_image_instance,
946                  (ii, printcharfun, escapeflag));
947   sprintf (buf, " 0x%x>", ii->header.uid);
948   write_c_string (buf, printcharfun);
949 }
950
951 static void
952 finalize_image_instance (void *header, int for_disksave)
953 {
954   Lisp_Image_Instance *i = (Lisp_Image_Instance *) header;
955
956   /* objects like this exist at dump time, so don't bomb out. */
957   if (IMAGE_INSTANCE_TYPE (i) == IMAGE_NOTHING
958       || 
959       NILP (IMAGE_INSTANCE_DEVICE (i)))
960     return;
961   if (for_disksave) finalose (i);
962
963   /* We can't use the domain here, because it might have
964      disappeared. */
965   MAYBE_DEVMETH (XDEVICE (IMAGE_INSTANCE_DEVICE (i)),
966                  finalize_image_instance, (i));
967
968   /* Make sure we don't try this twice. */
969   IMAGE_INSTANCE_DEVICE (i) = Qnil;
970 }
971
972 static int
973 image_instance_equal (Lisp_Object obj1, Lisp_Object obj2, int depth)
974 {
975   Lisp_Image_Instance *i1 = XIMAGE_INSTANCE (obj1);
976   Lisp_Image_Instance *i2 = XIMAGE_INSTANCE (obj2);
977
978   ERROR_CHECK_IMAGE_INSTANCE (obj1);
979   ERROR_CHECK_IMAGE_INSTANCE (obj2);
980
981   if (!EQ (IMAGE_INSTANCE_DOMAIN (i1),
982            IMAGE_INSTANCE_DOMAIN (i2))
983       || IMAGE_INSTANCE_TYPE (i1) != IMAGE_INSTANCE_TYPE (i2)
984       || IMAGE_INSTANCE_WIDTH (i1) != IMAGE_INSTANCE_WIDTH (i2)
985       || IMAGE_INSTANCE_MARGIN_WIDTH (i1) !=
986       IMAGE_INSTANCE_MARGIN_WIDTH (i2)
987       || IMAGE_INSTANCE_HEIGHT (i1) != IMAGE_INSTANCE_HEIGHT (i2)
988       || IMAGE_INSTANCE_XOFFSET (i1) != IMAGE_INSTANCE_XOFFSET (i2)
989       || IMAGE_INSTANCE_YOFFSET (i1) != IMAGE_INSTANCE_YOFFSET (i2))
990     return 0;
991   if (!internal_equal (IMAGE_INSTANCE_NAME (i1), IMAGE_INSTANCE_NAME (i2),
992                        depth + 1))
993     return 0;
994
995   switch (IMAGE_INSTANCE_TYPE (i1))
996     {
997     case IMAGE_NOTHING:
998       break;
999
1000     case IMAGE_TEXT:
1001       if (!internal_equal (IMAGE_INSTANCE_TEXT_STRING (i1),
1002                            IMAGE_INSTANCE_TEXT_STRING (i2),
1003                            depth + 1))
1004         return 0;
1005       break;
1006
1007     case IMAGE_MONO_PIXMAP:
1008     case IMAGE_COLOR_PIXMAP:
1009     case IMAGE_POINTER:
1010       if (!(IMAGE_INSTANCE_PIXMAP_DEPTH (i1) ==
1011             IMAGE_INSTANCE_PIXMAP_DEPTH (i2) &&
1012             IMAGE_INSTANCE_PIXMAP_SLICE (i1) ==
1013             IMAGE_INSTANCE_PIXMAP_SLICE (i2) &&
1014             EQ (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (i1),
1015                 IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (i2)) &&
1016             EQ (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (i1),
1017                 IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (i2)) &&
1018             internal_equal (IMAGE_INSTANCE_PIXMAP_FILENAME (i1),
1019                             IMAGE_INSTANCE_PIXMAP_FILENAME (i2),
1020                             depth + 1) &&
1021             internal_equal (IMAGE_INSTANCE_PIXMAP_MASK_FILENAME (i1),
1022                             IMAGE_INSTANCE_PIXMAP_MASK_FILENAME (i2),
1023                             depth + 1)))
1024         return 0;
1025       break;
1026
1027     case IMAGE_WIDGET:
1028       if (!(EQ (IMAGE_INSTANCE_WIDGET_TYPE (i1),
1029                 IMAGE_INSTANCE_WIDGET_TYPE (i2))
1030             && IMAGE_INSTANCE_SUBWINDOW_ID (i1) ==
1031             IMAGE_INSTANCE_SUBWINDOW_ID (i2)
1032             &&
1033             EQ (IMAGE_INSTANCE_WIDGET_FACE (i1),
1034                 IMAGE_INSTANCE_WIDGET_TYPE (i2))
1035             && internal_equal (IMAGE_INSTANCE_WIDGET_ITEMS (i1),
1036                                IMAGE_INSTANCE_WIDGET_ITEMS (i2),
1037                                depth + 1)
1038             && internal_equal (IMAGE_INSTANCE_LAYOUT_CHILDREN (i1),
1039                                IMAGE_INSTANCE_LAYOUT_CHILDREN (i2),
1040                                depth + 1)
1041             && internal_equal (IMAGE_INSTANCE_WIDGET_PROPS (i1),
1042                                IMAGE_INSTANCE_WIDGET_PROPS (i2),
1043                                depth + 1)
1044             && internal_equal (IMAGE_INSTANCE_WIDGET_WIDTH_SUBR (i1),
1045                                IMAGE_INSTANCE_WIDGET_WIDTH_SUBR (i2),
1046                                depth + 1)
1047             && internal_equal (IMAGE_INSTANCE_WIDGET_HEIGHT_SUBR (i1),
1048                                IMAGE_INSTANCE_WIDGET_HEIGHT_SUBR (i2),
1049                                depth + 1)
1050             ))
1051         return 0;
1052       break;
1053
1054     case IMAGE_SUBWINDOW:
1055       if (!(IMAGE_INSTANCE_SUBWINDOW_ID (i1) ==
1056             IMAGE_INSTANCE_SUBWINDOW_ID (i2)))
1057         return 0;
1058       break;
1059
1060     default:
1061       abort ();
1062     }
1063
1064   return DEVMETH_OR_GIVEN (DOMAIN_XDEVICE (i1->domain), 
1065                            image_instance_equal, (i1, i2, depth), 1);
1066 }
1067
1068 /* Image instance domain manipulators. We can't error check in these
1069    otherwise we get into infinite recursion. */
1070 Lisp_Object
1071 image_instance_device (Lisp_Object instance)
1072 {
1073   return XIMAGE_INSTANCE_DEVICE (instance);
1074 }
1075
1076 Lisp_Object
1077 image_instance_frame (Lisp_Object instance)
1078 {
1079   return XIMAGE_INSTANCE_FRAME (instance);
1080 }
1081
1082 Lisp_Object
1083 image_instance_window (Lisp_Object instance)
1084 {
1085   return DOMAIN_WINDOW (XIMAGE_INSTANCE_DOMAIN (instance));
1086 }
1087
1088 int
1089 image_instance_live_p (Lisp_Object instance)
1090 {
1091   return DOMAIN_LIVE_P (XIMAGE_INSTANCE_DOMAIN (instance));
1092 }
1093
1094 static unsigned long
1095 image_instance_hash (Lisp_Object obj, int depth)
1096 {
1097   Lisp_Image_Instance *i = XIMAGE_INSTANCE (obj);
1098   unsigned long hash = HASH4 (LISP_HASH (IMAGE_INSTANCE_DOMAIN (i)),
1099                               IMAGE_INSTANCE_WIDTH (i),
1100                               IMAGE_INSTANCE_MARGIN_WIDTH (i),
1101                               IMAGE_INSTANCE_HEIGHT (i));
1102
1103   ERROR_CHECK_IMAGE_INSTANCE (obj);
1104
1105   switch (IMAGE_INSTANCE_TYPE (i))
1106     {
1107     case IMAGE_NOTHING:
1108       break;
1109
1110     case IMAGE_TEXT:
1111       hash = HASH2 (hash, internal_hash (IMAGE_INSTANCE_TEXT_STRING (i),
1112                                          depth + 1));
1113       break;
1114
1115     case IMAGE_MONO_PIXMAP:
1116     case IMAGE_COLOR_PIXMAP:
1117     case IMAGE_POINTER:
1118       hash = HASH4 (hash, IMAGE_INSTANCE_PIXMAP_DEPTH (i),
1119                     IMAGE_INSTANCE_PIXMAP_SLICE (i),
1120                     internal_hash (IMAGE_INSTANCE_PIXMAP_FILENAME (i),
1121                                    depth + 1));
1122       break;
1123
1124     case IMAGE_WIDGET:
1125       /* We need the hash to be equivalent to what should be
1126          displayed. */
1127       hash = HASH5 (hash,
1128                     LISP_HASH (IMAGE_INSTANCE_WIDGET_TYPE (i)),
1129                     internal_hash (IMAGE_INSTANCE_WIDGET_PROPS (i), depth + 1),
1130                     internal_hash (IMAGE_INSTANCE_WIDGET_ITEMS (i), depth + 1),
1131                     internal_hash (IMAGE_INSTANCE_LAYOUT_CHILDREN (i), 
1132                                    depth + 1));
1133     case IMAGE_SUBWINDOW:
1134       hash = HASH2 (hash, (int) IMAGE_INSTANCE_SUBWINDOW_ID (i));
1135       break;
1136
1137     default:
1138       abort ();
1139     }
1140
1141   return HASH2 (hash, DEVMETH_OR_GIVEN 
1142                 (XDEVICE (image_instance_device (obj)),
1143                  image_instance_hash, (i, depth),
1144                  0));
1145 }
1146
1147 DEFINE_LRECORD_IMPLEMENTATION ("image-instance", image_instance,
1148                                mark_image_instance, print_image_instance,
1149                                finalize_image_instance, image_instance_equal,
1150                                image_instance_hash, 0,
1151                                Lisp_Image_Instance);
1152
1153 static Lisp_Object
1154 allocate_image_instance (Lisp_Object governing_domain, Lisp_Object glyph)
1155 {
1156   Lisp_Image_Instance *lp =
1157     alloc_lcrecord_type (Lisp_Image_Instance, &lrecord_image_instance);
1158   Lisp_Object val;
1159
1160   zero_lcrecord (lp);
1161   /* It's not possible to simply keep a record of the domain in which
1162      the instance was instantiated. This is because caching may mean
1163      that the domain becomes invalid but the instance remains
1164      valid. However, the only truly relevant domain is the domain in
1165      which the instance is cached since this is the one that will be
1166      common to the instances. */
1167   lp->domain = governing_domain;
1168   /* The cache domain is not quite sufficient since the domain can get
1169      deleted before the image instance does. We need to know the
1170      domain device in order to finalize the image instance
1171      properly. We therefore record the device also. */
1172   lp->device = DOMAIN_DEVICE (governing_domain);
1173   lp->type = IMAGE_NOTHING;
1174   lp->name = Qnil;
1175   lp->x_offset = 0;
1176   lp->y_offset = 0;
1177   lp->width = IMAGE_UNSPECIFIED_GEOMETRY;
1178   lp->margin_width = 0;
1179   lp->height = IMAGE_UNSPECIFIED_GEOMETRY;
1180   lp->parent = glyph;
1181   /* So that layouts get done. */
1182   lp->layout_changed = 1;
1183   lp->initialized = 0;
1184
1185   XSETIMAGE_INSTANCE (val, lp);
1186   MARK_GLYPHS_CHANGED;
1187
1188   return val;
1189 }
1190
1191 static enum image_instance_type
1192 decode_image_instance_type (Lisp_Object type, Error_behavior errb)
1193 {
1194   if (ERRB_EQ (errb, ERROR_ME))
1195     CHECK_SYMBOL (type);
1196
1197   if (EQ (type, Qnothing))      return IMAGE_NOTHING;
1198   if (EQ (type, Qtext))         return IMAGE_TEXT;
1199   if (EQ (type, Qmono_pixmap))  return IMAGE_MONO_PIXMAP;
1200   if (EQ (type, Qcolor_pixmap)) return IMAGE_COLOR_PIXMAP;
1201   if (EQ (type, Qpointer))      return IMAGE_POINTER;
1202   if (EQ (type, Qsubwindow))    return IMAGE_SUBWINDOW;
1203   if (EQ (type, Qwidget))    return IMAGE_WIDGET;
1204
1205   maybe_signal_simple_error ("Invalid image-instance type", type,
1206                              Qimage, errb);
1207
1208   return IMAGE_UNKNOWN; /* not reached */
1209 }
1210
1211 static Lisp_Object
1212 encode_image_instance_type (enum image_instance_type type)
1213 {
1214   switch (type)
1215     {
1216     case IMAGE_NOTHING:      return Qnothing;
1217     case IMAGE_TEXT:         return Qtext;
1218     case IMAGE_MONO_PIXMAP:  return Qmono_pixmap;
1219     case IMAGE_COLOR_PIXMAP: return Qcolor_pixmap;
1220     case IMAGE_POINTER:      return Qpointer;
1221     case IMAGE_SUBWINDOW:    return Qsubwindow;
1222     case IMAGE_WIDGET:    return Qwidget;
1223     default:
1224       abort ();
1225     }
1226
1227   return Qnil; /* not reached */
1228 }
1229
1230 static int
1231 decode_image_instance_type_list (Lisp_Object list)
1232 {
1233   Lisp_Object rest;
1234   int mask = 0;
1235
1236   if (NILP (list))
1237     return ~0;
1238
1239   if (!CONSP (list))
1240     {
1241       enum image_instance_type type =
1242         decode_image_instance_type (list, ERROR_ME);
1243       return image_instance_type_to_mask (type);
1244     }
1245
1246   EXTERNAL_LIST_LOOP (rest, list)
1247     {
1248       enum image_instance_type type =
1249         decode_image_instance_type (XCAR (rest), ERROR_ME);
1250       mask |= image_instance_type_to_mask (type);
1251     }
1252
1253   return mask;
1254 }
1255
1256 static Lisp_Object
1257 encode_image_instance_type_list (int mask)
1258 {
1259   int count = 0;
1260   Lisp_Object result = Qnil;
1261
1262   while (mask)
1263     {
1264       count++;
1265       if (mask & 1)
1266         result = Fcons (encode_image_instance_type
1267                         ((enum image_instance_type) count), result);
1268       mask >>= 1;
1269     }
1270
1271   return Fnreverse (result);
1272 }
1273
1274 DOESNT_RETURN
1275 incompatible_image_types (Lisp_Object instantiator, int given_dest_mask,
1276                           int desired_dest_mask)
1277 {
1278   signal_error
1279     (Qerror,
1280      list2
1281      (emacs_doprnt_string_lisp_2
1282       ((const Bufbyte *)
1283        "No compatible image-instance types given: wanted one of %s, got %s",
1284        Qnil, -1, 2,
1285        encode_image_instance_type_list (desired_dest_mask),
1286        encode_image_instance_type_list (given_dest_mask)),
1287       instantiator));
1288 }
1289
1290 static int
1291 valid_image_instance_type_p (Lisp_Object type)
1292 {
1293   return !NILP (memq_no_quit (type, Vimage_instance_type_list));
1294 }
1295
1296 DEFUN ("valid-image-instance-type-p", Fvalid_image_instance_type_p, 1, 1, 0, /*
1297 Given an IMAGE-INSTANCE-TYPE, return non-nil if it is valid.
1298 Valid types are some subset of 'nothing, 'text, 'mono-pixmap, 'color-pixmap,
1299 'pointer, 'subwindow, and 'widget, depending on how XEmacs was compiled.
1300 */
1301        (image_instance_type))
1302 {
1303   return valid_image_instance_type_p (image_instance_type) ? Qt : Qnil;
1304 }
1305
1306 DEFUN ("image-instance-type-list", Fimage_instance_type_list, 0, 0, 0, /*
1307 Return a list of valid image-instance types.
1308 */
1309        ())
1310 {
1311   return Fcopy_sequence (Vimage_instance_type_list);
1312 }
1313
1314 Error_behavior
1315 decode_error_behavior_flag (Lisp_Object no_error)
1316 {
1317   if (NILP (no_error))        return ERROR_ME;
1318   else if (EQ (no_error, Qt)) return ERROR_ME_NOT;
1319   else                        return ERROR_ME_WARN;
1320 }
1321
1322 Lisp_Object
1323 encode_error_behavior_flag (Error_behavior errb)
1324 {
1325   if (ERRB_EQ (errb, ERROR_ME))
1326     return Qnil;
1327   else if (ERRB_EQ (errb, ERROR_ME_NOT))
1328     return Qt;
1329   else
1330     {
1331       assert (ERRB_EQ (errb, ERROR_ME_WARN));
1332       return Qwarning;
1333     }
1334 }
1335
1336 /* Recurse up the hierarchy looking for the topmost glyph. This means
1337    that instances in layouts will inherit face properties from their
1338    parent. */
1339 Lisp_Object image_instance_parent_glyph (Lisp_Image_Instance* ii)
1340 {
1341   if (IMAGE_INSTANCEP (IMAGE_INSTANCE_PARENT (ii)))
1342     {
1343       return image_instance_parent_glyph
1344         (XIMAGE_INSTANCE (IMAGE_INSTANCE_PARENT (ii)));
1345     }
1346   return IMAGE_INSTANCE_PARENT (ii);
1347 }
1348
1349 static Lisp_Object
1350 make_image_instance_1 (Lisp_Object data, Lisp_Object domain,
1351                        Lisp_Object dest_types)
1352 {
1353   Lisp_Object ii;
1354   struct gcpro gcpro1;
1355   int dest_mask;
1356   Lisp_Object governing_domain;
1357
1358   if (IMAGE_INSTANCEP (data))
1359     signal_simple_error ("Image instances not allowed here", data);
1360   image_validate (data);
1361   domain = decode_domain (domain);
1362   /* instantiate_image_instantiator() will abort if given an
1363      image instance ... */
1364   dest_mask = decode_image_instance_type_list (dest_types);
1365   data = normalize_image_instantiator (data,
1366                                        DEVICE_TYPE (DOMAIN_XDEVICE (domain)),
1367                                        make_int (dest_mask));
1368   GCPRO1 (data);
1369   /* After normalizing the data, it's always either an image instance (which
1370      we filtered out above) or a vector. */
1371   if (EQ (XVECTOR_DATA (data)[0], Qinherit))
1372     signal_simple_error ("Inheritance not allowed here", data);
1373   governing_domain =
1374     get_image_instantiator_governing_domain (data, domain);
1375   ii = instantiate_image_instantiator (governing_domain, domain, data,
1376                                        Qnil, Qnil, dest_mask, Qnil);
1377   RETURN_UNGCPRO (ii);
1378 }
1379
1380 DEFUN ("make-image-instance", Fmake_image_instance, 1, 4, 0, /*
1381 Return a new `image-instance' object.
1382
1383 Image-instance objects encapsulate the way a particular image (pixmap,
1384 etc.) is displayed on a particular device.  In most circumstances, you
1385 do not need to directly create image instances; use a glyph instead.
1386 However, it may occasionally be useful to explicitly create image
1387 instances, if you want more control over the instantiation process.
1388
1389 DATA is an image instantiator, which describes the image; see
1390 `make-image-specifier' for a description of the allowed values.
1391
1392 DEST-TYPES should be a list of allowed image instance types that can
1393 be generated.  The recognized image instance types are
1394
1395 'nothing
1396   Nothing is displayed.
1397 'text
1398   Displayed as text.  The foreground and background colors and the
1399   font of the text are specified independent of the pixmap.  Typically
1400   these attributes will come from the face of the surrounding text,
1401   unless a face is specified for the glyph in which the image appears.
1402 'mono-pixmap
1403   Displayed as a mono pixmap (a pixmap with only two colors where the
1404   foreground and background can be specified independent of the pixmap;
1405   typically the pixmap assumes the foreground and background colors of
1406   the text around it, unless a face is specified for the glyph in which
1407   the image appears).
1408 'color-pixmap
1409   Displayed as a color pixmap.
1410 'pointer
1411   Used as the mouse pointer for a window.
1412 'subwindow
1413   A child window that is treated as an image.  This allows (e.g.)
1414   another program to be responsible for drawing into the window.
1415 'widget
1416   A child window that contains a window-system widget, e.g. a push
1417   button, text field, or slider.
1418
1419 The DEST-TYPES list is unordered.  If multiple destination types are
1420 possible for a given instantiator, the "most natural" type for the
1421 instantiator's format is chosen. (For XBM, the most natural types are
1422 `mono-pixmap', followed by `color-pixmap', followed by `pointer'.  For
1423 the other normal image formats, the most natural types are
1424 `color-pixmap', followed by `mono-pixmap', followed by `pointer'.  For
1425 the string and formatted-string formats, the most natural types are
1426 `text', followed by `mono-pixmap' (not currently implemented),
1427 followed by `color-pixmap' (not currently implemented).  For MS
1428 Windows resources, the most natural type for pointer resources is
1429 `pointer', and for the others it's `color-pixmap'.  The other formats
1430 can only be instantiated as one type. (If you want to control more
1431 specifically the order of the types into which an image is
1432 instantiated, just call `make-image-instance' repeatedly until it
1433 succeeds, passing less and less preferred destination types each
1434 time.)
1435
1436 See `make-image-specifier' for a description of the different image
1437 instantiator formats.
1438
1439 If DEST-TYPES is omitted, all possible types are allowed.
1440
1441 DOMAIN specifies the domain to which the image instance will be attached.
1442 This domain is termed the \"governing domain\".  The type of the governing
1443 domain depends on the image instantiator format. (Although, more correctly,
1444 it should probably depend on the image instance type.) For example, pixmap
1445 image instances are specific to a device, but widget image instances are
1446 specific to a particular XEmacs window because in order to display such a
1447 widget when two windows onto the same buffer want to display the widget,
1448 two separate underlying widgets must be created. (That's because a widget
1449 is actually a child window-system window, and all window-system windows have
1450 a unique existence on the screen.) This means that the governing domain for
1451 a pixmap image instance will be some device (most likely, the only existing
1452 device), whereas the governing domain for a widget image instance will be
1453 some XEmacs window.
1454
1455 If you specify an overly general DOMAIN (e.g. a frame when a window was
1456 wanted), an error is signaled.  If you specify an overly specific DOMAIN
1457 \(e.g. a window when a device was wanted), the corresponding general domain
1458 is fetched and used instead.  For `make-image-instance', it makes no
1459 difference whether you specify an overly specific domain or the properly
1460 general domain derived from it.  However, it does matter when creating an
1461 image instance by instantiating a specifier or glyph (e.g. with
1462 `glyph-image-instance'), because the more specific domain causes spec lookup
1463 to start there and proceed to more general domains. (It would also matter
1464 when creating an image instance with an instantiator format of `inherit',
1465 but we currently disallow this. #### We should fix this.)
1466
1467 If omitted, DOMAIN defaults to the selected window.
1468
1469 NO-ERROR controls what happens when the image cannot be generated.
1470 If nil, an error message is generated.  If t, no messages are
1471 generated and this function returns nil.  If anything else, a warning
1472 message is generated and this function returns nil.
1473 */
1474        (data, domain, dest_types, no_error))
1475 {
1476   Error_behavior errb = decode_error_behavior_flag (no_error);
1477
1478   return call_with_suspended_errors ((lisp_fn_t) make_image_instance_1,
1479                                      Qnil, Qimage, errb,
1480                                      3, data, domain, dest_types);
1481 }
1482
1483 DEFUN ("image-instance-p", Fimage_instance_p, 1, 1, 0, /*
1484 Return non-nil if OBJECT is an image instance.
1485 */
1486        (object))
1487 {
1488   return IMAGE_INSTANCEP (object) ? Qt : Qnil;
1489 }
1490
1491 DEFUN ("image-instance-type", Fimage_instance_type, 1, 1, 0, /*
1492 Return the type of the given image instance.
1493 The return value will be one of 'nothing, 'text, 'mono-pixmap,
1494 'color-pixmap, 'pointer, or 'subwindow.
1495 */
1496        (image_instance))
1497 {
1498   CHECK_IMAGE_INSTANCE (image_instance);
1499   ERROR_CHECK_IMAGE_INSTANCE (image_instance);
1500   return encode_image_instance_type (XIMAGE_INSTANCE_TYPE (image_instance));
1501 }
1502
1503 DEFUN ("image-instance-name", Fimage_instance_name, 1, 1, 0, /*
1504 Return the name of the given image instance.
1505 */
1506        (image_instance))
1507 {
1508   CHECK_IMAGE_INSTANCE (image_instance);
1509   return XIMAGE_INSTANCE_NAME (image_instance);
1510 }
1511
1512 DEFUN ("image-instance-domain", Fimage_instance_domain, 1, 1, 0, /*
1513 Return the governing domain of the given image instance.
1514 The governing domain of an image instance is the domain that the image
1515 instance is specific to.  It is NOT necessarily the domain that was
1516 given to the call to `specifier-instance' that resulted in the creation
1517 of this image instance.  See `make-image-instance' for more information
1518 on governing domains.
1519 */
1520        (image_instance))
1521 {
1522   CHECK_IMAGE_INSTANCE (image_instance);
1523   return XIMAGE_INSTANCE_DOMAIN (image_instance);
1524 }
1525
1526 DEFUN ("image-instance-string", Fimage_instance_string, 1, 1, 0, /*
1527 Return the string of the given image instance.
1528 This will only be non-nil for text image instances and widgets.
1529 */
1530        (image_instance))
1531 {
1532   CHECK_IMAGE_INSTANCE (image_instance);
1533   if (XIMAGE_INSTANCE_TYPE (image_instance) == IMAGE_TEXT)
1534     return XIMAGE_INSTANCE_TEXT_STRING (image_instance);
1535   else if (XIMAGE_INSTANCE_TYPE (image_instance) == IMAGE_WIDGET)
1536     return XIMAGE_INSTANCE_WIDGET_TEXT (image_instance);
1537   else
1538     return Qnil;
1539 }
1540
1541 DEFUN ("image-instance-property", Fimage_instance_property, 2, 2, 0, /*
1542 Return the given property of the given image instance.
1543 Returns nil if the property or the property method do not exist for
1544 the image instance in the domain.
1545 */
1546        (image_instance, prop))
1547 {
1548   Lisp_Image_Instance* ii;
1549   Lisp_Object type, ret;
1550   struct image_instantiator_methods* meths;
1551
1552   CHECK_IMAGE_INSTANCE (image_instance);
1553   ERROR_CHECK_IMAGE_INSTANCE (image_instance);
1554   CHECK_SYMBOL (prop);
1555   ii = XIMAGE_INSTANCE (image_instance);
1556
1557   /* ... then try device specific methods ... */
1558   type = encode_image_instance_type (IMAGE_INSTANCE_TYPE (ii));
1559   meths = decode_device_ii_format (image_instance_device (image_instance),
1560                                    type, ERROR_ME_NOT);
1561   if (meths && HAS_IIFORMAT_METH_P (meths, property)
1562       &&
1563       !UNBOUNDP (ret =  IIFORMAT_METH (meths, property, (image_instance, prop))))
1564     {
1565       return ret;
1566     }
1567   /* ... then format specific methods ... */
1568   meths = decode_device_ii_format (Qnil, type, ERROR_ME_NOT);
1569   if (meths && HAS_IIFORMAT_METH_P (meths, property)
1570       &&
1571       !UNBOUNDP (ret = IIFORMAT_METH (meths, property, (image_instance, prop))))
1572     {
1573       return ret;
1574     }
1575   /* ... then fail */
1576   return Qnil;
1577 }
1578
1579 DEFUN ("set-image-instance-property", Fset_image_instance_property, 3, 3, 0, /*
1580 Set the given property of the given image instance.
1581 Does nothing if the property or the property method do not exist for
1582 the image instance in the domain.
1583
1584 WARNING: If you are thinking about using this function, think again.
1585 You probably want to be using `set-glyph-image' to change the glyph's
1586 specifier.  Be especially wary if you are thinking of calling this
1587 function after having called `glyph-image-instance'.  Unless you are
1588 absolutely sure what you're doing, pretty much the only legitimate
1589 uses for this function are setting user-specified info in a widget,
1590 such as text in a text field.  */
1591        (image_instance, prop, val))
1592 {
1593   Lisp_Image_Instance* ii;
1594   Lisp_Object type, ret;
1595   struct image_instantiator_methods* meths;
1596
1597   CHECK_IMAGE_INSTANCE (image_instance);
1598   ERROR_CHECK_IMAGE_INSTANCE (image_instance);
1599   CHECK_SYMBOL (prop);
1600   ii = XIMAGE_INSTANCE (image_instance);
1601   type = encode_image_instance_type (IMAGE_INSTANCE_TYPE (ii));
1602   /* try device specific methods first ... */
1603   meths = decode_device_ii_format (image_instance_device (image_instance),
1604                                    type, ERROR_ME_NOT);
1605   if (meths && HAS_IIFORMAT_METH_P (meths, set_property)
1606       &&
1607       !UNBOUNDP (ret =
1608                  IIFORMAT_METH (meths, set_property, (image_instance, prop, val))))
1609     {
1610       val = ret;
1611     }
1612   else
1613     {
1614       /* ... then format specific methods ... */
1615       meths = decode_device_ii_format (Qnil, type, ERROR_ME_NOT);
1616       if (meths && HAS_IIFORMAT_METH_P (meths, set_property)
1617           &&
1618           !UNBOUNDP (ret =
1619                      IIFORMAT_METH (meths, set_property, (image_instance, prop, val))))
1620         {
1621           val = ret;
1622         }
1623       else
1624         {
1625           val = Qnil;
1626         }
1627     }
1628
1629   /* Make sure the image instance gets redisplayed. */
1630   set_image_instance_dirty_p (image_instance, 1);
1631   /* Force the glyph to be laid out again. */
1632   IMAGE_INSTANCE_LAYOUT_CHANGED (ii) = 1;
1633
1634   MARK_SUBWINDOWS_STATE_CHANGED;
1635   MARK_GLYPHS_CHANGED;
1636
1637   return val;
1638 }
1639
1640 DEFUN ("image-instance-file-name", Fimage_instance_file_name, 1, 1, 0, /*
1641 Return the file name from which IMAGE-INSTANCE was read, if known.
1642 */
1643        (image_instance))
1644 {
1645   CHECK_IMAGE_INSTANCE (image_instance);
1646   ERROR_CHECK_IMAGE_INSTANCE (image_instance);
1647
1648   switch (XIMAGE_INSTANCE_TYPE (image_instance))
1649     {
1650     case IMAGE_MONO_PIXMAP:
1651     case IMAGE_COLOR_PIXMAP:
1652     case IMAGE_POINTER:
1653       return XIMAGE_INSTANCE_PIXMAP_FILENAME (image_instance);
1654
1655     default:
1656       return Qnil;
1657     }
1658 }
1659
1660 DEFUN ("image-instance-mask-file-name", Fimage_instance_mask_file_name, 1, 1, 0, /*
1661 Return the file name from which IMAGE-INSTANCE's mask was read, if known.
1662 */
1663        (image_instance))
1664 {
1665   CHECK_IMAGE_INSTANCE (image_instance);
1666   ERROR_CHECK_IMAGE_INSTANCE (image_instance);
1667
1668   switch (XIMAGE_INSTANCE_TYPE (image_instance))
1669     {
1670     case IMAGE_MONO_PIXMAP:
1671     case IMAGE_COLOR_PIXMAP:
1672     case IMAGE_POINTER:
1673       return XIMAGE_INSTANCE_PIXMAP_MASK_FILENAME (image_instance);
1674
1675     default:
1676       return Qnil;
1677     }
1678 }
1679
1680 DEFUN ("image-instance-depth", Fimage_instance_depth, 1, 1, 0, /*
1681 Return the depth of the image instance.
1682 This is 0 for a bitmap, or a positive integer for a pixmap.
1683 */
1684        (image_instance))
1685 {
1686   CHECK_IMAGE_INSTANCE (image_instance);
1687   ERROR_CHECK_IMAGE_INSTANCE (image_instance);
1688
1689   switch (XIMAGE_INSTANCE_TYPE (image_instance))
1690     {
1691     case IMAGE_MONO_PIXMAP:
1692     case IMAGE_COLOR_PIXMAP:
1693     case IMAGE_POINTER:
1694       return make_int (XIMAGE_INSTANCE_PIXMAP_DEPTH (image_instance));
1695
1696     default:
1697       return Qnil;
1698     }
1699 }
1700
1701 DEFUN ("image-instance-height", Fimage_instance_height, 1, 1, 0, /*
1702 Return the height of the image instance, in pixels.
1703 */
1704        (image_instance))
1705 {
1706   CHECK_IMAGE_INSTANCE (image_instance);
1707   ERROR_CHECK_IMAGE_INSTANCE (image_instance);
1708
1709   switch (XIMAGE_INSTANCE_TYPE (image_instance))
1710     {
1711     case IMAGE_MONO_PIXMAP:
1712     case IMAGE_COLOR_PIXMAP:
1713     case IMAGE_POINTER:
1714     case IMAGE_SUBWINDOW:
1715     case IMAGE_WIDGET:
1716       return make_int (XIMAGE_INSTANCE_HEIGHT (image_instance));
1717
1718     default:
1719       return Qnil;
1720     }
1721 }
1722
1723 DEFUN ("image-instance-width", Fimage_instance_width, 1, 1, 0, /*
1724 Return the width of the image instance, in pixels.
1725 */
1726        (image_instance))
1727 {
1728   CHECK_IMAGE_INSTANCE (image_instance);
1729   ERROR_CHECK_IMAGE_INSTANCE (image_instance);
1730
1731   switch (XIMAGE_INSTANCE_TYPE (image_instance))
1732     {
1733     case IMAGE_MONO_PIXMAP:
1734     case IMAGE_COLOR_PIXMAP:
1735     case IMAGE_POINTER:
1736     case IMAGE_SUBWINDOW:
1737     case IMAGE_WIDGET:
1738       return make_int (XIMAGE_INSTANCE_WIDTH (image_instance));
1739
1740     default:
1741       return Qnil;
1742     }
1743 }
1744
1745 DEFUN ("image-instance-hotspot-x", Fimage_instance_hotspot_x, 1, 1, 0, /*
1746 Return the X coordinate of the image instance's hotspot, if known.
1747 This is a point relative to the origin of the pixmap.  When an image is
1748  used as a mouse pointer, the hotspot is the point on the image that sits
1749  over the location that the pointer points to.  This is, for example, the
1750  tip of the arrow or the center of the crosshairs.
1751 This will always be nil for a non-pointer image instance.
1752 */
1753        (image_instance))
1754 {
1755   CHECK_IMAGE_INSTANCE (image_instance);
1756   ERROR_CHECK_IMAGE_INSTANCE (image_instance);
1757
1758   switch (XIMAGE_INSTANCE_TYPE (image_instance))
1759     {
1760     case IMAGE_MONO_PIXMAP:
1761     case IMAGE_COLOR_PIXMAP:
1762     case IMAGE_POINTER:
1763       return XIMAGE_INSTANCE_PIXMAP_HOTSPOT_X (image_instance);
1764
1765     default:
1766       return Qnil;
1767     }
1768 }
1769
1770 DEFUN ("image-instance-hotspot-y", Fimage_instance_hotspot_y, 1, 1, 0, /*
1771 Return the Y coordinate of the image instance's hotspot, if known.
1772 This is a point relative to the origin of the pixmap.  When an image is
1773  used as a mouse pointer, the hotspot is the point on the image that sits
1774  over the location that the pointer points to.  This is, for example, the
1775  tip of the arrow or the center of the crosshairs.
1776 This will always be nil for a non-pointer image instance.
1777 */
1778        (image_instance))
1779 {
1780   CHECK_IMAGE_INSTANCE (image_instance);
1781   ERROR_CHECK_IMAGE_INSTANCE (image_instance);
1782
1783   switch (XIMAGE_INSTANCE_TYPE (image_instance))
1784     {
1785     case IMAGE_MONO_PIXMAP:
1786     case IMAGE_COLOR_PIXMAP:
1787     case IMAGE_POINTER:
1788       return XIMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (image_instance);
1789
1790     default:
1791       return Qnil;
1792     }
1793 }
1794
1795 DEFUN ("image-instance-foreground", Fimage_instance_foreground, 1, 1, 0, /*
1796 Return the foreground color of IMAGE-INSTANCE, if applicable.
1797 This will be a color instance or nil. (It will only be non-nil for
1798 colorized mono pixmaps and for pointers.)
1799 */
1800        (image_instance))
1801 {
1802   CHECK_IMAGE_INSTANCE (image_instance);
1803   ERROR_CHECK_IMAGE_INSTANCE (image_instance);
1804
1805   switch (XIMAGE_INSTANCE_TYPE (image_instance))
1806     {
1807     case IMAGE_MONO_PIXMAP:
1808     case IMAGE_COLOR_PIXMAP:
1809     case IMAGE_POINTER:
1810       return XIMAGE_INSTANCE_PIXMAP_FG (image_instance);
1811
1812     case IMAGE_WIDGET:
1813       return FACE_FOREGROUND (
1814                               XIMAGE_INSTANCE_WIDGET_FACE (image_instance),
1815                               XIMAGE_INSTANCE_FRAME
1816                               (image_instance));
1817
1818     default:
1819       return Qnil;
1820     }
1821 }
1822
1823 DEFUN ("image-instance-background", Fimage_instance_background, 1, 1, 0, /*
1824 Return the background color of IMAGE-INSTANCE, if applicable.
1825 This will be a color instance or nil. (It will only be non-nil for
1826 colorized mono pixmaps and for pointers.)
1827 */
1828        (image_instance))
1829 {
1830   CHECK_IMAGE_INSTANCE (image_instance);
1831   ERROR_CHECK_IMAGE_INSTANCE (image_instance);
1832
1833   switch (XIMAGE_INSTANCE_TYPE (image_instance))
1834     {
1835     case IMAGE_MONO_PIXMAP:
1836     case IMAGE_COLOR_PIXMAP:
1837     case IMAGE_POINTER:
1838       return XIMAGE_INSTANCE_PIXMAP_BG (image_instance);
1839
1840     case IMAGE_WIDGET:
1841       return FACE_BACKGROUND (
1842                               XIMAGE_INSTANCE_WIDGET_FACE (image_instance),
1843                               XIMAGE_INSTANCE_FRAME
1844                               (image_instance));
1845
1846     default:
1847       return Qnil;
1848     }
1849 }
1850
1851
1852 DEFUN ("colorize-image-instance", Fcolorize_image_instance, 3, 3, 0, /*
1853 Make the image instance be displayed in the given colors.
1854 This function returns a new image instance that is exactly like the
1855 specified one except that (if possible) the foreground and background
1856 colors and as specified.  Currently, this only does anything if the image
1857 instance is a mono pixmap; otherwise, the same image instance is returned.
1858 */
1859        (image_instance, foreground, background))
1860 {
1861   Lisp_Object new;
1862   Lisp_Object device;
1863
1864   CHECK_IMAGE_INSTANCE (image_instance);
1865   ERROR_CHECK_IMAGE_INSTANCE (image_instance);
1866   CHECK_COLOR_INSTANCE (foreground);
1867   CHECK_COLOR_INSTANCE (background);
1868
1869   device = image_instance_device (image_instance);
1870   if (!HAS_DEVMETH_P (XDEVICE (device), colorize_image_instance))
1871     return image_instance;
1872
1873   /* #### There should be a copy_image_instance(), which calls a
1874      device-specific method to copy the window-system subobject. */
1875   new = allocate_image_instance (XIMAGE_INSTANCE_DOMAIN (image_instance), 
1876                                  Qnil);
1877   copy_lcrecord (XIMAGE_INSTANCE (new), XIMAGE_INSTANCE (image_instance));
1878   /* note that if this method returns non-zero, this method MUST
1879      copy any window-system resources, so that when one image instance is
1880      freed, the other one is not hosed. */
1881   if (!DEVMETH (XDEVICE (device), colorize_image_instance, (new, foreground,
1882                                                             background)))
1883     return image_instance;
1884   return new;
1885 }
1886
1887
1888 /************************************************************************/
1889 /*                              Geometry calculations                   */
1890 /************************************************************************/
1891
1892 /* Find out desired geometry of the image instance. If there is no
1893    special function then just return the width and / or height. */
1894 void
1895 image_instance_query_geometry (Lisp_Object image_instance,
1896                                int* width, int* height,
1897                                enum image_instance_geometry disp,
1898                                Lisp_Object domain)
1899 {
1900   Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance);
1901   Lisp_Object type;
1902   struct image_instantiator_methods* meths;
1903   ERROR_CHECK_IMAGE_INSTANCE (image_instance);
1904
1905   type = encode_image_instance_type (IMAGE_INSTANCE_TYPE (ii));
1906   meths = decode_device_ii_format (Qnil, type, ERROR_ME_NOT);
1907
1908   if (meths && HAS_IIFORMAT_METH_P (meths, query_geometry))
1909     {
1910       IIFORMAT_METH (meths, query_geometry, (image_instance, width, height,
1911                                              disp, domain));
1912     }
1913   else
1914     {
1915       if (width)
1916         *width = IMAGE_INSTANCE_WIDTH (ii);
1917       if (height)
1918         *height = IMAGE_INSTANCE_HEIGHT (ii);
1919     }
1920 }
1921
1922 /* Layout the image instance using the provided dimensions. Layout
1923    widgets are going to do different kinds of calculations to
1924    determine what size to give things so we could make the layout
1925    function relatively simple to take account of that. An alternative
1926    approach is to consider separately the two cases, one where you
1927    don't mind what size you have (normal widgets) and one where you
1928    want to specifiy something (layout widgets). */
1929 void
1930 image_instance_layout (Lisp_Object image_instance,
1931                        int width, int height, Lisp_Object domain)
1932 {
1933   Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance);
1934   Lisp_Object type;
1935   struct image_instantiator_methods* meths;
1936
1937   ERROR_CHECK_IMAGE_INSTANCE (image_instance);
1938
1939   /* Nothing is as nothing does. */
1940   if (NOTHING_IMAGE_INSTANCEP (image_instance))
1941     return;
1942
1943   type = encode_image_instance_type (IMAGE_INSTANCE_TYPE (ii));
1944   meths = decode_device_ii_format (Qnil, type, ERROR_ME_NOT);
1945
1946   /* If geometry is unspecified then get some reasonable values for it. */
1947   if (width == IMAGE_UNSPECIFIED_GEOMETRY
1948       ||
1949       height == IMAGE_UNSPECIFIED_GEOMETRY)
1950     {
1951       int dwidth = IMAGE_UNSPECIFIED_GEOMETRY;
1952       int dheight = IMAGE_UNSPECIFIED_GEOMETRY;
1953
1954       /* Get the desired geometry. */
1955       if (meths && HAS_IIFORMAT_METH_P (meths, query_geometry))
1956         {
1957           IIFORMAT_METH (meths, query_geometry, (image_instance, &dwidth, &dheight,
1958                                                  IMAGE_DESIRED_GEOMETRY,
1959                                                  domain));
1960         }
1961       else
1962         {
1963           dwidth = IMAGE_INSTANCE_WIDTH (ii);
1964           dheight = IMAGE_INSTANCE_HEIGHT (ii);
1965         }
1966
1967       /* Compare with allowed geometry. */
1968       if (width == IMAGE_UNSPECIFIED_GEOMETRY)
1969         width = dwidth;
1970       if (height == IMAGE_UNSPECIFIED_GEOMETRY)
1971         height = dheight;
1972     }
1973
1974   /* If we don't have sane values then we cannot layout at this point and
1975      must just return. */
1976   if (width == IMAGE_UNSPECIFIED_GEOMETRY
1977       ||
1978       height == IMAGE_UNSPECIFIED_GEOMETRY)
1979       return;
1980
1981   /* At this point width and height should contain sane values. Thus
1982      we set the glyph geometry and lay it out. */
1983   if (IMAGE_INSTANCE_WIDTH (ii) != width
1984       ||
1985       IMAGE_INSTANCE_HEIGHT (ii) != height)
1986     {
1987       IMAGE_INSTANCE_SIZE_CHANGED (ii) = 1;
1988     }
1989
1990   IMAGE_INSTANCE_WIDTH (ii) = width;
1991   IMAGE_INSTANCE_HEIGHT (ii) = height;
1992
1993   if (IIFORMAT_METH_OR_GIVEN (meths, layout, 
1994                               (image_instance, width, height, domain), 1))
1995     /* Do not clear the dirty flag here - redisplay will do this for
1996        us at the end. */
1997     IMAGE_INSTANCE_LAYOUT_CHANGED (ii) = 0;
1998 }
1999
2000 /*
2001  * Mark image instance in W as dirty if (a) W's faces have changed and
2002  * (b) GLYPH_OR_II instance in W is a string.
2003  *
2004  * Return non-zero if instance has been marked dirty.
2005  */
2006 int
2007 invalidate_glyph_geometry_maybe (Lisp_Object glyph_or_ii, struct window* w)
2008 {
2009   if (XFRAME(WINDOW_FRAME(w))->faces_changed)
2010     {
2011       Lisp_Object image = glyph_or_ii;
2012
2013       if (GLYPHP (glyph_or_ii))
2014         {
2015           Lisp_Object window;
2016           XSETWINDOW (window, w);
2017           image = glyph_image_instance (glyph_or_ii, window, ERROR_ME_NOT, 1);
2018         }
2019
2020       if (TEXT_IMAGE_INSTANCEP (image))
2021         {
2022           Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image);
2023           IMAGE_INSTANCE_DIRTYP (ii) = 1;
2024           IMAGE_INSTANCE_LAYOUT_CHANGED (ii) = 1;
2025           if (GLYPHP (glyph_or_ii))
2026             XGLYPH_DIRTYP (glyph_or_ii) = 1;
2027           return 1;
2028         }
2029     }
2030
2031   return 0;
2032 }
2033
2034 \f
2035 /************************************************************************/
2036 /*                              error helpers                           */
2037 /************************************************************************/
2038 DOESNT_RETURN
2039 signal_image_error (const char *reason, Lisp_Object frob)
2040 {
2041   signal_error (Qimage_conversion_error,
2042                 list2 (build_translated_string (reason), frob));
2043 }
2044
2045 DOESNT_RETURN
2046 signal_image_error_2 (const char *reason, Lisp_Object frob0, Lisp_Object frob1)
2047 {
2048   signal_error (Qimage_conversion_error,
2049                 list3 (build_translated_string (reason), frob0, frob1));
2050 }
2051
2052 /****************************************************************************
2053  *                                  nothing                                 *
2054  ****************************************************************************/
2055
2056 static int
2057 nothing_possible_dest_types (void)
2058 {
2059   return IMAGE_NOTHING_MASK;
2060 }
2061
2062 static void
2063 nothing_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2064                      Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2065                      int dest_mask, Lisp_Object domain)
2066 {
2067   Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2068
2069   if (dest_mask & IMAGE_NOTHING_MASK)
2070     {
2071       IMAGE_INSTANCE_TYPE (ii) = IMAGE_NOTHING;
2072       IMAGE_INSTANCE_HEIGHT (ii) = 0;
2073       IMAGE_INSTANCE_WIDTH (ii) = 0;
2074     }
2075   else
2076     incompatible_image_types (instantiator, dest_mask, IMAGE_NOTHING_MASK);
2077 }
2078
2079 \f
2080 /****************************************************************************
2081  *                                  inherit                                 *
2082  ****************************************************************************/
2083
2084 static void
2085 inherit_validate (Lisp_Object instantiator)
2086 {
2087   face_must_be_present (instantiator);
2088 }
2089
2090 static Lisp_Object
2091 inherit_normalize (Lisp_Object inst, Lisp_Object console_type)
2092 {
2093   Lisp_Object face;
2094
2095   assert (XVECTOR_LENGTH (inst) == 3);
2096   face = XVECTOR_DATA (inst)[2];
2097   if (!FACEP (face))
2098     inst = vector3 (Qinherit, Q_face, Fget_face (face));
2099   return inst;
2100 }
2101
2102 static int
2103 inherit_possible_dest_types (void)
2104 {
2105   return IMAGE_MONO_PIXMAP_MASK;
2106 }
2107
2108 static void
2109 inherit_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2110                      Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2111                      int dest_mask, Lisp_Object domain)
2112 {
2113   /* handled specially in image_instantiate */
2114   abort ();
2115 }
2116
2117 \f
2118 /****************************************************************************
2119  *                                  string                                  *
2120  ****************************************************************************/
2121
2122 static void
2123 string_validate (Lisp_Object instantiator)
2124 {
2125   data_must_be_present (instantiator);
2126 }
2127
2128 static int
2129 string_possible_dest_types (void)
2130 {
2131   return IMAGE_TEXT_MASK;
2132 }
2133
2134 /* Called from autodetect_instantiate() */
2135 void
2136 string_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2137                     Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2138                     int dest_mask, Lisp_Object domain)
2139 {
2140   Lisp_Object string = find_keyword_in_vector (instantiator, Q_data);
2141   Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2142
2143   /* Should never get here with a domain other than a window. */
2144   assert (!NILP (string) && WINDOWP (DOMAIN_WINDOW (domain)));
2145   if (dest_mask & IMAGE_TEXT_MASK)
2146     {
2147       IMAGE_INSTANCE_TYPE (ii) = IMAGE_TEXT;
2148       IMAGE_INSTANCE_TEXT_STRING (ii) = string;
2149     }
2150   else
2151     incompatible_image_types (instantiator, dest_mask, IMAGE_TEXT_MASK);
2152 }
2153
2154 /* Sort out the size of the text that is being displayed. Calculating
2155    it dynamically allows us to change the text and still see
2156    everything. Note that the following methods are for text not string
2157    since that is what the instantiated type is. The first method is a
2158    helper that is used elsewhere for calculating text geometry. */
2159 void
2160 query_string_geometry (Lisp_Object string, Lisp_Object face,
2161                        int* width, int* height, int* descent, Lisp_Object domain)
2162 {
2163   struct font_metric_info fm;
2164   unsigned char charsets[NUM_LEADING_BYTES];
2165   struct face_cachel frame_cachel;
2166   struct face_cachel *cachel;
2167   Lisp_Object frame = DOMAIN_FRAME (domain);
2168
2169   /* Compute height */
2170   if (height)
2171     {
2172       /* Compute string metric info */
2173       find_charsets_in_bufbyte_string (charsets,
2174                                        XSTRING_DATA   (string),
2175                                        XSTRING_LENGTH (string));
2176
2177       /* Fallback to the default face if none was provided. */
2178       if (!NILP (face))
2179         {
2180           reset_face_cachel (&frame_cachel);
2181           update_face_cachel_data (&frame_cachel, frame, face);
2182           cachel = &frame_cachel;
2183         }
2184       else
2185         {
2186           cachel = WINDOW_FACE_CACHEL (DOMAIN_XWINDOW (domain),
2187                                        DEFAULT_INDEX);
2188         }
2189
2190       ensure_face_cachel_complete (cachel, domain, charsets);
2191       face_cachel_charset_font_metric_info (cachel, charsets, &fm);
2192
2193       *height = fm.ascent + fm.descent;
2194       /* #### descent only gets set if we query the height as well. */
2195       if (descent)
2196         *descent = fm.descent;
2197     }
2198
2199   /* Compute width */
2200   if (width)
2201     {
2202       if (!NILP (face))
2203         *width = redisplay_frame_text_width_string (XFRAME (frame),
2204                                                     face,
2205                                                     0, string, 0, -1);
2206       else
2207         *width = redisplay_frame_text_width_string (XFRAME (frame),
2208                                                     Vdefault_face,
2209                                                     0, string, 0, -1);
2210     }
2211 }
2212
2213 Lisp_Object
2214 query_string_font (Lisp_Object string, Lisp_Object face, Lisp_Object domain)
2215 {
2216   unsigned char charsets[NUM_LEADING_BYTES];
2217   struct face_cachel frame_cachel;
2218   struct face_cachel *cachel;
2219   int i;
2220   Lisp_Object frame = DOMAIN_FRAME (domain);
2221
2222   /* Compute string font info */
2223   find_charsets_in_bufbyte_string (charsets,
2224                                    XSTRING_DATA   (string),
2225                                    XSTRING_LENGTH (string));
2226
2227   reset_face_cachel (&frame_cachel);
2228   update_face_cachel_data (&frame_cachel, frame, face);
2229   cachel = &frame_cachel;
2230
2231   ensure_face_cachel_complete (cachel, domain, charsets);
2232
2233   for (i = 0; i < NUM_LEADING_BYTES; i++)
2234     {
2235       if (charsets[i])
2236         {
2237           return FACE_CACHEL_FONT (cachel,
2238                                    CHARSET_BY_LEADING_BYTE (i +
2239                                                             MIN_LEADING_BYTE));
2240
2241         }
2242     }
2243
2244   return Qnil;                  /* NOT REACHED */
2245 }
2246
2247 static void
2248 text_query_geometry (Lisp_Object image_instance,
2249                      int* width, int* height,
2250                      enum image_instance_geometry disp, Lisp_Object domain)
2251 {
2252   Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2253   int descent = 0;
2254
2255   query_string_geometry (IMAGE_INSTANCE_TEXT_STRING (ii),
2256                          IMAGE_INSTANCE_FACE (ii),
2257                          width, height, &descent, domain);
2258
2259   /* The descent gets set as a side effect of querying the
2260      geometry. */
2261   IMAGE_INSTANCE_TEXT_DESCENT (ii) = descent;
2262 }
2263
2264 /* set the properties of a string */
2265 static Lisp_Object
2266 text_set_property (Lisp_Object image_instance, Lisp_Object prop,
2267                    Lisp_Object val)
2268 {
2269   Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2270
2271   if (EQ (prop, Q_data))
2272     {
2273       CHECK_STRING (val);
2274       IMAGE_INSTANCE_TEXT_STRING (ii) = val;
2275
2276       return Qt;
2277     }
2278   return Qunbound;
2279 }
2280
2281 \f
2282 /****************************************************************************
2283  *                             formatted-string                             *
2284  ****************************************************************************/
2285
2286 static void
2287 formatted_string_validate (Lisp_Object instantiator)
2288 {
2289   data_must_be_present (instantiator);
2290 }
2291
2292 static int
2293 formatted_string_possible_dest_types (void)
2294 {
2295   return IMAGE_TEXT_MASK;
2296 }
2297
2298 static void
2299 formatted_string_instantiate (Lisp_Object image_instance,
2300                               Lisp_Object instantiator,
2301                               Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2302                               int dest_mask, Lisp_Object domain)
2303 {
2304   /* #### implement this */
2305   warn_when_safe (Qunimplemented, Qnotice,
2306                   "`formatted-string' not yet implemented; assuming `string'");
2307
2308   string_instantiate (image_instance, instantiator,
2309                       pointer_fg, pointer_bg, dest_mask, domain);
2310 }
2311
2312 \f
2313 /************************************************************************/
2314 /*                        pixmap file functions                         */
2315 /************************************************************************/
2316
2317 /* If INSTANTIATOR refers to inline data, return Qnil.
2318    If INSTANTIATOR refers to data in a file, return the full filename
2319    if it exists; otherwise, return a cons of (filename).
2320
2321    FILE_KEYWORD and DATA_KEYWORD are symbols specifying the
2322    keywords used to look up the file and inline data,
2323    respectively, in the instantiator.  Normally these would
2324    be Q_file and Q_data, but might be different for mask data. */
2325
2326 Lisp_Object
2327 potential_pixmap_file_instantiator (Lisp_Object instantiator,
2328                                     Lisp_Object file_keyword,
2329                                     Lisp_Object data_keyword,
2330                                     Lisp_Object console_type)
2331 {
2332   Lisp_Object file;
2333   Lisp_Object data;
2334
2335   assert (VECTORP (instantiator));
2336
2337   data = find_keyword_in_vector (instantiator, data_keyword);
2338   file = find_keyword_in_vector (instantiator, file_keyword);
2339
2340   if (!NILP (file) && NILP (data))
2341     {
2342       Lisp_Object retval = MAYBE_LISP_CONTYPE_METH
2343         (decode_console_type(console_type, ERROR_ME),
2344          locate_pixmap_file, (file));
2345
2346       if (!NILP (retval))
2347         return retval;
2348       else
2349         return Fcons (file, Qnil); /* should have been file */
2350     }
2351
2352   return Qnil;
2353 }
2354
2355 Lisp_Object
2356 simple_image_type_normalize (Lisp_Object inst, Lisp_Object console_type,
2357                              Lisp_Object image_type_tag)
2358 {
2359   /* This function can call lisp */
2360   Lisp_Object file = Qnil;
2361   struct gcpro gcpro1, gcpro2;
2362   Lisp_Object alist = Qnil;
2363
2364   GCPRO2 (file, alist);
2365
2366   /* Now, convert any file data into inline data.  At the end of this,
2367      `data' will contain the inline data (if any) or Qnil, and `file'
2368      will contain the name this data was derived from (if known) or
2369      Qnil.
2370
2371      Note that if we cannot generate any regular inline data, we
2372      skip out. */
2373
2374   file = potential_pixmap_file_instantiator (inst, Q_file, Q_data,
2375                                              console_type);
2376
2377   if (CONSP (file)) /* failure locating filename */
2378     signal_double_file_error ("Opening pixmap file",
2379                               "no such file or directory",
2380                               Fcar (file));
2381
2382   if (NILP (file)) /* no conversion necessary */
2383     RETURN_UNGCPRO (inst);
2384
2385   alist = tagged_vector_to_alist (inst);
2386
2387   {
2388     Lisp_Object data = make_string_from_file (file);
2389     alist = remassq_no_quit (Q_file, alist);
2390     /* there can't be a :data at this point. */
2391     alist = Fcons (Fcons (Q_file, file),
2392                    Fcons (Fcons (Q_data, data), alist));
2393   }
2394
2395   {
2396     Lisp_Object result = alist_to_tagged_vector (image_type_tag, alist);
2397     free_alist (alist);
2398     RETURN_UNGCPRO (result);
2399   }
2400 }
2401
2402 \f
2403 #ifdef HAVE_WINDOW_SYSTEM
2404 /**********************************************************************
2405  *                             XBM                                    *
2406  **********************************************************************/
2407
2408 /* Check if DATA represents a valid inline XBM spec (i.e. a list
2409    of (width height bits), with checking done on the dimensions).
2410    If not, signal an error. */
2411
2412 static void
2413 check_valid_xbm_inline (Lisp_Object data)
2414 {
2415   Lisp_Object width, height, bits;
2416
2417   if (!CONSP (data) ||
2418       !CONSP (XCDR (data)) ||
2419       !CONSP (XCDR (XCDR (data))) ||
2420       !NILP (XCDR (XCDR (XCDR (data)))))
2421     signal_simple_error ("Must be list of 3 elements", data);
2422
2423   width  = XCAR (data);
2424   height = XCAR (XCDR (data));
2425   bits   = XCAR (XCDR (XCDR (data)));
2426
2427   CHECK_STRING (bits);
2428
2429   if (!NATNUMP (width))
2430     signal_simple_error ("Width must be a natural number", width);
2431
2432   if (!NATNUMP (height))
2433     signal_simple_error ("Height must be a natural number", height);
2434
2435   if (((XINT (width) * XINT (height)) / 8) > XSTRING_CHAR_LENGTH (bits))
2436     signal_simple_error ("data is too short for width and height",
2437                          vector3 (width, height, bits));
2438 }
2439
2440 /* Validate method for XBM's. */
2441
2442 static void
2443 xbm_validate (Lisp_Object instantiator)
2444 {
2445   file_or_data_must_be_present (instantiator);
2446 }
2447
2448 /* Given a filename that is supposed to contain XBM data, return
2449    the inline representation of it as (width height bits).  Return
2450    the hotspot through XHOT and YHOT, if those pointers are not 0.
2451    If there is no hotspot, XHOT and YHOT will contain -1.
2452
2453    If the function fails:
2454
2455    -- if OK_IF_DATA_INVALID is set and the data was invalid,
2456       return Qt.
2457    -- maybe return an error, or return Qnil.
2458  */
2459
2460 #ifdef HAVE_X_WINDOWS
2461 #include <X11/Xlib.h>
2462 #else
2463 #define XFree(data) free(data)
2464 #endif
2465
2466 Lisp_Object
2467 bitmap_to_lisp_data (Lisp_Object name, int *xhot, int *yhot,
2468                      int ok_if_data_invalid)
2469 {
2470   unsigned int w, h;
2471   Extbyte *data;
2472   int result;
2473   const char *filename_ext;
2474
2475   TO_EXTERNAL_FORMAT (LISP_STRING, name,
2476                       C_STRING_ALLOCA, filename_ext,
2477                       Qfile_name);
2478   result = read_bitmap_data_from_file (filename_ext, &w, &h,
2479                                        &data, xhot, yhot);
2480
2481   if (result == BitmapSuccess)
2482     {
2483       Lisp_Object retval;
2484       int len = (w + 7) / 8 * h;
2485
2486       retval = list3 (make_int (w), make_int (h),
2487                       make_ext_string (data, len, Qbinary));
2488       XFree ((char *) data);
2489       return retval;
2490     }
2491
2492   switch (result)
2493     {
2494     case BitmapOpenFailed:
2495       {
2496         /* should never happen */
2497         signal_double_file_error ("Opening bitmap file",
2498                                   "no such file or directory",
2499                                   name);
2500       }
2501     case BitmapFileInvalid:
2502       {
2503         if (ok_if_data_invalid)
2504           return Qt;
2505         signal_double_file_error ("Reading bitmap file",
2506                                   "invalid data in file",
2507                                   name);
2508       }
2509     case BitmapNoMemory:
2510       {
2511         signal_double_file_error ("Reading bitmap file",
2512                                   "out of memory",
2513                                   name);
2514       }
2515     default:
2516       {
2517         signal_double_file_error_2 ("Reading bitmap file",
2518                                     "unknown error code",
2519                                     make_int (result), name);
2520       }
2521     }
2522
2523   return Qnil; /* not reached */
2524 }
2525
2526 Lisp_Object
2527 xbm_mask_file_munging (Lisp_Object alist, Lisp_Object file,
2528                        Lisp_Object mask_file, Lisp_Object console_type)
2529 {
2530   /* This is unclean but it's fairly standard -- a number of the
2531      bitmaps in /usr/include/X11/bitmaps use it -- so we support
2532      it. */
2533   if (NILP (mask_file)
2534       /* don't override explicitly specified mask data. */
2535       && NILP (assq_no_quit (Q_mask_data, alist))
2536       && !NILP (file))
2537     {
2538       mask_file = MAYBE_LISP_CONTYPE_METH
2539         (decode_console_type(console_type, ERROR_ME),
2540          locate_pixmap_file, (concat2 (file, build_string ("Mask"))));
2541       if (NILP (mask_file))
2542         mask_file = MAYBE_LISP_CONTYPE_METH
2543           (decode_console_type(console_type, ERROR_ME),
2544            locate_pixmap_file, (concat2 (file, build_string ("msk"))));
2545     }
2546
2547   if (!NILP (mask_file))
2548     {
2549       Lisp_Object mask_data =
2550         bitmap_to_lisp_data (mask_file, 0, 0, 0);
2551       alist = remassq_no_quit (Q_mask_file, alist);
2552       /* there can't be a :mask-data at this point. */
2553       alist = Fcons (Fcons (Q_mask_file, mask_file),
2554                      Fcons (Fcons (Q_mask_data, mask_data), alist));
2555     }
2556
2557   return alist;
2558 }
2559
2560 /* Normalize method for XBM's. */
2561
2562 static Lisp_Object
2563 xbm_normalize (Lisp_Object inst, Lisp_Object console_type)
2564 {
2565   Lisp_Object file = Qnil, mask_file = Qnil;
2566   struct gcpro gcpro1, gcpro2, gcpro3;
2567   Lisp_Object alist = Qnil;
2568
2569   GCPRO3 (file, mask_file, alist);
2570
2571   /* Now, convert any file data into inline data for both the regular
2572      data and the mask data.  At the end of this, `data' will contain
2573      the inline data (if any) or Qnil, and `file' will contain
2574      the name this data was derived from (if known) or Qnil.
2575      Likewise for `mask_file' and `mask_data'.
2576
2577      Note that if we cannot generate any regular inline data, we
2578      skip out. */
2579
2580   file = potential_pixmap_file_instantiator (inst, Q_file, Q_data,
2581                                              console_type);
2582   mask_file = potential_pixmap_file_instantiator (inst, Q_mask_file,
2583                                                   Q_mask_data, console_type);
2584
2585   if (CONSP (file)) /* failure locating filename */
2586     signal_double_file_error ("Opening bitmap file",
2587                               "no such file or directory",
2588                               Fcar (file));
2589
2590   if (NILP (file) && NILP (mask_file)) /* no conversion necessary */
2591     RETURN_UNGCPRO (inst);
2592
2593   alist = tagged_vector_to_alist (inst);
2594
2595   if (!NILP (file))
2596     {
2597       int xhot, yhot;
2598       Lisp_Object data = bitmap_to_lisp_data (file, &xhot, &yhot, 0);
2599       alist = remassq_no_quit (Q_file, alist);
2600       /* there can't be a :data at this point. */
2601       alist = Fcons (Fcons (Q_file, file),
2602                      Fcons (Fcons (Q_data, data), alist));
2603
2604       if (xhot != -1 && NILP (assq_no_quit (Q_hotspot_x, alist)))
2605         alist = Fcons (Fcons (Q_hotspot_x, make_int (xhot)),
2606                        alist);
2607       if (yhot != -1 && NILP (assq_no_quit (Q_hotspot_y, alist)))
2608         alist = Fcons (Fcons (Q_hotspot_y, make_int (yhot)),
2609                        alist);
2610     }
2611
2612   alist = xbm_mask_file_munging (alist, file, mask_file, console_type);
2613
2614   {
2615     Lisp_Object result = alist_to_tagged_vector (Qxbm, alist);
2616     free_alist (alist);
2617     RETURN_UNGCPRO (result);
2618   }
2619 }
2620
2621 \f
2622 static int
2623 xbm_possible_dest_types (void)
2624 {
2625   return
2626     IMAGE_MONO_PIXMAP_MASK  |
2627     IMAGE_COLOR_PIXMAP_MASK |
2628     IMAGE_POINTER_MASK;
2629 }
2630
2631 #endif
2632
2633 \f
2634 #ifdef HAVE_XFACE
2635 /**********************************************************************
2636  *                             X-Face                                 *
2637  **********************************************************************/
2638
2639 static void
2640 xface_validate (Lisp_Object instantiator)
2641 {
2642   file_or_data_must_be_present (instantiator);
2643 }
2644
2645 static Lisp_Object
2646 xface_normalize (Lisp_Object inst, Lisp_Object console_type)
2647 {
2648   /* This function can call lisp */
2649   Lisp_Object file = Qnil, mask_file = Qnil;
2650   struct gcpro gcpro1, gcpro2, gcpro3;
2651   Lisp_Object alist = Qnil;
2652
2653   GCPRO3 (file, mask_file, alist);
2654
2655   /* Now, convert any file data into inline data for both the regular
2656      data and the mask data.  At the end of this, `data' will contain
2657      the inline data (if any) or Qnil, and `file' will contain
2658      the name this data was derived from (if known) or Qnil.
2659      Likewise for `mask_file' and `mask_data'.
2660
2661      Note that if we cannot generate any regular inline data, we
2662      skip out. */
2663
2664   file = potential_pixmap_file_instantiator (inst, Q_file, Q_data,
2665                                              console_type);
2666   mask_file = potential_pixmap_file_instantiator (inst, Q_mask_file,
2667                                                   Q_mask_data, console_type);
2668
2669   if (CONSP (file)) /* failure locating filename */
2670     signal_double_file_error ("Opening bitmap file",
2671                               "no such file or directory",
2672                               Fcar (file));
2673
2674   if (NILP (file) && NILP (mask_file)) /* no conversion necessary */
2675     RETURN_UNGCPRO (inst);
2676
2677   alist = tagged_vector_to_alist (inst);
2678
2679   {
2680     Lisp_Object data = make_string_from_file (file);
2681     alist = remassq_no_quit (Q_file, alist);
2682     /* there can't be a :data at this point. */
2683     alist = Fcons (Fcons (Q_file, file),
2684                    Fcons (Fcons (Q_data, data), alist));
2685   }
2686
2687   alist = xbm_mask_file_munging (alist, file, mask_file, console_type);
2688
2689   {
2690     Lisp_Object result = alist_to_tagged_vector (Qxface, alist);
2691     free_alist (alist);
2692     RETURN_UNGCPRO (result);
2693   }
2694 }
2695
2696 static int
2697 xface_possible_dest_types (void)
2698 {
2699   return
2700     IMAGE_MONO_PIXMAP_MASK  |
2701     IMAGE_COLOR_PIXMAP_MASK |
2702     IMAGE_POINTER_MASK;
2703 }
2704
2705 #endif /* HAVE_XFACE */
2706
2707 \f
2708 #ifdef HAVE_XPM
2709
2710 /**********************************************************************
2711  *                             XPM                                    *
2712  **********************************************************************/
2713
2714 Lisp_Object
2715 pixmap_to_lisp_data (Lisp_Object name, int ok_if_data_invalid)
2716 {
2717   char **data;
2718   int result;
2719   char *fname = 0;
2720
2721   TO_EXTERNAL_FORMAT (LISP_STRING, name,
2722                       C_STRING_ALLOCA, fname,
2723                       Qfile_name);
2724   result = XpmReadFileToData (fname, &data);
2725
2726   if (result == XpmSuccess)
2727     {
2728       Lisp_Object retval = Qnil;
2729       struct buffer *old_buffer = current_buffer;
2730       Lisp_Object temp_buffer =
2731         Fget_buffer_create (build_string (" *pixmap conversion*"));
2732       int elt;
2733       int height, width, ncolors;
2734       struct gcpro gcpro1, gcpro2, gcpro3;
2735       int speccount = specpdl_depth ();
2736
2737       GCPRO3 (name, retval, temp_buffer);
2738
2739       specbind (Qinhibit_quit, Qt);
2740       set_buffer_internal (XBUFFER (temp_buffer));
2741       Ferase_buffer (Qnil);
2742
2743       buffer_insert_c_string (current_buffer, "/* XPM */\r");
2744       buffer_insert_c_string (current_buffer, "static char *pixmap[] = {\r");
2745
2746       sscanf (data[0], "%d %d %d", &height, &width, &ncolors);
2747       for (elt = 0; elt <= width + ncolors; elt++)
2748         {
2749           buffer_insert_c_string (current_buffer, "\"");
2750           buffer_insert_c_string (current_buffer, data[elt]);
2751
2752           if (elt < width + ncolors)
2753             buffer_insert_c_string (current_buffer, "\",\r");
2754           else
2755             buffer_insert_c_string (current_buffer, "\"};\r");
2756         }
2757
2758       retval = Fbuffer_substring (Qnil, Qnil, Qnil);
2759       XpmFree (data);
2760
2761       set_buffer_internal (old_buffer);
2762       unbind_to (speccount, Qnil);
2763
2764       RETURN_UNGCPRO (retval);
2765     }
2766
2767   switch (result)
2768     {
2769     case XpmFileInvalid:
2770       {
2771         if (ok_if_data_invalid)
2772           return Qt;
2773         signal_image_error ("invalid XPM data in file", name);
2774       }
2775     case XpmNoMemory:
2776       {
2777         signal_double_file_error ("Reading pixmap file",
2778                                   "out of memory", name);
2779       }
2780     case XpmOpenFailed:
2781       {
2782         /* should never happen? */
2783         signal_double_file_error ("Opening pixmap file",
2784                                   "no such file or directory", name);
2785       }
2786     default:
2787       {
2788         signal_double_file_error_2 ("Parsing pixmap file",
2789                                     "unknown error code",
2790                                     make_int (result), name);
2791         break;
2792       }
2793     }
2794
2795   return Qnil; /* not reached */
2796 }
2797
2798 static void
2799 check_valid_xpm_color_symbols (Lisp_Object data)
2800 {
2801   Lisp_Object rest;
2802
2803   for (rest = data; !NILP (rest); rest = XCDR (rest))
2804     {
2805       if (!CONSP (rest) ||
2806           !CONSP (XCAR (rest)) ||
2807           !STRINGP (XCAR (XCAR (rest))) ||
2808           (!STRINGP (XCDR (XCAR (rest))) &&
2809            !COLOR_SPECIFIERP (XCDR (XCAR (rest)))))
2810         signal_simple_error ("Invalid color symbol alist", data);
2811     }
2812 }
2813
2814 static void
2815 xpm_validate (Lisp_Object instantiator)
2816 {
2817   file_or_data_must_be_present (instantiator);
2818 }
2819
2820 Lisp_Object Vxpm_color_symbols;
2821
2822 Lisp_Object
2823 evaluate_xpm_color_symbols (void)
2824 {
2825   Lisp_Object rest, results = Qnil;
2826   struct gcpro gcpro1, gcpro2;
2827
2828   GCPRO2 (rest, results);
2829   for (rest = Vxpm_color_symbols; !NILP (rest); rest = XCDR (rest))
2830     {
2831       Lisp_Object name, value, cons;
2832
2833       CHECK_CONS (rest);
2834       cons = XCAR (rest);
2835       CHECK_CONS (cons);
2836       name = XCAR (cons);
2837       CHECK_STRING (name);
2838       value = XCDR (cons);
2839       CHECK_CONS (value);
2840       value = XCAR (value);
2841       value = Feval (value);
2842       if (NILP (value))
2843         continue;
2844       if (!STRINGP (value) && !COLOR_SPECIFIERP (value))
2845         signal_simple_error
2846           ("Result from xpm-color-symbols eval must be nil, string, or color",
2847            value);
2848       results = Fcons (Fcons (name, value), results);
2849     }
2850   UNGCPRO;                      /* no more evaluation */
2851   return results;
2852 }
2853
2854 static Lisp_Object
2855 xpm_normalize (Lisp_Object inst, Lisp_Object console_type)
2856 {
2857   Lisp_Object file = Qnil;
2858   Lisp_Object color_symbols;
2859   struct gcpro gcpro1, gcpro2;
2860   Lisp_Object alist = Qnil;
2861
2862   GCPRO2 (file, alist);
2863
2864   /* Now, convert any file data into inline data.  At the end of this,
2865      `data' will contain the inline data (if any) or Qnil, and
2866      `file' will contain the name this data was derived from (if
2867      known) or Qnil.
2868
2869      Note that if we cannot generate any regular inline data, we
2870      skip out. */
2871
2872   file = potential_pixmap_file_instantiator (inst, Q_file, Q_data,
2873                                              console_type);
2874
2875   if (CONSP (file)) /* failure locating filename */
2876     signal_double_file_error ("Opening pixmap file",
2877                               "no such file or directory",
2878                               Fcar (file));
2879
2880   color_symbols = find_keyword_in_vector_or_given (inst, Q_color_symbols,
2881                                                    Qunbound);
2882
2883   if (NILP (file) && !UNBOUNDP (color_symbols))
2884     /* no conversion necessary */
2885     RETURN_UNGCPRO (inst);
2886
2887   alist = tagged_vector_to_alist (inst);
2888
2889   if (!NILP (file))
2890     {
2891       Lisp_Object data = pixmap_to_lisp_data (file, 0);
2892       alist = remassq_no_quit (Q_file, alist);
2893       /* there can't be a :data at this point. */
2894       alist = Fcons (Fcons (Q_file, file),
2895                      Fcons (Fcons (Q_data, data), alist));
2896     }
2897
2898   if (UNBOUNDP (color_symbols))
2899     {
2900       color_symbols = evaluate_xpm_color_symbols ();
2901       alist = Fcons (Fcons (Q_color_symbols, color_symbols),
2902                      alist);
2903     }
2904
2905   {
2906     Lisp_Object result = alist_to_tagged_vector (Qxpm, alist);
2907     free_alist (alist);
2908     RETURN_UNGCPRO (result);
2909   }
2910 }
2911
2912 static int
2913 xpm_possible_dest_types (void)
2914 {
2915   return
2916     IMAGE_MONO_PIXMAP_MASK  |
2917     IMAGE_COLOR_PIXMAP_MASK |
2918     IMAGE_POINTER_MASK;
2919 }
2920
2921 #endif /* HAVE_XPM */
2922
2923 \f
2924 /****************************************************************************
2925  *                         Image Specifier Object                           *
2926  ****************************************************************************/
2927
2928 DEFINE_SPECIFIER_TYPE (image);
2929
2930 static void
2931 image_create (Lisp_Object obj)
2932 {
2933   Lisp_Specifier *image = XIMAGE_SPECIFIER (obj);
2934
2935   IMAGE_SPECIFIER_ALLOWED (image) = ~0; /* all are allowed */
2936   IMAGE_SPECIFIER_ATTACHEE (image) = Qnil;
2937   IMAGE_SPECIFIER_ATTACHEE_PROPERTY (image) = Qnil;
2938 }
2939
2940 static void
2941 image_mark (Lisp_Object obj)
2942 {
2943   Lisp_Specifier *image = XIMAGE_SPECIFIER (obj);
2944
2945   mark_object (IMAGE_SPECIFIER_ATTACHEE (image));
2946   mark_object (IMAGE_SPECIFIER_ATTACHEE_PROPERTY (image));
2947 }
2948
2949 static Lisp_Object
2950 image_instantiate_cache_result (Lisp_Object locative)
2951 {
2952   /* locative = (instance instantiator . subtable)
2953
2954      So we are using the instantiator as the key and the instance as
2955      the value. Since the hashtable is key-weak this means that the
2956      image instance will stay around as long as the instantiator stays
2957      around. The instantiator is stored in the `image' slot of the
2958      glyph, so as long as the glyph is marked the instantiator will be
2959      as well and hence the cached image instance also.*/
2960   Fputhash (XCAR (XCDR (locative)), XCAR (locative), XCDR (XCDR (locative)));
2961   free_cons (XCONS (XCDR (locative)));
2962   free_cons (XCONS (locative));
2963   return Qnil;
2964 }
2965
2966 /* Given a specification for an image, return an instance of
2967    the image which matches the given instantiator and which can be
2968    displayed in the given domain. */
2969
2970 static Lisp_Object
2971 image_instantiate (Lisp_Object specifier, Lisp_Object matchspec,
2972                    Lisp_Object domain, Lisp_Object instantiator,
2973                    Lisp_Object depth)
2974 {
2975   Lisp_Object glyph = IMAGE_SPECIFIER_ATTACHEE (XIMAGE_SPECIFIER (specifier));
2976   int dest_mask = XIMAGE_SPECIFIER_ALLOWED (specifier);
2977   int pointerp = dest_mask & image_instance_type_to_mask (IMAGE_POINTER);
2978
2979   if (IMAGE_INSTANCEP (instantiator))
2980     {
2981       /* make sure that the image instance's governing domain and type are
2982          matching. */
2983       Lisp_Object governing_domain = XIMAGE_INSTANCE_DOMAIN (instantiator);
2984
2985       if ((DEVICEP (governing_domain)
2986            && EQ (governing_domain, DOMAIN_DEVICE (domain)))
2987           || (FRAMEP (governing_domain)
2988               && EQ (governing_domain, DOMAIN_FRAME (domain)))
2989           || (WINDOWP (governing_domain)
2990               && EQ (governing_domain, DOMAIN_WINDOW (domain))))
2991         {
2992           int mask =
2993             image_instance_type_to_mask (XIMAGE_INSTANCE_TYPE (instantiator));
2994           if (mask & dest_mask)
2995             return instantiator;
2996           else
2997             signal_simple_error ("Type of image instance not allowed here",
2998                                  instantiator);
2999         }
3000       else
3001         signal_simple_error_2 ("Wrong domain for image instance",
3002                                instantiator, domain);
3003     }
3004   else if (VECTORP (instantiator)
3005            && EQ (XVECTOR_DATA (instantiator)[0], Qinherit))
3006     {
3007       assert (XVECTOR_LENGTH (instantiator) == 3);
3008       return (FACE_PROPERTY_INSTANCE
3009               (Fget_face (XVECTOR_DATA (instantiator)[2]),
3010                Qbackground_pixmap, domain, 0, depth));
3011     }
3012   else
3013     {
3014       Lisp_Object instance = Qnil;
3015       Lisp_Object subtable = Qnil;
3016       Lisp_Object ls3 = Qnil;
3017       Lisp_Object pointer_fg = Qnil;
3018       Lisp_Object pointer_bg = Qnil;
3019       Lisp_Object governing_domain =
3020         get_image_instantiator_governing_domain (instantiator, domain);
3021       struct gcpro gcpro1;
3022       
3023       GCPRO1 (instance);
3024
3025       /* We have to put subwindow, widget and text image instances in
3026          a per-window cache so that we can see the same glyph in
3027          different windows. We use governing_domain to determine the type
3028          of image_instance that will be created. */
3029
3030       if (pointerp)
3031         {
3032           pointer_fg = FACE_FOREGROUND (Vpointer_face, domain);
3033           pointer_bg = FACE_BACKGROUND (Vpointer_face, domain);
3034           ls3 = list3 (instantiator, pointer_fg, pointer_bg);
3035         }
3036
3037       /* First look in the device cache. */
3038       if (DEVICEP (governing_domain))
3039         {
3040           subtable = Fgethash (make_int (dest_mask), 
3041                                XDEVICE (governing_domain)->
3042                                image_instance_cache,
3043                                Qunbound);
3044           if (UNBOUNDP (subtable))
3045             {
3046               /* For the image instance cache, we do comparisons with
3047                  EQ rather than with EQUAL, as we do for color and
3048                  font names.  The reasons are:
3049                  
3050                  1) pixmap data can be very long, and thus the hashing
3051                  and comparing will take awhile.
3052
3053                  2) It's not so likely that we'll run into things that
3054                  are EQUAL but not EQ (that can happen a lot with
3055                  faces, because their specifiers are copied around);
3056                  but pixmaps tend not to be in faces.
3057                  
3058                  However, if the image-instance could be a pointer, we
3059                  have to use EQUAL because we massaged the
3060                  instantiator into a cons3 also containing the
3061                  foreground and background of the pointer face.  */
3062
3063               subtable = make_lisp_hash_table 
3064                 (20, pointerp ? HASH_TABLE_KEY_CAR_WEAK
3065                  : HASH_TABLE_KEY_WEAK,
3066                  pointerp ? HASH_TABLE_EQUAL
3067                  : HASH_TABLE_EQ);
3068               Fputhash (make_int (dest_mask), subtable,
3069                         XDEVICE (governing_domain)->image_instance_cache);
3070               instance = Qunbound;
3071             }
3072           else
3073             {
3074               instance = Fgethash (pointerp ? ls3 : instantiator,
3075                                    subtable, Qunbound);
3076             }
3077         }
3078       else if (WINDOWP (governing_domain))
3079         {
3080           /* Subwindows have a per-window cache and have to be treated
3081              differently. */
3082           instance =
3083             Fgethash (instantiator,
3084                       XWINDOW (governing_domain)->subwindow_instance_cache,
3085                       Qunbound);
3086         }
3087       else
3088         abort ();       /* We're not allowed anything else currently. */
3089
3090       /* If we don't have an instance at this point then create
3091          one. */
3092       if (UNBOUNDP (instance))
3093         {
3094           Lisp_Object locative =
3095             noseeum_cons (Qnil,
3096                           noseeum_cons (pointerp ? ls3 : instantiator,
3097                                         DEVICEP (governing_domain) ? subtable 
3098                                         : XWINDOW (governing_domain)
3099                                         ->subwindow_instance_cache));
3100           int speccount = specpdl_depth ();
3101
3102           /* Make sure we cache the failures, too.  Use an
3103              unwind-protect to catch such errors.  If we fail, the
3104              unwind-protect records nil in the hash table.  If we
3105              succeed, we change the car of the locative to the
3106              resulting instance, which gets recorded instead. */
3107           record_unwind_protect (image_instantiate_cache_result,
3108                                  locative);
3109           instance = 
3110             instantiate_image_instantiator (governing_domain,
3111                                             domain, instantiator,
3112                                             pointer_fg, pointer_bg,
3113                                             dest_mask, glyph);
3114
3115           /* We need a per-frame cache for redisplay. */
3116           cache_subwindow_instance_in_frame_maybe (instance);
3117
3118           Fsetcar (locative, instance);
3119 #ifdef ERROR_CHECK_GLYPHS
3120           if (image_instance_type_to_mask (XIMAGE_INSTANCE_TYPE (instance))
3121               & (IMAGE_SUBWINDOW_MASK | IMAGE_WIDGET_MASK))
3122               assert (EQ (XIMAGE_INSTANCE_FRAME (instance),
3123                           DOMAIN_FRAME (domain)));
3124 #endif
3125           unbind_to (speccount, Qnil);
3126 #ifdef ERROR_CHECK_GLYPHS
3127           if (image_instance_type_to_mask (XIMAGE_INSTANCE_TYPE (instance))
3128               & (IMAGE_SUBWINDOW_MASK | IMAGE_WIDGET_MASK))
3129             assert (EQ (Fgethash ((pointerp ? ls3 : instantiator),
3130                                   XWINDOW (governing_domain)
3131                                   ->subwindow_instance_cache,
3132                                   Qunbound), instance));
3133 #endif
3134         }
3135       else
3136         free_list (ls3);
3137
3138       if (NILP (instance))
3139         signal_simple_error ("Can't instantiate image (probably cached)",
3140                              instantiator);
3141 #ifdef ERROR_CHECK_GLYPHS
3142       if (image_instance_type_to_mask (XIMAGE_INSTANCE_TYPE (instance))
3143           & (IMAGE_SUBWINDOW_MASK | IMAGE_WIDGET_MASK))
3144         assert (EQ (XIMAGE_INSTANCE_FRAME (instance),
3145                     DOMAIN_FRAME (domain)));
3146 #endif
3147       ERROR_CHECK_IMAGE_INSTANCE (instance);
3148       RETURN_UNGCPRO (instance);
3149     }
3150
3151   abort ();
3152   return Qnil; /* not reached */
3153 }
3154
3155 /* Validate an image instantiator. */
3156
3157 static void
3158 image_validate (Lisp_Object instantiator)
3159 {
3160   if (IMAGE_INSTANCEP (instantiator) || STRINGP (instantiator))
3161     return;
3162   else if (VECTORP (instantiator))
3163     {
3164       Lisp_Object *elt = XVECTOR_DATA (instantiator);
3165       int instantiator_len = XVECTOR_LENGTH (instantiator);
3166       struct image_instantiator_methods *meths;
3167       Lisp_Object already_seen = Qnil;
3168       struct gcpro gcpro1;
3169       int i;
3170
3171       if (instantiator_len < 1)
3172         signal_simple_error ("Vector length must be at least 1",
3173                              instantiator);
3174
3175       meths = decode_image_instantiator_format (elt[0], ERROR_ME);
3176       if (!(instantiator_len & 1))
3177         signal_simple_error
3178           ("Must have alternating keyword/value pairs", instantiator);
3179
3180       GCPRO1 (already_seen);
3181
3182       for (i = 1; i < instantiator_len; i += 2)
3183         {
3184           Lisp_Object keyword = elt[i];
3185           Lisp_Object value = elt[i+1];
3186           int j;
3187
3188           CHECK_SYMBOL (keyword);
3189           if (!SYMBOL_IS_KEYWORD (keyword))
3190             signal_simple_error ("Symbol must begin with a colon", keyword);
3191
3192           for (j = 0; j < Dynarr_length (meths->keywords); j++)
3193             if (EQ (keyword, Dynarr_at (meths->keywords, j).keyword))
3194               break;
3195
3196           if (j == Dynarr_length (meths->keywords))
3197             signal_simple_error ("Unrecognized keyword", keyword);
3198
3199           if (!Dynarr_at (meths->keywords, j).multiple_p)
3200             {
3201               if (!NILP (memq_no_quit (keyword, already_seen)))
3202                 signal_simple_error
3203                   ("Keyword may not appear more than once", keyword);
3204               already_seen = Fcons (keyword, already_seen);
3205             }
3206
3207           (Dynarr_at (meths->keywords, j).validate) (value);
3208         }
3209
3210       UNGCPRO;
3211
3212       MAYBE_IIFORMAT_METH (meths, validate, (instantiator));
3213     }
3214   else
3215     signal_simple_error ("Must be string or vector", instantiator);
3216 }
3217
3218 static void
3219 image_after_change (Lisp_Object specifier, Lisp_Object locale)
3220 {
3221   Lisp_Object attachee =
3222     IMAGE_SPECIFIER_ATTACHEE (XIMAGE_SPECIFIER (specifier));
3223   Lisp_Object property =
3224     IMAGE_SPECIFIER_ATTACHEE_PROPERTY (XIMAGE_SPECIFIER (specifier));
3225   if (FACEP (attachee))
3226     face_property_was_changed (attachee, property, locale);
3227   else if (GLYPHP (attachee))
3228     glyph_property_was_changed (attachee, property, locale);
3229 }
3230
3231 void
3232 set_image_attached_to (Lisp_Object obj, Lisp_Object face_or_glyph,
3233                        Lisp_Object property)
3234 {
3235   Lisp_Specifier *image = XIMAGE_SPECIFIER (obj);
3236
3237   IMAGE_SPECIFIER_ATTACHEE (image) = face_or_glyph;
3238   IMAGE_SPECIFIER_ATTACHEE_PROPERTY (image) = property;
3239 }
3240
3241 static Lisp_Object
3242 image_going_to_add (Lisp_Object specifier, Lisp_Object locale,
3243                     Lisp_Object tag_set, Lisp_Object instantiator)
3244 {
3245   Lisp_Object possible_console_types = Qnil;
3246   Lisp_Object rest;
3247   Lisp_Object retlist = Qnil;
3248   struct gcpro gcpro1, gcpro2;
3249
3250   LIST_LOOP (rest, Vconsole_type_list)
3251     {
3252       Lisp_Object contype = XCAR (rest);
3253       if (!NILP (memq_no_quit (contype, tag_set)))
3254         possible_console_types = Fcons (contype, possible_console_types);
3255     }
3256
3257   if (XINT (Flength (possible_console_types)) > 1)
3258     /* two conflicting console types specified */
3259     return Qnil;
3260
3261   if (NILP (possible_console_types))
3262     possible_console_types = Vconsole_type_list;
3263
3264   GCPRO2 (retlist, possible_console_types);
3265
3266   LIST_LOOP (rest, possible_console_types)
3267     {
3268       Lisp_Object contype = XCAR (rest);
3269       Lisp_Object newinst = call_with_suspended_errors
3270         ((lisp_fn_t) normalize_image_instantiator,
3271          Qnil, Qimage, ERROR_ME_NOT, 3, instantiator, contype,
3272          make_int (XIMAGE_SPECIFIER_ALLOWED (specifier)));
3273
3274       if (!NILP (newinst))
3275         {
3276           Lisp_Object newtag;
3277           if (NILP (memq_no_quit (contype, tag_set)))
3278             newtag = Fcons (contype, tag_set);
3279           else
3280             newtag = tag_set;
3281           retlist = Fcons (Fcons (newtag, newinst), retlist);
3282         }
3283     }
3284
3285   UNGCPRO;
3286
3287   return retlist;
3288 }
3289
3290 /* Copy an image instantiator. We can't use Fcopy_tree since widgets
3291    may contain circular references which would send Fcopy_tree into
3292    infloop death. */
3293 static Lisp_Object
3294 image_copy_vector_instantiator (Lisp_Object instantiator)
3295 {
3296   int i;
3297   struct image_instantiator_methods *meths;
3298   Lisp_Object *elt;
3299   int instantiator_len;
3300
3301   CHECK_VECTOR (instantiator);
3302
3303   instantiator = Fcopy_sequence (instantiator);
3304   elt = XVECTOR_DATA (instantiator);
3305   instantiator_len = XVECTOR_LENGTH (instantiator);
3306
3307   meths = decode_image_instantiator_format (elt[0], ERROR_ME);
3308
3309   for (i = 1; i < instantiator_len; i += 2)
3310     {
3311       int j;
3312       Lisp_Object keyword = elt[i];
3313       Lisp_Object value = elt[i+1];
3314
3315       /* Find the keyword entry. */
3316       for (j = 0; j < Dynarr_length (meths->keywords); j++)
3317         {
3318           if (EQ (keyword, Dynarr_at (meths->keywords, j).keyword))
3319             break;
3320         }
3321
3322       /* Only copy keyword values that should be copied. */
3323       if (Dynarr_at (meths->keywords, j).copy_p
3324           &&
3325           (CONSP (value) || VECTORP (value)))
3326         {
3327           elt [i+1] = Fcopy_tree (value, Qt);
3328         }
3329     }
3330
3331   return instantiator;
3332 }
3333
3334 static Lisp_Object
3335 image_copy_instantiator (Lisp_Object arg)
3336 {
3337   if (CONSP (arg))
3338     {
3339       Lisp_Object rest;
3340       rest = arg = Fcopy_sequence (arg);
3341       while (CONSP (rest))
3342         {
3343           Lisp_Object elt = XCAR (rest);
3344           if (CONSP (elt))
3345             XCAR (rest) = Fcopy_tree (elt, Qt);
3346           else if (VECTORP (elt))
3347             XCAR (rest) = image_copy_vector_instantiator (elt);
3348           if (VECTORP (XCDR (rest))) /* hack for (a b . [c d]) */
3349             XCDR (rest) = Fcopy_tree (XCDR (rest), Qt);
3350           rest = XCDR (rest);
3351         }
3352     }
3353   else if (VECTORP (arg))
3354     {
3355       arg = image_copy_vector_instantiator (arg);
3356     }
3357   return arg;
3358 }
3359
3360 DEFUN ("image-specifier-p", Fimage_specifier_p, 1, 1, 0, /*
3361 Return non-nil if OBJECT is an image specifier.
3362 See `make-image-specifier' for a description of image instantiators.
3363 */
3364        (object))
3365 {
3366   return IMAGE_SPECIFIERP (object) ? Qt : Qnil;
3367 }
3368
3369 \f
3370 /****************************************************************************
3371  *                             Glyph Object                                 *
3372  ****************************************************************************/
3373
3374 static Lisp_Object
3375 mark_glyph (Lisp_Object obj)
3376 {
3377   Lisp_Glyph *glyph = XGLYPH (obj);
3378
3379   mark_object (glyph->image);
3380   mark_object (glyph->contrib_p);
3381   mark_object (glyph->baseline);
3382   mark_object (glyph->face);
3383
3384   return glyph->plist;
3385 }
3386
3387 static void
3388 print_glyph (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
3389 {
3390   Lisp_Glyph *glyph = XGLYPH (obj);
3391   char buf[20];
3392
3393   if (print_readably)
3394     error ("printing unreadable object #<glyph 0x%x>", glyph->header.uid);
3395
3396   write_c_string ("#<glyph (", printcharfun);
3397   print_internal (Fglyph_type (obj), printcharfun, 0);
3398   write_c_string (") ", printcharfun);
3399   print_internal (glyph->image, printcharfun, 1);
3400   sprintf (buf, "0x%x>", glyph->header.uid);
3401   write_c_string (buf, printcharfun);
3402 }
3403
3404 /* Glyphs are equal if all of their display attributes are equal.  We
3405    don't compare names or doc-strings, because that would make equal
3406    be eq.
3407
3408    This isn't concerned with "unspecified" attributes, that's what
3409    #'glyph-differs-from-default-p is for. */
3410 static int
3411 glyph_equal (Lisp_Object obj1, Lisp_Object obj2, int depth)
3412 {
3413   Lisp_Glyph *g1 = XGLYPH (obj1);
3414   Lisp_Glyph *g2 = XGLYPH (obj2);
3415
3416   depth++;
3417
3418   return (internal_equal (g1->image,     g2->image,     depth) &&
3419           internal_equal (g1->contrib_p, g2->contrib_p, depth) &&
3420           internal_equal (g1->baseline,  g2->baseline,  depth) &&
3421           internal_equal (g1->face,      g2->face,      depth) &&
3422           !plists_differ (g1->plist,     g2->plist, 0, 0, depth + 1));
3423 }
3424
3425 static unsigned long
3426 glyph_hash (Lisp_Object obj, int depth)
3427 {
3428   depth++;
3429
3430   /* No need to hash all of the elements; that would take too long.
3431      Just hash the most common ones. */
3432   return HASH2 (internal_hash (XGLYPH (obj)->image, depth),
3433                 internal_hash (XGLYPH (obj)->face,  depth));
3434 }
3435
3436 static Lisp_Object
3437 glyph_getprop (Lisp_Object obj, Lisp_Object prop)
3438 {
3439   Lisp_Glyph *g = XGLYPH (obj);
3440
3441   if (EQ (prop, Qimage))     return g->image;
3442   if (EQ (prop, Qcontrib_p)) return g->contrib_p;
3443   if (EQ (prop, Qbaseline))  return g->baseline;
3444   if (EQ (prop, Qface))      return g->face;
3445
3446   return external_plist_get (&g->plist, prop, 0, ERROR_ME);
3447 }
3448
3449 static int
3450 glyph_putprop (Lisp_Object obj, Lisp_Object prop, Lisp_Object value)
3451 {
3452   if (EQ (prop, Qimage)     ||
3453       EQ (prop, Qcontrib_p) ||
3454       EQ (prop, Qbaseline))
3455     return 0;
3456
3457   if (EQ (prop, Qface))
3458     {
3459       XGLYPH (obj)->face = Fget_face (value);
3460       return 1;
3461     }
3462
3463   external_plist_put (&XGLYPH (obj)->plist, prop, value, 0, ERROR_ME);
3464   return 1;
3465 }
3466
3467 static int
3468 glyph_remprop (Lisp_Object obj, Lisp_Object prop)
3469 {
3470   if (EQ (prop, Qimage)     ||
3471       EQ (prop, Qcontrib_p) ||
3472       EQ (prop, Qbaseline))
3473     return -1;
3474
3475   if (EQ (prop, Qface))
3476     {
3477       XGLYPH (obj)->face = Qnil;
3478       return 1;
3479     }
3480
3481   return external_remprop (&XGLYPH (obj)->plist, prop, 0, ERROR_ME);
3482 }
3483
3484 static Lisp_Object
3485 glyph_plist (Lisp_Object obj)
3486 {
3487   Lisp_Glyph *glyph = XGLYPH (obj);
3488   Lisp_Object result = glyph->plist;
3489
3490   result = cons3 (Qface,      glyph->face,      result);
3491   result = cons3 (Qbaseline,  glyph->baseline,  result);
3492   result = cons3 (Qcontrib_p, glyph->contrib_p, result);
3493   result = cons3 (Qimage,     glyph->image,     result);
3494
3495   return result;
3496 }
3497
3498 static const struct lrecord_description glyph_description[] = {
3499   { XD_LISP_OBJECT, offsetof (Lisp_Glyph, image) },
3500   { XD_LISP_OBJECT, offsetof (Lisp_Glyph, contrib_p) },
3501   { XD_LISP_OBJECT, offsetof (Lisp_Glyph, baseline) },
3502   { XD_LISP_OBJECT, offsetof (Lisp_Glyph, face) },
3503   { XD_LISP_OBJECT, offsetof (Lisp_Glyph, plist) },
3504   { XD_END }
3505 };
3506
3507 DEFINE_LRECORD_IMPLEMENTATION_WITH_PROPS ("glyph", glyph,
3508                                           mark_glyph, print_glyph, 0,
3509                                           glyph_equal, glyph_hash, glyph_description,
3510                                           glyph_getprop, glyph_putprop,
3511                                           glyph_remprop, glyph_plist,
3512                                           Lisp_Glyph);
3513 \f
3514 Lisp_Object
3515 allocate_glyph (enum glyph_type type,
3516                 void (*after_change) (Lisp_Object glyph, Lisp_Object property,
3517                                       Lisp_Object locale))
3518 {
3519   /* This function can GC */
3520   Lisp_Object obj = Qnil;
3521   Lisp_Glyph *g = alloc_lcrecord_type (Lisp_Glyph, &lrecord_glyph);
3522
3523   g->type = type;
3524   g->image = Fmake_specifier (Qimage); /* This function can GC */
3525   g->dirty = 0;
3526   switch (g->type)
3527     {
3528     case GLYPH_BUFFER:
3529       XIMAGE_SPECIFIER_ALLOWED (g->image) =
3530         IMAGE_NOTHING_MASK | IMAGE_TEXT_MASK
3531         | IMAGE_MONO_PIXMAP_MASK | IMAGE_COLOR_PIXMAP_MASK
3532         | IMAGE_SUBWINDOW_MASK | IMAGE_WIDGET_MASK;
3533       break;
3534     case GLYPH_POINTER:
3535       XIMAGE_SPECIFIER_ALLOWED (g->image) =
3536         IMAGE_NOTHING_MASK | IMAGE_POINTER_MASK;
3537       break;
3538     case GLYPH_ICON:
3539       XIMAGE_SPECIFIER_ALLOWED (g->image) =
3540         IMAGE_NOTHING_MASK | IMAGE_MONO_PIXMAP_MASK
3541         | IMAGE_COLOR_PIXMAP_MASK;
3542       break;
3543     default:
3544       abort ();
3545     }
3546
3547   /* I think Fmake_specifier can GC.  I think set_specifier_fallback can GC. */
3548   /* We're getting enough reports of odd behavior in this area it seems */
3549   /* best to GCPRO everything. */
3550   {
3551     Lisp_Object tem1 = list1 (Fcons (Qnil, Vthe_nothing_vector));
3552     Lisp_Object tem2 = list1 (Fcons (Qnil, Qt));
3553     Lisp_Object tem3 = list1 (Fcons (Qnil, Qnil));
3554     struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
3555
3556     GCPRO4 (obj, tem1, tem2, tem3);
3557
3558     set_specifier_fallback (g->image, tem1);
3559     g->contrib_p = Fmake_specifier (Qboolean);
3560     set_specifier_fallback (g->contrib_p, tem2);
3561     /* #### should have a specifier for the following */
3562     g->baseline = Fmake_specifier (Qgeneric);
3563     set_specifier_fallback (g->baseline, tem3);
3564     g->face = Qnil;
3565     g->plist = Qnil;
3566     g->after_change = after_change;
3567     XSETGLYPH (obj, g);
3568
3569     set_image_attached_to (g->image, obj, Qimage);
3570     UNGCPRO;
3571   }
3572
3573   return obj;
3574 }
3575
3576 static enum glyph_type
3577 decode_glyph_type (Lisp_Object type, Error_behavior errb)
3578 {
3579   if (NILP (type))
3580     return GLYPH_BUFFER;
3581
3582   if (ERRB_EQ (errb, ERROR_ME))
3583     CHECK_SYMBOL (type);
3584
3585   if (EQ (type, Qbuffer))  return GLYPH_BUFFER;
3586   if (EQ (type, Qpointer)) return GLYPH_POINTER;
3587   if (EQ (type, Qicon))    return GLYPH_ICON;
3588
3589   maybe_signal_simple_error ("Invalid glyph type", type, Qimage, errb);
3590
3591   return GLYPH_UNKNOWN;
3592 }
3593
3594 static int
3595 valid_glyph_type_p (Lisp_Object type)
3596 {
3597   return !NILP (memq_no_quit (type, Vglyph_type_list));
3598 }
3599
3600 DEFUN ("valid-glyph-type-p", Fvalid_glyph_type_p, 1, 1, 0, /*
3601 Given a GLYPH-TYPE, return non-nil if it is valid.
3602 Valid types are `buffer', `pointer', and `icon'.
3603 */
3604        (glyph_type))
3605 {
3606   return valid_glyph_type_p (glyph_type) ? Qt : Qnil;
3607 }
3608
3609 DEFUN ("glyph-type-list", Fglyph_type_list, 0, 0, 0, /*
3610 Return a list of valid glyph types.
3611 */
3612        ())
3613 {
3614   return Fcopy_sequence (Vglyph_type_list);
3615 }
3616
3617 DEFUN ("make-glyph-internal", Fmake_glyph_internal, 0, 1, 0, /*
3618 Create and return a new uninitialized glyph or type TYPE.
3619
3620 TYPE specifies the type of the glyph; this should be one of `buffer',
3621 `pointer', or `icon', and defaults to `buffer'.  The type of the glyph
3622 specifies in which contexts the glyph can be used, and controls the
3623 allowable image types into which the glyph's image can be
3624 instantiated.
3625
3626 `buffer' glyphs can be used as the begin-glyph or end-glyph of an
3627 extent, in the modeline, and in the toolbar.  Their image can be
3628 instantiated as `nothing', `mono-pixmap', `color-pixmap', `text',
3629 and `subwindow'.
3630
3631 `pointer' glyphs can be used to specify the mouse pointer.  Their
3632 image can be instantiated as `pointer'.
3633
3634 `icon' glyphs can be used to specify the icon used when a frame is
3635 iconified.  Their image can be instantiated as `mono-pixmap' and
3636 `color-pixmap'.
3637 */
3638        (type))
3639 {
3640   enum glyph_type typeval = decode_glyph_type (type, ERROR_ME);
3641   return allocate_glyph (typeval, 0);
3642 }
3643
3644 DEFUN ("glyphp", Fglyphp, 1, 1, 0, /*
3645 Return non-nil if OBJECT is a glyph.
3646
3647 A glyph is an object used for pixmaps, widgets and the like.  It is used
3648 in begin-glyphs and end-glyphs attached to extents, in marginal and textual
3649 annotations, in overlay arrows (overlay-arrow-* variables), in toolbar
3650 buttons, and the like.  Much more detailed information can be found at
3651 `make-glyph'.  Its image is described using an image specifier --
3652 see `make-image-specifier'.  See also `make-image-instance' for further
3653 information.
3654 */
3655        (object))
3656 {
3657   return GLYPHP (object) ? Qt : Qnil;
3658 }
3659
3660 DEFUN ("glyph-type", Fglyph_type, 1, 1, 0, /*
3661 Return the type of the given glyph.
3662 The return value will be one of 'buffer, 'pointer, or 'icon.
3663 */
3664        (glyph))
3665 {
3666   CHECK_GLYPH (glyph);
3667   switch (XGLYPH_TYPE (glyph))
3668     {
3669     default: abort ();
3670     case GLYPH_BUFFER:  return Qbuffer;
3671     case GLYPH_POINTER: return Qpointer;
3672     case GLYPH_ICON:    return Qicon;
3673     }
3674 }
3675
3676 Lisp_Object
3677 glyph_image_instance (Lisp_Object glyph, Lisp_Object domain,
3678                       Error_behavior errb, int no_quit)
3679 {
3680   Lisp_Object specifier = GLYPH_IMAGE (XGLYPH (glyph));
3681
3682   /* This can never return Qunbound.  All glyphs have 'nothing as
3683      a fallback. */
3684   Lisp_Object image_instance = specifier_instance (specifier, Qunbound,
3685                                                    domain, errb, no_quit, 0,
3686                                                    Qzero);
3687   assert (!UNBOUNDP (image_instance));
3688   ERROR_CHECK_IMAGE_INSTANCE (image_instance);
3689
3690   return image_instance;
3691 }
3692
3693 static Lisp_Object
3694 glyph_image_instance_maybe (Lisp_Object glyph_or_image, Lisp_Object window)
3695 {
3696   Lisp_Object instance = glyph_or_image;
3697
3698   if (GLYPHP (glyph_or_image))
3699     instance = glyph_image_instance (glyph_or_image, window, ERROR_ME_NOT, 1);
3700
3701   return instance;
3702 }
3703
3704 /*****************************************************************************
3705  glyph_width
3706
3707  Return the width of the given GLYPH on the given WINDOW.
3708  Calculations are done based on recursively querying the geometry of
3709  the associated image instances.
3710  ****************************************************************************/
3711 unsigned short
3712 glyph_width (Lisp_Object glyph_or_image, Lisp_Object domain)
3713 {
3714   Lisp_Object instance = glyph_image_instance_maybe (glyph_or_image,
3715                                                      domain);
3716   if (!IMAGE_INSTANCEP (instance))
3717     return 0;
3718
3719   if (XIMAGE_INSTANCE_NEEDS_LAYOUT (instance))
3720     image_instance_layout (instance, IMAGE_UNSPECIFIED_GEOMETRY,
3721                            IMAGE_UNSPECIFIED_GEOMETRY, domain);
3722
3723   return XIMAGE_INSTANCE_WIDTH (instance);
3724 }
3725
3726 DEFUN ("glyph-width", Fglyph_width, 1, 2, 0, /*
3727 Return the width of GLYPH on WINDOW.
3728 This may not be exact as it does not take into account all of the context
3729 that redisplay will.
3730 */
3731        (glyph, window))
3732 {
3733   XSETWINDOW (window, decode_window (window));
3734   CHECK_GLYPH (glyph);
3735
3736   return make_int (glyph_width (glyph, window));
3737 }
3738
3739 unsigned short
3740 glyph_ascent (Lisp_Object glyph_or_image, Lisp_Object domain)
3741 {
3742   Lisp_Object instance = glyph_image_instance_maybe (glyph_or_image,
3743                                                      domain);
3744   if (!IMAGE_INSTANCEP (instance))
3745     return 0;
3746
3747   if (XIMAGE_INSTANCE_NEEDS_LAYOUT (instance))
3748     image_instance_layout (instance, IMAGE_UNSPECIFIED_GEOMETRY,
3749                            IMAGE_UNSPECIFIED_GEOMETRY, domain);
3750
3751   if (XIMAGE_INSTANCE_TYPE (instance) == IMAGE_TEXT)
3752     return XIMAGE_INSTANCE_TEXT_ASCENT (instance);
3753   else
3754     return XIMAGE_INSTANCE_HEIGHT (instance);
3755 }
3756
3757 unsigned short
3758 glyph_descent (Lisp_Object glyph_or_image, Lisp_Object domain)
3759 {
3760   Lisp_Object instance = glyph_image_instance_maybe (glyph_or_image,
3761                                                      domain);
3762   if (!IMAGE_INSTANCEP (instance))
3763     return 0;
3764
3765   if (XIMAGE_INSTANCE_NEEDS_LAYOUT (instance))
3766     image_instance_layout (instance, IMAGE_UNSPECIFIED_GEOMETRY,
3767                            IMAGE_UNSPECIFIED_GEOMETRY, domain);
3768
3769   if (XIMAGE_INSTANCE_TYPE (instance) ==  IMAGE_TEXT)
3770     return XIMAGE_INSTANCE_TEXT_DESCENT (instance);
3771   else
3772     return 0;
3773 }
3774
3775 /* strictly a convenience function. */
3776 unsigned short
3777 glyph_height (Lisp_Object glyph_or_image, Lisp_Object domain)
3778 {
3779   Lisp_Object instance = glyph_image_instance_maybe (glyph_or_image,
3780                                                      domain);
3781
3782   if (!IMAGE_INSTANCEP (instance))
3783     return 0;
3784
3785   if (XIMAGE_INSTANCE_NEEDS_LAYOUT (instance))
3786     image_instance_layout (instance, IMAGE_UNSPECIFIED_GEOMETRY,
3787                            IMAGE_UNSPECIFIED_GEOMETRY, domain);
3788
3789   return XIMAGE_INSTANCE_HEIGHT (instance);
3790 }
3791
3792 DEFUN ("glyph-ascent", Fglyph_ascent, 1, 2, 0, /*
3793 Return the ascent value of GLYPH on WINDOW.
3794 This may not be exact as it does not take into account all of the context
3795 that redisplay will.
3796 */
3797        (glyph, window))
3798 {
3799   XSETWINDOW (window, decode_window (window));
3800   CHECK_GLYPH (glyph);
3801
3802   return make_int (glyph_ascent (glyph, window));
3803 }
3804
3805 DEFUN ("glyph-descent", Fglyph_descent, 1, 2, 0, /*
3806 Return the descent value of GLYPH on WINDOW.
3807 This may not be exact as it does not take into account all of the context
3808 that redisplay will.
3809 */
3810        (glyph, window))
3811 {
3812   XSETWINDOW (window, decode_window (window));
3813   CHECK_GLYPH (glyph);
3814
3815   return make_int (glyph_descent (glyph, window));
3816 }
3817
3818 /* This is redundant but I bet a lot of people expect it to exist. */
3819 DEFUN ("glyph-height", Fglyph_height, 1, 2, 0, /*
3820 Return the height of GLYPH on WINDOW.
3821 This may not be exact as it does not take into account all of the context
3822 that redisplay will.
3823 */
3824        (glyph, window))
3825 {
3826   XSETWINDOW (window, decode_window (window));
3827   CHECK_GLYPH (glyph);
3828
3829   return make_int (glyph_height (glyph, window));
3830 }
3831
3832 static void
3833 set_glyph_dirty_p (Lisp_Object glyph_or_image, Lisp_Object window, int dirty)
3834 {
3835   Lisp_Object instance = glyph_or_image;
3836
3837   if (!NILP (glyph_or_image))
3838     {
3839       if (GLYPHP (glyph_or_image))
3840         {
3841           instance = glyph_image_instance (glyph_or_image, window,
3842                                            ERROR_ME_NOT, 1);
3843           XGLYPH_DIRTYP (glyph_or_image) = dirty;
3844         }
3845
3846       if (!IMAGE_INSTANCEP (instance))
3847         return;
3848
3849       XIMAGE_INSTANCE_DIRTYP (instance) = dirty;
3850     }
3851 }
3852
3853 static void
3854 set_image_instance_dirty_p (Lisp_Object instance, int dirty)
3855 {
3856   if (IMAGE_INSTANCEP (instance))
3857     {
3858       XIMAGE_INSTANCE_DIRTYP (instance) = dirty;
3859       /* Now cascade up the hierarchy. */
3860       set_image_instance_dirty_p (XIMAGE_INSTANCE_PARENT (instance),
3861                                   dirty);
3862     }
3863   else if (GLYPHP (instance))
3864     {
3865       XGLYPH_DIRTYP (instance) = dirty;
3866     }
3867 }
3868
3869 /* #### do we need to cache this info to speed things up? */
3870
3871 Lisp_Object
3872 glyph_baseline (Lisp_Object glyph, Lisp_Object domain)
3873 {
3874   if (!GLYPHP (glyph))
3875     return Qnil;
3876   else
3877     {
3878       Lisp_Object retval =
3879         specifier_instance_no_quit (GLYPH_BASELINE (XGLYPH (glyph)),
3880                                     /* #### look into ERROR_ME_NOT */
3881                                     Qunbound, domain, ERROR_ME_NOT,
3882                                     0, Qzero);
3883       if (!NILP (retval) && !INTP (retval))
3884         retval = Qnil;
3885       else if (INTP (retval))
3886         {
3887           if (XINT (retval) < 0)
3888             retval = Qzero;
3889           if (XINT (retval) > 100)
3890             retval = make_int (100);
3891         }
3892       return retval;
3893     }
3894 }
3895
3896 Lisp_Object
3897 glyph_face (Lisp_Object glyph, Lisp_Object domain)
3898 {
3899   /* #### Domain parameter not currently used but it will be */
3900   return GLYPHP (glyph) ? GLYPH_FACE (XGLYPH (glyph)) : Qnil;
3901 }
3902
3903 int
3904 glyph_contrib_p (Lisp_Object glyph, Lisp_Object domain)
3905 {
3906   if (!GLYPHP (glyph))
3907     return 0;
3908   else
3909     return !NILP (specifier_instance_no_quit
3910                   (GLYPH_CONTRIB_P (XGLYPH (glyph)), Qunbound, domain,
3911                    /* #### look into ERROR_ME_NOT */
3912                    ERROR_ME_NOT, 0, Qzero));
3913 }
3914
3915 static void
3916 glyph_property_was_changed (Lisp_Object glyph, Lisp_Object property,
3917                             Lisp_Object locale)
3918 {
3919   if (XGLYPH (glyph)->after_change)
3920     (XGLYPH (glyph)->after_change) (glyph, property, locale);
3921 }
3922
3923 #if 0                           /* Not used for now */
3924 static void
3925 glyph_query_geometry (Lisp_Object glyph_or_image, Lisp_Object window,
3926                       unsigned int* width, unsigned int* height,
3927                       enum image_instance_geometry disp, Lisp_Object domain)
3928 {
3929   Lisp_Object instance = glyph_or_image;
3930
3931   if (GLYPHP (glyph_or_image))
3932     instance = glyph_image_instance (glyph_or_image, window, ERROR_ME_NOT, 1);
3933
3934   image_instance_query_geometry (instance, width, height, disp, domain);
3935 }
3936
3937 static void
3938 glyph_layout (Lisp_Object glyph_or_image, Lisp_Object window,
3939               unsigned int width, unsigned int height, Lisp_Object domain)
3940 {
3941   Lisp_Object instance = glyph_or_image;
3942
3943   if (GLYPHP (glyph_or_image))
3944     instance = glyph_image_instance (glyph_or_image, window, ERROR_ME_NOT, 1);
3945
3946   image_instance_layout (instance, width, height, domain);
3947 }
3948 #endif
3949
3950 \f
3951 /*****************************************************************************
3952  *                     glyph cachel functions                                *
3953  *****************************************************************************/
3954
3955 /* #### All of this is 95% copied from face cachels.  Consider
3956   consolidating.
3957
3958   Why do we need glyph_cachels? Simply because a glyph_cachel captures
3959   per-window information about a particular glyph. A glyph itself is
3960   not created in any particular context, so if we were to rely on a
3961   glyph to tell us about its dirtiness we would not be able to reset
3962   the dirty flag after redisplaying it as it may exist in other
3963   contexts. When we have redisplayed we need to know which glyphs to
3964   reset the dirty flags on - the glyph_cachels give us a nice list we
3965   can iterate through doing this.  */
3966 void
3967 mark_glyph_cachels (glyph_cachel_dynarr *elements)
3968 {
3969   int elt;
3970
3971   if (!elements)
3972     return;
3973
3974   for (elt = 0; elt < Dynarr_length (elements); elt++)
3975     {
3976       struct glyph_cachel *cachel = Dynarr_atp (elements, elt);
3977       mark_object (cachel->glyph);
3978     }
3979 }
3980
3981 static void
3982 update_glyph_cachel_data (struct window *w, Lisp_Object glyph,
3983                           struct glyph_cachel *cachel)
3984 {
3985   if (!cachel->updated || NILP (cachel->glyph) || !EQ (cachel->glyph, glyph)
3986       || XGLYPH_DIRTYP (cachel->glyph)
3987       || XFRAME(WINDOW_FRAME(w))->faces_changed)
3988     {
3989       Lisp_Object window, instance;
3990
3991       XSETWINDOW (window, w);
3992
3993       cachel->glyph   = glyph;
3994       /* Speed things up slightly by grabbing the glyph instantiation
3995          and passing it to the size functions. */
3996       instance = glyph_image_instance (glyph, window, ERROR_ME_NOT, 1);
3997
3998       if (!IMAGE_INSTANCEP (instance))
3999         return;
4000
4001       /* Mark text instance of the glyph dirty if faces have changed,
4002          because its geometry might have changed. */
4003       invalidate_glyph_geometry_maybe (instance, w);
4004
4005       /* #### Do the following 2 lines buy us anything? --kkm */
4006       XGLYPH_DIRTYP (glyph) = XIMAGE_INSTANCE_DIRTYP (instance);
4007       cachel->dirty   = XGLYPH_DIRTYP (glyph);
4008       cachel->width   = glyph_width   (instance, window);
4009       cachel->ascent  = glyph_ascent  (instance, window);
4010       cachel->descent = glyph_descent (instance, window);
4011     }
4012
4013   cachel->updated = 1;
4014 }
4015
4016 static void
4017 add_glyph_cachel (struct window *w, Lisp_Object glyph)
4018 {
4019   struct glyph_cachel new_cachel;
4020
4021   xzero (new_cachel);
4022   new_cachel.glyph = Qnil;
4023
4024   update_glyph_cachel_data (w, glyph, &new_cachel);
4025   Dynarr_add (w->glyph_cachels, new_cachel);
4026 }
4027
4028 glyph_index
4029 get_glyph_cachel_index (struct window *w, Lisp_Object glyph)
4030 {
4031   int elt;
4032
4033   if (noninteractive)
4034     return 0;
4035
4036   for (elt = 0; elt < Dynarr_length (w->glyph_cachels); elt++)
4037     {
4038       struct glyph_cachel *cachel =
4039         Dynarr_atp (w->glyph_cachels, elt);
4040
4041       if (EQ (cachel->glyph, glyph) && !NILP (glyph))
4042         {
4043           update_glyph_cachel_data (w, glyph, cachel);
4044           return elt;
4045         }
4046     }
4047
4048   /* If we didn't find the glyph, add it and then return its index. */
4049   add_glyph_cachel (w, glyph);
4050   return elt;
4051 }
4052
4053 void
4054 reset_glyph_cachels (struct window *w)
4055 {
4056   Dynarr_reset (w->glyph_cachels);
4057   get_glyph_cachel_index (w, Vcontinuation_glyph);
4058   get_glyph_cachel_index (w, Vtruncation_glyph);
4059   get_glyph_cachel_index (w, Vhscroll_glyph);
4060   get_glyph_cachel_index (w, Vcontrol_arrow_glyph);
4061   get_glyph_cachel_index (w, Voctal_escape_glyph);
4062   get_glyph_cachel_index (w, Vinvisible_text_glyph);
4063 }
4064
4065 void
4066 mark_glyph_cachels_as_not_updated (struct window *w)
4067 {
4068   int elt;
4069
4070   /* We need to have a dirty flag to tell if the glyph has changed.
4071      We can check to see if each glyph variable is actually a
4072      completely different glyph, though. */
4073 #define FROB(glyph_obj, gindex)                                         \
4074   update_glyph_cachel_data (w, glyph_obj,                               \
4075                               Dynarr_atp (w->glyph_cachels, gindex))
4076
4077   FROB (Vcontinuation_glyph, CONT_GLYPH_INDEX);
4078   FROB (Vtruncation_glyph, TRUN_GLYPH_INDEX);
4079   FROB (Vhscroll_glyph, HSCROLL_GLYPH_INDEX);
4080   FROB (Vcontrol_arrow_glyph, CONTROL_GLYPH_INDEX);
4081   FROB (Voctal_escape_glyph, OCT_ESC_GLYPH_INDEX);
4082   FROB (Vinvisible_text_glyph, INVIS_GLYPH_INDEX);
4083 #undef FROB
4084
4085   for (elt = 0; elt < Dynarr_length (w->glyph_cachels); elt++)
4086     {
4087       Dynarr_atp (w->glyph_cachels, elt)->updated = 0;
4088     }
4089 }
4090
4091 /* Unset the dirty bit on all the glyph cachels that have it. */
4092 void
4093 mark_glyph_cachels_as_clean (struct window* w)
4094 {
4095   int elt;
4096   Lisp_Object window;
4097   XSETWINDOW (window, w);
4098   for (elt = 0; elt < Dynarr_length (w->glyph_cachels); elt++)
4099     {
4100       struct glyph_cachel *cachel = Dynarr_atp (w->glyph_cachels, elt);
4101       cachel->dirty = 0;
4102       set_glyph_dirty_p (cachel->glyph, window, 0);
4103     }
4104 }
4105
4106 #ifdef MEMORY_USAGE_STATS
4107
4108 int
4109 compute_glyph_cachel_usage (glyph_cachel_dynarr *glyph_cachels,
4110                             struct overhead_stats *ovstats)
4111 {
4112   int total = 0;
4113
4114   if (glyph_cachels)
4115     total += Dynarr_memory_usage (glyph_cachels, ovstats);
4116
4117   return total;
4118 }
4119
4120 #endif /* MEMORY_USAGE_STATS */
4121
4122
4123 \f
4124 /*****************************************************************************
4125  *                     subwindow cachel functions                                    *
4126  *****************************************************************************/
4127 /* Subwindows are curious in that you have to physically unmap them to
4128    not display them. It is problematic deciding what to do in
4129    redisplay. We have two caches - a per-window instance cache that
4130    keeps track of subwindows on a window, these are linked to their
4131    instantiator in the hashtable and when the instantiator goes away
4132    we want the instance to go away also. However we also have a
4133    per-frame instance cache that we use to determine if a subwindow is
4134    obscuring an area that we want to clear. We need to be able to flip
4135    through this quickly so a hashtable is not suitable hence the
4136    subwindow_cachels. This is a weak list so unreference instances
4137    will get deleted properly. */
4138
4139 /* redisplay in general assumes that drawing something will erase
4140    what was there before. unfortunately this does not apply to
4141    subwindows that need to be specifically unmapped in order to
4142    disappear. we take a brute force approach - on the basis that its
4143    cheap - and unmap all subwindows in a display line */
4144
4145 /* Put new instances in the frame subwindow cache. This is less costly than
4146    doing it every time something gets mapped, and deleted instances will be
4147    removed automatically. */
4148 static void
4149 cache_subwindow_instance_in_frame_maybe (Lisp_Object instance)
4150 {
4151   Lisp_Image_Instance* ii = XIMAGE_INSTANCE (instance);
4152   if (!NILP (DOMAIN_FRAME (IMAGE_INSTANCE_DOMAIN (ii))))
4153     {
4154       struct frame* f = DOMAIN_XFRAME (IMAGE_INSTANCE_DOMAIN (ii));
4155       XWEAK_LIST_LIST (FRAME_SUBWINDOW_CACHE (f))
4156         = Fcons (instance, XWEAK_LIST_LIST (FRAME_SUBWINDOW_CACHE (f)));
4157     }
4158 }
4159
4160 /* Unmap and finalize all subwindow instances in the frame cache. This
4161    is necessary because GC will not guarantee the order things get
4162    deleted in and moreover, frame finalization deletes the window
4163    system windows before deleting XEmacs windows, and hence
4164    subwindows.  */
4165 void
4166 free_frame_subwindow_instance_cache (struct frame* f)
4167 {
4168   Lisp_Object rest;
4169
4170   LIST_LOOP (rest, XWEAK_LIST_LIST (FRAME_SUBWINDOW_CACHE (f)))
4171     {
4172       Lisp_Image_Instance *ii = XIMAGE_INSTANCE (XCAR (rest));
4173       /* Make sure that the subwindow is unmapped so that window
4174          deletion will not try and do it again. */
4175       unmap_subwindow (XCAR (rest));
4176       finalize_image_instance (ii, 0);
4177     }
4178 }
4179
4180 /* Unmap and remove all instances from the frame cache. */
4181 void
4182 reset_frame_subwindow_instance_cache (struct frame* f)
4183 {
4184   Lisp_Object rest;
4185
4186   LIST_LOOP (rest, XWEAK_LIST_LIST (FRAME_SUBWINDOW_CACHE (f)))
4187     {
4188       Lisp_Object value = XCAR (rest);
4189       /* Make sure that the subwindow is unmapped so that window
4190          deletion will not try and do it again. */
4191       unmap_subwindow (value);
4192       XWEAK_LIST_LIST (FRAME_SUBWINDOW_CACHE (f))
4193         = delq_no_quit (value, XWEAK_LIST_LIST (FRAME_SUBWINDOW_CACHE (f)));
4194     }
4195 }
4196
4197 /*****************************************************************************
4198  *                              subwindow exposure ignorance                    *
4199  *****************************************************************************/
4200 /* when we unmap subwindows the associated window system will generate
4201    expose events. This we do not want as redisplay already copes with
4202    the repainting necessary. Worse, we can get in an endless cycle of
4203    redisplay if we are not careful. Thus we keep a per-frame list of
4204    expose events that are going to come and ignore them as
4205    required. */
4206
4207 struct expose_ignore_blocktype
4208 {
4209   Blocktype_declare (struct expose_ignore);
4210 } *the_expose_ignore_blocktype;
4211
4212 int
4213 check_for_ignored_expose (struct frame* f, int x, int y, int width, int height)
4214 {
4215   struct expose_ignore *ei, *prev;
4216   /* the ignore list is FIFO so we should generally get a match with
4217      the first element in the list */
4218   for (ei = f->subwindow_exposures, prev = 0; ei; ei = ei->next)
4219     {
4220       /* Checking for exact matches just isn't good enough as we
4221          mighte get exposures for partially obscure subwindows, thus
4222          we have to check for overlaps. Being conservative we will
4223          check for exposures wholly contained by the subwindow, this
4224          might give us what we want.*/
4225       if (ei->x <= x && ei->y <= y
4226           && ei->x + ei->width >= x + width
4227           && ei->y + ei->height >= y + height)
4228         {
4229 #ifdef DEBUG_WIDGETS
4230           stderr_out ("ignored %d+%d, %dx%d for exposure %d+%d, %dx%d\n",
4231                       x, y, width, height, ei->x, ei->y, ei->width, ei->height);
4232 #endif
4233           if (!prev)
4234             f->subwindow_exposures = ei->next;
4235           else
4236             prev->next = ei->next;
4237
4238           if (ei == f->subwindow_exposures_tail)
4239             f->subwindow_exposures_tail = prev;
4240
4241           Blocktype_free (the_expose_ignore_blocktype, ei);
4242           return 1;
4243         }
4244       prev = ei;
4245     }
4246   return 0;
4247 }
4248
4249 static void
4250 register_ignored_expose (struct frame* f, int x, int y, int width, int height)
4251 {
4252   if (!hold_ignored_expose_registration)
4253     {
4254       struct expose_ignore *ei;
4255
4256       ei = Blocktype_alloc (the_expose_ignore_blocktype);
4257
4258       ei->next = NULL;
4259       ei->x = x;
4260       ei->y = y;
4261       ei->width = width;
4262       ei->height = height;
4263
4264       /* we have to add the exposure to the end of the list, since we
4265          want to check the oldest events first. for speed we keep a record
4266          of the end so that we can add right to it. */
4267       if (f->subwindow_exposures_tail)
4268         {
4269           f->subwindow_exposures_tail->next = ei;
4270         }
4271       if (!f->subwindow_exposures)
4272         {
4273           f->subwindow_exposures = ei;
4274         }
4275       f->subwindow_exposures_tail = ei;
4276     }
4277 }
4278
4279 /****************************************************************************
4280  find_matching_subwindow
4281
4282  See if there is a subwindow that completely encloses the requested
4283  area.
4284  ****************************************************************************/
4285 int find_matching_subwindow (struct frame* f, int x, int y, int width, int height)
4286 {
4287   Lisp_Object rest;
4288
4289   LIST_LOOP (rest, XWEAK_LIST_LIST (FRAME_SUBWINDOW_CACHE (f)))
4290     {
4291       Lisp_Image_Instance *ii = XIMAGE_INSTANCE (XCAR (rest));
4292
4293       if (IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (ii)
4294           &&
4295           IMAGE_INSTANCE_DISPLAY_X (ii) <= x 
4296           && 
4297           IMAGE_INSTANCE_DISPLAY_Y (ii) <= y 
4298           &&
4299           IMAGE_INSTANCE_DISPLAY_X (ii)
4300           + IMAGE_INSTANCE_DISPLAY_WIDTH (ii) >= x + width
4301           &&
4302           IMAGE_INSTANCE_DISPLAY_Y (ii)
4303           + IMAGE_INSTANCE_DISPLAY_HEIGHT (ii) >= y + height)
4304         {
4305           return 1;
4306         }
4307     }
4308   return 0;
4309 }
4310
4311 \f
4312 /*****************************************************************************
4313  *                              subwindow functions                          *
4314  *****************************************************************************/
4315
4316 /* Update the displayed characteristics of a subwindow. This function
4317    should generally only get called if the subwindow is actually
4318    dirty. */
4319 void
4320 update_subwindow (Lisp_Object subwindow)
4321 {
4322   Lisp_Image_Instance* ii = XIMAGE_INSTANCE (subwindow);
4323   int count = specpdl_depth ();
4324
4325   /* The update method is allowed to call eval.  Since it is quite
4326      common for this function to get called from somewhere in
4327      redisplay we need to make sure that quits are ignored.  Otherwise
4328      Fsignal will abort. */
4329   specbind (Qinhibit_quit, Qt);
4330
4331   ERROR_CHECK_IMAGE_INSTANCE (subwindow);
4332
4333   if (WIDGET_IMAGE_INSTANCEP (subwindow))
4334     {
4335       if (image_instance_changed (subwindow))
4336         update_widget (subwindow);
4337       /* Reset the changed flags. */
4338       IMAGE_INSTANCE_WIDGET_FACE_CHANGED (ii) = 0;
4339       IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii) = 0;
4340       IMAGE_INSTANCE_TEXT_CHANGED (ii) = 0;
4341     }
4342   else if (IMAGE_INSTANCE_TYPE (ii) == IMAGE_SUBWINDOW
4343            &&
4344            !NILP (IMAGE_INSTANCE_FRAME (ii)))
4345     {
4346       MAYBE_DEVMETH (DOMAIN_XDEVICE (ii->domain),
4347                      update_subwindow, (ii));
4348     }
4349
4350   IMAGE_INSTANCE_SIZE_CHANGED (ii) = 0;
4351   /* This function is typically called by redisplay just before
4352      outputting the information to the screen. Thus we record a hash
4353      of the output to determine whether on-screen is the same as
4354      recorded structure. This approach has limitations in there is a
4355      good chance that hash values will be different for the same
4356      visual appearance. However, we would rather that then the other
4357      way round - it simply means that we will get more displays than
4358      we might need. We can get better hashing by making the depth
4359      negative - currently it will recurse down 7 levels.*/
4360   IMAGE_INSTANCE_DISPLAY_HASH (ii) = internal_hash (subwindow, 
4361                                                     IMAGE_INSTANCE_HASH_DEPTH);
4362
4363   unbind_to (count, Qnil);
4364 }
4365
4366 int
4367 image_instance_changed (Lisp_Object subwindow)
4368 {
4369   Lisp_Image_Instance* ii = XIMAGE_INSTANCE (subwindow);
4370
4371   if (internal_hash (subwindow, IMAGE_INSTANCE_HASH_DEPTH) != 
4372       IMAGE_INSTANCE_DISPLAY_HASH (ii))
4373     return 1;
4374   /* #### I think there is probably a bug here. This gets called for
4375      layouts - and yet the pending items are always nil for
4376      layouts. We are saved by layout optimization, but I'm undecided
4377      as to what the correct fix is. */
4378   else if (WIDGET_IMAGE_INSTANCEP (subwindow)
4379            && (!internal_equal (IMAGE_INSTANCE_WIDGET_ITEMS (ii),
4380                                 IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii), 0)
4381                || !NILP (IMAGE_INSTANCE_LAYOUT_CHILDREN (ii))))
4382     return 1;
4383   else
4384     return 0;
4385 }
4386
4387 /* Update all the subwindows on a frame. */
4388 void
4389 update_widget_instances (Lisp_Object frame)
4390 {
4391   struct frame* f;
4392   Lisp_Object rest;
4393
4394   /* Its possible for the preceeding callback to have deleted the
4395      frame, so cope with this. */
4396   if (!FRAMEP (frame) || !FRAME_LIVE_P (XFRAME (frame)))
4397     return;
4398
4399   CHECK_FRAME (frame);
4400   f = XFRAME (frame);
4401   
4402   /* If we get called we know something has changed. */
4403   LIST_LOOP (rest, XWEAK_LIST_LIST (FRAME_SUBWINDOW_CACHE (f)))
4404     {
4405       Lisp_Object widget = XCAR (rest);
4406       
4407       if (XIMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (widget)
4408           &&
4409           image_instance_changed (widget))
4410         {
4411           set_image_instance_dirty_p (widget, 1);
4412           MARK_FRAME_GLYPHS_CHANGED (f);
4413         }
4414     }
4415 }
4416
4417 /* remove a subwindow from its frame */
4418 void unmap_subwindow (Lisp_Object subwindow)
4419 {
4420   Lisp_Image_Instance* ii = XIMAGE_INSTANCE (subwindow);
4421   struct frame* f;
4422
4423   ERROR_CHECK_IMAGE_INSTANCE (subwindow);
4424
4425   if (!image_instance_type_to_mask (IMAGE_INSTANCE_TYPE (ii))
4426       & (IMAGE_WIDGET_MASK | IMAGE_SUBWINDOW_MASK)
4427       ||
4428       !IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (ii))
4429     return;
4430
4431 #ifdef DEBUG_WIDGETS
4432   stderr_out ("unmapping subwindow %d\n", IMAGE_INSTANCE_SUBWINDOW_ID (ii));
4433 #endif
4434   f = XFRAME (IMAGE_INSTANCE_FRAME (ii));
4435
4436   /* make sure we don't get expose events */
4437   register_ignored_expose (f, IMAGE_INSTANCE_DISPLAY_X (ii),
4438                            IMAGE_INSTANCE_DISPLAY_Y (ii),
4439                            IMAGE_INSTANCE_DISPLAY_WIDTH (ii),
4440                            IMAGE_INSTANCE_DISPLAY_HEIGHT (ii));
4441   IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (ii) = 0;
4442
4443   MAYBE_DEVMETH (XDEVICE (IMAGE_INSTANCE_DEVICE (ii)), 
4444                  unmap_subwindow, (ii));
4445 }
4446
4447 /* show a subwindow in its frame */
4448 void map_subwindow (Lisp_Object subwindow, int x, int y,
4449                     struct display_glyph_area *dga)
4450 {
4451   Lisp_Image_Instance* ii = XIMAGE_INSTANCE (subwindow);
4452   struct frame* f;
4453
4454   ERROR_CHECK_IMAGE_INSTANCE (subwindow);
4455
4456   if (!image_instance_type_to_mask (IMAGE_INSTANCE_TYPE (ii))
4457       & (IMAGE_WIDGET_MASK | IMAGE_SUBWINDOW_MASK))
4458     return;
4459
4460 #ifdef DEBUG_WIDGETS
4461   stderr_out ("mapping subwindow %d, %dx%d@%d+%d\n",
4462               IMAGE_INSTANCE_SUBWINDOW_ID (ii),
4463               dga->width, dga->height, x, y);
4464 #endif
4465   f = XFRAME (IMAGE_INSTANCE_FRAME (ii));
4466   IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (ii) = 1;
4467   IMAGE_INSTANCE_DISPLAY_X (ii) = x;
4468   IMAGE_INSTANCE_DISPLAY_Y (ii) = y;
4469   IMAGE_INSTANCE_DISPLAY_WIDTH (ii) = dga->width;
4470   IMAGE_INSTANCE_DISPLAY_HEIGHT (ii) = dga->height;
4471
4472   MAYBE_DEVMETH (DOMAIN_XDEVICE (ii->domain),
4473                  map_subwindow, (ii, x, y, dga));
4474 }
4475
4476 static int
4477 subwindow_possible_dest_types (void)
4478 {
4479   return IMAGE_SUBWINDOW_MASK;
4480 }
4481
4482 int
4483 subwindow_governing_domain (void)
4484 {
4485   return GOVERNING_DOMAIN_WINDOW;
4486 }
4487
4488 /* Partially instantiate a subwindow. */
4489 void
4490 subwindow_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
4491                        Lisp_Object pointer_fg, Lisp_Object pointer_bg,
4492                        int dest_mask, Lisp_Object domain)
4493 {
4494   Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
4495   Lisp_Object device = image_instance_device (image_instance);
4496   Lisp_Object frame = DOMAIN_FRAME (domain);
4497   Lisp_Object width = find_keyword_in_vector (instantiator, Q_pixel_width);
4498   Lisp_Object height = find_keyword_in_vector (instantiator, Q_pixel_height);
4499
4500   if (NILP (frame))
4501     signal_simple_error ("No selected frame", device);
4502
4503   if (!(dest_mask & IMAGE_SUBWINDOW_MASK))
4504     incompatible_image_types (instantiator, dest_mask, IMAGE_SUBWINDOW_MASK);
4505
4506   ii->data = 0;
4507   IMAGE_INSTANCE_SUBWINDOW_ID (ii) = 0;
4508   IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (ii) = 0;
4509
4510   if (INTP (width))
4511     {
4512       int w = 1;
4513       if (XINT (width) > 1)
4514         w = XINT (width);
4515       IMAGE_INSTANCE_WIDTH (ii) = w;
4516       IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii) = 0;
4517     }
4518
4519   if (INTP (height))
4520     {
4521       int h = 1;
4522       if (XINT (height) > 1)
4523         h = XINT (height);
4524       IMAGE_INSTANCE_HEIGHT (ii) = h;
4525       IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii) = 0;
4526     }
4527 }
4528
4529 /* This is just a backup in case no-one has assigned a suitable geometry. 
4530    #### It should really query the enclose window for geometry. */
4531 static void
4532 subwindow_query_geometry (Lisp_Object image_instance, int* width,
4533                           int* height, enum image_instance_geometry disp,
4534                           Lisp_Object domain)
4535 {
4536   if (width)    *width = 20;
4537   if (height)   *height = 20;
4538 }
4539
4540 DEFUN ("subwindowp", Fsubwindowp, 1, 1, 0, /*
4541 Return non-nil if OBJECT is a subwindow.
4542 */
4543        (object))
4544 {
4545   CHECK_IMAGE_INSTANCE (object);
4546   return (XIMAGE_INSTANCE_TYPE (object) == IMAGE_SUBWINDOW) ? Qt : Qnil;
4547 }
4548
4549 DEFUN ("image-instance-subwindow-id", Fimage_instance_subwindow_id, 1, 1, 0, /*
4550 Return the window id of SUBWINDOW as a number.
4551 */
4552        (subwindow))
4553 {
4554   CHECK_SUBWINDOW_IMAGE_INSTANCE (subwindow);
4555   return make_int ((int) XIMAGE_INSTANCE_SUBWINDOW_ID (subwindow));
4556 }
4557
4558 DEFUN ("resize-subwindow", Fresize_subwindow, 1, 3, 0, /*
4559 Resize SUBWINDOW to WIDTH x HEIGHT.
4560 If a value is nil that parameter is not changed.
4561 */
4562        (subwindow, width, height))
4563 {
4564   int neww, newh;
4565   Lisp_Image_Instance* ii;
4566
4567   CHECK_SUBWINDOW_IMAGE_INSTANCE (subwindow);
4568   ii = XIMAGE_INSTANCE (subwindow);
4569
4570   if (NILP (width))
4571     neww = IMAGE_INSTANCE_WIDTH (ii);
4572   else
4573     neww = XINT (width);
4574
4575   if (NILP (height))
4576     newh = IMAGE_INSTANCE_HEIGHT (ii);
4577   else
4578     newh = XINT (height);
4579
4580   /* The actual resizing gets done asychronously by
4581      update_subwindow. */
4582   IMAGE_INSTANCE_HEIGHT (ii) = newh;
4583   IMAGE_INSTANCE_WIDTH (ii) = neww;
4584   IMAGE_INSTANCE_SIZE_CHANGED (ii) = 1;
4585
4586   return subwindow;
4587 }
4588
4589 DEFUN ("force-subwindow-map", Fforce_subwindow_map, 1, 1, 0, /*
4590 Generate a Map event for SUBWINDOW.
4591 */
4592        (subwindow))
4593 {
4594   CHECK_SUBWINDOW_IMAGE_INSTANCE (subwindow);
4595 #if 0
4596   map_subwindow (subwindow, 0, 0);
4597 #endif
4598   return subwindow;
4599 }
4600
4601 \f
4602 /*****************************************************************************
4603  *                              display tables                               *
4604  *****************************************************************************/
4605
4606 /* Get the display tables for use currently on window W with face
4607    FACE.  #### This will have to be redone.  */
4608
4609 void
4610 get_display_tables (struct window *w, face_index findex,
4611                     Lisp_Object *face_table, Lisp_Object *window_table)
4612 {
4613   Lisp_Object tem;
4614   tem = WINDOW_FACE_CACHEL_DISPLAY_TABLE (w, findex);
4615   if (UNBOUNDP (tem))
4616     tem = Qnil;
4617   if (!LISTP (tem))
4618     tem = noseeum_cons (tem, Qnil);
4619   *face_table = tem;
4620   tem = w->display_table;
4621   if (UNBOUNDP (tem))
4622     tem = Qnil;
4623   if (!LISTP (tem))
4624     tem = noseeum_cons (tem, Qnil);
4625   *window_table = tem;
4626 }
4627
4628 Lisp_Object
4629 display_table_entry (Emchar ch, Lisp_Object face_table,
4630                      Lisp_Object window_table)
4631 {
4632   Lisp_Object tail;
4633
4634   /* Loop over FACE_TABLE, and then over WINDOW_TABLE. */
4635   for (tail = face_table; 1; tail = XCDR (tail))
4636     {
4637       Lisp_Object table;
4638       if (NILP (tail))
4639         {
4640           if (!NILP (window_table))
4641             {
4642               tail = window_table;
4643               window_table = Qnil;
4644             }
4645           else
4646             return Qnil;
4647         }
4648       table = XCAR (tail);
4649
4650       if (VECTORP (table))
4651         {
4652           if (ch < XVECTOR_LENGTH (table) && !NILP (XVECTOR_DATA (table)[ch]))
4653             return XVECTOR_DATA (table)[ch];
4654           else
4655             continue;
4656         }
4657       else if (CHAR_TABLEP (table)
4658                && XCHAR_TABLE_TYPE (table) == CHAR_TABLE_TYPE_CHAR)
4659         {
4660           return get_char_table (ch, XCHAR_TABLE (table));
4661         }
4662       else if (CHAR_TABLEP (table)
4663                && XCHAR_TABLE_TYPE (table) == CHAR_TABLE_TYPE_GENERIC)
4664         {
4665           Lisp_Object gotit = get_char_table (ch, XCHAR_TABLE (table));
4666           if (!NILP (gotit))
4667             return gotit;
4668           else
4669             continue;
4670         }
4671       else if (RANGE_TABLEP (table))
4672         {
4673           Lisp_Object gotit = Fget_range_table (make_char (ch), table, Qnil);
4674           if (!NILP (gotit))
4675             return gotit;
4676           else
4677             continue;
4678         }
4679       else
4680         abort ();
4681     }
4682 }
4683
4684 /*****************************************************************************
4685  *                              timeouts for animated glyphs                      *
4686  *****************************************************************************/
4687 static Lisp_Object Qglyph_animated_timeout_handler;
4688
4689 DEFUN ("glyph-animated-timeout-handler", Fglyph_animated_timeout_handler, 1, 1, 0, /*
4690 Callback function for updating animated images.
4691 Don't use this.
4692 */
4693        (arg))
4694 {
4695   CHECK_WEAK_LIST (arg);
4696
4697   if (!NILP (XWEAK_LIST_LIST (arg)) && !NILP (XCAR (XWEAK_LIST_LIST (arg))))
4698     {
4699       Lisp_Object value = XCAR (XWEAK_LIST_LIST (arg));
4700
4701       if (IMAGE_INSTANCEP (value))
4702         {
4703           Lisp_Image_Instance* ii = XIMAGE_INSTANCE (value);
4704
4705           if (COLOR_PIXMAP_IMAGE_INSTANCEP (value)
4706               &&
4707               IMAGE_INSTANCE_PIXMAP_MAXSLICE (ii) > 1
4708               &&
4709               !disable_animated_pixmaps)
4710             {
4711               /* Increment the index of the image slice we are currently
4712                  viewing. */
4713               IMAGE_INSTANCE_PIXMAP_SLICE (ii) =
4714                 (IMAGE_INSTANCE_PIXMAP_SLICE (ii) + 1)
4715                 % IMAGE_INSTANCE_PIXMAP_MAXSLICE (ii);
4716               /* We might need to kick redisplay at this point - but we
4717                  also might not. */
4718               MARK_DEVICE_FRAMES_GLYPHS_CHANGED
4719                 (XDEVICE (image_instance_device (value)));
4720               /* Cascade dirtiness so that we can have an animated glyph in a layout
4721                  for instance. */
4722               set_image_instance_dirty_p (value, 1);
4723             }
4724         }
4725     }
4726   return Qnil;
4727 }
4728
4729 Lisp_Object add_glyph_animated_timeout (EMACS_INT tickms, Lisp_Object image)
4730 {
4731   Lisp_Object ret = Qnil;
4732
4733   if (tickms > 0 && IMAGE_INSTANCEP (image))
4734     {
4735       double ms = ((double)tickms) / 1000.0;
4736       struct gcpro gcpro1;
4737       Lisp_Object holder = make_weak_list (WEAK_LIST_SIMPLE);
4738
4739       GCPRO1 (holder);
4740       XWEAK_LIST_LIST (holder) = Fcons (image, Qnil);
4741
4742       ret = Fadd_timeout (make_float (ms),
4743                           Qglyph_animated_timeout_handler,
4744                           holder, make_float (ms));
4745
4746       UNGCPRO;
4747     }
4748   return ret;
4749 }
4750
4751 void disable_glyph_animated_timeout (int i)
4752 {
4753   Lisp_Object id;
4754   XSETINT (id, i);
4755
4756   Fdisable_timeout (id);
4757 }
4758
4759 \f
4760 /*****************************************************************************
4761  *                              initialization                               *
4762  *****************************************************************************/
4763
4764 void
4765 syms_of_glyphs (void)
4766 {
4767   INIT_LRECORD_IMPLEMENTATION (glyph);
4768   INIT_LRECORD_IMPLEMENTATION (image_instance);
4769
4770   /* image instantiators */
4771
4772   DEFSUBR (Fimage_instantiator_format_list);
4773   DEFSUBR (Fvalid_image_instantiator_format_p);
4774   DEFSUBR (Fset_console_type_image_conversion_list);
4775   DEFSUBR (Fconsole_type_image_conversion_list);
4776
4777   defkeyword (&Q_file, ":file");
4778   defkeyword (&Q_data, ":data");
4779   defkeyword (&Q_face, ":face");
4780   defkeyword (&Q_pixel_height, ":pixel-height");
4781   defkeyword (&Q_pixel_width, ":pixel-width");
4782
4783 #ifdef HAVE_XPM
4784   defkeyword (&Q_color_symbols, ":color-symbols");
4785 #endif
4786 #ifdef HAVE_WINDOW_SYSTEM
4787   defkeyword (&Q_mask_file, ":mask-file");
4788   defkeyword (&Q_mask_data, ":mask-data");
4789   defkeyword (&Q_hotspot_x, ":hotspot-x");
4790   defkeyword (&Q_hotspot_y, ":hotspot-y");
4791   defkeyword (&Q_foreground, ":foreground");
4792   defkeyword (&Q_background, ":background");
4793 #endif
4794   /* image specifiers */
4795
4796   DEFSUBR (Fimage_specifier_p);
4797   /* Qimage in general.c */
4798
4799   /* image instances */
4800
4801   defsymbol (&Qimage_instancep, "image-instance-p");
4802
4803   defsymbol (&Qnothing_image_instance_p, "nothing-image-instance-p");
4804   defsymbol (&Qtext_image_instance_p, "text-image-instance-p");
4805   defsymbol (&Qmono_pixmap_image_instance_p, "mono-pixmap-image-instance-p");
4806   defsymbol (&Qcolor_pixmap_image_instance_p, "color-pixmap-image-instance-p");
4807   defsymbol (&Qpointer_image_instance_p, "pointer-image-instance-p");
4808   defsymbol (&Qwidget_image_instance_p, "widget-image-instance-p");
4809   defsymbol (&Qsubwindow_image_instance_p, "subwindow-image-instance-p");
4810
4811   DEFSUBR (Fmake_image_instance);
4812   DEFSUBR (Fimage_instance_p);
4813   DEFSUBR (Fimage_instance_type);
4814   DEFSUBR (Fvalid_image_instance_type_p);
4815   DEFSUBR (Fimage_instance_type_list);
4816   DEFSUBR (Fimage_instance_name);
4817   DEFSUBR (Fimage_instance_domain);
4818   DEFSUBR (Fimage_instance_string);
4819   DEFSUBR (Fimage_instance_file_name);
4820   DEFSUBR (Fimage_instance_mask_file_name);
4821   DEFSUBR (Fimage_instance_depth);
4822   DEFSUBR (Fimage_instance_height);
4823   DEFSUBR (Fimage_instance_width);
4824   DEFSUBR (Fimage_instance_hotspot_x);
4825   DEFSUBR (Fimage_instance_hotspot_y);
4826   DEFSUBR (Fimage_instance_foreground);
4827   DEFSUBR (Fimage_instance_background);
4828   DEFSUBR (Fimage_instance_property);
4829   DEFSUBR (Fset_image_instance_property);
4830   DEFSUBR (Fcolorize_image_instance);
4831   /* subwindows */
4832   DEFSUBR (Fsubwindowp);
4833   DEFSUBR (Fimage_instance_subwindow_id);
4834   DEFSUBR (Fresize_subwindow);
4835   DEFSUBR (Fforce_subwindow_map);
4836
4837   /* Qnothing defined as part of the "nothing" image-instantiator
4838      type. */
4839   /* Qtext defined in general.c */
4840   defsymbol (&Qmono_pixmap, "mono-pixmap");
4841   defsymbol (&Qcolor_pixmap, "color-pixmap");
4842   /* Qpointer defined in general.c */
4843
4844   /* glyphs */
4845
4846   defsymbol (&Qglyphp, "glyphp");
4847   defsymbol (&Qcontrib_p, "contrib-p");
4848   defsymbol (&Qbaseline, "baseline");
4849
4850   defsymbol (&Qbuffer_glyph_p, "buffer-glyph-p");
4851   defsymbol (&Qpointer_glyph_p, "pointer-glyph-p");
4852   defsymbol (&Qicon_glyph_p, "icon-glyph-p");
4853
4854   defsymbol (&Qconst_glyph_variable, "const-glyph-variable");
4855
4856   DEFSUBR (Fglyph_type);
4857   DEFSUBR (Fvalid_glyph_type_p);
4858   DEFSUBR (Fglyph_type_list);
4859   DEFSUBR (Fglyphp);
4860   DEFSUBR (Fmake_glyph_internal);
4861   DEFSUBR (Fglyph_width);
4862   DEFSUBR (Fglyph_ascent);
4863   DEFSUBR (Fglyph_descent);
4864   DEFSUBR (Fglyph_height);
4865
4866   /* Qbuffer defined in general.c. */
4867   /* Qpointer defined above */
4868
4869   /* Unfortunately, timeout handlers must be lisp functions. This is
4870      for animated glyphs. */
4871   defsymbol (&Qglyph_animated_timeout_handler,
4872              "glyph-animated-timeout-handler");
4873   DEFSUBR (Fglyph_animated_timeout_handler);
4874
4875   /* Errors */
4876   deferror (&Qimage_conversion_error,
4877             "image-conversion-error",
4878             "image-conversion error", Qio_error);
4879
4880 }
4881
4882 static const struct lrecord_description image_specifier_description[] = {
4883   { XD_LISP_OBJECT, specifier_data_offset + offsetof (struct image_specifier, attachee) },
4884   { XD_LISP_OBJECT, specifier_data_offset + offsetof (struct image_specifier, attachee_property) },
4885   { XD_END }
4886 };
4887
4888 void
4889 specifier_type_create_image (void)
4890 {
4891   /* image specifiers */
4892
4893   INITIALIZE_SPECIFIER_TYPE_WITH_DATA (image, "image", "imagep");
4894
4895   SPECIFIER_HAS_METHOD (image, create);
4896   SPECIFIER_HAS_METHOD (image, mark);
4897   SPECIFIER_HAS_METHOD (image, instantiate);
4898   SPECIFIER_HAS_METHOD (image, validate);
4899   SPECIFIER_HAS_METHOD (image, after_change);
4900   SPECIFIER_HAS_METHOD (image, going_to_add);
4901   SPECIFIER_HAS_METHOD (image, copy_instantiator);
4902 }
4903
4904 void
4905 reinit_specifier_type_create_image (void)
4906 {
4907   REINITIALIZE_SPECIFIER_TYPE (image);
4908 }
4909
4910
4911 static const struct lrecord_description iike_description_1[] = {
4912   { XD_LISP_OBJECT, offsetof (ii_keyword_entry, keyword) },
4913   { XD_END }
4914 };
4915
4916 static const struct struct_description iike_description = {
4917   sizeof (ii_keyword_entry),
4918   iike_description_1
4919 };
4920
4921 static const struct lrecord_description iiked_description_1[] = {
4922   XD_DYNARR_DESC (ii_keyword_entry_dynarr, &iike_description),
4923   { XD_END }
4924 };
4925
4926 static const struct struct_description iiked_description = {
4927   sizeof (ii_keyword_entry_dynarr),
4928   iiked_description_1
4929 };
4930
4931 static const struct lrecord_description iife_description_1[] = {
4932   { XD_LISP_OBJECT, offsetof (image_instantiator_format_entry, symbol) },
4933   { XD_LISP_OBJECT, offsetof (image_instantiator_format_entry, device) },
4934   { XD_STRUCT_PTR,  offsetof (image_instantiator_format_entry, meths),  1, &iim_description },
4935   { XD_END }
4936 };
4937
4938 static const struct struct_description iife_description = {
4939   sizeof (image_instantiator_format_entry),
4940   iife_description_1
4941 };
4942
4943 static const struct lrecord_description iifed_description_1[] = {
4944   XD_DYNARR_DESC (image_instantiator_format_entry_dynarr, &iife_description),
4945   { XD_END }
4946 };
4947
4948 static const struct struct_description iifed_description = {
4949   sizeof (image_instantiator_format_entry_dynarr),
4950   iifed_description_1
4951 };
4952
4953 static const struct lrecord_description iim_description_1[] = {
4954   { XD_LISP_OBJECT, offsetof (struct image_instantiator_methods, symbol) },
4955   { XD_LISP_OBJECT, offsetof (struct image_instantiator_methods, device) },
4956   { XD_STRUCT_PTR,  offsetof (struct image_instantiator_methods, keywords), 1, &iiked_description },
4957   { XD_STRUCT_PTR,  offsetof (struct image_instantiator_methods, consoles), 1, &cted_description },
4958   { XD_END }
4959 };
4960
4961 const struct struct_description iim_description = {
4962   sizeof(struct image_instantiator_methods),
4963   iim_description_1
4964 };
4965
4966 void
4967 image_instantiator_format_create (void)
4968 {
4969   /* image instantiators */
4970
4971   the_image_instantiator_format_entry_dynarr =
4972     Dynarr_new (image_instantiator_format_entry);
4973
4974   Vimage_instantiator_format_list = Qnil;
4975   staticpro (&Vimage_instantiator_format_list);
4976
4977   dumpstruct (&the_image_instantiator_format_entry_dynarr, &iifed_description);
4978
4979   INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (nothing, "nothing");
4980
4981   IIFORMAT_HAS_METHOD (nothing, possible_dest_types);
4982   IIFORMAT_HAS_METHOD (nothing, instantiate);
4983
4984   INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (inherit, "inherit");
4985
4986   IIFORMAT_HAS_METHOD (inherit, validate);
4987   IIFORMAT_HAS_METHOD (inherit, normalize);
4988   IIFORMAT_HAS_METHOD (inherit, possible_dest_types);
4989   IIFORMAT_HAS_METHOD (inherit, instantiate);
4990
4991   IIFORMAT_VALID_KEYWORD (inherit, Q_face, check_valid_face);
4992
4993   INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (string, "string");
4994
4995   IIFORMAT_HAS_METHOD (string, validate);
4996   IIFORMAT_HAS_SHARED_METHOD (string, governing_domain, subwindow);
4997   IIFORMAT_HAS_METHOD (string, possible_dest_types);
4998   IIFORMAT_HAS_METHOD (string, instantiate);
4999
5000   IIFORMAT_VALID_KEYWORD (string, Q_data, check_valid_string);
5001   /* Do this so we can set strings. */
5002   /* #### Andy, what is this?  This is a bogus format and should not be
5003      visible to the user. */
5004   INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (text, "text");
5005   IIFORMAT_HAS_METHOD (text, set_property);
5006   IIFORMAT_HAS_METHOD (text, query_geometry);
5007
5008   INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (formatted_string, "formatted-string");
5009
5010   IIFORMAT_HAS_METHOD (formatted_string, validate);
5011   IIFORMAT_HAS_METHOD (formatted_string, possible_dest_types);
5012   IIFORMAT_HAS_METHOD (formatted_string, instantiate);
5013   IIFORMAT_VALID_KEYWORD (formatted_string, Q_data, check_valid_string);
5014
5015   /* Do this so pointers have geometry. */
5016   /* #### Andy, what is this?  This is a bogus format and should not be
5017      visible to the user. */
5018   INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (pointer, "pointer");
5019   IIFORMAT_HAS_SHARED_METHOD (pointer, query_geometry, subwindow);
5020
5021   /* subwindows */
5022   INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (subwindow, "subwindow");
5023   IIFORMAT_HAS_METHOD (subwindow, possible_dest_types);
5024   IIFORMAT_HAS_METHOD (subwindow, governing_domain);
5025   IIFORMAT_HAS_METHOD (subwindow, instantiate);
5026   IIFORMAT_HAS_METHOD (subwindow, query_geometry);
5027   IIFORMAT_VALID_KEYWORD (subwindow, Q_pixel_width, check_valid_int);
5028   IIFORMAT_VALID_KEYWORD (subwindow, Q_pixel_height, check_valid_int);
5029
5030 #ifdef HAVE_WINDOW_SYSTEM
5031   INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (xbm, "xbm");
5032
5033   IIFORMAT_HAS_METHOD (xbm, validate);
5034   IIFORMAT_HAS_METHOD (xbm, normalize);
5035   IIFORMAT_HAS_METHOD (xbm, possible_dest_types);
5036
5037   IIFORMAT_VALID_KEYWORD (xbm, Q_data, check_valid_xbm_inline);
5038   IIFORMAT_VALID_KEYWORD (xbm, Q_file, check_valid_string);
5039   IIFORMAT_VALID_KEYWORD (xbm, Q_mask_data, check_valid_xbm_inline);
5040   IIFORMAT_VALID_KEYWORD (xbm, Q_mask_file, check_valid_string);
5041   IIFORMAT_VALID_KEYWORD (xbm, Q_hotspot_x, check_valid_int);
5042   IIFORMAT_VALID_KEYWORD (xbm, Q_hotspot_y, check_valid_int);
5043   IIFORMAT_VALID_KEYWORD (xbm, Q_foreground, check_valid_string);
5044   IIFORMAT_VALID_KEYWORD (xbm, Q_background, check_valid_string);
5045 #endif /* HAVE_WINDOW_SYSTEM */
5046
5047 #ifdef HAVE_XFACE
5048   INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (xface, "xface");
5049
5050   IIFORMAT_HAS_METHOD (xface, validate);
5051   IIFORMAT_HAS_METHOD (xface, normalize);
5052   IIFORMAT_HAS_METHOD (xface, possible_dest_types);
5053
5054   IIFORMAT_VALID_KEYWORD (xface, Q_data, check_valid_string);
5055   IIFORMAT_VALID_KEYWORD (xface, Q_file, check_valid_string);
5056   IIFORMAT_VALID_KEYWORD (xface, Q_hotspot_x, check_valid_int);
5057   IIFORMAT_VALID_KEYWORD (xface, Q_hotspot_y, check_valid_int);
5058   IIFORMAT_VALID_KEYWORD (xface, Q_foreground, check_valid_string);
5059   IIFORMAT_VALID_KEYWORD (xface, Q_background, check_valid_string);
5060 #endif
5061
5062 #ifdef HAVE_XPM
5063   INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (xpm, "xpm");
5064
5065   IIFORMAT_HAS_METHOD (xpm, validate);
5066   IIFORMAT_HAS_METHOD (xpm, normalize);
5067   IIFORMAT_HAS_METHOD (xpm, possible_dest_types);
5068
5069   IIFORMAT_VALID_KEYWORD (xpm, Q_data, check_valid_string);
5070   IIFORMAT_VALID_KEYWORD (xpm, Q_file, check_valid_string);
5071   IIFORMAT_VALID_KEYWORD (xpm, Q_color_symbols, check_valid_xpm_color_symbols);
5072 #endif /* HAVE_XPM */
5073 }
5074
5075 void
5076 reinit_vars_of_glyphs (void)
5077 {
5078   the_expose_ignore_blocktype =
5079     Blocktype_new (struct expose_ignore_blocktype);
5080
5081   hold_ignored_expose_registration = 0;
5082 }
5083
5084
5085 void
5086 vars_of_glyphs (void)
5087 {
5088   reinit_vars_of_glyphs ();
5089
5090   Vthe_nothing_vector = vector1 (Qnothing);
5091   staticpro (&Vthe_nothing_vector);
5092
5093   /* image instances */
5094
5095   Vimage_instance_type_list = Fcons (Qnothing,
5096                                      list6 (Qtext, Qmono_pixmap, Qcolor_pixmap,
5097                                             Qpointer, Qsubwindow, Qwidget));
5098   staticpro (&Vimage_instance_type_list);
5099
5100   /* glyphs */
5101
5102   Vglyph_type_list = list3 (Qbuffer, Qpointer, Qicon);
5103   staticpro (&Vglyph_type_list);
5104
5105   /* The octal-escape glyph, control-arrow-glyph and
5106      invisible-text-glyph are completely initialized in glyphs.el */
5107
5108   DEFVAR_LISP ("octal-escape-glyph", &Voctal_escape_glyph /*
5109 What to prefix character codes displayed in octal with.
5110 */);
5111   Voctal_escape_glyph = allocate_glyph (GLYPH_BUFFER, redisplay_glyph_changed);
5112
5113   DEFVAR_LISP ("control-arrow-glyph", &Vcontrol_arrow_glyph /*
5114 What to use as an arrow for control characters.
5115 */);
5116   Vcontrol_arrow_glyph = allocate_glyph (GLYPH_BUFFER,
5117                                          redisplay_glyph_changed);
5118
5119   DEFVAR_LISP ("invisible-text-glyph", &Vinvisible_text_glyph /*
5120 What to use to indicate the presence of invisible text.
5121 This is the glyph that is displayed when an ellipsis is called for
5122 \(see `selective-display-ellipses' and `buffer-invisibility-spec').
5123 Normally this is three dots ("...").
5124 */);
5125   Vinvisible_text_glyph = allocate_glyph (GLYPH_BUFFER,
5126                                           redisplay_glyph_changed);
5127
5128   /* Partially initialized in glyphs.el */
5129   DEFVAR_LISP ("hscroll-glyph", &Vhscroll_glyph /*
5130 What to display at the beginning of horizontally scrolled lines.
5131 */);
5132   Vhscroll_glyph = allocate_glyph (GLYPH_BUFFER, redisplay_glyph_changed);
5133 #ifdef HAVE_WINDOW_SYSTEM
5134   Fprovide (Qxbm);
5135 #endif
5136 #ifdef HAVE_XPM
5137   Fprovide (Qxpm);
5138
5139   DEFVAR_LISP ("xpm-color-symbols", &Vxpm_color_symbols /*
5140 Definitions of logical color-names used when reading XPM files.
5141 Elements of this list should be of the form (COLOR-NAME FORM-TO-EVALUATE).
5142 The COLOR-NAME should be a string, which is the name of the color to define;
5143 the FORM should evaluate to a `color' specifier object, or a string to be
5144 passed to `make-color-instance'.  If a loaded XPM file references a symbolic
5145 color called COLOR-NAME, it will display as the computed color instead.
5146
5147 The default value of this variable defines the logical color names
5148 \"foreground\" and \"background\" to be the colors of the `default' face.
5149 */ );
5150   Vxpm_color_symbols = Qnil; /* initialized in x-faces.el */
5151 #endif /* HAVE_XPM */
5152 #ifdef HAVE_XFACE
5153   Fprovide (Qxface);
5154 #endif
5155
5156   DEFVAR_BOOL ("disable-animated-pixmaps", &disable_animated_pixmaps /*
5157 Whether animated pixmaps should be animated.
5158 Default is t.
5159 */);
5160   disable_animated_pixmaps = 0;
5161 }
5162
5163 void
5164 specifier_vars_of_glyphs (void)
5165 {
5166   /* #### Can we GC here? The set_specifier_* calls definitely need */
5167   /* protection. */
5168   /* display tables */
5169
5170   DEFVAR_SPECIFIER ("current-display-table", &Vcurrent_display_table /*
5171 *The display table currently in use.
5172 This is a specifier; use `set-specifier' to change it.
5173
5174 Display tables are used to control how characters are displayed.  Each
5175 time that redisplay processes a character, it is looked up in all the
5176 display tables that apply (obtained by calling `specifier-instance' on
5177 `current-display-table' and any overriding display tables specified in
5178 currently active faces).  The first entry found that matches the
5179 character determines how the character is displayed.  If there is no
5180 matching entry, the default display method is used. (Non-control
5181 characters are displayed as themselves and control characters are
5182 displayed according to the buffer-local variable `ctl-arrow'.  Control
5183 characters are further affected by `control-arrow-glyph' and
5184 `octal-escape-glyph'.)
5185
5186 Each instantiator in this specifier and the display-table specifiers
5187 in faces is a display table or a list of such tables.  If a list, each
5188 table will be searched in turn for an entry matching a particular
5189 character.  Each display table is one of
5190
5191 -- a vector, specifying values for characters starting at 0
5192 -- a char table, either of type `char' or `generic'
5193 -- a range table
5194
5195 Each entry in a display table should be one of
5196
5197 -- nil (this entry is ignored and the search continues)
5198 -- a character (use this character; if it happens to be the same as
5199    the original character, default processing happens, otherwise
5200    redisplay attempts to display this character directly;
5201    #### At some point recursive display-table lookup will be
5202    implemented.)
5203 -- a string (display each character in the string directly;
5204    #### At some point recursive display-table lookup will be
5205    implemented.)
5206 -- a glyph (display the glyph;
5207    #### At some point recursive display-table lookup will be
5208    implemented when a string glyph is being processed.)
5209 -- a cons of the form (format "STRING") where STRING is a printf-like
5210    spec used to process the character. #### Unfortunately no
5211    formatting directives other than %% are implemented.
5212 -- a vector (each element of the vector is processed recursively;
5213    in such a case, nil elements in the vector are simply ignored)
5214
5215 #### At some point in the near future, display tables are likely to
5216 be expanded to include other features, such as referencing characters
5217 in particular fonts and allowing the character search to continue
5218 all the way up the chain of specifier instantiators.  These features
5219 are necessary to properly display Unicode characters.
5220 */ );
5221   Vcurrent_display_table = Fmake_specifier (Qdisplay_table);
5222   set_specifier_fallback (Vcurrent_display_table,
5223                           list1 (Fcons (Qnil, Qnil)));
5224   set_specifier_caching (Vcurrent_display_table,
5225                          offsetof (struct window, display_table),
5226                          some_window_value_changed,
5227                          0, 0);
5228 }
5229
5230 void
5231 complex_vars_of_glyphs (void)
5232 {
5233   /* Partially initialized in glyphs-x.c, glyphs.el */
5234   DEFVAR_LISP ("truncation-glyph", &Vtruncation_glyph /*
5235 What to display at the end of truncated lines.
5236 */ );
5237   Vtruncation_glyph = allocate_glyph (GLYPH_BUFFER, redisplay_glyph_changed);
5238
5239   /* Partially initialized in glyphs-x.c, glyphs.el */
5240   DEFVAR_LISP ("continuation-glyph", &Vcontinuation_glyph /*
5241 What to display at the end of wrapped lines.
5242 */ );
5243   Vcontinuation_glyph = allocate_glyph (GLYPH_BUFFER, redisplay_glyph_changed);
5244
5245   /* Partially initialized in glyphs-x.c, glyphs.el */
5246   DEFVAR_LISP ("xemacs-logo", &Vxemacs_logo /*
5247 The glyph used to display the XEmacs logo at startup.
5248 */ );
5249   Vxemacs_logo = allocate_glyph (GLYPH_BUFFER, 0);
5250 }