+/* This is a subroutine of single_keymap_panes that handles one
+ keymap entry.
+ KEY is a key in a keymap and ITEM is its binding.
+ PENDING_MAPS_PTR points to a list of keymaps waiting to be made into
+ separate panes.
+ If NOTREAL is nonzero, only check for equivalent key bindings, don't
+ evaluate expressions in menu items and don't make any menu.
+ If we encounter submenus deeper than MAXDEPTH levels, ignore them.
+ NOTBUTTONS_PTR is only used when simulating toggle boxes and radio
+ buttons. It points to variable notbuttons in single_keymap_panes,
+ which keeps track of if we have seen a button in this menu or not. */
+
+static void
+single_menu_item (key, item, pending_maps_ptr, notreal, maxdepth,
+ notbuttons_ptr)
+ Lisp_Object key, item;
+ Lisp_Object *pending_maps_ptr;
+ int maxdepth, notreal;
+ int *notbuttons_ptr;
+{
+ Lisp_Object map, item_string, enabled;
+ struct gcpro gcpro1, gcpro2;
+ int res;
+
+ /* Parse the menu item and leave the result in item_properties. */
+ GCPRO2 (key, item);
+ res = parse_menu_item (item, notreal, 0);
+ UNGCPRO;
+ if (!res)
+ return; /* Not a menu item. */
+
+ map = XVECTOR (item_properties)->contents[ITEM_PROPERTY_MAP];
+
+ if (notreal)
+ {
+ /* We don't want to make a menu, just traverse the keymaps to
+ precompute equivalent key bindings. */
+ if (!NILP (map))
+ single_keymap_panes (map, Qnil, key, 1, maxdepth - 1);
+ return;
+ }
+
+ enabled = XVECTOR (item_properties)->contents[ITEM_PROPERTY_ENABLE];
+ item_string = XVECTOR (item_properties)->contents[ITEM_PROPERTY_NAME];
+
+ if (!NILP (map) && XSTRING (item_string)->data[0] == '@')
+ {
+ if (!NILP (enabled))
+ /* An enabled separate pane. Remember this to handle it later. */
+ *pending_maps_ptr = Fcons (Fcons (map, Fcons (item_string, key)),
+ *pending_maps_ptr);
+ return;
+ }
+
+#ifndef HAVE_BOXES
+ /* Simulate radio buttons and toggle boxes by putting a prefix in
+ front of them. */
+ {
+ Lisp_Object prefix = Qnil;
+ Lisp_Object type = XVECTOR (item_properties)->contents[ITEM_PROPERTY_TYPE];
+ if (!NILP (type))
+ {
+ Lisp_Object selected
+ = XVECTOR (item_properties)->contents[ITEM_PROPERTY_SELECTED];
+
+ if (*notbuttons_ptr)
+ /* The first button. Line up previous items in this menu. */
+ {
+ int index = *notbuttons_ptr; /* Index for first item this menu. */
+ int submenu = 0;
+ Lisp_Object tem;
+ while (index < menu_items_used)
+ {
+ tem
+ = XVECTOR (menu_items)->contents[index + MENU_ITEMS_ITEM_NAME];
+ if (NILP (tem))
+ {
+ index++;
+ submenu++; /* Skip sub menu. */
+ }
+ else if (EQ (tem, Qlambda))
+ {
+ index++;
+ submenu--; /* End sub menu. */
+ }
+ else if (EQ (tem, Qt))
+ index += 3; /* Skip new pane marker. */
+ else if (EQ (tem, Qquote))
+ index++; /* Skip a left, right divider. */
+ else
+ {
+ if (!submenu && XSTRING (tem)->data[0] != '\0'
+ && XSTRING (tem)->data[0] != '-')
+ XVECTOR (menu_items)->contents[index + MENU_ITEMS_ITEM_NAME]
+ = concat2 (build_string (" "), tem);
+ index += MENU_ITEMS_ITEM_LENGTH;
+ }
+ }
+ *notbuttons_ptr = 0;
+ }
+
+ /* Calculate prefix, if any, for this item. */
+ if (EQ (type, QCtoggle))
+ prefix = build_string (NILP (selected) ? "[ ] " : "[X] ");
+ else if (EQ (type, QCradio))
+ prefix = build_string (NILP (selected) ? "( ) " : "(*) ");
+ }
+ /* Not a button. If we have earlier buttons, then we need a prefix. */
+ else if (!*notbuttons_ptr && XSTRING (item_string)->data[0] != '\0'
+ && XSTRING (item_string)->data[0] != '-')
+ prefix = build_string (" ");
+
+ if (!NILP (prefix))
+ item_string = concat2 (prefix, item_string);
+ }
+#endif /* not HAVE_BOXES */
+
+#ifndef USE_X_TOOLKIT
+ if (!NILP(map))
+ /* Indicate visually that this is a submenu. */
+ item_string = concat2 (item_string, build_string (" >"));
+#endif
+
+ push_menu_item (item_string, enabled, key,
+ XVECTOR (item_properties)->contents[ITEM_PROPERTY_DEF],
+ XVECTOR (item_properties)->contents[ITEM_PROPERTY_KEYEQ],
+ XVECTOR (item_properties)->contents[ITEM_PROPERTY_TYPE],
+ XVECTOR (item_properties)->contents[ITEM_PROPERTY_SELECTED],
+ XVECTOR (item_properties)->contents[ITEM_PROPERTY_HELP]);
+
+#ifdef USE_X_TOOLKIT
+ /* Display a submenu using the toolkit. */
+ if (! (NILP (map) || NILP (enabled)))
+ {
+ push_submenu_start ();
+ single_keymap_panes (map, Qnil, key, 0, maxdepth - 1);
+ push_submenu_end ();
+ }
+#endif
+}
+\f
+/* Push all the panes and items of a menu described by the