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