XEmacs 21.2.28 "Hermes".
[chise/xemacs-chise.git.1] / src / glyphs-widget.c
1 /* Widget-specific glyph objects.
2    Copyright (C) 1998, 1999, 2000 Andy Piper.
3
4 This file is part of XEmacs.
5
6 XEmacs is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
9 later version.
10
11 XEmacs is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with XEmacs; see the file COPYING.  If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA.  */
20
21 /* Synched up with: Not in FSF. */
22
23 /* written by Andy Piper <andy@xemacs.org> */
24
25 #include <config.h>
26 #include "lisp.h"
27 #include "lstream.h"
28 #include "console.h"
29 #include "device.h"
30 #include "faces.h"
31 #include "glyphs.h"
32 #include "objects.h"
33 #include "bytecode.h"
34 #include "window.h"
35 #include "buffer.h"
36 #include "frame.h"
37 #include "insdel.h"
38 #include "opaque.h"
39
40 DEFINE_IMAGE_INSTANTIATOR_FORMAT (button);
41 DEFINE_IMAGE_INSTANTIATOR_FORMAT (combo_box);
42 Lisp_Object Qcombo_box;
43 DEFINE_IMAGE_INSTANTIATOR_FORMAT (edit_field);
44 Lisp_Object Qedit_field;
45 DEFINE_IMAGE_INSTANTIATOR_FORMAT (scrollbar);
46 Lisp_Object Qscrollbar;
47 DEFINE_IMAGE_INSTANTIATOR_FORMAT (widget);
48 DEFINE_IMAGE_INSTANTIATOR_FORMAT (label);
49 Lisp_Object Qlabel;
50 DEFINE_IMAGE_INSTANTIATOR_FORMAT (progress_gauge);
51 Lisp_Object Qprogress_gauge;
52 DEFINE_IMAGE_INSTANTIATOR_FORMAT (tree_view);
53 Lisp_Object Qtree_view;
54 DEFINE_IMAGE_INSTANTIATOR_FORMAT (tab_control);
55 Lisp_Object Qtab_control;
56 DEFINE_IMAGE_INSTANTIATOR_FORMAT (layout);
57 Lisp_Object Qlayout;
58
59 Lisp_Object Q_descriptor, Q_height, Q_width, Q_properties, Q_items;
60 Lisp_Object Q_image, Q_text, Q_percent, Q_orientation, Q_justify, Q_border;
61 Lisp_Object Qetched_in, Qetched_out, Qbevel_in, Qbevel_out;
62
63 #ifdef DEBUG_WIDGETS
64 int debug_widget_instances;
65 #endif
66
67 /* TODO:
68    - tooltips for controls, especially buttons.
69    - keyboard traversal.
70    - lisp configurable layout.
71  */
72
73 /* In MS-Windows normal windows work in pixels, dialog boxes work in
74    dialog box units. Why? sigh. We could reuse the metrics for dialogs
75    if this were not the case. As it is we have to position things
76    pixel wise. I'm not even sure that X has this problem at least for
77    buttons in groups. */
78 static int
79 widget_possible_dest_types (void)
80 {
81   return IMAGE_WIDGET_MASK;
82 }
83
84 static void
85 check_valid_glyph_or_instantiator (Lisp_Object data)
86 {
87   Lisp_Object glyph = data;
88   if (SYMBOLP (data))
89     glyph = XSYMBOL (data)->value;
90
91   if (IMAGE_INSTANCEP (glyph))
92     CHECK_IMAGE_INSTANCE (glyph);
93   else if (!CONSP (glyph) && !VECTORP (glyph))
94     CHECK_BUFFER_GLYPH (glyph);
95 }
96
97 static void
98 check_valid_orientation (Lisp_Object data)
99 {
100   if (!EQ (data, Qhorizontal)
101       &&
102       !EQ (data, Qvertical))
103     signal_simple_error ("unknown orientation for layout", data);
104 }
105
106 static void
107 check_valid_tab_orientation (Lisp_Object data)
108 {
109   if (!EQ (data, Qtop)
110       &&
111       !EQ (data, Qbottom)
112       &&
113       !EQ (data, Qleft)
114       &&
115       !EQ (data, Qright))
116     signal_simple_error ("unknown orientation for tab control", data);
117 }
118
119 static void
120 check_valid_justification (Lisp_Object data)
121 {
122   if (!EQ (data, Qleft) && !EQ (data, Qright) && !EQ (data, Qcenter))
123     signal_simple_error ("unknown justification for layout", data);
124 }
125
126 static void
127 check_valid_border (Lisp_Object data)
128 {
129   if (!EQ (data, Qt) && !EQ (data, Qetched_in) && !EQ (data, Qetched_out)
130       && !EQ (data, Qbevel_in) && !EQ (data, Qbevel_out)
131       && !GLYPHP (data) && !VECTORP (data))
132     signal_simple_error ("unknown border style for layout", data);
133 }
134
135 static void
136 check_valid_anything (Lisp_Object data)
137 {
138 }
139
140 static void
141 check_valid_callback (Lisp_Object data)
142 {
143     if (!SYMBOLP (data)
144         && !COMPILED_FUNCTIONP (data)
145         && !CONSP (data))
146     {
147         signal_simple_error (":callback must be a function or expression", data);
148     }
149 }
150
151 static void
152 check_valid_symbol (Lisp_Object data)
153 {
154     CHECK_SYMBOL (data);
155 }
156
157 static void
158 check_valid_string_or_vector (Lisp_Object data)
159 {
160     if (!STRINGP (data) && !VECTORP (data))
161         signal_simple_error (":descriptor must be a string or a vector", data);
162 }
163
164 void
165 check_valid_item_list_1 (Lisp_Object items)
166 {
167   Lisp_Object rest;
168
169   CHECK_LIST (items);
170   EXTERNAL_LIST_LOOP (rest, items)
171     {
172       if (STRINGP (XCAR (rest)))
173         CHECK_STRING (XCAR (rest));
174       else if (VECTORP (XCAR (rest)))
175         gui_parse_item_keywords (XCAR (rest));
176       else if (LISTP (XCAR (rest)))
177         check_valid_item_list_1 (XCAR (rest));
178       else
179         signal_simple_error ("Items must be vectors, lists or strings", items);
180     }
181 }
182
183 static void
184 check_valid_item_list (Lisp_Object data)
185 {
186   Lisp_Object items;
187
188   Fcheck_valid_plist (data);
189   items = Fplist_get (data, Q_items, Qnil);
190
191   check_valid_item_list_1 (items);
192 }
193
194 static void
195 check_valid_glyph_or_instantiator_list (Lisp_Object data)
196 {
197   Lisp_Object rest;
198
199   CHECK_LIST (data);
200   EXTERNAL_LIST_LOOP (rest, data)
201     {
202       check_valid_glyph_or_instantiator (XCAR (rest));
203     }
204 }
205
206 static Lisp_Object
207 glyph_instantiator_to_glyph (Lisp_Object sym)
208 {
209   /* This function calls lisp. */
210   Lisp_Object glyph = sym;
211   struct gcpro gcpro1;
212           
213   GCPRO1 (glyph);
214   /* if we have a symbol get at the actual data */
215   if (SYMBOLP (glyph))
216     glyph = XSYMBOL (glyph)->value;
217           
218   if (CONSP (glyph))
219     glyph = Feval (glyph);
220
221   /* Be really helpful to the user. */
222   if (VECTORP (glyph))
223     {
224       glyph = call1 (intern ("make-glyph"), glyph);
225     }
226
227   /* substitute the new glyph */
228   RETURN_UNGCPRO (glyph);
229 }
230
231 static void 
232 substitute_keyword_value (Lisp_Object inst, Lisp_Object key, Lisp_Object val)
233 {
234   int i;
235   /* substitute the new glyph */
236   for (i = 0; i < XVECTOR_LENGTH (inst); i++)
237     {
238       if (EQ (key, XVECTOR_DATA (inst)[i]))
239         {
240           XVECTOR_DATA (inst)[i+1] = val;
241           break;
242         }
243     }
244 }
245
246 /* Wire widget property invocations to specific widgets. The problem
247    we are solving here is that when instantiators get converted to
248    instances they lose some type information (they just become
249    subwindows or widgets for example). For widgets we need to preserve
250    this type information so that we can do widget specific operations
251    on the instances. This is encoded in the widget type
252    field. widget_property gets invoked by decoding the primary type
253    (Qwidget), <widget>_property then invokes based on the secondary
254    type (Qedit_field for example). It is debatable whether we should
255    wire things in this generalised way rather than treating widgets
256    specially in image_instance_property. */
257 static Lisp_Object 
258 widget_property (Lisp_Object image_instance, Lisp_Object prop)
259 {
260   Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance);
261   struct image_instantiator_methods* meths;
262
263   /* first see if its a general property ... */
264   if (!NILP (Fplist_member (IMAGE_INSTANCE_WIDGET_PROPS (ii), prop)))
265     return Fplist_get (IMAGE_INSTANCE_WIDGET_PROPS (ii), prop, Qnil);
266
267   /* .. then try device specific methods ... */
268   meths = decode_device_ii_format (IMAGE_INSTANCE_DEVICE (ii), 
269                                    IMAGE_INSTANCE_WIDGET_TYPE (ii), 
270                                    ERROR_ME_NOT);
271   if (meths && HAS_IIFORMAT_METH_P (meths, property))
272     return IIFORMAT_METH (meths, property, (image_instance, prop));
273   /* ... then format specific methods ... */
274   meths = decode_device_ii_format (Qnil, IMAGE_INSTANCE_WIDGET_TYPE (ii), 
275                                    ERROR_ME_NOT);
276   if (meths && HAS_IIFORMAT_METH_P (meths, property))
277     return IIFORMAT_METH (meths, property, (image_instance, prop));
278   /* ... then fail */
279   return Qunbound;
280 }
281
282 static Lisp_Object 
283 widget_set_property (Lisp_Object image_instance, Lisp_Object prop, Lisp_Object val)
284 {
285   Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance);
286   struct image_instantiator_methods* meths;
287   Lisp_Object ret;
288
289   /* PIck up any generic properties that we might need to keep hold
290      of. */
291   if (EQ (prop, Q_text))
292     {
293       IMAGE_INSTANCE_WIDGET_TEXT (ii) = val;
294     }
295
296   /* Now try device specific methods first ... */
297   meths = decode_device_ii_format (IMAGE_INSTANCE_DEVICE (ii), 
298                                    IMAGE_INSTANCE_WIDGET_TYPE (ii), 
299                                    ERROR_ME_NOT);
300   if (meths && HAS_IIFORMAT_METH_P (meths, set_property)
301       &&
302       !UNBOUNDP (ret = 
303                  IIFORMAT_METH (meths, set_property, (image_instance, prop, val))))
304     {
305       return ret;
306     }
307   /* ... then format specific methods ... */
308   meths = decode_device_ii_format (Qnil, IMAGE_INSTANCE_WIDGET_TYPE (ii), 
309                                    ERROR_ME_NOT);
310   if (meths && HAS_IIFORMAT_METH_P (meths, set_property)
311       &&
312       !UNBOUNDP (ret = 
313                  IIFORMAT_METH (meths, set_property, (image_instance, prop, val))))
314     {
315       return ret;
316     }
317   /* we didn't do any device specific properties, so shove the property in our plist */
318   IMAGE_INSTANCE_WIDGET_PROPS (ii)
319     = Fplist_put (IMAGE_INSTANCE_WIDGET_PROPS (ii), prop, val);
320   return val;
321 }
322
323 /* Query for a widgets desired geometry. If no type specific method is
324    provided then use the widget text to calculate sizes. */
325 static void 
326 widget_query_geometry (Lisp_Object image_instance, 
327                        unsigned int* width, unsigned int* height,
328                        enum image_instance_geometry disp, Lisp_Object domain)
329 {
330   Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance);
331   struct image_instantiator_methods* meths;
332
333   /* First just set up what we already have. */
334   if (width)    *width = IMAGE_INSTANCE_WIDTH (ii);
335   if (height)   *height = IMAGE_INSTANCE_HEIGHT (ii);
336   
337   if (IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii)
338       ||
339       IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii))
340     {
341       /* .. then try device specific methods ... */
342       meths = decode_device_ii_format (IMAGE_INSTANCE_DEVICE (ii), 
343                                        IMAGE_INSTANCE_WIDGET_TYPE (ii), 
344                                        ERROR_ME_NOT);
345       if (meths && HAS_IIFORMAT_METH_P (meths, query_geometry))
346         IIFORMAT_METH (meths, query_geometry, (image_instance, 
347                                                width, height, disp,
348                                                domain));
349       else
350         {
351           /* ... then format specific methods ... */
352           meths = decode_device_ii_format (Qnil, IMAGE_INSTANCE_WIDGET_TYPE (ii), 
353                                            ERROR_ME_NOT);
354           if (meths && HAS_IIFORMAT_METH_P (meths, query_geometry))
355             IIFORMAT_METH (meths, query_geometry, (image_instance, 
356                                                    width, height, disp,
357                                                    domain));
358           else 
359             {
360               unsigned int w, h;
361               
362               /* Then if we are allowed to resize the widget, make the
363                  size the same as the text dimensions. */
364               query_string_geometry (IMAGE_INSTANCE_WIDGET_TEXT (ii),
365                                      IMAGE_INSTANCE_WIDGET_FACE (ii),
366                                      &w, &h, 0, domain);
367               /* Adjust the size for borders. */
368               if (IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii))
369                 *width = w + 2 * WIDGET_BORDER_WIDTH;
370               if (IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii))
371                 *height = h +  2 * WIDGET_BORDER_HEIGHT;
372             }
373         }
374     }
375 }
376
377 static void 
378 widget_layout (Lisp_Object image_instance, 
379                unsigned int width, unsigned int height, Lisp_Object domain)
380 {
381   Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance);
382   struct image_instantiator_methods* meths;
383
384   /* .. then try device specific methods ... */
385   meths = decode_device_ii_format (IMAGE_INSTANCE_DEVICE (ii), 
386                                    IMAGE_INSTANCE_WIDGET_TYPE (ii), 
387                                    ERROR_ME_NOT);
388   if (meths && HAS_IIFORMAT_METH_P (meths, layout))
389     IIFORMAT_METH (meths, layout, (image_instance, 
390                                    width, height, domain));
391   else
392     {
393       /* ... then format specific methods ... */
394       meths = decode_device_ii_format (Qnil, IMAGE_INSTANCE_WIDGET_TYPE (ii), 
395                                        ERROR_ME_NOT);
396       if (meths && HAS_IIFORMAT_METH_P (meths, layout))
397         IIFORMAT_METH (meths, layout, (image_instance, 
398                                        width, height, domain));
399     }
400 }
401
402 static void
403 widget_validate (Lisp_Object instantiator)
404 {
405   Lisp_Object desc = find_keyword_in_vector (instantiator, Q_descriptor);
406
407   if (NILP (desc))
408     signal_simple_error ("Must supply :descriptor", instantiator);
409
410   if (VECTORP (desc))
411     gui_parse_item_keywords (desc);
412
413   if (!NILP (find_keyword_in_vector (instantiator, Q_width))
414       && !NILP (find_keyword_in_vector (instantiator, Q_pixel_width)))
415     signal_simple_error ("Must supply only one of :width and :pixel-width", instantiator);
416
417   if (!NILP (find_keyword_in_vector (instantiator, Q_height))
418              && !NILP (find_keyword_in_vector (instantiator, Q_pixel_height)))
419     signal_simple_error ("Must supply only one of :height and :pixel-height", instantiator);
420 }
421
422 static void
423 combo_box_validate (Lisp_Object instantiator)
424 {
425   widget_validate (instantiator);
426   if (NILP (find_keyword_in_vector (instantiator, Q_properties)))
427     signal_simple_error ("Must supply item list", instantiator);
428 }
429
430 /* we need to convert things like glyphs to images, eval expressions
431    etc.*/
432 static Lisp_Object
433 widget_normalize (Lisp_Object inst, Lisp_Object console_type)
434 {
435   /* This function can call lisp */
436   Lisp_Object glyph = find_keyword_in_vector (inst, Q_image);
437
438   /* we need to eval glyph if its an expression, we do this for the
439      same reasons we normalize file to data. */
440   if (!NILP (glyph))
441     {
442       substitute_keyword_value (inst, Q_image, glyph_instantiator_to_glyph (glyph));
443     }
444
445   return inst;
446 }
447
448 static void
449 initialize_widget_image_instance (Lisp_Image_Instance *ii, Lisp_Object type)
450 {
451   /*  initialize_subwindow_image_instance (ii);*/
452   IMAGE_INSTANCE_WIDGET_TYPE (ii) = type;
453   IMAGE_INSTANCE_WIDGET_PROPS (ii) = Qnil;
454   SET_IMAGE_INSTANCE_WIDGET_FACE (ii, Qnil);
455   IMAGE_INSTANCE_WIDGET_ITEMS (ii) = allocate_gui_item ();
456   IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii) = 1;
457   IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii) = 1;
458   IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) = 0;
459   IMAGE_INSTANCE_SUBWINDOW_JUSTIFY (ii) = 0;
460 }
461
462 /* Instantiate a button widget. Unfortunately instantiated widgets are
463    particular to a frame since they need to have a parent. It's not
464    like images where you just select the image into the context you
465    want to display it in and BitBlt it. So image instances can have a
466    many-to-one relationship with things you see, whereas widgets can
467    only be one-to-one (i.e. per frame) */
468 void
469 widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
470                     Lisp_Object pointer_fg, Lisp_Object pointer_bg,
471                     int dest_mask, Lisp_Object domain)
472 {
473   Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
474   Lisp_Object face = find_keyword_in_vector (instantiator, Q_face);
475   Lisp_Object height = find_keyword_in_vector (instantiator, Q_height);
476   Lisp_Object width = find_keyword_in_vector (instantiator, Q_width);
477   Lisp_Object pixwidth = find_keyword_in_vector (instantiator, Q_pixel_width);
478   Lisp_Object pixheight = find_keyword_in_vector (instantiator, Q_pixel_height);
479   Lisp_Object desc = find_keyword_in_vector (instantiator, Q_descriptor);
480   Lisp_Object glyph = find_keyword_in_vector (instantiator, Q_image);
481   Lisp_Object props = find_keyword_in_vector (instantiator, Q_properties);
482   Lisp_Object items = find_keyword_in_vector (instantiator, Q_items);
483   Lisp_Object orient = find_keyword_in_vector (instantiator, Q_orientation);
484   int pw=0, ph=0, tw=0, th=0;
485   
486   /* this just does pixel type sizing */
487   subwindow_instantiate (image_instance, instantiator, pointer_fg, pointer_bg,
488                          dest_mask, domain);
489
490   if (!(dest_mask & (IMAGE_WIDGET_MASK | IMAGE_LAYOUT_MASK)))
491     incompatible_image_types (instantiator, dest_mask, 
492                               IMAGE_WIDGET_MASK | IMAGE_LAYOUT_MASK);
493
494   initialize_widget_image_instance (ii, XVECTOR_DATA (instantiator)[0]);
495
496   IMAGE_INSTANCE_TYPE (ii) = IMAGE_WIDGET;
497   IMAGE_INSTANCE_WIDGET_PROPS (ii) = props;
498
499   /* retrieve the fg and bg colors */
500   if (!NILP (face))
501     SET_IMAGE_INSTANCE_WIDGET_FACE (ii, Fget_face (face));
502   
503   /* Do layout specific initialisation. This feels a bit tacky, but
504      the alternative is a myriad of different little functions. */
505   if (EQ (IMAGE_INSTANCE_WIDGET_TYPE (ii), Qlayout))
506     {
507       Lisp_Object rest, children = Qnil;
508       Lisp_Object border = find_keyword_in_vector (instantiator, Q_border);
509
510       if (NILP (orient))
511         {
512           IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) = LAYOUT_VERTICAL;
513         }
514       IMAGE_INSTANCE_TYPE (ii) = IMAGE_LAYOUT;
515       
516       if (EQ (border, Qt))
517         {
518           IMAGE_INSTANCE_LAYOUT_BORDER (ii) = Qetched_in;
519         }
520       else if (GLYPHP (border))
521         {
522           /* We are going to be sneaky here and add the border text as
523              just another child, the layout and output routines don't know
524              this and will just display at the offsets we prescribe. */
525           children = Fcons (glyph_image_instance (border, domain, ERROR_ME, 1),
526                             children);
527           IMAGE_INSTANCE_LAYOUT_BORDER (ii) = make_int (0);
528         }
529       else
530         {
531           IMAGE_INSTANCE_LAYOUT_BORDER (ii) = border;
532         }
533
534       /* Pick up the sub-widgets. */
535       LIST_LOOP (rest, items)
536         {
537           /* make sure the image is instantiated */
538           Lisp_Object gii = glyph_image_instance (XCAR (rest), domain, ERROR_ME, 1);
539           children = Fcons (gii, children);
540           /* Make sure elements in the layout are in the order the
541              user expected. */
542           children = Fnreverse (children);
543         }
544       IMAGE_INSTANCE_LAYOUT_CHILDREN (ii) = children;
545     }
546   /* retrieve the gui item information. This is easy if we have been
547      provided with a vector, more difficult if we have just been given
548      keywords */
549   else if (STRINGP (desc) || NILP (desc))
550     {
551       /* big cheat - we rely on the fact that a gui item looks like an instantiator */
552       IMAGE_INSTANCE_WIDGET_ITEMS (ii) = 
553         gui_parse_item_keywords_no_errors (instantiator);
554       IMAGE_INSTANCE_WIDGET_TEXT (ii) = desc;
555     }
556   else
557     IMAGE_INSTANCE_WIDGET_ITEMS (ii) =
558       gui_parse_item_keywords_no_errors (desc);
559
560   /* Pick up the orientation before we do our first layout. */
561   if (EQ (orient, Qleft) || EQ (orient, Qright) || EQ (orient, Qvertical))
562     IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) = 1;
563
564   /* parse more gui items out of the properties */
565   if (!NILP (props)
566       && !EQ (IMAGE_INSTANCE_WIDGET_TYPE (ii), Qlayout))
567     {
568       if (NILP (items))
569         {
570           items = Fplist_get (props, Q_items, Qnil);
571         }
572       if (!NILP (items))
573         {
574           IMAGE_INSTANCE_WIDGET_ITEMS (ii) = 
575             Fcons (IMAGE_INSTANCE_WIDGET_ITEMS (ii), 
576                    parse_gui_item_tree_children (items));
577         }
578     }
579
580   /* Normalize size information. We now only assign sizes if the user
581      gives us some explicitly, or there are some constraints that we
582      can't change later on. Otherwise we postpone sizing until query
583      geometry gets called. */
584   if (!NILP (pixwidth))         /* pixwidth takes precendent */
585     {
586       pw = XINT (pixwidth);
587       IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii) = 0;
588     }
589   else if (!NILP (width))
590     {
591       tw = XINT (width);
592       IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii) = 0;
593     }
594
595   if (!NILP (pixheight))
596     {
597       ph = XINT (pixheight);
598       IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii) = 0;
599     }
600   else if (!NILP (height) && XINT (height) > 1)
601     {
602       th = XINT (height);
603       IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii) = 0;
604     }
605
606   /* Taking the default face information when the user has specified
607      size in characters is probably as good as any since the widget
608      face is more likely to be proportional and thus give inadequate
609      results. Using character sizes can only ever be approximate
610      anyway. */
611   if (tw || th)
612     {
613       int charwidth, charheight;
614       default_face_font_info (domain, 0, 0, &charheight, &charwidth, 0);
615       if (tw)
616         pw = charwidth * tw;
617       if (th)
618         ph = charheight * th;
619     }
620
621   /* for a widget with an image pick up the dimensions from that */
622   if (!NILP (glyph))
623     {
624       if (!pw)
625         pw = glyph_width (glyph, domain) + 2 * WIDGET_BORDER_WIDTH;
626       if (!ph)
627         ph = glyph_height (glyph, domain) + 2 * WIDGET_BORDER_HEIGHT;
628       IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii) = 0;
629       IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii) = 0;
630     }
631
632   /* When we create the widgets the window system expects a valid
633      size, so If we still don' t have sizes, call layout to pick them
634      up. If query_geometry or layout relies on the widget being in
635      existence then we are in catch 22. */
636   image_instance_layout (image_instance, 
637                          pw ? pw : IMAGE_UNSPECIFIED_GEOMETRY,
638                          ph ? ph : IMAGE_UNSPECIFIED_GEOMETRY,
639                          domain);
640   /* Layout has already been done so we don't need to re-layout. */
641   IMAGE_INSTANCE_DIRTYP (ii) = 0;
642
643 #ifdef DEBUG_WIDGETS
644   debug_widget_instances++;
645   stderr_out ("instantiated ");
646   debug_print (instantiator);
647   stderr_out ("%d widgets instantiated\n", debug_widget_instances);
648 #endif
649 }
650
651 /* tree-view geometry - get the height right */
652 static void
653 tree_view_query_geometry (Lisp_Object image_instance, 
654                           unsigned int* width, unsigned int* height,
655                           enum image_instance_geometry disp, Lisp_Object domain)
656 {
657   Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
658   Lisp_Object items = IMAGE_INSTANCE_WIDGET_ITEMS (ii);
659
660   
661   if (*width)
662     {
663       /* #### what should this be. reconsider when X has tree views. */
664       query_string_geometry (IMAGE_INSTANCE_WIDGET_TEXT (ii),
665                              IMAGE_INSTANCE_WIDGET_FACE (ii),
666                              width, 0, 0, domain);
667     }
668   if (*height)
669     {
670       int len, h;
671       default_face_font_info (domain, 0, 0, &h, 0, 0);
672       GET_LIST_LENGTH (items, len);
673       *height = len * h;
674     }
675 }
676
677 /* Get the geometry of a tab control. This is based on the number of
678    items and text therin in the tab control. */
679 static void
680 tab_control_query_geometry (Lisp_Object image_instance, 
681                             unsigned int* width, unsigned int* height,
682                             enum image_instance_geometry disp, Lisp_Object domain)
683 {
684   Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
685   Lisp_Object items = IMAGE_INSTANCE_WIDGET_ITEMS (ii);
686   Lisp_Object rest;
687   unsigned int tw = 0, th = 0;
688
689   LIST_LOOP (rest, items)
690     {
691       unsigned int h, w;
692
693       query_string_geometry (XGUI_ITEM (XCAR (rest))->name,
694                              IMAGE_INSTANCE_WIDGET_FACE (ii),
695                              &w, &h, 0, domain);
696       tw += 2 * WIDGET_BORDER_WIDTH; /* some bias */
697       tw += w;
698       th = max (th, h + 2 * WIDGET_BORDER_HEIGHT);
699     }
700
701   /* Fixup returned values depending on orientation. */
702   if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii))
703     {
704       if (height)       *height = tw;
705       if (width)        *width = th;
706     }
707   else
708     {
709       if (height)       *height = th;
710       if (width)        *width = tw;
711     }
712 }
713
714 \f
715 /*****************************************************************************
716  *                              widget layout                               *
717  *****************************************************************************/
718 static int
719 layout_possible_dest_types (void)
720 {
721   return IMAGE_LAYOUT_MASK;
722 }
723
724 /* we need to convert things like glyphs to images, eval expressions
725    etc.*/
726 static Lisp_Object
727 layout_normalize (Lisp_Object inst, Lisp_Object console_type)
728 {
729   /* This function can call lisp */
730   Lisp_Object items = find_keyword_in_vector (inst, Q_items);
731   Lisp_Object border = find_keyword_in_vector (inst, Q_border);
732   /* we need to eval glyph if its an expression, we do this for the
733      same reasons we normalize file to data. */
734   if (!NILP (items))
735     {
736       Lisp_Object rest;
737       LIST_LOOP (rest, items)
738         {
739           /* substitute the new glyph */
740           Fsetcar (rest, glyph_instantiator_to_glyph (XCAR (rest)));
741         }
742     }
743   /* normalize the border spec. */
744   if (VECTORP (border) || CONSP (border))
745     {
746       substitute_keyword_value (inst, Q_border, glyph_instantiator_to_glyph (border));
747     }
748   return inst;
749 }
750
751 /* Layout widget. Sizing commentary: we have a number of problems that
752    we would like to address. Some consider some of these more
753    important than others. It used to be that size information was
754    determined at instantiation time and was then fixed forever
755    after. Generally this is not what we want. Users want size to be
756    "big enough" to accommodate whatever they are trying to show and
757    this is dependent on text length, lines, font metrics etc. Of
758    course these attributes can change dynamically and so the size
759    should changed dynamically also. Only in a few limited cases should
760    the size be fixed and remain fixed. Of course this actually means
761    that we don't really want to specifiy the size *at all* for most
762    widgets - we want it to be discovered dynamically. Thus we can
763    envisage the following scenarios:
764    
765    1. A button is sized to accommodate its text, the text changes and the
766    button should change size also.  
767
768    2. A button is given an explicit size. Its size should never change.
769
770    3. Layout is put inside an area. The size of the area changes, the
771    layout should change with it. 
772
773    4. A button grows to accommodate additional text. The whitespace
774    around it should be modified to cope with the new layout
775    requirements. 
776
777    5. A button grows. The area surrounding it should grow also if
778    possible. 
779
780    What metrics are important?
781    1. Actual width and height.
782    
783    2. Whether the width and height are what the widget actually wants, or
784    whether it can grow or shrink. 
785
786    Text glyphs are particularly troublesome since their metrics depend
787    on the context in which they are being viewed. For instance they
788    can appear differently depending on the window face, frame face or
789    glyph face. In order to simplify this text glyphs can now only have
790    a glyph-face or image-instance face. All other glyphs are
791    essentially fixed in appearance. Perhaps the problem is that text
792    glyphs are cached on a device basis like most other glyphs. Instead
793    they should be cached per-window and then the instance would be
794    fixed and we wouldn't have to mess around with font metrics and the
795    rest. */
796
797 /* Query the geometry of a layout widget. We assume that we can only
798    get here if the size is not already fixed. */
799 static void
800 layout_query_geometry (Lisp_Object image_instance, unsigned int* width,
801                        unsigned int* height, enum image_instance_geometry disp,
802                        Lisp_Object domain)
803 {
804   Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
805   Lisp_Object items = IMAGE_INSTANCE_LAYOUT_CHILDREN (ii), rest;
806   int maxph = 0, maxpw = 0, nitems = 0, ph_adjust = 0;
807
808   /* Flip through the items to work out how much stuff we have to display */
809   LIST_LOOP (rest, items)
810     {
811       Lisp_Object glyph = XCAR (rest);
812       unsigned int gheight, gwidth;
813       
814       image_instance_query_geometry (glyph, &gwidth, &gheight, disp, domain);
815
816       /* Pick up the border text if we have one. */
817       if (INTP (IMAGE_INSTANCE_LAYOUT_BORDER (ii))
818           && NILP (XCDR (rest)))
819         {
820           ph_adjust = gheight / 2;
821         }
822       else
823         {
824
825           nitems ++;
826           if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) 
827               == LAYOUT_HORIZONTAL)
828             {
829               maxph = max (maxph, gheight);
830               maxpw += gwidth;
831             }
832           else
833             {
834               maxpw = max (maxpw, gwidth);
835               maxph += gheight;
836             }
837         }
838     }
839
840   /* work out spacing between items and bounds of the layout.  No user
841       provided width so we just do default spacing. */
842   if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) 
843       == LAYOUT_HORIZONTAL)
844     *width = maxpw + (nitems + 1) * WIDGET_BORDER_WIDTH * 2;
845   else 
846     *width = maxpw + 2 * WIDGET_BORDER_WIDTH * 2;
847
848   /* Work out vertical spacings. */
849   if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) 
850       == LAYOUT_VERTICAL)
851     *height = maxph + (nitems + 1) * WIDGET_BORDER_HEIGHT * 2 + ph_adjust;
852   else 
853     *height = maxph + 2 * WIDGET_BORDER_HEIGHT * 2 + ph_adjust;
854 }
855
856
857 static void
858 layout_layout (Lisp_Object image_instance, 
859                unsigned int width, unsigned int height, Lisp_Object domain)
860 {
861   Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
862   Lisp_Object rest;
863   Lisp_Object items = IMAGE_INSTANCE_LAYOUT_CHILDREN (ii);
864   int x, y, maxph = 0, maxpw = 0, nitems = 0,
865     horiz_spacing, vert_spacing, ph_adjust = 0;
866   unsigned int gheight, gwidth;
867
868   /* flip through the items to work out how much stuff we have to display */
869   LIST_LOOP (rest, items)
870     {
871       Lisp_Object glyph = XCAR (rest);
872       
873       image_instance_query_geometry (glyph, &gwidth, &gheight, 
874                                      IMAGE_DESIRED_GEOMETRY, domain);
875
876       /* Pick up the border text if we have one. */
877       if (INTP (IMAGE_INSTANCE_LAYOUT_BORDER (ii))
878           && NILP (XCDR (rest)))
879         {
880           XIMAGE_INSTANCE_XOFFSET (glyph) = 10; /* Really, what should this be? */
881           XIMAGE_INSTANCE_YOFFSET (glyph) = 0;
882           ph_adjust = gheight / 2;
883           IMAGE_INSTANCE_LAYOUT_BORDER (ii) = make_int (ph_adjust);
884         }
885       else
886         {
887
888           nitems ++;
889           if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) 
890               == LAYOUT_HORIZONTAL)
891             {
892               maxph = max (maxph, gheight);
893               maxpw += gwidth;
894             }
895           else
896             {
897               maxpw = max (maxpw, gwidth);
898               maxph += gheight;
899             }
900         }
901     }
902
903   /* work out spacing between items and bounds of the layout */
904   if (width < maxpw)
905     /* The user wants a smaller space than the largest item, so we
906        just provide default spacing and will let the output routines
907        clip.. */
908     horiz_spacing = WIDGET_BORDER_WIDTH * 2;
909   else if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) 
910            == LAYOUT_HORIZONTAL)
911     /* We have a larger area to display in so distribute the space
912        evenly. */
913     horiz_spacing = (width - maxpw) / (nitems + 1);
914   else
915     horiz_spacing = (width - maxpw) / 2;
916
917   if (height < maxph)
918     vert_spacing = WIDGET_BORDER_HEIGHT * 2;
919   else if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) 
920            == LAYOUT_VERTICAL)
921     vert_spacing = (height - (maxph + ph_adjust)) / (nitems + 1);
922   else
923     vert_spacing = (height - (maxph + ph_adjust)) / 2;
924
925   y = vert_spacing + ph_adjust;
926   x = horiz_spacing;
927
928   /* Now flip through putting items where we want them, paying
929      attention to justification. Make sure we don't mess with the
930      border glyph. */
931   LIST_LOOP (rest, items)
932     {
933       Lisp_Object glyph = XCAR (rest);
934
935       image_instance_query_geometry (glyph, &gwidth, &gheight, 
936                                      IMAGE_DESIRED_GEOMETRY, domain);
937
938       if (!INTP (IMAGE_INSTANCE_LAYOUT_BORDER (ii))
939           || !NILP (XCDR (rest)))
940       {
941         if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) 
942             == LAYOUT_HORIZONTAL)
943           {
944             if (IMAGE_INSTANCE_SUBWINDOW_JUSTIFY (ii) 
945                 == LAYOUT_JUSTIFY_RIGHT)
946               y = height - (gheight + vert_spacing);
947             if (IMAGE_INSTANCE_SUBWINDOW_JUSTIFY (ii) 
948                 == LAYOUT_JUSTIFY_CENTER)
949               y = (height - gheight) / 2;
950           }
951         else 
952           {
953             if (IMAGE_INSTANCE_SUBWINDOW_JUSTIFY (ii) 
954                 == LAYOUT_JUSTIFY_RIGHT)
955               x = width - (gwidth + horiz_spacing);
956             if (IMAGE_INSTANCE_SUBWINDOW_JUSTIFY (ii) 
957                 == LAYOUT_JUSTIFY_CENTER)
958               x = (width - gwidth) / 2;
959           }
960         
961         XIMAGE_INSTANCE_XOFFSET (glyph) = x;
962         XIMAGE_INSTANCE_YOFFSET (glyph) = y;
963         
964         if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) 
965             == LAYOUT_HORIZONTAL)
966           {
967             x += (gwidth + horiz_spacing);
968           }
969         else
970           {
971             y += (gheight + vert_spacing);
972           }
973       }
974       
975       /* Now layout subwidgets if they require it. */
976       image_instance_layout (glyph, gwidth, gheight, domain);
977     }
978
979   IMAGE_INSTANCE_SUBWINDOW_WIDTH (ii) = width;
980   IMAGE_INSTANCE_SUBWINDOW_HEIGHT (ii) = height;
981 }
982
983 \f
984 /************************************************************************/
985 /*                            initialization                            */
986 /************************************************************************/
987
988 void
989 syms_of_glyphs_widget (void)
990 {
991   defkeyword (&Q_descriptor, ":descriptor");
992   defkeyword (&Q_height, ":height");
993   defkeyword (&Q_width, ":width");
994   defkeyword (&Q_properties, ":properties");
995   defkeyword (&Q_items, ":items");
996   defkeyword (&Q_image, ":image");
997   defkeyword (&Q_percent, ":percent");
998   defkeyword (&Q_text, ":text");
999   defkeyword (&Q_orientation, ":orientation");
1000   defkeyword (&Q_justify, ":justify");
1001   defkeyword (&Q_border, ":border");
1002
1003   defsymbol (&Qetched_in, "etched-in");
1004   defsymbol (&Qetched_out, "etched-out");
1005   defsymbol (&Qbevel_in, "bevel-in");
1006   defsymbol (&Qbevel_out, "bevel-out");
1007 }
1008
1009 #define VALID_GUI_KEYWORDS(type) do {                                                   \
1010   IIFORMAT_VALID_NONCOPY_KEYWORD (type, Q_active, check_valid_anything);                \
1011   IIFORMAT_VALID_KEYWORD (type, Q_suffix, check_valid_anything);                        \
1012   IIFORMAT_VALID_KEYWORD (type, Q_keys, check_valid_string);                            \
1013   IIFORMAT_VALID_KEYWORD (type, Q_style, check_valid_symbol);                           \
1014   IIFORMAT_VALID_NONCOPY_KEYWORD (type, Q_selected, check_valid_anything);              \
1015   IIFORMAT_VALID_KEYWORD (type, Q_filter, check_valid_anything);                        \
1016   IIFORMAT_VALID_KEYWORD (type, Q_config, check_valid_symbol);                          \
1017   IIFORMAT_VALID_KEYWORD (type, Q_included, check_valid_anything);                      \
1018   IIFORMAT_VALID_KEYWORD (type, Q_key_sequence, check_valid_string);                    \
1019   IIFORMAT_VALID_KEYWORD (type, Q_accelerator, check_valid_string);                     \
1020   IIFORMAT_VALID_KEYWORD (type, Q_label, check_valid_anything);                         \
1021   IIFORMAT_VALID_NONCOPY_KEYWORD (type, Q_callback, check_valid_callback);              \
1022   IIFORMAT_VALID_NONCOPY_KEYWORD (type, Q_descriptor, check_valid_string_or_vector);    \
1023 } while (0)
1024
1025 #define VALID_WIDGET_KEYWORDS(type) do {                                \
1026   IIFORMAT_VALID_KEYWORD (type, Q_width, check_valid_int);              \
1027   IIFORMAT_VALID_KEYWORD (type, Q_height, check_valid_int);             \
1028   IIFORMAT_VALID_KEYWORD (type, Q_pixel_width, check_valid_int);        \
1029   IIFORMAT_VALID_KEYWORD (type, Q_pixel_height, check_valid_int);       \
1030   IIFORMAT_VALID_KEYWORD (type, Q_face, check_valid_face);              \
1031 } while (0)
1032
1033
1034 static void image_instantiator_widget (void)
1035 { /* we only do this for properties */
1036   INITIALIZE_IMAGE_INSTANTIATOR_FORMAT_NO_SYM (widget, "widget");
1037   IIFORMAT_HAS_METHOD (widget, property);
1038   IIFORMAT_HAS_METHOD (widget, set_property);
1039   IIFORMAT_HAS_METHOD (widget, query_geometry);
1040   IIFORMAT_HAS_METHOD (widget, layout);
1041 }
1042
1043 static void image_instantiator_buttons (void)
1044 {
1045   INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (button, "button");
1046   IIFORMAT_HAS_SHARED_METHOD (button, validate, widget);
1047   IIFORMAT_HAS_SHARED_METHOD (button, possible_dest_types, widget);
1048   IIFORMAT_HAS_SHARED_METHOD (button, instantiate, widget);
1049   IIFORMAT_HAS_SHARED_METHOD (button, normalize, widget);
1050   IIFORMAT_VALID_KEYWORD (button,
1051                           Q_image, check_valid_glyph_or_instantiator);
1052   VALID_WIDGET_KEYWORDS (button);
1053   VALID_GUI_KEYWORDS (button);
1054 }
1055
1056 static void image_instantiator_edit_fields (void)
1057 {
1058   INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (edit_field, "edit-field");
1059   IIFORMAT_HAS_SHARED_METHOD (edit_field, validate, widget);
1060   IIFORMAT_HAS_SHARED_METHOD (edit_field, possible_dest_types, widget);
1061   IIFORMAT_HAS_SHARED_METHOD (edit_field, instantiate, widget);
1062   VALID_WIDGET_KEYWORDS (edit_field);
1063   VALID_GUI_KEYWORDS (edit_field);
1064 }
1065
1066 static void image_instantiator_combo_box (void)
1067 {
1068   INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (combo_box, "combo-box");
1069   IIFORMAT_HAS_METHOD (combo_box, validate);
1070   IIFORMAT_HAS_SHARED_METHOD (combo_box, possible_dest_types, widget);
1071   VALID_GUI_KEYWORDS (combo_box);
1072
1073   IIFORMAT_VALID_KEYWORD (combo_box, Q_width, check_valid_int);
1074   IIFORMAT_VALID_KEYWORD (combo_box, Q_height, check_valid_int);
1075   IIFORMAT_VALID_KEYWORD (combo_box, Q_pixel_width, check_valid_int);
1076   IIFORMAT_VALID_KEYWORD (combo_box, Q_face, check_valid_face);
1077   IIFORMAT_VALID_KEYWORD (combo_box, Q_properties, check_valid_item_list);
1078 }
1079
1080 static void image_instantiator_scrollbar (void)
1081 {
1082   INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (scrollbar, "scrollbar");
1083   IIFORMAT_HAS_SHARED_METHOD (scrollbar, validate, widget);
1084   IIFORMAT_HAS_SHARED_METHOD (scrollbar, possible_dest_types, widget);
1085   IIFORMAT_HAS_SHARED_METHOD (scrollbar, instantiate, widget);
1086   VALID_GUI_KEYWORDS (scrollbar);
1087
1088   IIFORMAT_VALID_KEYWORD (scrollbar, Q_pixel_width, check_valid_int);
1089   IIFORMAT_VALID_KEYWORD (scrollbar, Q_pixel_height, check_valid_int);
1090   IIFORMAT_VALID_KEYWORD (scrollbar, Q_face, check_valid_face);
1091 }
1092
1093 static void image_instantiator_progress_guage (void)
1094 {
1095   INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (progress_gauge, "progress-gauge");
1096   IIFORMAT_HAS_SHARED_METHOD (progress_gauge, validate, widget);
1097   IIFORMAT_HAS_SHARED_METHOD (progress_gauge, possible_dest_types, widget);
1098   IIFORMAT_HAS_SHARED_METHOD (progress_gauge, instantiate, widget);
1099   VALID_WIDGET_KEYWORDS (progress_gauge);
1100   VALID_GUI_KEYWORDS (progress_gauge);
1101 }
1102
1103 static void image_instantiator_tree_view (void)
1104 {
1105   INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (tree_view, "tree-view");
1106   IIFORMAT_HAS_SHARED_METHOD (tree_view, validate, combo_box);
1107   IIFORMAT_HAS_SHARED_METHOD (tree_view, possible_dest_types, widget);
1108   IIFORMAT_HAS_SHARED_METHOD (tree_view, instantiate, widget);
1109   IIFORMAT_HAS_METHOD (tree_view, query_geometry);
1110   VALID_WIDGET_KEYWORDS (tree_view);
1111   VALID_GUI_KEYWORDS (tree_view);
1112   IIFORMAT_VALID_KEYWORD (tree_view, Q_properties, check_valid_item_list);
1113 }
1114
1115 static void image_instantiator_tab_control (void)
1116 {
1117   INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (tab_control, "tab-control");
1118   IIFORMAT_HAS_SHARED_METHOD (tab_control, validate, combo_box);
1119   IIFORMAT_HAS_SHARED_METHOD (tab_control, possible_dest_types, widget);
1120   IIFORMAT_HAS_SHARED_METHOD (tab_control, instantiate, widget);
1121   IIFORMAT_HAS_METHOD (tab_control, query_geometry);
1122   VALID_WIDGET_KEYWORDS (tab_control);
1123   VALID_GUI_KEYWORDS (tab_control);
1124   IIFORMAT_VALID_KEYWORD (tab_control, Q_orientation, check_valid_tab_orientation);
1125   IIFORMAT_VALID_KEYWORD (tab_control, Q_properties, check_valid_item_list);
1126 }
1127
1128 static void image_instantiator_labels (void)
1129 {
1130   INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (label, "label");
1131   IIFORMAT_HAS_SHARED_METHOD (label, possible_dest_types, widget);
1132   IIFORMAT_HAS_SHARED_METHOD (label, instantiate, widget);
1133   VALID_WIDGET_KEYWORDS (label);
1134   IIFORMAT_VALID_KEYWORD (label, Q_descriptor, check_valid_string);
1135 }
1136
1137 static void image_instantiator_layout (void)
1138 {
1139   INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (layout, "layout");
1140   IIFORMAT_HAS_METHOD (layout, possible_dest_types);
1141   IIFORMAT_HAS_SHARED_METHOD (layout, instantiate, widget);
1142   IIFORMAT_HAS_METHOD (layout, normalize);
1143   IIFORMAT_HAS_METHOD (layout, query_geometry);
1144   IIFORMAT_HAS_METHOD (layout, layout);
1145   IIFORMAT_VALID_KEYWORD (layout, Q_pixel_width, check_valid_int);
1146   IIFORMAT_VALID_KEYWORD (layout, Q_pixel_height, check_valid_int);
1147   IIFORMAT_VALID_KEYWORD (layout, Q_orientation, check_valid_orientation);
1148   IIFORMAT_VALID_KEYWORD (layout, Q_justify, check_valid_justification);
1149   IIFORMAT_VALID_KEYWORD (layout, Q_border, check_valid_border);
1150   IIFORMAT_VALID_KEYWORD (layout, Q_items,
1151                           check_valid_glyph_or_instantiator_list);
1152 }
1153
1154 void
1155 image_instantiator_format_create_glyphs_widget (void)
1156 {
1157   image_instantiator_widget();
1158   image_instantiator_buttons();
1159   image_instantiator_edit_fields();
1160   image_instantiator_combo_box();
1161   image_instantiator_scrollbar();
1162   image_instantiator_progress_guage();
1163   image_instantiator_tree_view();
1164   image_instantiator_tab_control();
1165   image_instantiator_labels();
1166   image_instantiator_layout();
1167 }
1168
1169 void
1170 reinit_vars_of_glyphs_widget (void)
1171 {
1172 #ifdef DEBUG_WIDGETS
1173   debug_widget_instances = 0;
1174 #endif
1175 }
1176
1177 void
1178 vars_of_glyphs_widget (void)
1179 {
1180   reinit_vars_of_glyphs_widget ();
1181 }