+int
+gui_item_equal_sans_selected (Lisp_Object obj1, Lisp_Object obj2, int depth)
+{
+ Lisp_Gui_Item *p1 = XGUI_ITEM (obj1);
+ Lisp_Gui_Item *p2 = XGUI_ITEM (obj2);
+
+ if (!(internal_equal (p1->name, p2->name, depth + 1)
+ &&
+ internal_equal (p1->callback, p2->callback, depth + 1)
+ &&
+ internal_equal (p1->callback_ex, p2->callback_ex, depth + 1)
+ &&
+ EQ (p1->suffix, p2->suffix)
+ &&
+ EQ (p1->active, p2->active)
+ &&
+ EQ (p1->included, p2->included)
+ &&
+ EQ (p1->config, p2->config)
+ &&
+ EQ (p1->filter, p2->filter)
+ &&
+ EQ (p1->style, p2->style)
+ &&
+ EQ (p1->accelerator, p2->accelerator)
+ &&
+ EQ (p1->keys, p2->keys)
+ &&
+ EQ (p1->value, p2->value)))
+ return 0;
+ return 1;
+}
+
+static int
+gui_item_equal (Lisp_Object obj1, Lisp_Object obj2, int depth)
+{
+ Lisp_Gui_Item *p1 = XGUI_ITEM (obj1);
+ Lisp_Gui_Item *p2 = XGUI_ITEM (obj2);
+
+ if (!(gui_item_equal_sans_selected (obj1, obj2, depth)
+ &&
+ EQ (p1->selected, p2->selected)))
+ return 0;
+ return 1;
+}
+
+static void
+print_gui_item (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
+{
+ Lisp_Gui_Item *g = XGUI_ITEM (obj);
+ char buf[20];
+
+ if (print_readably)
+ error ("printing unreadable object #<gui-item 0x%x>", g->header.uid);
+
+ write_c_string ("#<gui-item ", printcharfun);
+ sprintf (buf, "0x%x>", g->header.uid);
+ write_c_string (buf, printcharfun);
+}
+
+Lisp_Object
+copy_gui_item (Lisp_Object gui_item)
+{
+ Lisp_Object ret = allocate_gui_item ();
+ Lisp_Gui_Item *lp, *g = XGUI_ITEM (gui_item);
+
+ lp = XGUI_ITEM (ret);
+ lp->name = g->name;
+ lp->callback = g->callback;
+ lp->callback_ex = g->callback_ex;
+ lp->suffix = g->suffix;
+ lp->active = g->active;
+ lp->included = g->included;
+ lp->config = g->config;
+ lp->filter = g->filter;
+ lp->style = g->style;
+ lp->selected = g->selected;
+ lp->keys = g->keys;
+ lp->accelerator = g->accelerator;
+ lp->value = g->value;
+
+ return ret;
+}
+
+Lisp_Object
+copy_gui_item_tree (Lisp_Object arg)
+{
+ if (CONSP (arg))
+ {
+ Lisp_Object rest = arg = Fcopy_sequence (arg);
+ while (CONSP (rest))
+ {
+ XCAR (rest) = copy_gui_item_tree (XCAR (rest));
+ rest = XCDR (rest);
+ }
+ return arg;
+ }
+ else if (GUI_ITEMP (arg))
+ return copy_gui_item (arg);
+ else
+ return arg;
+}
+
+/* parse a glyph descriptor into a tree of gui items.
+
+ The gui_item slot of an image instance can be a single item or an
+ arbitrarily nested hierarchy of item lists. */
+
+static Lisp_Object
+parse_gui_item_tree_item (Lisp_Object entry)
+{
+ Lisp_Object ret = entry;
+ struct gcpro gcpro1;
+
+ GCPRO1 (ret);
+
+ if (VECTORP (entry))
+ {
+ ret = gui_parse_item_keywords_no_errors (entry);
+ }
+ else if (STRINGP (entry))
+ {
+ CHECK_STRING (entry);
+ }
+ else
+ syntax_error ("item must be a vector or a string", entry);
+
+ RETURN_UNGCPRO (ret);
+}
+
+Lisp_Object
+parse_gui_item_tree_children (Lisp_Object list)
+{
+ Lisp_Object rest, ret = Qnil, sub = Qnil;
+ struct gcpro gcpro1, gcpro2;
+
+ GCPRO2 (ret, sub);
+ CHECK_CONS (list);
+ /* recursively add items to the tree view */
+ LIST_LOOP (rest, list)
+ {
+ if (CONSP (XCAR (rest)))
+ sub = parse_gui_item_tree_list (XCAR (rest));
+ else
+ sub = parse_gui_item_tree_item (XCAR (rest));
+
+ ret = Fcons (sub, ret);
+ }
+ /* make the order the same as the items we have parsed */
+ RETURN_UNGCPRO (Fnreverse (ret));
+}
+
+static Lisp_Object
+parse_gui_item_tree_list (Lisp_Object list)
+{
+ Lisp_Object ret;
+ struct gcpro gcpro1;
+ CHECK_CONS (list);
+ /* first one can never be a list */
+ ret = parse_gui_item_tree_item (XCAR (list));
+ GCPRO1 (ret);
+ ret = Fcons (ret, parse_gui_item_tree_children (XCDR (list)));
+ RETURN_UNGCPRO (ret);
+}
+
+static void
+finalize_gui_item (void* header, int for_disksave)
+{
+}
+
+DEFINE_LRECORD_IMPLEMENTATION ("gui-item", gui_item,
+ mark_gui_item, print_gui_item,
+ finalize_gui_item, gui_item_equal,
+ gui_item_hash,
+ 0,
+ Lisp_Gui_Item);
+