+static Lisp_Object
+mark_gui_item (Lisp_Object obj)
+{
+ Lisp_Gui_Item *p = XGUI_ITEM (obj);
+
+ mark_object (p->name);
+ mark_object (p->callback);
+ mark_object (p->config);
+ mark_object (p->suffix);
+ mark_object (p->active);
+ mark_object (p->included);
+ mark_object (p->config);
+ mark_object (p->filter);
+ mark_object (p->style);
+ mark_object (p->selected);
+ mark_object (p->keys);
+ mark_object (p->accelerator);
+
+ return Qnil;
+}
+
+static unsigned long
+gui_item_hash (Lisp_Object obj, int depth)
+{
+ Lisp_Gui_Item *p = XGUI_ITEM (obj);
+
+ return HASH2 (HASH5 (internal_hash (p->name, depth + 1),
+ internal_hash (p->callback, depth + 1),
+ internal_hash (p->suffix, depth + 1),
+ internal_hash (p->active, depth + 1),
+ internal_hash (p->included, depth + 1)),
+ HASH5 (internal_hash (p->config, depth + 1),
+ internal_hash (p->filter, depth + 1),
+ internal_hash (p->style, depth + 1),
+ internal_hash (p->selected, depth + 1),
+ internal_hash (p->keys, depth + 1)));
+}
+
+int
+gui_item_id_hash (Lisp_Object hashtable, Lisp_Object gitem, int slot)
+{
+ int hashid = gui_item_hash (gitem, 0);
+ int id = GUI_ITEM_ID_BITS (hashid, slot);
+ while (!NILP (Fgethash (make_int (id),
+ hashtable, Qnil)))
+ {
+ id = GUI_ITEM_ID_BITS (id + 1, slot);
+ }
+ return id;
+}
+
+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 (!(internal_equal (p1->name, p2->name, depth + 1)
+ &&
+ internal_equal (p1->callback, p2->callback, 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->selected, p2->selected)
+ &&
+ EQ (p1->accelerator, p2->accelerator)
+ &&
+ EQ (p1->keys, p2->keys)))
+ 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);
+}
+
+/* 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;
+ if (VECTORP (entry))
+ {
+ ret = gui_parse_item_keywords_no_errors (entry);
+ }
+ else if (STRINGP (entry))
+ {
+ CHECK_STRING (entry);
+ }
+ else
+ signal_simple_error ("item must be a vector or a string", entry);
+
+ return ret;
+}
+
+Lisp_Object parse_gui_item_tree_children (Lisp_Object list)
+{
+ Lisp_Object rest, ret = Qnil;
+ CHECK_CONS (list);
+ /* recursively add items to the tree view */
+ LIST_LOOP (rest, list)
+ {
+ Lisp_Object sub;
+ 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 Fnreverse (ret);
+}
+
+static Lisp_Object parse_gui_item_tree_list (Lisp_Object list)
+{
+ Lisp_Object ret;
+ CHECK_CONS (list);
+ /* first one can never be a list */
+ ret = parse_gui_item_tree_item (XCAR (list));
+ return Fcons (ret, parse_gui_item_tree_children (XCDR (list)));
+}
+
+DEFINE_LRECORD_IMPLEMENTATION ("gui-item", gui_item,
+ mark_gui_item, print_gui_item,
+ 0, gui_item_equal,
+ gui_item_hash,
+ 0,
+ Lisp_Gui_Item);