]> git.eshelyaron.com Git - emacs.git/commitdiff
(menu_bar_items): Accept old vector as arg. Return a vector.
authorRichard M. Stallman <rms@gnu.org>
Wed, 2 Mar 1994 04:11:11 +0000 (04:11 +0000)
committerRichard M. Stallman <rms@gnu.org>
Wed, 2 Mar 1994 04:11:11 +0000 (04:11 +0000)
(menu_bar_one_keymap, menu_bar_item): Associated changes.
(make_lispy_event): Use FRAME_MENU_BAR_LINES as vector.

src/keyboard.c

index 6d190e213d1d7e475ffb6994a686a8808739aeac..fc9ce849e00c071da09ec3ff0a4b21b02afcf5a2 100644 (file)
@@ -985,35 +985,6 @@ command_loop_1 ()
          && !NILP (Ffboundp (Qrecompute_lucid_menubar)))
        call0 (Qrecompute_lucid_menubar);
 
-#if 0 /* This is done in xdisp.c now.  */
-#ifdef MULTI_FRAME
-      for (tem = Vframe_list; CONSP (tem); tem = XCONS (tem)->cdr)
-       {
-         struct frame *f = XFRAME (XCONS (tem)->car);
-         struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
-
-         /* If the user has switched buffers or windows, we need to
-            recompute to reflect the new bindings.  But we'll
-            recompute when update_mode_lines is set too; that means
-            that people can use force-mode-line-update to request
-            that the menu bar be recomputed.  The adverse effect on
-            the rest of the redisplay algorithm is about the same as
-            windows_or_buffers_changed anyway.  */
-         if (windows_or_buffers_changed
-             || update_mode_lines
-             || (XFASTINT (w->last_modified) < MODIFF
-                 && (XFASTINT (w->last_modified)
-                     <= XBUFFER (w->buffer)->save_modified)))
-           {
-             struct buffer *prev = current_buffer;
-             current_buffer = XBUFFER (w->buffer);
-             FRAME_MENU_BAR_ITEMS (f) = menu_bar_items ();
-             current_buffer = prev;
-           }
-       }
-#endif /* MULTI_FRAME */
-#endif /* 0 */
-
       /* Read next key sequence; i gets its length.  */
       i = read_key_sequence (keybuf, (sizeof keybuf / sizeof (keybuf[0])), Qnil);
 
@@ -2509,26 +2480,32 @@ make_lispy_event (event)
            if (row < FRAME_MENU_BAR_LINES (f))
 #endif
              {
-               Lisp_Object items;
+               Lisp_Object items, item;
 
 #ifdef USE_X_TOOLKIT
                /* The click happened in the menubar.
                   Look for the menu item selected.  */
-               items = map_event_to_object (event, f);
+               item = map_event_to_object (event, f);
 
                XFASTINT (event->y) = 1;
 #else /* not USE_X_TOOLKIT  */
                int hpos;
+               int i;
 
                items = FRAME_MENU_BAR_ITEMS (f);
-               for (; CONSP (items); items = XCONS (items)->cdr)
+               for (i = 0; i < XVECTOR (items)->size; i += 3)
                  {
                    Lisp_Object pos, string;
-                   pos = Fcdr (Fcdr (Fcar (items)));
-                   string = Fcar (Fcdr (Fcar (items)));
+                   string = XVECTOR (items)->contents[i + 1];
+                   pos = XVECTOR (items)->contents[i + 2];
+                   if (NILP (string))
+                     break;
                    if (column >= XINT (pos)
                        && column < XINT (pos) + XSTRING (string)->size)
-                     break;
+                     {
+                       item = XVECTOR (items)->contents[i];
+                       break;
+                     }
                  }
 #endif /* not USE_X_TOOLKIT  */
 
@@ -2539,11 +2516,7 @@ make_lispy_event (event)
                                         Fcons (make_number (event->timestamp),
                                                Qnil))));
 
-               if (CONSP (items))
-                 return Fcons (Fcar (Fcar (items)),
-                               Fcons (position, Qnil));
-               else
-                 return Fcons (Qnil, Fcons (position, Qnil));
+               return Fcons (item, Fcons (position, Qnil));
              }
 
            window = window_from_coordinates (f, column, row, &part);
@@ -3476,15 +3449,24 @@ map_prompt (map)
   return Qnil;
 }
 
-static Lisp_Object menu_bar_item ();
-static Lisp_Object menu_bar_one_keymap ();
+static void menu_bar_item ();
+static void menu_bar_one_keymap ();
+
+/* These variables hold the vector under construction within
+   menu_bar_items and its subroutines, and the current index
+   for storing into that vector.  */
+static Lisp_Object menu_bar_items_vector;
+static Lisp_Object menu_bar_items_index;
 
-/* Return a list of menu items for a menu bar, appropriate
-   to the current buffer.
-   The elements have the form (KEY STRING . nil).  */
+/* Return a vector of menu items for a menu bar, appropriate
+   to the current buffer.  Each item has three elements in the vector:
+   KEY STRING nil.
+
+   OLD is an old vector we can optionally reuse, or nil.  */
 
 Lisp_Object
-menu_bar_items ()
+menu_bar_items (old)
+     Lisp_Object old;
 {
   /* The number of keymaps we're scanning right now, and the number of
      keymaps we have allocated space for.  */
@@ -3501,6 +3483,10 @@ menu_bar_items ()
   int mapno;
   Lisp_Object oquit;
 
+  int i;
+
+  struct gcpro gcpro1;
+
   /* In order to build the menus, we need to call the keymap
      accessors.  They all call QUIT.  But this function is called
      during redisplay, during which a quit is fatal.  So inhibit
@@ -3510,6 +3496,14 @@ menu_bar_items ()
   oquit = Vinhibit_quit;
   Vinhibit_quit = Qt; 
 
+  if (!NILP (old))
+    menu_bar_items_vector = old;
+  else
+    menu_bar_items_vector = Fmake_vector (make_number (24), Qnil);
+  menu_bar_items_index = 0;
+
+  GCPRO1 (menu_bar_items_vector);
+
   /* Build our list of keymaps.
      If we recognize a function key and replace its escape sequence in
      keybuf with its symbol, or if the sequence starts with a mouse
@@ -3551,29 +3545,63 @@ menu_bar_items ()
 
       tem = Fkeymapp (def);
       if (!NILP (tem))
-       result = menu_bar_one_keymap (def, result);
+       menu_bar_one_keymap (def);
     }
 
+  /* Move to the end those items that should be at the end.  */
+
   for (tail = Vmenu_bar_final_items; CONSP (tail); tail = XCONS (tail)->cdr)
     {
-      Lisp_Object elt;
+      int i;
+      int end = menu_bar_items_index;
+
+      for (i = 0; i < end; i += 3)
+       if (EQ (XCONS (tail)->car, XVECTOR (menu_bar_items_vector)->contents[i]))
+         {
+           Lisp_Object tem;
+           end -= 3;
+#define EXCH(a, b) tem = a, a = b, b = tem
+           EXCH (XVECTOR (menu_bar_items_vector)->contents[i],
+                 XVECTOR (menu_bar_items_vector)->contents[end]);
+           EXCH (XVECTOR (menu_bar_items_vector)->contents[i + 1],
+                 XVECTOR (menu_bar_items_vector)->contents[end + 1]);
+           EXCH (XVECTOR (menu_bar_items_vector)->contents[i + 2],
+                 XVECTOR (menu_bar_items_vector)->contents[end + 2]);
+#undef EXCH
+           i -= 3;
+         }
+    }
 
-      elt = Fassq (XCONS (tail)->car, result);
-      if (!NILP (elt))
-       result = Fcons (elt, Fdelq (elt, result));
+  /* Add nil, nil, nil at the end.  */
+  i = menu_bar_items_index;
+  if (i + 3 > XVECTOR (menu_bar_items_vector)->size)
+    {
+      Lisp_Object tem;
+      int newsize = 2 * i;
+      tem = Fmake_vector (make_number (2 * i), Qnil);
+      bcopy (XVECTOR (menu_bar_items_vector)->contents,
+            XVECTOR (tem)->contents, i * sizeof (Lisp_Object));
+      menu_bar_items_vector = tem;
     }
+  /* Add this item.  */
+  XVECTOR (menu_bar_items_vector)->contents[i++] = Qnil;
+  XVECTOR (menu_bar_items_vector)->contents[i++] = Qnil;
+  XVECTOR (menu_bar_items_vector)->contents[i++] = Qnil;
+  menu_bar_items_index = i;
 
-  result = Fnreverse (result);
   Vinhibit_quit = oquit;
-  return result;
+  UNGCPRO;
+  return menu_bar_items_vector;
 }
 \f
 /* Scan one map KEYMAP, accumulating any menu items it defines
-   that have not yet been seen in RESULT.  Return the updated RESULT.  */
+   that have not yet been seen in RESULT.  Return the updated RESULT.
+   *OLD is the frame's old menu bar list; we swipe elts from that
+   to avoid consing.  */
 
-static Lisp_Object
-menu_bar_one_keymap (keymap, result)
-     Lisp_Object keymap, result;
+static void
+menu_bar_one_keymap (keymap)
+     Lisp_Object keymap;
 {
   Lisp_Object tail, item, key, binding, item_string, table;
 
@@ -3589,12 +3617,10 @@ menu_bar_one_keymap (keymap, result)
            {
              item_string = XCONS (binding)->car;
              if (XTYPE (item_string) == Lisp_String)
-               result = menu_bar_item (key, item_string,
-                                       Fcdr (binding), result);
+               menu_bar_item (key, item_string, Fcdr (binding));
            }
          else if (EQ (binding, Qundefined))
-           result = menu_bar_item (key, item_string,
-                                   binding, result);
+           menu_bar_item (key, item_string, binding);
        }
       else if (XTYPE (item) == Lisp_Vector)
        {
@@ -3610,17 +3636,13 @@ menu_bar_one_keymap (keymap, result)
                {
                  item_string = XCONS (binding)->car;
                  if (XTYPE (item_string) == Lisp_String)
-                   result = menu_bar_item (key, item_string,
-                                           Fcdr (binding), result);
+                   menu_bar_item (key, item_string, Fcdr (binding));
                }
              else if (EQ (binding, Qundefined))
-               result = menu_bar_item (key, item_string,
-                                       binding, result);
+               menu_bar_item (key, item_string, binding);
            }
        }
     }
-
-  return result;
 }
 
 /* This is used as the handler when calling internal_condition_case_1.  */
@@ -3632,19 +3654,29 @@ menu_bar_item_1 (arg)
   return Qnil;
 }
 
-static Lisp_Object
-menu_bar_item (key, item_string, def, result)
-     Lisp_Object key, item_string, def, result;
+static void
+menu_bar_item (key, item_string, def)
+     Lisp_Object key, item_string, def;
 {
   Lisp_Object tem;
   Lisp_Object enabled;
+  int i;
 
   if (EQ (def, Qundefined))
     {
       /* If a map has an explicit nil as definition,
         discard any previously made menu bar item.  */
-      tem = Fassq (key, result);
-      return Fdelq (tem, result);
+
+      for (i = 0; i < menu_bar_items_index; i += 3)
+       if (EQ (key, XVECTOR (menu_bar_items_vector)->contents[i]))
+         {
+           if (menu_bar_items_index > i + 3)
+             bcopy (&XVECTOR (menu_bar_items_vector)->contents[i + 3],
+                    &XVECTOR (menu_bar_items_vector)->contents[i],
+                    (menu_bar_items_index - i - 3) * sizeof (Lisp_Object));
+           menu_bar_items_index -= 3;
+           return;
+         }
     }
 
   /* See if this entry is enabled.  */
@@ -3662,13 +3694,34 @@ menu_bar_item (key, item_string, def, result)
                                             menu_bar_item_1);
     }
 
-  /* Add an entry for this key and string
-     if there is none yet.  */
-  tem = Fassq (key, result);
-  if (!NILP (enabled) && NILP (tem))
-    result = Fcons (Fcons (key, Fcons (item_string, Qnil)), result);
+  /* Ignore this item if it's not enabled.  */
+  if (NILP (enabled))
+    return;
 
-  return result;
+  /* If there's already such an item, don't make another.  */
+  for (i = 0; i < menu_bar_items_index; i += 3)
+    if (EQ (key, XVECTOR (menu_bar_items_vector)->contents[i]))
+      break;
+
+  /* If we did not find this item, add it at the end.  */
+  if (i == menu_bar_items_index)
+    {
+      /* If vector is too small, get a bigger one.  */
+      if (i + 3 > XVECTOR (menu_bar_items_vector)->size)
+       {
+         Lisp_Object tem;
+         int newsize = 2 * i;
+         tem = Fmake_vector (make_number (2 * i), Qnil);
+         bcopy (XVECTOR (menu_bar_items_vector)->contents,
+                XVECTOR (tem)->contents, i * sizeof (Lisp_Object));
+         menu_bar_items_vector = tem;
+       }
+      /* Add this item.  */
+      XVECTOR (menu_bar_items_vector)->contents[i++] = key;
+      XVECTOR (menu_bar_items_vector)->contents[i++] = item_string;
+      XVECTOR (menu_bar_items_vector)->contents[i++] = Qnil;
+      menu_bar_items_index = i;
+    }
 }
 \f
 /* Read a character using menus based on maps in the array MAPS.