This commit was generated by cvs2svn to compensate for changes in r1383,
[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       IMAGE_INSTANCE_TEXT_CHANGED (ii) = 1;
295     }
296
297   /* Now try device specific methods first ... */
298   meths = decode_device_ii_format (IMAGE_INSTANCE_DEVICE (ii), 
299                                    IMAGE_INSTANCE_WIDGET_TYPE (ii), 
300                                    ERROR_ME_NOT);
301   if (meths && HAS_IIFORMAT_METH_P (meths, set_property)
302       &&
303       !UNBOUNDP (ret = 
304                  IIFORMAT_METH (meths, set_property, (image_instance, prop, val))))
305     {
306       return ret;
307     }
308   /* ... then format specific methods ... */
309   meths = decode_device_ii_format (Qnil, IMAGE_INSTANCE_WIDGET_TYPE (ii), 
310                                    ERROR_ME_NOT);
311   if (meths && HAS_IIFORMAT_METH_P (meths, set_property)
312       &&
313       !UNBOUNDP (ret = 
314                  IIFORMAT_METH (meths, set_property, (image_instance, prop, val))))
315     {
316       return ret;
317     }
318   /* we didn't do any device specific properties, so shove the property in our plist */
319   IMAGE_INSTANCE_WIDGET_PROPS (ii)
320     = Fplist_put (IMAGE_INSTANCE_WIDGET_PROPS (ii), prop, val);
321   return val;
322 }
323
324 /* Like the rest of redisplay, we want widget updates to occur
325 asynchronously. Thus toolkit specific methods for setting properties
326 must be called by redisplay instead of by *_set_property. Thus
327 *_set_property records the change and this function actually
328 implements it. We want to be slightly clever about this however by
329 supplying format specific functions for the updates instead of lumping
330 them all into this function. Note that there is no need for format
331 generic functions. */
332 void
333 update_widget (Lisp_Object widget)
334 {
335   Lisp_Image_Instance* ii = XIMAGE_INSTANCE (widget);
336   struct image_instantiator_methods* meths;
337
338   if (IMAGE_INSTANCE_TYPE (ii) != IMAGE_WIDGET)
339     return;
340
341   /* Device generic methods. We must update the widget's size as it
342      may have been changed by the the layout routines. We also do this
343      here so that explicit resizing from lisp does not result in
344      synchronous updates. */
345   MAYBE_DEVMETH (XDEVICE (ii->device), update_widget, (ii));
346
347   /* Device-format specific methods */
348   meths = decode_device_ii_format (IMAGE_INSTANCE_DEVICE (ii), 
349                                    IMAGE_INSTANCE_WIDGET_TYPE (ii), 
350                                    ERROR_ME_NOT);
351   MAYBE_IIFORMAT_METH (meths, update, (widget));
352 }
353
354 /* Query for a widgets desired geometry. If no type specific method is
355    provided then use the widget text to calculate sizes. */
356 static void 
357 widget_query_geometry (Lisp_Object image_instance, 
358                        unsigned int* width, unsigned int* height,
359                        enum image_instance_geometry disp, Lisp_Object domain)
360 {
361   Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance);
362   struct image_instantiator_methods* meths;
363
364   /* First just set up what we already have. */
365   if (width)    *width = IMAGE_INSTANCE_WIDTH (ii);
366   if (height)   *height = IMAGE_INSTANCE_HEIGHT (ii);
367   
368   if (IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii)
369       ||
370       IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii))
371     {
372       /* .. then try device specific methods ... */
373       meths = decode_device_ii_format (IMAGE_INSTANCE_DEVICE (ii), 
374                                        IMAGE_INSTANCE_WIDGET_TYPE (ii), 
375                                        ERROR_ME_NOT);
376       if (meths && HAS_IIFORMAT_METH_P (meths, query_geometry))
377         IIFORMAT_METH (meths, query_geometry, (image_instance, 
378                                                width, height, disp,
379                                                domain));
380       else
381         {
382           /* ... then format specific methods ... */
383           meths = decode_device_ii_format (Qnil, IMAGE_INSTANCE_WIDGET_TYPE (ii), 
384                                            ERROR_ME_NOT);
385           if (meths && HAS_IIFORMAT_METH_P (meths, query_geometry))
386             IIFORMAT_METH (meths, query_geometry, (image_instance, 
387                                                    width, height, disp,
388                                                    domain));
389           else 
390             {
391               unsigned int w, h;
392               
393               /* Then if we are allowed to resize the widget, make the
394                  size the same as the text dimensions. */
395               query_string_geometry (IMAGE_INSTANCE_WIDGET_TEXT (ii),
396                                      IMAGE_INSTANCE_WIDGET_FACE (ii),
397                                      &w, &h, 0, domain);
398               /* Adjust the size for borders. */
399               if (IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii))
400                 *width = w + 2 * WIDGET_BORDER_WIDTH;
401               if (IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii))
402                 *height = h +  2 * WIDGET_BORDER_HEIGHT;
403             }
404         }
405     }
406 }
407
408 static void 
409 widget_layout (Lisp_Object image_instance, 
410                unsigned int width, unsigned int height, Lisp_Object domain)
411 {
412   Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance);
413   struct image_instantiator_methods* meths;
414
415   /* .. then try device specific methods ... */
416   meths = decode_device_ii_format (IMAGE_INSTANCE_DEVICE (ii), 
417                                    IMAGE_INSTANCE_WIDGET_TYPE (ii), 
418                                    ERROR_ME_NOT);
419   if (meths && HAS_IIFORMAT_METH_P (meths, layout))
420     IIFORMAT_METH (meths, layout, (image_instance, 
421                                    width, height, domain));
422   else
423     {
424       /* ... then format specific methods ... */
425       meths = decode_device_ii_format (Qnil, IMAGE_INSTANCE_WIDGET_TYPE (ii), 
426                                        ERROR_ME_NOT);
427       if (meths && HAS_IIFORMAT_METH_P (meths, layout))
428         IIFORMAT_METH (meths, layout, (image_instance, 
429                                        width, height, domain));
430     }
431 }
432
433 static void
434 widget_validate (Lisp_Object instantiator)
435 {
436   Lisp_Object desc = find_keyword_in_vector (instantiator, Q_descriptor);
437
438   if (NILP (desc))
439     signal_simple_error ("Must supply :descriptor", instantiator);
440
441   if (VECTORP (desc))
442     gui_parse_item_keywords (desc);
443
444   if (!NILP (find_keyword_in_vector (instantiator, Q_width))
445       && !NILP (find_keyword_in_vector (instantiator, Q_pixel_width)))
446     signal_simple_error ("Must supply only one of :width and :pixel-width", instantiator);
447
448   if (!NILP (find_keyword_in_vector (instantiator, Q_height))
449              && !NILP (find_keyword_in_vector (instantiator, Q_pixel_height)))
450     signal_simple_error ("Must supply only one of :height and :pixel-height", instantiator);
451 }
452
453 static void
454 combo_box_validate (Lisp_Object instantiator)
455 {
456   widget_validate (instantiator);
457   if (NILP (find_keyword_in_vector (instantiator, Q_properties)))
458     signal_simple_error ("Must supply item list", instantiator);
459 }
460
461 /* we need to convert things like glyphs to images, eval expressions
462    etc.*/
463 static Lisp_Object
464 widget_normalize (Lisp_Object inst, Lisp_Object console_type)
465 {
466   /* This function can call lisp */
467   Lisp_Object glyph = find_keyword_in_vector (inst, Q_image);
468
469   /* we need to eval glyph if its an expression, we do this for the
470      same reasons we normalize file to data. */
471   if (!NILP (glyph))
472     {
473       substitute_keyword_value (inst, Q_image, glyph_instantiator_to_glyph (glyph));
474     }
475
476   return inst;
477 }
478
479 static void
480 initialize_widget_image_instance (Lisp_Image_Instance *ii, Lisp_Object type)
481 {
482   /*  initialize_subwindow_image_instance (ii);*/
483   IMAGE_INSTANCE_WIDGET_TYPE (ii) = type;
484   IMAGE_INSTANCE_WIDGET_PROPS (ii) = Qnil;
485   SET_IMAGE_INSTANCE_WIDGET_FACE (ii, Qnil);
486   IMAGE_INSTANCE_WIDGET_ITEMS (ii) = allocate_gui_item ();
487   IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii) = 1;
488   IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii) = 1;
489   IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) = 0;
490   IMAGE_INSTANCE_SUBWINDOW_JUSTIFY (ii) = 0;
491 }
492
493 /* Instantiate a button widget. Unfortunately instantiated widgets are
494    particular to a frame since they need to have a parent. It's not
495    like images where you just select the image into the context you
496    want to display it in and BitBlt it. So image instances can have a
497    many-to-one relationship with things you see, whereas widgets can
498    only be one-to-one (i.e. per frame) */
499 void
500 widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
501                     Lisp_Object pointer_fg, Lisp_Object pointer_bg,
502                     int dest_mask, Lisp_Object domain)
503 {
504   Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
505   Lisp_Object face = find_keyword_in_vector (instantiator, Q_face);
506   Lisp_Object height = find_keyword_in_vector (instantiator, Q_height);
507   Lisp_Object width = find_keyword_in_vector (instantiator, Q_width);
508   Lisp_Object pixwidth = find_keyword_in_vector (instantiator, Q_pixel_width);
509   Lisp_Object pixheight = find_keyword_in_vector (instantiator, Q_pixel_height);
510   Lisp_Object desc = find_keyword_in_vector (instantiator, Q_descriptor);
511   Lisp_Object glyph = find_keyword_in_vector (instantiator, Q_image);
512   Lisp_Object props = find_keyword_in_vector (instantiator, Q_properties);
513   Lisp_Object items = find_keyword_in_vector (instantiator, Q_items);
514   Lisp_Object orient = find_keyword_in_vector (instantiator, Q_orientation);
515   int pw=0, ph=0, tw=0, th=0;
516   
517   /* this just does pixel type sizing */
518   subwindow_instantiate (image_instance, instantiator, pointer_fg, pointer_bg,
519                          dest_mask, domain);
520
521   if (!(dest_mask & (IMAGE_WIDGET_MASK | IMAGE_LAYOUT_MASK)))
522     incompatible_image_types (instantiator, dest_mask, 
523                               IMAGE_WIDGET_MASK | IMAGE_LAYOUT_MASK);
524
525   initialize_widget_image_instance (ii, XVECTOR_DATA (instantiator)[0]);
526
527   IMAGE_INSTANCE_TYPE (ii) = IMAGE_WIDGET;
528   IMAGE_INSTANCE_WIDGET_PROPS (ii) = props;
529
530   /* retrieve the fg and bg colors */
531   if (!NILP (face))
532     SET_IMAGE_INSTANCE_WIDGET_FACE (ii, Fget_face (face));
533   
534   /* Do layout specific initialisation. This feels a bit tacky, but
535      the alternative is a myriad of different little functions. */
536   if (EQ (IMAGE_INSTANCE_WIDGET_TYPE (ii), Qlayout))
537     {
538       Lisp_Object rest, children = Qnil;
539       Lisp_Object border = find_keyword_in_vector (instantiator, Q_border);
540
541       if (NILP (orient))
542         {
543           IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) = LAYOUT_VERTICAL;
544         }
545       IMAGE_INSTANCE_TYPE (ii) = IMAGE_LAYOUT;
546       
547       if (EQ (border, Qt))
548         {
549           IMAGE_INSTANCE_LAYOUT_BORDER (ii) = Qetched_in;
550         }
551       else if (GLYPHP (border))
552         {
553           /* We are going to be sneaky here and add the border text as
554              just another child, the layout and output routines don't know
555              this and will just display at the offsets we prescribe. */
556           Lisp_Object gii = glyph_image_instance (border, domain, ERROR_ME, 1);
557           /* make sure we are designated as the parent. */
558           XIMAGE_INSTANCE_PARENT (gii) = image_instance;
559           children = Fcons (gii, children);
560           IMAGE_INSTANCE_LAYOUT_BORDER (ii) = make_int (0);
561         }
562       else
563         {
564           IMAGE_INSTANCE_LAYOUT_BORDER (ii) = border;
565         }
566
567       /* Pick up the sub-widgets. */
568       LIST_LOOP (rest, items)
569         {
570           /* make sure the image is instantiated */
571           Lisp_Object gii = glyph_image_instance (XCAR (rest), domain, ERROR_ME, 1);
572           /* make sure we are designated as the parent. */
573           XIMAGE_INSTANCE_PARENT (gii) = image_instance;
574           children = Fcons (gii, children);
575           /* Make sure elements in the layout are in the order the
576              user expected. */
577           children = Fnreverse (children);
578         }
579       IMAGE_INSTANCE_LAYOUT_CHILDREN (ii) = children;
580     }
581   /* retrieve the gui item information. This is easy if we have been
582      provided with a vector, more difficult if we have just been given
583      keywords */
584   else if (STRINGP (desc) || NILP (desc))
585     {
586       /* big cheat - we rely on the fact that a gui item looks like an instantiator */
587       IMAGE_INSTANCE_WIDGET_ITEMS (ii) = 
588         gui_parse_item_keywords_no_errors (instantiator);
589       IMAGE_INSTANCE_WIDGET_TEXT (ii) = desc;
590     }
591   else
592     IMAGE_INSTANCE_WIDGET_ITEMS (ii) =
593       gui_parse_item_keywords_no_errors (desc);
594
595   /* Pick up the orientation before we do our first layout. */
596   if (EQ (orient, Qleft) || EQ (orient, Qright) || EQ (orient, Qvertical))
597     IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) = 1;
598
599   /* parse more gui items out of the properties */
600   if (!NILP (props)
601       && !EQ (IMAGE_INSTANCE_WIDGET_TYPE (ii), Qlayout))
602     {
603       if (NILP (items))
604         {
605           items = Fplist_get (props, Q_items, Qnil);
606         }
607       if (!NILP (items))
608         {
609           IMAGE_INSTANCE_WIDGET_ITEMS (ii) = 
610             Fcons (IMAGE_INSTANCE_WIDGET_ITEMS (ii), 
611                    parse_gui_item_tree_children (items));
612         }
613     }
614
615   /* Normalize size information. We now only assign sizes if the user
616      gives us some explicitly, or there are some constraints that we
617      can't change later on. Otherwise we postpone sizing until query
618      geometry gets called. */
619   if (!NILP (pixwidth))         /* pixwidth takes precendent */
620     {
621       pw = XINT (pixwidth);
622       IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii) = 0;
623     }
624   else if (!NILP (width))
625     {
626       tw = XINT (width);
627       IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii) = 0;
628     }
629
630   if (!NILP (pixheight))
631     {
632       ph = XINT (pixheight);
633       IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii) = 0;
634     }
635   else if (!NILP (height) && XINT (height) > 1)
636     {
637       th = XINT (height);
638       IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii) = 0;
639     }
640
641   /* Taking the default face information when the user has specified
642      size in characters is probably as good as any since the widget
643      face is more likely to be proportional and thus give inadequate
644      results. Using character sizes can only ever be approximate
645      anyway. */
646   if (tw || th)
647     {
648       int charwidth, charheight;
649       default_face_font_info (domain, 0, 0, &charheight, &charwidth, 0);
650       if (tw)
651         pw = charwidth * tw;
652       if (th)
653         ph = charheight * th;
654     }
655
656   /* for a widget with an image pick up the dimensions from that */
657   if (!NILP (glyph))
658     {
659       if (!pw)
660         pw = glyph_width (glyph, domain) + 2 * WIDGET_BORDER_WIDTH;
661       if (!ph)
662         ph = glyph_height (glyph, domain) + 2 * WIDGET_BORDER_HEIGHT;
663       IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii) = 0;
664       IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii) = 0;
665     }
666
667   /* When we create the widgets the window system expects a valid
668      size, so If we still don' t have sizes, call layout to pick them
669      up. If query_geometry or layout relies on the widget being in
670      existence then we are in catch 22. */
671   image_instance_layout (image_instance, 
672                          pw ? pw : IMAGE_UNSPECIFIED_GEOMETRY,
673                          ph ? ph : IMAGE_UNSPECIFIED_GEOMETRY,
674                          domain);
675
676 #ifdef DEBUG_WIDGETS
677   debug_widget_instances++;
678   stderr_out ("instantiated ");
679   debug_print (instantiator);
680   stderr_out ("%d widgets instantiated\n", debug_widget_instances);
681 #endif
682 }
683
684 /* tree-view geometry - get the height right */
685 static void
686 tree_view_query_geometry (Lisp_Object image_instance, 
687                           unsigned int* width, unsigned int* height,
688                           enum image_instance_geometry disp, Lisp_Object domain)
689 {
690   Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
691   Lisp_Object items = IMAGE_INSTANCE_WIDGET_ITEMS (ii);
692
693   
694   if (*width)
695     {
696       /* #### what should this be. reconsider when X has tree views. */
697       query_string_geometry (IMAGE_INSTANCE_WIDGET_TEXT (ii),
698                              IMAGE_INSTANCE_WIDGET_FACE (ii),
699                              width, 0, 0, domain);
700     }
701   if (*height)
702     {
703       int len, h;
704       default_face_font_info (domain, 0, 0, &h, 0, 0);
705       GET_LIST_LENGTH (items, len);
706       *height = len * h;
707     }
708 }
709
710 /* Get the geometry of a tab control. This is based on the number of
711    items and text therin in the tab control. */
712 static void
713 tab_control_query_geometry (Lisp_Object image_instance, 
714                             unsigned int* width, unsigned int* height,
715                             enum image_instance_geometry disp, Lisp_Object domain)
716 {
717   Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
718   Lisp_Object items = XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii));
719   Lisp_Object rest;
720   unsigned int tw = 0, th = 0;
721
722   LIST_LOOP (rest, items)
723     {
724       unsigned int h, w;
725
726       query_string_geometry (XGUI_ITEM (XCAR (rest))->name,
727                              IMAGE_INSTANCE_WIDGET_FACE (ii),
728                              &w, &h, 0, domain);
729       tw += 5 * WIDGET_BORDER_WIDTH; /* some bias */
730       tw += w;
731       th = max (th, h + 2 * WIDGET_BORDER_HEIGHT);
732     }
733
734   /* Fixup returned values depending on orientation. */
735   if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii))
736     {
737       if (height)       *height = tw;
738       if (width)        *width = th;
739     }
740   else
741     {
742       if (height)       *height = th;
743       if (width)        *width = tw;
744     }
745 }
746
747 /* Get the geometry of a tab control. This is based on the number of
748    items and text therin in the tab control. */
749 static Lisp_Object
750 tab_control_set_property (Lisp_Object image_instance, 
751                           Lisp_Object prop,
752                           Lisp_Object val)
753 {
754   /* Record new items for update. *_tab_control_update will do the
755      rest. */
756   if (EQ (prop, Q_items))
757     {
758       Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance);
759       check_valid_item_list_1 (val);
760
761       IMAGE_INSTANCE_WIDGET_ITEMS (ii) =
762         Fcons (XCAR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)),
763                parse_gui_item_tree_children (val));
764       
765       IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii) = 1;
766
767       return Qt;
768     }
769   return Qunbound;
770 }
771
772 /* set the properties of a progres guage */
773 static Lisp_Object
774 progress_gauge_set_property (Lisp_Object image_instance,
775                              Lisp_Object prop,
776                              Lisp_Object val)
777 {
778   Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
779
780   if (EQ (prop, Q_percent))
781     {
782       CHECK_INT (val);
783       IMAGE_INSTANCE_WIDGET_PROPS (ii)
784         = Fplist_put (IMAGE_INSTANCE_WIDGET_PROPS (ii), prop, val);
785       IMAGE_INSTANCE_WIDGET_PERCENT_CHANGED (ii) = 1;
786
787       return Qt;
788     }
789   return Qunbound;
790 }
791
792 \f
793 /*****************************************************************************
794  *                              widget layout                               *
795  *****************************************************************************/
796 static int
797 layout_possible_dest_types (void)
798 {
799   return IMAGE_LAYOUT_MASK;
800 }
801
802 /* we need to convert things like glyphs to images, eval expressions
803    etc.*/
804 static Lisp_Object
805 layout_normalize (Lisp_Object inst, Lisp_Object console_type)
806 {
807   /* This function can call lisp */
808   Lisp_Object items = find_keyword_in_vector (inst, Q_items);
809   Lisp_Object border = find_keyword_in_vector (inst, Q_border);
810   /* we need to eval glyph if its an expression, we do this for the
811      same reasons we normalize file to data. */
812   if (!NILP (items))
813     {
814       Lisp_Object rest;
815       LIST_LOOP (rest, items)
816         {
817           /* substitute the new glyph */
818           Fsetcar (rest, glyph_instantiator_to_glyph (XCAR (rest)));
819         }
820     }
821   /* normalize the border spec. */
822   if (VECTORP (border) || CONSP (border))
823     {
824       substitute_keyword_value (inst, Q_border, glyph_instantiator_to_glyph (border));
825     }
826   return inst;
827 }
828
829 /* Layout widget. Sizing commentary: we have a number of problems that
830    we would like to address. Some consider some of these more
831    important than others. It used to be that size information was
832    determined at instantiation time and was then fixed forever
833    after. Generally this is not what we want. Users want size to be
834    "big enough" to accommodate whatever they are trying to show and
835    this is dependent on text length, lines, font metrics etc. Of
836    course these attributes can change dynamically and so the size
837    should changed dynamically also. Only in a few limited cases should
838    the size be fixed and remain fixed. Of course this actually means
839    that we don't really want to specifiy the size *at all* for most
840    widgets - we want it to be discovered dynamically. Thus we can
841    envisage the following scenarios:
842    
843    1. A button is sized to accommodate its text, the text changes and the
844    button should change size also.  
845
846    2. A button is given an explicit size. Its size should never change.
847
848    3. Layout is put inside an area. The size of the area changes, the
849    layout should change with it. 
850
851    4. A button grows to accommodate additional text. The whitespace
852    around it should be modified to cope with the new layout
853    requirements. 
854
855    5. A button grows. The area surrounding it should grow also if
856    possible. 
857
858    What metrics are important?
859    1. Actual width and height.
860    
861    2. Whether the width and height are what the widget actually wants, or
862    whether it can grow or shrink. 
863
864    Text glyphs are particularly troublesome since their metrics depend
865    on the context in which they are being viewed. For instance they
866    can appear differently depending on the window face, frame face or
867    glyph face. In order to simplify this text glyphs can now only have
868    a glyph-face or image-instance face. All other glyphs are
869    essentially fixed in appearance. Perhaps the problem is that text
870    glyphs are cached on a device basis like most other glyphs. Instead
871    they should be cached per-window and then the instance would be
872    fixed and we wouldn't have to mess around with font metrics and the
873    rest. */
874
875 /* Query the geometry of a layout widget. We assume that we can only
876    get here if the size is not already fixed. */
877 static void
878 layout_query_geometry (Lisp_Object image_instance, unsigned int* width,
879                        unsigned int* height, enum image_instance_geometry disp,
880                        Lisp_Object domain)
881 {
882   Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
883   Lisp_Object items = IMAGE_INSTANCE_LAYOUT_CHILDREN (ii), rest;
884   int maxph = 0, maxpw = 0, nitems = 0, ph_adjust = 0;
885
886   /* Flip through the items to work out how much stuff we have to display */
887   LIST_LOOP (rest, items)
888     {
889       Lisp_Object glyph = XCAR (rest);
890       unsigned int gheight, gwidth;
891       
892       image_instance_query_geometry (glyph, &gwidth, &gheight, disp, domain);
893
894       /* Pick up the border text if we have one. */
895       if (INTP (IMAGE_INSTANCE_LAYOUT_BORDER (ii))
896           && NILP (XCDR (rest)))
897         {
898           ph_adjust = gheight / 2;
899         }
900       else
901         {
902
903           nitems ++;
904           if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) 
905               == LAYOUT_HORIZONTAL)
906             {
907               maxph = max (maxph, gheight);
908               maxpw += gwidth;
909             }
910           else
911             {
912               maxpw = max (maxpw, gwidth);
913               maxph += gheight;
914             }
915         }
916     }
917
918   /* work out spacing between items and bounds of the layout.  No user
919       provided width so we just do default spacing. */
920   if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) 
921       == LAYOUT_HORIZONTAL)
922     *width = maxpw + (nitems + 1) * WIDGET_BORDER_WIDTH * 2;
923   else 
924     *width = maxpw + 2 * WIDGET_BORDER_WIDTH * 2;
925
926   /* Work out vertical spacings. */
927   if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) 
928       == LAYOUT_VERTICAL)
929     *height = maxph + (nitems + 1) * WIDGET_BORDER_HEIGHT * 2 + ph_adjust;
930   else 
931     *height = maxph + 2 * WIDGET_BORDER_HEIGHT * 2 + ph_adjust;
932 }
933
934
935 static void
936 layout_layout (Lisp_Object image_instance, 
937                unsigned int width, unsigned int height, Lisp_Object domain)
938 {
939   Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
940   Lisp_Object rest;
941   Lisp_Object items = IMAGE_INSTANCE_LAYOUT_CHILDREN (ii);
942   int x, y, maxph = 0, maxpw = 0, nitems = 0,
943     horiz_spacing, vert_spacing, ph_adjust = 0;
944   unsigned int gheight, gwidth;
945
946   /* flip through the items to work out how much stuff we have to display */
947   LIST_LOOP (rest, items)
948     {
949       Lisp_Object glyph = XCAR (rest);
950       
951       image_instance_query_geometry (glyph, &gwidth, &gheight, 
952                                      IMAGE_DESIRED_GEOMETRY, domain);
953
954       /* Pick up the border text if we have one. */
955       if (INTP (IMAGE_INSTANCE_LAYOUT_BORDER (ii))
956           && NILP (XCDR (rest)))
957         {
958           XIMAGE_INSTANCE_XOFFSET (glyph) = 10; /* Really, what should this be? */
959           XIMAGE_INSTANCE_YOFFSET (glyph) = 0;
960           ph_adjust = gheight / 2;
961           IMAGE_INSTANCE_LAYOUT_BORDER (ii) = make_int (ph_adjust);
962         }
963       else
964         {
965           nitems ++;
966           if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) 
967               == LAYOUT_HORIZONTAL)
968             {
969               maxph = max (maxph, gheight);
970               maxpw += gwidth;
971             }
972           else
973             {
974               maxpw = max (maxpw, gwidth);
975               maxph += gheight;
976             }
977         }
978     }
979
980   /* work out spacing between items and bounds of the layout */
981   if (width < maxpw)
982     /* The user wants a smaller space than the largest item, so we
983        just provide default spacing and will let the output routines
984        clip.. */
985     horiz_spacing = WIDGET_BORDER_WIDTH * 2;
986   else if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) 
987            == LAYOUT_HORIZONTAL)
988     /* We have a larger area to display in so distribute the space
989        evenly. */
990     horiz_spacing = (width - maxpw) / (nitems + 1);
991   else
992     horiz_spacing = (width - maxpw) / 2;
993
994   if (height < maxph)
995     vert_spacing = WIDGET_BORDER_HEIGHT * 2;
996   else if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) 
997            == LAYOUT_VERTICAL)
998     vert_spacing = (height - (maxph + ph_adjust)) / (nitems + 1);
999   else
1000     vert_spacing = (height - (maxph + ph_adjust)) / 2;
1001
1002   y = vert_spacing + ph_adjust;
1003   x = horiz_spacing;
1004
1005   /* Now flip through putting items where we want them, paying
1006      attention to justification. Make sure we don't mess with the
1007      border glyph. */
1008   LIST_LOOP (rest, items)
1009     {
1010       Lisp_Object glyph = XCAR (rest);
1011
1012       image_instance_query_geometry (glyph, &gwidth, &gheight, 
1013                                      IMAGE_DESIRED_GEOMETRY, domain);
1014
1015       if (!INTP (IMAGE_INSTANCE_LAYOUT_BORDER (ii))
1016           || !NILP (XCDR (rest)))
1017       {
1018         if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) 
1019             == LAYOUT_HORIZONTAL)
1020           {
1021             if (IMAGE_INSTANCE_SUBWINDOW_JUSTIFY (ii) 
1022                 == LAYOUT_JUSTIFY_RIGHT)
1023               y = height - (gheight + vert_spacing);
1024             if (IMAGE_INSTANCE_SUBWINDOW_JUSTIFY (ii) 
1025                 == LAYOUT_JUSTIFY_CENTER)
1026               y = (height - gheight) / 2;
1027           }
1028         else 
1029           {
1030             if (IMAGE_INSTANCE_SUBWINDOW_JUSTIFY (ii) 
1031                 == LAYOUT_JUSTIFY_RIGHT)
1032               x = width - (gwidth + horiz_spacing);
1033             if (IMAGE_INSTANCE_SUBWINDOW_JUSTIFY (ii) 
1034                 == LAYOUT_JUSTIFY_CENTER)
1035               x = (width - gwidth) / 2;
1036           }
1037         
1038         XIMAGE_INSTANCE_XOFFSET (glyph) = x;
1039         XIMAGE_INSTANCE_YOFFSET (glyph) = y;
1040         
1041         if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) 
1042             == LAYOUT_HORIZONTAL)
1043           {
1044             x += (gwidth + horiz_spacing);
1045           }
1046         else
1047           {
1048             y += (gheight + vert_spacing);
1049           }
1050       }
1051       
1052       /* Now layout subwidgets if they require it. */
1053       image_instance_layout (glyph, gwidth, gheight, domain);
1054     }
1055 }
1056
1057 \f
1058 /************************************************************************/
1059 /*                            initialization                            */
1060 /************************************************************************/
1061
1062 void
1063 syms_of_glyphs_widget (void)
1064 {
1065   defkeyword (&Q_descriptor, ":descriptor");
1066   defkeyword (&Q_height, ":height");
1067   defkeyword (&Q_width, ":width");
1068   defkeyword (&Q_properties, ":properties");
1069   defkeyword (&Q_items, ":items");
1070   defkeyword (&Q_image, ":image");
1071   defkeyword (&Q_percent, ":percent");
1072   defkeyword (&Q_text, ":text");
1073   defkeyword (&Q_orientation, ":orientation");
1074   defkeyword (&Q_justify, ":justify");
1075   defkeyword (&Q_border, ":border");
1076
1077   defsymbol (&Qetched_in, "etched-in");
1078   defsymbol (&Qetched_out, "etched-out");
1079   defsymbol (&Qbevel_in, "bevel-in");
1080   defsymbol (&Qbevel_out, "bevel-out");
1081 }
1082
1083 #define VALID_GUI_KEYWORDS(type) do {                                                   \
1084   IIFORMAT_VALID_NONCOPY_KEYWORD (type, Q_active, check_valid_anything);                \
1085   IIFORMAT_VALID_KEYWORD (type, Q_suffix, check_valid_anything);                        \
1086   IIFORMAT_VALID_KEYWORD (type, Q_keys, check_valid_string);                            \
1087   IIFORMAT_VALID_KEYWORD (type, Q_style, check_valid_symbol);                           \
1088   IIFORMAT_VALID_NONCOPY_KEYWORD (type, Q_selected, check_valid_anything);              \
1089   IIFORMAT_VALID_KEYWORD (type, Q_filter, check_valid_anything);                        \
1090   IIFORMAT_VALID_KEYWORD (type, Q_config, check_valid_symbol);                          \
1091   IIFORMAT_VALID_KEYWORD (type, Q_included, check_valid_anything);                      \
1092   IIFORMAT_VALID_KEYWORD (type, Q_key_sequence, check_valid_string);                    \
1093   IIFORMAT_VALID_KEYWORD (type, Q_accelerator, check_valid_string);                     \
1094   IIFORMAT_VALID_KEYWORD (type, Q_label, check_valid_anything);                         \
1095   IIFORMAT_VALID_NONCOPY_KEYWORD (type, Q_callback, check_valid_callback);              \
1096   IIFORMAT_VALID_NONCOPY_KEYWORD (type, Q_descriptor, check_valid_string_or_vector);    \
1097 } while (0)
1098
1099 #define VALID_WIDGET_KEYWORDS(type) do {                                \
1100   IIFORMAT_VALID_KEYWORD (type, Q_width, check_valid_int);              \
1101   IIFORMAT_VALID_KEYWORD (type, Q_height, check_valid_int);             \
1102   IIFORMAT_VALID_KEYWORD (type, Q_pixel_width, check_valid_int);        \
1103   IIFORMAT_VALID_KEYWORD (type, Q_pixel_height, check_valid_int);       \
1104   IIFORMAT_VALID_KEYWORD (type, Q_face, check_valid_face);              \
1105 } while (0)
1106
1107
1108 static void image_instantiator_widget (void)
1109 { /* we only do this for properties */
1110   INITIALIZE_IMAGE_INSTANTIATOR_FORMAT_NO_SYM (widget, "widget");
1111   IIFORMAT_HAS_METHOD (widget, property);
1112   IIFORMAT_HAS_METHOD (widget, set_property);
1113   IIFORMAT_HAS_METHOD (widget, query_geometry);
1114   IIFORMAT_HAS_METHOD (widget, layout);
1115 }
1116
1117 static void image_instantiator_buttons (void)
1118 {
1119   INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (button, "button");
1120   IIFORMAT_HAS_SHARED_METHOD (button, validate, widget);
1121   IIFORMAT_HAS_SHARED_METHOD (button, possible_dest_types, widget);
1122   IIFORMAT_HAS_SHARED_METHOD (button, instantiate, widget);
1123   IIFORMAT_HAS_SHARED_METHOD (button, normalize, widget);
1124   IIFORMAT_VALID_KEYWORD (button,
1125                           Q_image, check_valid_glyph_or_instantiator);
1126   VALID_WIDGET_KEYWORDS (button);
1127   VALID_GUI_KEYWORDS (button);
1128 }
1129
1130 static void image_instantiator_edit_fields (void)
1131 {
1132   INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (edit_field, "edit-field");
1133   IIFORMAT_HAS_SHARED_METHOD (edit_field, validate, widget);
1134   IIFORMAT_HAS_SHARED_METHOD (edit_field, possible_dest_types, widget);
1135   IIFORMAT_HAS_SHARED_METHOD (edit_field, instantiate, widget);
1136   VALID_WIDGET_KEYWORDS (edit_field);
1137   VALID_GUI_KEYWORDS (edit_field);
1138 }
1139
1140 static void image_instantiator_combo_box (void)
1141 {
1142   INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (combo_box, "combo-box");
1143   IIFORMAT_HAS_METHOD (combo_box, validate);
1144   IIFORMAT_HAS_SHARED_METHOD (combo_box, possible_dest_types, widget);
1145   VALID_GUI_KEYWORDS (combo_box);
1146
1147   IIFORMAT_VALID_KEYWORD (combo_box, Q_width, check_valid_int);
1148   IIFORMAT_VALID_KEYWORD (combo_box, Q_height, check_valid_int);
1149   IIFORMAT_VALID_KEYWORD (combo_box, Q_pixel_width, check_valid_int);
1150   IIFORMAT_VALID_KEYWORD (combo_box, Q_face, check_valid_face);
1151   IIFORMAT_VALID_KEYWORD (combo_box, Q_properties, check_valid_item_list);
1152 }
1153
1154 static void image_instantiator_scrollbar (void)
1155 {
1156   INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (scrollbar, "scrollbar");
1157   IIFORMAT_HAS_SHARED_METHOD (scrollbar, validate, widget);
1158   IIFORMAT_HAS_SHARED_METHOD (scrollbar, possible_dest_types, widget);
1159   IIFORMAT_HAS_SHARED_METHOD (scrollbar, instantiate, widget);
1160   VALID_GUI_KEYWORDS (scrollbar);
1161
1162   IIFORMAT_VALID_KEYWORD (scrollbar, Q_pixel_width, check_valid_int);
1163   IIFORMAT_VALID_KEYWORD (scrollbar, Q_pixel_height, check_valid_int);
1164   IIFORMAT_VALID_KEYWORD (scrollbar, Q_face, check_valid_face);
1165 }
1166
1167 static void image_instantiator_progress_guage (void)
1168 {
1169   INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (progress_gauge, "progress-gauge");
1170   IIFORMAT_HAS_SHARED_METHOD (progress_gauge, validate, widget);
1171   IIFORMAT_HAS_SHARED_METHOD (progress_gauge, possible_dest_types, widget);
1172   IIFORMAT_HAS_SHARED_METHOD (progress_gauge, instantiate, widget);
1173   IIFORMAT_HAS_METHOD (progress_gauge, set_property);
1174   VALID_WIDGET_KEYWORDS (progress_gauge);
1175   VALID_GUI_KEYWORDS (progress_gauge);
1176 }
1177
1178 static void image_instantiator_tree_view (void)
1179 {
1180   INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (tree_view, "tree-view");
1181   IIFORMAT_HAS_SHARED_METHOD (tree_view, validate, combo_box);
1182   IIFORMAT_HAS_SHARED_METHOD (tree_view, possible_dest_types, widget);
1183   IIFORMAT_HAS_SHARED_METHOD (tree_view, instantiate, widget);
1184   IIFORMAT_HAS_METHOD (tree_view, query_geometry);
1185   VALID_WIDGET_KEYWORDS (tree_view);
1186   VALID_GUI_KEYWORDS (tree_view);
1187   IIFORMAT_VALID_KEYWORD (tree_view, Q_properties, check_valid_item_list);
1188 }
1189
1190 static void image_instantiator_tab_control (void)
1191 {
1192   INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (tab_control, "tab-control");
1193   IIFORMAT_HAS_SHARED_METHOD (tab_control, validate, combo_box);
1194   IIFORMAT_HAS_SHARED_METHOD (tab_control, possible_dest_types, widget);
1195   IIFORMAT_HAS_SHARED_METHOD (tab_control, instantiate, widget);
1196   IIFORMAT_HAS_METHOD (tab_control, query_geometry);
1197   IIFORMAT_HAS_METHOD (tab_control, set_property);
1198   VALID_WIDGET_KEYWORDS (tab_control);
1199   VALID_GUI_KEYWORDS (tab_control);
1200   IIFORMAT_VALID_KEYWORD (tab_control, Q_orientation, check_valid_tab_orientation);
1201   IIFORMAT_VALID_KEYWORD (tab_control, Q_properties, check_valid_item_list);
1202 }
1203
1204 static void image_instantiator_labels (void)
1205 {
1206   INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (label, "label");
1207   IIFORMAT_HAS_SHARED_METHOD (label, possible_dest_types, widget);
1208   IIFORMAT_HAS_SHARED_METHOD (label, instantiate, widget);
1209   VALID_WIDGET_KEYWORDS (label);
1210   IIFORMAT_VALID_KEYWORD (label, Q_descriptor, check_valid_string);
1211 }
1212
1213 static void image_instantiator_layout (void)
1214 {
1215   INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (layout, "layout");
1216   IIFORMAT_HAS_METHOD (layout, possible_dest_types);
1217   IIFORMAT_HAS_SHARED_METHOD (layout, instantiate, widget);
1218   IIFORMAT_HAS_METHOD (layout, normalize);
1219   IIFORMAT_HAS_METHOD (layout, query_geometry);
1220   IIFORMAT_HAS_METHOD (layout, layout);
1221   IIFORMAT_VALID_KEYWORD (layout, Q_pixel_width, check_valid_int);
1222   IIFORMAT_VALID_KEYWORD (layout, Q_pixel_height, check_valid_int);
1223   IIFORMAT_VALID_KEYWORD (layout, Q_orientation, check_valid_orientation);
1224   IIFORMAT_VALID_KEYWORD (layout, Q_justify, check_valid_justification);
1225   IIFORMAT_VALID_KEYWORD (layout, Q_border, check_valid_border);
1226   IIFORMAT_VALID_KEYWORD (layout, Q_items,
1227                           check_valid_glyph_or_instantiator_list);
1228 }
1229
1230 void
1231 image_instantiator_format_create_glyphs_widget (void)
1232 {
1233   image_instantiator_widget();
1234   image_instantiator_buttons();
1235   image_instantiator_edit_fields();
1236   image_instantiator_combo_box();
1237   image_instantiator_scrollbar();
1238   image_instantiator_progress_guage();
1239   image_instantiator_tree_view();
1240   image_instantiator_tab_control();
1241   image_instantiator_labels();
1242   image_instantiator_layout();
1243 }
1244
1245 void
1246 reinit_vars_of_glyphs_widget (void)
1247 {
1248 #ifdef DEBUG_WIDGETS
1249   debug_widget_instances = 0;
1250 #endif
1251 }
1252
1253 void
1254 vars_of_glyphs_widget (void)
1255 {
1256   reinit_vars_of_glyphs_widget ();
1257 }