diff src/xmenu.c @ 2747:f258c79c9162

(Fx_popup_menu): Add a vector of prefix keys for the panes. (keymap_panes): Allocate that vector. (single_keymap_panes): Fill in that vector. (xmenu_show): Return a list of events, not just one event.
author Richard M. Stallman <rms@gnu.org>
date Wed, 12 May 1993 05:17:47 +0000
parents 6700e25af205
children e94a593c3952
line wrap: on
line diff
--- a/src/xmenu.c	Tue May 11 23:23:34 1993 +0000
+++ b/src/xmenu.c	Wed May 12 05:17:47 1993 +0000
@@ -100,13 +100,16 @@
 \(STRING . REAL-DEFINITION).  To give the menu a title, put a string into\n\
 the keymap as a top-level element.\n\n\
 You can also use a list of keymaps as MENU.\n\
-  Then each keymap makes a separate pane.\n\n\
+  Then each keymap makes a separate pane.\n\
+When MENU is a keymap or a list of keymaps, the return value\n\
+is a list of events.\n\n\
 Alternatively, you can specify a menu of multiple panes\n\
   with a list of the form (TITLE PANE1 PANE2...),\n\
 where each pane is a list of form (TITLE ITEM1 ITEM2...).\n\
 Each ITEM is normally a cons cell (STRING . VALUE);\n\
 but a string can appear as an item--that makes a nonselectable line\n\
-in the menu.")
+in the menu.\n\
+With this form of menu, the return value is VALUE from the chosen item.")
   (position, menu)
      Lisp_Object position, menu;
 {
@@ -117,6 +120,7 @@
   char ***names;
   int **enables;
   Lisp_Object **obj_list;
+  Lisp_Object *prefixes;
   int *items;
   char *title;
   char *error_name;
@@ -213,7 +217,7 @@
 
       /* Extract the detailed info to make one pane.  */
       number_of_panes = keymap_panes (&obj_list, &menus, &names, &enables,
-				      &items, maps, nmaps);
+				      &items, &prefixes, maps, nmaps);
       /* The menu title seems to be ignored,
 	 so put it in the pane title.  */
       if (menus[0] == 0)
@@ -225,6 +229,7 @@
       ltitle = Fcar (menu);
       CHECK_STRING (ltitle, 1);
       title = (char *) XSTRING (ltitle)->data;
+      prefixes = 0;
       number_of_panes = list_of_panes (&obj_list, &menus, &names, &enables,
 				       &items, Fcdr (menu));
     }
@@ -261,8 +266,8 @@
       abort ();
 
     selection = xmenu_show (root, XMenu_xpos, XMenu_ypos, names, enables,
-			    menus, items, number_of_panes, obj_list, title,
-			    &error_name);
+			    menus, prefixes, items, number_of_panes, obj_list,
+			    title, &error_name);
   }
   UNBLOCK_INPUT;
   /* fprintf (stderr, "selection = %x\n", selection);  */
@@ -298,12 +303,13 @@
 
 Lisp_Object
 xmenu_show (parent, startx, starty, line_list, enable_list, pane_list,
-	    line_cnt, pane_cnt, item_list, title, error)
+	    prefixes, line_cnt, pane_cnt, item_list, title, error)
      Window parent;		
      int startx, starty;	/* upper left corner position BROKEN */
      char **line_list[];   	/* list of strings for items */
      int *enable_list[];   	/* list of strings for items */
      char *pane_list[];		/* list of pane titles */
+     Lisp_Object *prefixes;	/* Prefix key for each pane */
      char *title;
      int pane_cnt;		/* total number of panes */
      Lisp_Object *item_list[];	/* All items */
@@ -405,6 +411,12 @@
       fprintf (stderr, "pane= %d line = %d\n", panes, selidx);
 #endif
       entry = item_list[panes][selidx];
+      if (prefixes != 0)
+	{
+	  entry = Fcons (entry, Qnil);
+	  if (!NILP (prefixes[panes]))
+	    entry = Fcons (prefixes[panes], entry);
+	}
       break;
     case XM_FAILURE:
       /* free (datap_save); */
@@ -435,12 +447,13 @@
    KEYMAPS is a vector of keymaps.  NMAPS gives the length of KEYMAPS.  */
 
 int
-keymap_panes (vector, panes, names, enables, items, keymaps, nmaps)
+keymap_panes (vector, panes, names, enables, items, prefixes, keymaps, nmaps)
      Lisp_Object ***vector;	/* RETURN all menu objects */
      char ***panes;		/* RETURN pane names */
      char ****names;		/* RETURN all line names */
      int ***enables;		/* RETURN enable-flags of lines */
      int **items;		/* RETURN number of items per pane */
+     Lisp_Object **prefixes;	/* RETURN vector of prefix keys, per pane */
      Lisp_Object *keymaps;
      int nmaps;
 {
@@ -459,13 +472,14 @@
   *items = (int *) xmalloc (npanes_allocated * sizeof (int));
   *names = (char ***) xmalloc (npanes_allocated * sizeof (char **));
   *enables = (int **) xmalloc (npanes_allocated * sizeof (int *));
+  *prefixes = (Lisp_Object *) xmalloc (npanes_allocated * sizeof (Lisp_Object));
 
   /* 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++)
     single_keymap_panes (keymaps[mapno], panes, vector, names, enables, items,
-			 &p, &npanes_allocated, "");
+			 prefixes, &p, &npanes_allocated, "");
 
   /* Return the number of panes.  */
   return p;
@@ -476,7 +490,7 @@
    The other arguments are passed along
    or point to local variables of the previous function.  */
 
-single_keymap_panes (keymap, panes, vector, names, enables, items,
+single_keymap_panes (keymap, panes, vector, names, enables, items, prefixes,
 		     p_ptr, npanes_allocated_ptr, pane_name)
      Lisp_Object keymap;
      Lisp_Object ***vector;	/* RETURN all menu objects */
@@ -484,6 +498,7 @@
      char ****names;		/* RETURN all line names */
      int ***enables;		/* RETURN enable flags of lines */
      int **items;		/* RETURN number of items per pane */
+     Lisp_Object **prefixes;	/* RETURN vector of prefix keys, per pane */
      int *p_ptr;
      int *npanes_allocated_ptr;
      char *pane_name;
@@ -508,6 +523,10 @@
       *items
 	= (int *) xrealloc (*items,
 			    *npanes_allocated_ptr * sizeof (int));
+      *prefixes
+	= (Lisp_Object *) xrealloc (*prefixes,
+				    (*npanes_allocated_ptr
+				     * sizeof (Lisp_Object)));
       *names
 	= (char ***) xrealloc (*names,
 			       *npanes_allocated_ptr * sizeof (char **));
@@ -519,6 +538,10 @@
   /* When a menu comes from keymaps, don't give names to the panes.  */
   (*panes)[*p_ptr] = pane_name;
 
+  /* Normally put nil as pane's prefix key.
+     Caller will override this if appropriate.  */
+  (*prefixes)[*p_ptr] = Qnil;
+
   /* Get the length of the list level of the keymap.  */
   i = XFASTINT (Flength (keymap));
 
@@ -563,7 +586,7 @@
 		    }
 		  tem = Fkeymapp (def);
 		  if (XSTRING (item2)->data[0] == '@' && !NILP (tem))
-		    pending_maps = Fcons (Fcons (def, item2),
+		    pending_maps = Fcons (Fcons (def, Fcons (item2, XCONS (item)->car)),
 					  pending_maps);
 		  else
 		    {
@@ -609,7 +632,7 @@
 
 		      tem = Fkeymapp (def);
 		      if (XSTRING (item2)->data[0] == '@' && !NILP (tem))
-			pending_maps = Fcons (Fcons (def, item2),
+			pending_maps = Fcons (Fcons (def, Fcons (item2, character)),
 					      pending_maps);
 		      else
 			{
@@ -642,12 +665,15 @@
   /* Process now any submenus which want to be panes at this level.  */
   while (!NILP (pending_maps))
     {
-      Lisp_Object elt;
+      Lisp_Object elt, eltcdr;
+      int panenum = *p_ptr;
       elt = Fcar (pending_maps);
+      eltcdr = XCONS (elt)->cdr;
       single_keymap_panes (Fcar (elt), panes, vector, names, enables, items,
-			   p_ptr, npanes_allocated_ptr,
+			   prefixes, p_ptr, npanes_allocated_ptr,
 			   /* Add 1 to discard the @.  */
-			   (char *) XSTRING (XCONS (elt)->cdr)->data + 1);
+			   (char *) XSTRING (XCONS (eltcdr)->car)->data + 1);
+      (*prefixes)[panenum] = XCONS (eltcdr)->cdr;
       pending_maps = Fcdr (pending_maps);
     }
 }