/* Set up data in menu_items for a menu bar item whose event type is ITEM_KEY (with string ITEM_NAME) and whose contents come from the list of keymaps MAPS. */ bool parse_single_submenu (Lisp_Object item_key, Lisp_Object item_name, Lisp_Object maps) { Lisp_Object length; EMACS_INT len; Lisp_Object *mapvec; ptrdiff_t i; bool top_level_items = 0; USE_SAFE_ALLOCA; length = Flength (maps); len = XINT (length); /* Convert the list MAPS into a vector MAPVEC. */ SAFE_ALLOCA_LISP (mapvec, len); for (i = 0; i < len; i++) { mapvec[i] = Fcar (maps); maps = Fcdr (maps); } /* Loop over the given keymaps, making a pane for each map. But don't make a pane that is empty--ignore that map instead. */ for (i = 0; i < len; i++) { if (!KEYMAPP (mapvec[i])) { /* Here we have a command at top level in the menu bar as opposed to a submenu. */ top_level_items = 1; push_menu_pane (Qnil, Qnil); push_menu_item (item_name, Qt, item_key, mapvec[i], Qnil, Qnil, Qnil, Qnil); } else { Lisp_Object prompt; prompt = Fkeymap_prompt (mapvec[i]); single_keymap_panes (mapvec[i], !NILP (prompt) ? prompt : item_name, item_key, 10); } } SAFE_FREE (); return top_level_items; }
static emacs_value module_funcall (emacs_env *env, emacs_value fun, ptrdiff_t nargs, emacs_value args[]) { MODULE_FUNCTION_BEGIN (module_nil); /* Make a new Lisp_Object array starting with the function as the first arg, because that's what Ffuncall takes. */ Lisp_Object *newargs; USE_SAFE_ALLOCA; SAFE_ALLOCA_LISP (newargs, nargs + 1); newargs[0] = value_to_lisp (fun); for (ptrdiff_t i = 0; i < nargs; i++) newargs[1 + i] = value_to_lisp (args[i]); emacs_value result = lisp_to_value (Ffuncall (nargs + 1, newargs)); SAFE_FREE (); return result; }
/* As above, but return the menu selection instead of storing in kb buffer. If KEYMAPS, return full prefixes to selection. */ Lisp_Object find_and_return_menu_selection (struct frame *f, bool keymaps, void *client_data) { Lisp_Object prefix, entry; int i; Lisp_Object *subprefix_stack; int submenu_depth = 0; USE_SAFE_ALLOCA; prefix = entry = Qnil; i = 0; SAFE_ALLOCA_LISP (subprefix_stack, menu_items_used); while (i < menu_items_used) { if (EQ (AREF (menu_items, i), Qnil)) { subprefix_stack[submenu_depth++] = prefix; prefix = entry; i++; } else if (EQ (AREF (menu_items, i), Qlambda)) { prefix = subprefix_stack[--submenu_depth]; i++; } else if (EQ (AREF (menu_items, i), Qt)) { prefix = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX); i += MENU_ITEMS_PANE_LENGTH; } /* Ignore a nil in the item list. It's meaningful only for dialog boxes. */ else if (EQ (AREF (menu_items, i), Qquote)) i += 1; else { entry = AREF (menu_items, i + MENU_ITEMS_ITEM_VALUE); if (aref_addr (menu_items, i) == client_data) { if (keymaps) { int j; entry = list1 (entry); if (!NILP (prefix)) entry = Fcons (prefix, entry); for (j = submenu_depth - 1; j >= 0; j--) if (!NILP (subprefix_stack[j])) entry = Fcons (subprefix_stack[j], entry); } SAFE_FREE (); return entry; } i += MENU_ITEMS_ITEM_LENGTH; } } SAFE_FREE (); return Qnil; }