(menubar_selection_callback, dialog_selection_callback)
[bpt/emacs.git] / src / xmenu.c
index 4503c64..fd7c9a3 100644 (file)
@@ -151,6 +151,47 @@ static int menu_items_submenu_depth;
    Xt on behalf of one of the widget sets.  */
 static int popup_activated_flag;
 
+/* This holds a Lisp vector
+   which contains frames that have menu bars.
+   Each frame that has a menu bar is found at some index in this vector
+   and the menu bar widget refers to the frame through that index.  */
+static Lisp_Object frame_vector;
+\f
+/* Return the index of FRAME in frame_vector.
+   If FRAME isn't in frame_vector yet, put it in,
+   lengthening the vector if necessary.  */
+
+static int
+frame_vector_add_frame (f)
+     FRAME_PTR *f;
+{
+  int length = XVECTOR (frame_vector)->size;
+  int i, empty = -1;
+  Lisp_Object new, frame;
+
+  XSETFRAME (frame, f);
+
+  for (i = 0; i < length; i++)
+    {
+      if (EQ (frame, XVECTOR (frame_vector)->contents[i]))
+       return i;
+      if (NILP (XVECTOR (frame_vector)->contents[i]))
+       empty = i;
+    }
+
+  if (empty >= 0)
+    {
+      XVECTOR (frame_vector)->contents[empty] = frame;
+      return empty;
+    }
+
+  new = Fmake_vector (make_number (length * 2), Qnil);
+  bcopy (XVECTOR (frame_vector)->contents,
+        XVECTOR (new)->contents, sizeof (Lisp_Object) * length);
+  
+  XVECTOR (frame_vector)->contents[length] = frame;
+  return length;
+}
 \f
 /* Initialize the menu_items structure if we haven't already done so.
    Also mark it as currently empty.  */
@@ -355,22 +396,6 @@ menu_item_equiv_key (item_string, item1, descrip_ptr)
           We don't try both, because that makes easymenu menus slow.  */
        savedkey = Fwhere_is_internal (def, Qnil, Qt, Qnil);
 
-
-      if (VECTORP (savedkey)
-         && EQ (XVECTOR (savedkey)->contents[0], Qmenu_bar))
-       savedkey = Qnil;
-      /* Reject two-key sequences that start with a mouse click.
-        These are probably menu items.  */
-      if (VECTORP (savedkey)
-         && XVECTOR (savedkey)->size > 1
-         && SYMBOLP (XVECTOR (savedkey)->contents[0]))
-       {
-         Lisp_Object tem;
-
-         tem = Fget (XVECTOR (savedkey)->contents[0], Qevent_kind);
-         if (EQ (tem, Qmouse_click))
-           savedkey = Qnil;
-       }
       if (!NILP (savedkey))
        {
          descrip = Fkey_description (savedkey);
@@ -742,13 +767,14 @@ cached information about equivalent key sequences.")
       if (EQ (position, Qt))
        {
          /* Use the mouse's current position.  */
-         FRAME_PTR new_f = 0;
+         FRAME_PTR new_f = selected_frame;
          Lisp_Object bar_window;
          int part;
          unsigned long time;
 
          if (mouse_position_hook)
-           (*mouse_position_hook) (&new_f, &bar_window, &part, &x, &y, &time);
+           (*mouse_position_hook) (&new_f, 1, &bar_window,
+                                   &part, &x, &y, &time);
          if (new_f != 0)
            XSETFRAME (window, new_f);
          else
@@ -932,13 +958,13 @@ on the left of the dialog box and all following items on the right.\n\
     {
 #if 0 /* Using the frame the mouse is on may not be right.  */
       /* Use the mouse's current position.  */
-      FRAME_PTR new_f = 0;
+      FRAME_PTR new_f = selected_frame;
       Lisp_Object bar_window;
       int part;
       unsigned long time;
       Lisp_Object x, y;
 
-      (*mouse_position_hook) (&new_f, &bar_window, &part, &x, &y, &time);
+      (*mouse_position_hook) (&new_f, 1, &bar_window, &part, &x, &y, &time);
 
       if (new_f != 0)
        XSETFRAME (window, new_f);
@@ -1075,7 +1101,7 @@ menubar_selection_callback (widget, id, client_data)
      XtPointer client_data;
 {
   Lisp_Object prefix;
-  FRAME_PTR f = (FRAME_PTR) id;
+  FRAME_PTR f = XFRAME (XVECTOR (frame_vector)->contents[id]);
   Lisp_Object vector;
   Lisp_Object *subprefix_stack;
   int submenu_depth = 0;
@@ -1104,40 +1130,42 @@ menubar_selection_callback (widget, id, client_data)
        }
       else if (EQ (XVECTOR (vector)->contents[i], Qt))
        {
-         prefix
-           = XVECTOR (vector)->contents[i + MENU_ITEMS_PANE_PREFIX];
+         prefix = XVECTOR (vector)->contents[i + MENU_ITEMS_PANE_PREFIX];
          i += MENU_ITEMS_PANE_LENGTH;
        }
       else
        {
-         entry
-           = XVECTOR (vector)->contents[i + MENU_ITEMS_ITEM_VALUE];
-         if ((int) client_data == i)
+         entry = XVECTOR (vector)->contents[i + MENU_ITEMS_ITEM_VALUE];
+         /* The EMACS_INT cast avoids a warning.  There's no problem
+            as long as pointers have enough bits to hold small integers.  */
+         if ((int) (EMACS_INT) client_data == i)
            {
              int j;
              struct input_event buf;
+             Lisp_Object frame;
 
+             XSETFRAME (frame, f);
              buf.kind = menu_bar_event;
-             buf.frame_or_window = Qmenu_bar;
+             buf.frame_or_window = Fcons (frame, Qmenu_bar);
              kbd_buffer_store_event (&buf);
 
              for (j = 0; j < submenu_depth; j++)
                if (!NILP (subprefix_stack[j]))
                  {
                    buf.kind = menu_bar_event;
-                   buf.frame_or_window = subprefix_stack[j];
+                   buf.frame_or_window = Fcons (frame, subprefix_stack[j]);
                    kbd_buffer_store_event (&buf);
                  }
 
              if (!NILP (prefix))
                {
                  buf.kind = menu_bar_event;
-                 buf.frame_or_window = prefix;
+                 buf.frame_or_window = Fcons (frame, prefix);
                  kbd_buffer_store_event (&buf);
                }
 
              buf.kind = menu_bar_event;
-             buf.frame_or_window = entry;
+             buf.frame_or_window = Fcons (frame, entry);
              kbd_buffer_store_event (&buf);
 
              return;
@@ -1316,7 +1344,9 @@ single_submenu (item_key, item_name, maps)
          if (!NILP (descrip))
            wv->key = (char *) XSTRING (descrip)->data;
          wv->value = 0;
-         wv->call_data = (!NILP (def) ? (void *) i : 0);
+         /* The EMACS_INT cast avoids a warning.  There's no problem
+            as long as pointers have enough bits to hold small integers.  */
+         wv->call_data = (!NILP (def) ? (void *) (EMACS_INT) i : 0);
          wv->enabled = !NILP (enable);
          prev_wv = wv;
 
@@ -1393,10 +1423,12 @@ set_frame_menubar (f, first_time)
      int first_time;
 {
   Widget menubar_widget = f->display.x->menubar_widget;
-  int id = (int) f;
-  Lisp_Object tail, items;
+  Lisp_Object tail, items, frame;
   widget_value *wv, *first_wv, *prev_wv = 0;
   int i;
+  int id;
+
+  id = frame_vector_add_frame (f);
 
   BLOCK_INPUT;
 
@@ -1508,12 +1540,13 @@ free_frame_menubar (f)
   int id;
 
   menubar_widget = f->display.x->menubar_widget;
-  id = (int) f;
   
   if (menubar_widget)
     {
+      id = frame_vector_add_frame (f);
       BLOCK_INPUT;
       lw_destroy_all_widgets (id);
+      XVECTOR (frame_vector)->contents[id] = Qnil;
       UNBLOCK_INPUT;
     }
 }
@@ -1835,7 +1868,9 @@ dialog_selection_callback (widget, id, client_data)
      LWLIB_ID id;
      XtPointer client_data;
 {
-  if ((int)client_data != -1)
+  /* The EMACS_INT cast avoids a warning.  There's no problem
+     as long as pointers have enough bits to hold small integers.  */
+  if ((int) (EMACS_INT) client_data != -1)
     menu_item_selection = (Lisp_Object *) client_data;
   BLOCK_INPUT;
   lw_destroy_all_widgets (id);
@@ -2367,6 +2402,9 @@ syms_of_xmenu ()
   widget_id_tick = (1<<16);    
 #endif
 
+  staticpro (&frame_vector);
+  frame_vector = Fmake_vector (make_number (10), Qnil);
+
   defsubr (&Sx_popup_menu);
   defsubr (&Sx_popup_dialog);
 }