XEmacs 21.2.27 "Hera".
[chise/xemacs-chise.git.1] / src / menubar-x.c
index fac1c60..62f4afc 100644 (file)
@@ -27,9 +27,7 @@ Boston, MA 02111-1307, USA.  */
 #include "lisp.h"
 
 #include "console-x.h"
-#include "EmacsManager.h"
 #include "EmacsFrame.h"
-#include "EmacsShell.h"
 #include "gui-x.h"
 
 #include "buffer.h"
@@ -96,14 +94,11 @@ menu_item_descriptor_to_widget_value_1 (Lisp_Object desc,
      prohibits GC. */
   /* !!#### This function has not been Mule-ized */
   int menubar_root_p = (menu_type == MENUBAR_TYPE && depth == 0);
-  widget_value *wv;
-  Lisp_Object wv_closure;
   int count = specpdl_depth ();
   int partition_seen = 0;
+  widget_value *wv = xmalloc_widget_value ();
+  Lisp_Object wv_closure = make_opaque_ptr (wv);
 
-  wv = xmalloc_widget_value ();
-
-  wv_closure = make_opaque_ptr (wv);
   record_unwind_protect (widget_value_unwind, wv_closure);
 
   if (STRINGP (desc))
@@ -122,13 +117,19 @@ menu_item_descriptor_to_widget_value_1 (Lisp_Object desc,
        }
       else
        {
-         wv->name = string_chars;
+         wv->name = xstrdup (string_chars);
          wv->enabled = 1;
+         /* dverna Dec. 98: command_builder_operate_menu_accelerator will
+            manipulate the accel as a Lisp_Object if the widget has a name.
+            Since simple labels have a name, but no accel, we *must* set it
+            to nil */
+         wv->accel = LISP_TO_VOID (Qnil);
        }
     }
   else if (VECTORP (desc))
     {
-      if (!button_item_to_widget_value (desc, wv, 1,
+      Lisp_Object gui_item = gui_parse_item_keywords (desc);
+      if (!button_item_to_widget_value (gui_item, wv, 1,
                                        (menu_type == MENUBAR_TYPE
                                         && depth <= 1)))
        {
@@ -146,13 +147,16 @@ menu_item_descriptor_to_widget_value_1 (Lisp_Object desc,
        {
          Lisp_Object key, val;
          Lisp_Object include_p = Qnil, hook_fn = Qnil, config_tag = Qnil;
+         Lisp_Object active_p = Qt;
          Lisp_Object accel;
          int included_spec = 0;
+         int active_spec = 0;
          wv->type = CASCADE_TYPE;
          wv->enabled = 1;
          wv->name = (char *) XSTRING_DATA (LISP_GETTEXT (XCAR (desc)));
+         wv->name = xstrdup (wv->name);
 
-         accel = menu_name_to_accelerator (wv->name);
+         accel = gui_name_accelerator (LISP_GETTEXT (XCAR (desc)));
          wv->accel = LISP_TO_VOID (accel);
 
          desc = Fcdr (desc);
@@ -162,7 +166,7 @@ menu_item_descriptor_to_widget_value_1 (Lisp_Object desc,
              Lisp_Object cascade = desc;
              desc = Fcdr (desc);
              if (NILP (desc))
-               signal_simple_error ("keyword in menu lacks a value",
+               signal_simple_error ("Keyword in menu lacks a value",
                                     cascade);
              val = Fcar (desc);
              desc = Fcdr (desc);
@@ -172,6 +176,8 @@ menu_item_descriptor_to_widget_value_1 (Lisp_Object desc,
                config_tag = val;
              else if (EQ (key, Q_filter))
                hook_fn = val;
+             else if (EQ (key, Q_active))
+               active_p = val, active_spec = 1;
              else if (EQ (key, Q_accelerator))
                {
                  if ( SYMBOLP (val)
@@ -180,8 +186,12 @@ menu_item_descriptor_to_widget_value_1 (Lisp_Object desc,
                  else
                    signal_simple_error ("bad keyboard accelerator", val);
                }
+             else if (EQ (key, Q_label))
+               {
+                 /* implement in 21.2 */
+               }
              else
-               signal_simple_error ("unknown menu cascade keyword", cascade);
+               signal_simple_error ("Unknown menu cascade keyword", cascade);
            }
 
          if ((!NILP (config_tag)
@@ -191,7 +201,11 @@ menu_item_descriptor_to_widget_value_1 (Lisp_Object desc,
              wv = NULL;
              goto menu_item_done;
            }
-         if (!NILP (hook_fn))
+
+         if (active_spec)
+           active_p = Feval (active_p);
+
+         if (!NILP (hook_fn) && !NILP (active_p))
            {
 #if defined LWLIB_MENUBARS_LUCID || defined LWLIB_MENUBARS_MOTIF
              if (filter_p || depth == 0)
@@ -210,6 +224,7 @@ menu_item_descriptor_to_widget_value_1 (Lisp_Object desc,
                  incr_wv->type = INCREMENTAL_TYPE;
                  incr_wv->enabled = 1;
                  incr_wv->name = wv->name;
+                 incr_wv->name = xstrdup (wv->name);
                  /* This is automatically GC protected through
                     the call to lw_map_widget_values(); no need
                     to worry. */
@@ -226,7 +241,7 @@ menu_item_descriptor_to_widget_value_1 (Lisp_Object desc,
              widget_value *title_wv = xmalloc_widget_value ();
              widget_value *sep_wv = xmalloc_widget_value ();
              title_wv->type = TEXT_TYPE;
-             title_wv->name = wv->name;
+             title_wv->name = xstrdup (wv->name);
              title_wv->enabled = 1;
              title_wv->next = sep_wv;
              sep_wv->type = SEPARATOR_TYPE;
@@ -236,20 +251,37 @@ menu_item_descriptor_to_widget_value_1 (Lisp_Object desc,
              wv->contents = title_wv;
              prev = sep_wv;
            }
+         wv->enabled = ! NILP (active_p);
+         if (deep_p && !wv->enabled  && !NILP (desc))
+           {
+             widget_value *dummy;
+             /* Add a fake entry so the menus show up */
+             wv->contents = dummy = xmalloc_widget_value ();
+             dummy->name = xstrdup ("(inactive)");
+             dummy->accel = LISP_TO_VOID (Qnil);
+             dummy->enabled = 0;
+             dummy->selected = 0;
+             dummy->value = NULL;
+             dummy->type = BUTTON_TYPE;
+             dummy->call_data = NULL;
+             dummy->next = NULL;
+
+             goto menu_item_done;
+       }
+
        }
       else if (menubar_root_p)
        {
-         wv->name = (char *) "menubar";
+         wv->name = xstrdup ("menubar");
          wv->type = CASCADE_TYPE; /* Well, nothing else seems to fit and
                                      this is ignored anyway...  */
        }
       else
        {
-         signal_simple_error ("menu name (first element) must be a string",
+         signal_simple_error ("Menu name (first element) must be a string",
                                desc);
        }
 
-      wv->enabled = 1;
       if (deep_p || menubar_root_p)
        {
          widget_value *next;
@@ -260,7 +292,7 @@ menu_item_descriptor_to_widget_value_1 (Lisp_Object desc,
                {
                  if (partition_seen)
                    error (
-                    "more than one partition (nil) in menubar description");
+                    "More than one partition (nil) in menubar description");
                  partition_seen = 1;
                  next = xmalloc_widget_value ();
                  next->type = PUSHRIGHT_TYPE;
@@ -285,7 +317,7 @@ menu_item_descriptor_to_widget_value_1 (Lisp_Object desc,
   else if (NILP (desc))
     error ("nil may not appear in menu descriptions");
   else
-    signal_simple_error ("unrecognized menu descriptor", desc);
+    signal_simple_error ("Unrecognized menu descriptor", desc);
 
 menu_item_done:
 
@@ -328,11 +360,38 @@ int in_menu_callback;
 static Lisp_Object
 restore_in_menu_callback (Lisp_Object val)
 {
-    in_menu_callback = XINT(val);
+    in_menu_callback = XINT (val);
     return Qnil;
 }
 #endif /* LWLIB_MENUBARS_LUCID || LWLIB_MENUBARS_MOTIF */
 
+#if 0
+/* #### Sort of a hack needed to process Vactivate_menubar_hook
+   correctly wrt buffer-local values.  A correct solution would
+   involve adding a callback mechanism to run_hook().  This function
+   is currently unused.  */
+static int
+my_run_hook (Lisp_Object hooksym, int allow_global_p)
+{
+  /* This function can GC */
+  Lisp_Object tail;
+  Lisp_Object value = Fsymbol_value (hooksym);
+  int changes = 0;
+
+  if (!NILP (value) && (!CONSP (value) || EQ (XCAR (value), Qlambda)))
+    return !EQ (call0 (value), Qt);
+
+  EXTERNAL_LIST_LOOP (tail, value)
+    {
+      if (allow_global_p && EQ (XCAR (tail), Qt))
+       changes |= my_run_hook (Fdefault_value (hooksym), 0);
+      if (!EQ (call0 (XCAR (tail)), Qt))
+       changes = 1;
+    }
+  return changes;
+}
+#endif
+
 
 /* The order in which callbacks are run is funny to say the least.
    It's sometimes tricky to avoid running a callback twice, and to
@@ -358,12 +417,9 @@ static void
 pre_activate_callback (Widget widget, LWLIB_ID id, XtPointer client_data)
 {
   /* This function can GC */
-  struct gcpro gcpro1;
   struct device *d = get_device_from_display (XtDisplay (widget));
   struct frame *f = x_any_window_to_frame (d, XtWindow (widget));
-  Lisp_Object rest = Qnil;
   Lisp_Object frame;
-  int any_changes = 0;
   int count;
 
   /* set in lwlib to the time stamp associated with the most recent menu
@@ -409,33 +465,28 @@ pre_activate_callback (Widget widget, LWLIB_ID id, XtPointer client_data)
          wv = xmalloc_widget_value ();
          wv->type = CASCADE_TYPE;
          wv->next = NULL;
+         wv->accel = LISP_TO_VOID (Qnil);
          wv->contents = xmalloc_widget_value ();
          wv->contents->type = TEXT_TYPE;
-         wv->contents->name = (char *) "No menu";
+         wv->contents->name = xstrdup ("No menu");
          wv->contents->next = NULL;
+         wv->contents->accel = LISP_TO_VOID (Qnil);
        }
       assert (wv && wv->type == CASCADE_TYPE && wv->contents);
       replace_widget_value_tree (hack_wv, wv->contents);
       free_popup_widget_value_tree (wv);
     }
+  else if (!POPUP_DATAP (FRAME_MENUBAR_DATA (f)))
+    return;
   else
     {
-      if (!POPUP_DATAP (FRAME_MENUBAR_DATA (f)))
-       return;
+#if 0 /* Unused, see comment below. */
+      int any_changes;
+
       /* #### - this menubar update mechanism is expensively anti-social and
         the activate-menubar-hook is now mostly obsolete. */
-      /* make the activate-menubar-hook be a list of functions, not a single
-        function, just to simplify things. */
-      if (!NILP (Vactivate_menubar_hook) &&
-         (!CONSP (Vactivate_menubar_hook) ||
-          EQ (XCAR (Vactivate_menubar_hook), Qlambda)))
-       Vactivate_menubar_hook = Fcons (Vactivate_menubar_hook, Qnil);
-
-      GCPRO1 (rest);
-      for (rest = Vactivate_menubar_hook; !NILP (rest); rest = Fcdr (rest))
-       if (!EQ (call0 (XCAR (rest)), Qt))
-         any_changes = 1;
-#if 0
+      any_changes = my_run_hook (Qactivate_menubar_hook, 1);
+
       /* #### - It is necessary to *ALWAYS* call set_frame_menubar() now that
         incremental menus are implemented.  If a subtree of a menu has been
         updated incrementally (a destructive operation), then that subtree
@@ -446,36 +497,35 @@ pre_activate_callback (Widget widget, LWLIB_ID id, XtPointer client_data)
         that an INCREMENTAL_TYPE widget_value can be recreated...  Hmmmmm. */
       if (any_changes ||
          !XFRAME_MENUBAR_DATA (f)->menubar_contents_up_to_date)
-#endif
        set_frame_menubar (f, 1, 0);
+#else
+      run_hook (Qactivate_menubar_hook);
+      set_frame_menubar (f, 1, 0);
+#endif
       DEVICE_X_MOUSE_TIMESTAMP (XDEVICE (FRAME_DEVICE (f))) =
        DEVICE_X_GLOBAL_MOUSE_TIMESTAMP (XDEVICE (FRAME_DEVICE (f))) =
        x_focus_timestamp_really_sucks_fix_me_better;
-      UNGCPRO;
     }
 }
 
 static widget_value *
 compute_menubar_data (struct frame *f, Lisp_Object menubar, int deep_p)
 {
-  widget_value *data;
-
   if (NILP (menubar))
-    data = 0;
+    return 0;
   else
     {
-      Lisp_Object old_buffer;
+      widget_value *data;
       int count = specpdl_depth ();
 
-      old_buffer = Fcurrent_buffer ();
-      record_unwind_protect (Fset_buffer, old_buffer);
-      Fset_buffer ( XWINDOW (FRAME_SELECTED_WINDOW (f))->buffer);
+      record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
+      Fset_buffer (XWINDOW (FRAME_SELECTED_WINDOW (f))->buffer);
       data = menu_item_descriptor_to_widget_value (menubar, MENUBAR_TYPE,
                                                   deep_p, 0);
-      Fset_buffer (old_buffer);
       unbind_to (count, Qnil);
+
+      return data;
     }
-  return data;
 }
 
 static int
@@ -485,7 +535,7 @@ set_frame_menubar (struct frame *f, int deep_p, int first_time_p)
   Lisp_Object menubar;
   int menubar_visible;
   long id;
-  /* As for the toolbar, the minibuffer does not have its own menubar. */
+  /* As with the toolbar, the minibuffer does not have its own menubar. */
   struct window *w = XWINDOW (FRAME_LAST_NONMINIBUF_WINDOW (f));
 
   if (! FRAME_X_P (f))
@@ -521,7 +571,7 @@ set_frame_menubar (struct frame *f, int deep_p, int first_time_p)
   if (NILP (FRAME_MENUBAR_DATA (f)))
     {
       struct popup_data *mdata =
-       alloc_lcrecord_type (struct popup_data, lrecord_popup_data);
+       alloc_lcrecord_type (struct popup_data, &lrecord_popup_data);
 
       mdata->id = new_lwlib_id ();
       mdata->last_menubar_buffer = Qnil;
@@ -567,7 +617,7 @@ set_frame_menubar (struct frame *f, int deep_p, int first_time_p)
 }
 
 
-/* Called from x_create_widgets() to create the inital menubar of a frame
+/* Called from x_create_widgets() to create the initial menubar of a frame
    before it is mapped, so that the window is mapped with the menubar already
    there instead of us tacking it on later and thrashing the window after it
    is visible. */
@@ -621,7 +671,6 @@ make_dummy_xbutton_event (XEvent *dummy,
   if (eev)
     {
       Position shellx, shelly, framex, framey;
-      Widget shell = XtParent (daddy);
       Arg al [2];
       btn->time = eev->timestamp;
       btn->button = eev->event.button.button;
@@ -629,14 +678,21 @@ make_dummy_xbutton_event (XEvent *dummy,
       btn->subwindow = (Window) NULL;
       btn->x = eev->event.button.x;
       btn->y = eev->event.button.y;
-      XtSetArg (al [0], XtNx, &shellx);
-      XtSetArg (al [1], XtNy, &shelly);
-      XtGetValues (shell, al, 2);
+      shellx = shelly = 0;
+#ifndef HAVE_WMCOMMAND
+      {
+       Widget shell = XtParent (daddy);
+
+       XtSetArg (al [0], XtNx, &shellx);
+       XtSetArg (al [1], XtNy, &shelly);
+       XtGetValues (shell, al, 2);
+      }
+#endif
       XtSetArg (al [0], XtNx, &framex);
       XtSetArg (al [1], XtNy, &framey);
       XtGetValues (daddy, al, 2);
       btn->x_root = shellx + framex + btn->x;
-      btn->y_root = shelly + framey + btn->y;;
+      btn->y_root = shelly + framey + btn->y;
       btn->state = ButtonPressMask; /* all buttons pressed */
     }
   else
@@ -801,9 +857,15 @@ console_type_create_menubar_x (void)
 }
 
 void
-vars_of_menubar_x (void)
+reinit_vars_of_menubar_x (void)
 {
   last_popup_menu_selection_callback_id = (LWLIB_ID) -1;
+}
+
+void
+vars_of_menubar_x (void)
+{
+  reinit_vars_of_menubar_x ();
 
 #if defined (LWLIB_MENUBARS_LUCID)
   Fprovide (intern ("lucid-menubars"));