-/* This is a recursive subroutine of keymap_panes.
- It handles one keymap, KEYMAP.
- The other arguments are passed along
- or point to local variables of the previous function.
- If NOTREAL is nonzero,
- don't bother really computing whether an item is enabled. */
-
-Lisp_Object
-get_single_keymap_event (keymap, lpnum)
- Lisp_Object keymap;
- int * lpnum;
-{
- Lisp_Object pending_maps;
- Lisp_Object tail, item, item1, item_string, table;
- struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
-
- pending_maps = Qnil;
-
- for (tail = keymap; XTYPE (tail) == Lisp_Cons; tail = XCONS (tail)->cdr)
- {
- /* Look at each key binding, and if it has a menu string,
- make a menu item from it. */
-
- item = XCONS (tail)->car;
-
- if (XTYPE (item) == Lisp_Cons)
- {
- item1 = XCONS (item)->cdr;
-
- if (CONSP (item1))
- {
- item_string = XCONS (item1)->car;
- if (XTYPE (item_string) == Lisp_String)
- {
- /* This is the real definition--the function to run. */
-
- Lisp_Object def;
-
- /* These are the saved equivalent keyboard key sequence
- and its key-description. */
-
- Lisp_Object descrip;
- Lisp_Object tem, enabled;
-
- /* GCPRO because ...enabled_p will call eval
- and ..._equiv_key may autoload something.
- Protecting KEYMAP preserves everything we use;
- aside from that, must protect whatever might be
- a string. Since there's no GCPRO5, we refetch
- item_string instead of protecting it. */
-
- descrip = def = Qnil;
- GCPRO3 (keymap, pending_maps, def);
-
- def = menu_item_equiv_key (item_string, item1, &descrip);
-
- UNGCPRO;
-
- item_string = XCONS (item1)->car;
-
- tem = Fkeymapp (def);
- if (XSTRING (item_string)->data[0] == '@' && !NILP (tem))
- {
- pending_maps = Fcons (Fcons (def,
- Fcons (item_string,
- XCONS (item)->car)),
- pending_maps);
- }
- else
- {
- Lisp_Object submap;
-
- GCPRO4 (keymap, pending_maps, item, item_string);
-
- submap = get_keymap_1 (def, 0, 1);
-
- UNGCPRO;
-
- if (NILP (submap))
- {
- if (--(*lpnum) == 0)
- {
- return (Fcons (XCONS (item)->car, Qnil));
- }
- }
- else
- /* Display a submenu. */
- {
- Lisp_Object event = get_single_keymap_event (submap,
- lpnum);
-
- if (*lpnum <= 0)
- {
- if (!NILP (XCONS (item)->car))
- event = Fcons (XCONS (item)->car, event);
-
- return (event);
- }
- }
- }
- }
- }
- }
- else if (VECTORP (item))
- {
- /* Loop over the char values represented in the vector. */
- int len = XVECTOR (item)->size;
- int c;
- for (c = 0; c < len; c++)
- {
- Lisp_Object character;
- XSETFASTINT (character, c);
- item1 = XVECTOR (item)->contents[c];
- if (XTYPE (item1) == Lisp_Cons)
- {
- item_string = XCONS (item1)->car;
- if (XTYPE (item_string) == Lisp_String)
- {
- Lisp_Object def;
-
- /* These are the saved equivalent keyboard key sequence
- and its key-description. */
- Lisp_Object descrip;
- Lisp_Object tem, enabled;
-
- /* GCPRO because ...enabled_p will call eval
- and ..._equiv_key may autoload something.
- Protecting KEYMAP preserves everything we use;
- aside from that, must protect whatever might be
- a string. Since there's no GCPRO5, we refetch
- item_string instead of protecting it. */
- GCPRO4 (keymap, pending_maps, def, descrip);
- descrip = def = Qnil;
-
- def = menu_item_equiv_key (item_string, item1, &descrip);
-
- UNGCPRO;
-
- item_string = XCONS (item1)->car;
-
- tem = Fkeymapp (def);
- if (XSTRING (item_string)->data[0] == '@' && !NILP (tem))
- pending_maps = Fcons (Fcons (def, Fcons (item_string, character)),
- pending_maps);
- else
- {
- Lisp_Object submap;
-
- GCPRO4 (keymap, pending_maps, descrip, item_string);
-
- submap = get_keymap_1 (def, 0, 1);
-
- UNGCPRO;
-
- if (NILP (submap))
- {
- if (--(*lpnum) == 0)
- {
- return (Fcons (character, Qnil));
- }
- }
- else
- /* Display a submenu. */
- {
- Lisp_Object event = get_single_keymap_event (submap,
- lpnum);
-
- if (*lpnum <= 0)
- {
- if (!NILP (character))
- event = Fcons (character, event);
-
- return (event);
- }
- }
- }
- }
- }
- }
- }
- }
-
- /* Process now any submenus which want to be panes at this level. */
- while (!NILP (pending_maps))
- {
- Lisp_Object elt, eltcdr, string;
- elt = Fcar (pending_maps);
- eltcdr = XCONS (elt)->cdr;
- string = XCONS (eltcdr)->car;
- /* We no longer discard the @ from the beginning of the string here.
- Instead, we do this in w32menu_show. */
- {
- Lisp_Object event = get_single_keymap_event (Fcar (elt), lpnum);
-
- if (*lpnum <= 0)
- {
- if (!NILP (XCONS (eltcdr)->cdr))
- event = Fcons (XCONS (eltcdr)->cdr, event);
-
- return (event);
- }
- }
-
- pending_maps = Fcdr (pending_maps);
- }
-
- return (Qnil);
-}
-
-/* Look through KEYMAPS, a vector of keymaps that is NMAPS long,
- and generate menu panes for them in menu_items.
- If NOTREAL is nonzero,
- don't bother really computing whether an item is enabled. */
-
-static Lisp_Object
-get_keymap_event (keymaps, nmaps, lpnum)
- Lisp_Object *keymaps;
- int nmaps;
- int * lpnum;
-{
- int mapno;
- Lisp_Object event = Qnil;
-
- /* Loop over the given keymaps, making a pane for each map.
- But don't make a pane that is empty--ignore that map instead.
- P is the number of panes we have made so far. */
- for (mapno = 0; mapno < nmaps; mapno++)
- {
- event = get_single_keymap_event (keymaps[mapno], lpnum);
-
- if (*lpnum <= 0) break;
- }
-
- return (event);
-}
-
-static Lisp_Object
-get_list_of_items_event (pane, lpnum)
- Lisp_Object pane;
- int * lpnum;
-{
- Lisp_Object tail, item, item1;
-
- for (tail = pane; !NILP (tail); tail = Fcdr (tail))
- {
- item = Fcar (tail);
- if (STRINGP (item))
- {
- if (-- (*lpnum) == 0)
- {
- return (Qnil);
- }
- }
- else if (!NILP (item))
- {
- if (--(*lpnum) == 0)
- {
- CHECK_CONS (item, 0);
- return (Fcdr (item));
- }
- }
- }
-
- return (Qnil);
-}
-
-/* Push all the panes and items of a menu described by the
- alist-of-alists MENU.
- This handles old-fashioned calls to x-popup-menu. */
-
-static Lisp_Object
-get_list_of_panes_event (menu, lpnum)
- Lisp_Object menu;
- int * lpnum;
-{
- Lisp_Object tail;
-
- for (tail = menu; !NILP (tail); tail = Fcdr (tail))
- {
- Lisp_Object elt, pane_name, pane_data;
- Lisp_Object event;
-
- elt = Fcar (tail);
- pane_data = Fcdr (elt);
- CHECK_CONS (pane_data, 0);
-
- event = get_list_of_items_event (pane_data, lpnum);
-
- if (*lpnum <= 0)
- {
- return (event);
- }
- }
-
- return (Qnil);
-}
-
-Lisp_Object
-get_menu_event (menu, lpnum)
- Lisp_Object menu;
- int * lpnum;
-{
- Lisp_Object keymap, tem;
- Lisp_Object event;
-
- /* Decode the menu items from what was specified. */
-
- keymap = Fkeymapp (menu);
- tem = Qnil;
- if (XTYPE (menu) == Lisp_Cons)
- tem = Fkeymapp (Fcar (menu));
-
- if (!NILP (keymap))
- {
- keymap = get_keymap (menu);
-
- event = get_keymap_event (menu, 1, lpnum);
- }
- else if (!NILP (tem))
- {
- /* We were given a list of keymaps. */
- int nmaps = XFASTINT (Flength (menu));
- Lisp_Object *maps
- = (Lisp_Object *) alloca (nmaps * sizeof (Lisp_Object));
- int i;
-
- /* The first keymap that has a prompt string
- supplies the menu title. */
- for (tem = menu, i = 0; XTYPE (tem) == Lisp_Cons; tem = Fcdr (tem))
- {
- Lisp_Object prompt;
-
- maps[i++] = keymap = get_keymap (Fcar (tem));
- }
-
- event = get_keymap_event (maps, nmaps, lpnum);
- }
- else