+/* parse tree's of gui items into widget_value hierarchies */
+static void gui_item_children_to_widget_values (Lisp_Object
+ gui_object_instance,
+ Lisp_Object items,
+ widget_value* parent,
+ int accel_p);
+
+static widget_value *
+gui_items_to_widget_values_1 (Lisp_Object gui_object_instance,
+ Lisp_Object items, widget_value* parent,
+ widget_value* prev, int accel_p)
+{
+ widget_value* wv = 0;
+
+ assert ((parent || prev) && !(parent && prev));
+ /* now walk the tree creating widget_values as appropriate */
+ if (!CONSP (items))
+ {
+ wv = xmalloc_widget_value ();
+ if (parent)
+ parent->contents = wv;
+ else
+ prev->next = wv;
+ if (!button_item_to_widget_value (gui_object_instance,
+ items, wv, 0, 1, 0, accel_p))
+ {
+ free_widget_value_tree (wv);
+ if (parent)
+ parent->contents = 0;
+ else
+ prev->next = 0;
+ }
+ else
+ wv->value = xstrdup (wv->name); /* what a mess... */
+ }
+ else
+ {
+ /* first one is the parent */
+ if (CONSP (XCAR (items)))
+ syntax_error ("parent item must not be a list", XCAR (items));
+
+ if (parent)
+ wv = gui_items_to_widget_values_1 (gui_object_instance,
+ XCAR (items), parent, 0, accel_p);
+ else
+ wv = gui_items_to_widget_values_1 (gui_object_instance,
+ XCAR (items), 0, prev, accel_p);
+ /* the rest are the children */
+ gui_item_children_to_widget_values (gui_object_instance,
+ XCDR (items), wv, accel_p);
+ }
+ return wv;
+}
+
+static void
+gui_item_children_to_widget_values (Lisp_Object gui_object_instance,
+ Lisp_Object items, widget_value* parent,
+ int accel_p)
+{
+ widget_value* wv = 0, *prev = 0;
+ Lisp_Object rest;
+ CHECK_CONS (items);
+
+ /* first one is master */
+ prev = gui_items_to_widget_values_1 (gui_object_instance, XCAR (items),
+ parent, 0, accel_p);
+ /* the rest are the children */
+ LIST_LOOP (rest, XCDR (items))
+ {
+ Lisp_Object tab = XCAR (rest);
+ wv = gui_items_to_widget_values_1 (gui_object_instance, tab, 0, prev,
+ accel_p);
+ prev = wv;
+ }
+}
+
+widget_value *
+gui_items_to_widget_values (Lisp_Object gui_object_instance, Lisp_Object items,
+ int accel_p)
+{
+ /* This function can GC */
+ widget_value *control = 0, *tmp = 0;
+ int count = specpdl_depth ();
+ Lisp_Object wv_closure;
+
+ if (NILP (items))
+ syntax_error ("must have some items", items);
+
+ /* Inhibit GC during this conversion. The reasons for this are
+ the same as in menu_item_descriptor_to_widget_value(); see
+ the large comment above that function. */
+ record_unwind_protect (restore_gc_inhibit,
+ make_int (gc_currently_forbidden));
+ gc_currently_forbidden = 1;
+
+ /* Also make sure that we free the partially-created widget_value
+ tree on Lisp error. */
+ control = xmalloc_widget_value ();
+ wv_closure = make_opaque_ptr (control);
+ record_unwind_protect (widget_value_unwind, wv_closure);
+
+ gui_items_to_widget_values_1 (gui_object_instance, items, control, 0,
+ accel_p);
+
+ /* mess about getting the data we really want */
+ tmp = control;
+ control = control->contents;
+ tmp->next = 0;
+ tmp->contents = 0;
+ free_widget_value_tree (tmp);
+
+ /* No more need to free the half-filled-in structures. */
+ set_opaque_ptr (wv_closure, 0);
+ unbind_to (count, Qnil);
+
+ return control;
+}