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