]> code.delx.au - gnu-emacs/blobdiff - src/xmenu.c
Update copyright year to 2015
[gnu-emacs] / src / xmenu.c
index 2d41350e737f3f53b5401cc43b08635cbf3da848..c6bb9faee6678bc09fc6784ae8cd4cc7dff1c96c 100644 (file)
@@ -1,6 +1,6 @@
 /* X Communication module for terminals which understand the X protocol.
 
-Copyright (C) 1986, 1988, 1993-1994, 1996, 1999-2014 Free Software
+Copyright (C) 1986, 1988, 1993-1994, 1996, 1999-2015 Free Software
 Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -117,7 +117,7 @@ static int popup_activated_flag;
 \f
 #ifdef USE_X_TOOLKIT
 
-static int next_menubar_widget_id;
+static LWLIB_ID next_menubar_widget_id;
 
 /* Return the frame whose ->output_data.x->id equals ID, or 0 if none.  */
 
@@ -139,53 +139,6 @@ menubar_id_to_frame (LWLIB_ID id)
 }
 
 #endif
-\f
-#ifdef HAVE_X_WINDOWS
-/* Return the mouse position in *X and *Y.  The coordinates are window
-   relative for the edit window in frame F.
-   This is for Fx_popup_menu.  The mouse_position_hook can not
-   be used for X, as it returns window relative coordinates
-   for the window where the mouse is in.  This could be the menu bar,
-   the scroll bar or the edit window.  Fx_popup_menu needs to be
-   sure it is the edit window.  */
-void
-mouse_position_for_popup (struct frame *f, int *x, int *y)
-{
-  Window root, dummy_window;
-  int dummy;
-
-  eassert (FRAME_X_P (f));
-
-  block_input ();
-
-  XQueryPointer (FRAME_X_DISPLAY (f),
-                 DefaultRootWindow (FRAME_X_DISPLAY (f)),
-
-                 /* The root window which contains the pointer.  */
-                 &root,
-
-                 /* Window pointer is on, not used  */
-                 &dummy_window,
-
-                 /* The position on that root window.  */
-                 x, y,
-
-                 /* x/y in dummy_window coordinates, not used.  */
-                 &dummy, &dummy,
-
-                 /* Modifier keys and pointer buttons, about which
-                    we don't care.  */
-                 (unsigned int *) &dummy);
-
-  unblock_input ();
-
-  /* x_menu_show expects window coordinates, not root window
-     coordinates.  Translate.  */
-  *x -= f->left_pos + FRAME_OUTER_TO_INNER_DIFF_X (f);
-  *y -= f->top_pos + FRAME_OUTER_TO_INNER_DIFF_Y (f);
-}
-
-#endif /* HAVE_X_WINDOWS */
 
 #ifndef MSDOS
 
@@ -674,7 +627,6 @@ update_frame_menubar (struct frame *f)
   xg_update_frame_menubar (f);
 #else
   struct x_output *x;
-  int columns, rows;
 
   eassert (FRAME_X_P (f));
 
@@ -684,10 +636,6 @@ update_frame_menubar (struct frame *f)
     return;
 
   block_input ();
-  /* Save the size of the frame because the pane widget doesn't accept
-     to resize itself. So force it.  */
-  columns = FRAME_COLS (f);
-  rows = FRAME_LINES (f);
 
   /* Do the voodoo which means "I'm changing lots of things, don't try
      to refigure sizes until I'm done."  */
@@ -708,10 +656,16 @@ update_frame_menubar (struct frame *f)
   XtManageChild (x->edit_widget);
   lw_refigure_widget (x->column_widget, True);
 
-  /* Force the pane widget to resize itself with the right values.  */
-  EmacsFrameSetCharSize (x->edit_widget, columns, rows);
+  /* Force the pane widget to resize itself.  */
+#ifdef USE_LUCID
+  /* For reasons I don't know Lucid wants to add one pixel to the frame
+     height when adding the menu bar.  Compensate that here.  */
+  adjust_frame_size (f, -1, FRAME_TEXT_HEIGHT (f) - 1, 2, 0, Qmenu_bar_lines);
+#else
+  adjust_frame_size (f, -1, -1, 2, 0, Qmenu_bar_lines);
+#endif /* USE_LUCID */
   unblock_input ();
-#endif
+#endif /* USE_GTK */
 }
 
 #ifdef USE_LUCID
@@ -752,7 +706,7 @@ apply_systemfont_to_menu (struct frame *f, Widget w)
 void
 set_frame_menubar (struct frame *f, bool first_time, bool deep_p)
 {
-  xt_or_gtk_widget menubar_widget;
+  xt_or_gtk_widget menubar_widget, old_widget;
 #ifdef USE_X_TOOLKIT
   LWLIB_ID id;
 #endif
@@ -765,7 +719,7 @@ set_frame_menubar (struct frame *f, bool first_time, bool deep_p)
 
   eassert (FRAME_X_P (f));
 
-  menubar_widget = f->output_data.x->menubar_widget;
+  menubar_widget = old_widget = f->output_data.x->menubar_widget;
 
   XSETFRAME (Vmenu_updating_frame, f);
 
@@ -785,12 +739,6 @@ set_frame_menubar (struct frame *f, bool first_time, bool deep_p)
       f->output_data.x->saved_menu_event->type = 0;
     }
 
-#ifdef USE_GTK
-  /* If we have detached menus, we must update deep so detached menus
-     also gets updated.  */
-  deep_p = deep_p || xg_have_tear_offs (f);
-#endif
-
   if (deep_p)
     {
       /* Make a widget-value tree representing the entire menu trees.  */
@@ -1070,7 +1018,7 @@ set_frame_menubar (struct frame *f, bool first_time, bool deep_p)
 #endif /* USE_LUCID */
 #endif /* 1 */
 
-    f->output_data.x->menubar_height = menubar_size;
+    FRAME_MENUBAR_HEIGHT (f) = menubar_size;
   }
 #endif /* not USE_GTK */
 
@@ -1108,12 +1056,18 @@ void
 free_frame_menubar (struct frame *f)
 {
   Widget menubar_widget;
+#ifdef USE_MOTIF
+  /* Motif automatically shrinks the frame in lw_destroy_all_widgets.
+     If we want to preserve the old height, calculate it now so we can
+     restore it below.  */
+  int old_height = FRAME_TEXT_HEIGHT (f) + FRAME_MENUBAR_HEIGHT (f);
+#endif
 
   eassert (FRAME_X_P (f));
 
   menubar_widget = f->output_data.x->menubar_widget;
 
-  f->output_data.x->menubar_height = 0;
+  FRAME_MENUBAR_HEIGHT (f) = 0;
 
   if (menubar_widget)
     {
@@ -1145,9 +1099,20 @@ free_frame_menubar (struct frame *f)
          XtVaGetValues (f->output_data.x->widget, XtNx, &x1, XtNy, &y1, NULL);
          if (x1 == 0 && y1 == 0)
            XtVaSetValues (f->output_data.x->widget, XtNx, x0, XtNy, y0, NULL);
+         if (frame_inhibit_resize (f, 0, Qmenu_bar_lines))
+           adjust_frame_size (f, -1, old_height, 1, 0, Qmenu_bar_lines);
+         else
+#endif /* USE_MOTIF */
+           adjust_frame_size (f, -1, -1, 2, 0, Qmenu_bar_lines);
+       }
+      else
+       {
+#ifdef USE_MOTIF
+         if (frame_inhibit_resize (f, 0, Qmenu_bar_lines))
+           adjust_frame_size (f, -1, old_height, 1, 0, Qmenu_bar_lines);
 #endif
-         x_set_window_size (f, 0, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), 1);
        }
+
       unblock_input ();
     }
 }
@@ -1320,8 +1285,8 @@ create_and_show_popup_menu (struct frame *f, widget_value *first_wv,
 /* We need a unique id for each widget handled by the Lucid Widget
    library.
 
-   For the main windows, and popup menus, we use this counter,
-   which we increment each time after use.  This starts from 1<<16.
+   For the main windows, and popup menus, we use this counter, which we
+   increment each time after use.  This starts from WIDGET_ID_TICK_START.
 
    For menu bars, we use numbers starting at 0, counted in
    next_menubar_widget_id.  */
@@ -1333,17 +1298,13 @@ popup_selection_callback (Widget widget, LWLIB_ID id, XtPointer client_data)
   menu_item_selection = client_data;
 }
 
-/* ARG is the LWLIB ID of the dialog box, represented
-   as a Lisp object as (HIGHPART . LOWPART).  */
+/* ID is the LWLIB ID of the dialog box.  */
 
 static void
-pop_down_menu (Lisp_Object arg)
+pop_down_menu (int id)
 {
-  LWLIB_ID id = (XINT (XCAR (arg)) << 4 * sizeof (LWLIB_ID)
-                 | XINT (XCDR (arg)));
-
   block_input ();
-  lw_destroy_all_widgets (id);
+  lw_destroy_all_widgets ((LWLIB_ID) id);
   unblock_input ();
   popup_activated_flag = 0;
 }
@@ -1409,11 +1370,9 @@ create_and_show_popup_menu (struct frame *f, widget_value *first_wv,
   x_activate_timeout_atimer ();
 
   {
-    int fact = 4 * sizeof (LWLIB_ID);
     ptrdiff_t specpdl_count = SPECPDL_INDEX ();
-    record_unwind_protect (pop_down_menu,
-                           Fcons (make_number (menu_id >> (fact)),
-                                  make_number (menu_id & ~(-1 << (fact)))));
+
+    record_unwind_protect_int (pop_down_menu, (int) menu_id);
 
     /* Process events that apply to the menu.  */
     popup_get_selection (0, FRAME_DISPLAY_INFO (f), menu_id, 1);
@@ -1779,12 +1738,10 @@ create_and_show_dialog (struct frame *f, widget_value *first_wv)
      Also handle timers.  */
   {
     ptrdiff_t count = SPECPDL_INDEX ();
-    int fact = 4 * sizeof (LWLIB_ID);
 
     /* xdialog_show_unwind is responsible for popping the dialog box down.  */
-    record_unwind_protect (pop_down_menu,
-                           Fcons (make_number (dialog_id >> (fact)),
-                                  make_number (dialog_id & ~(-1 << (fact)))));
+
+    record_unwind_protect_int (pop_down_menu, (int) dialog_id);
 
     popup_get_selection (0, FRAME_DISPLAY_INFO (f), dialog_id, 1);
 
@@ -2069,7 +2026,8 @@ x_menu_show (struct frame *f, int x, int y, int menuflags,
   Window root;
   XMenu *menu;
   int pane, selidx, lpane, status;
-  Lisp_Object entry, pane_prefix;
+  Lisp_Object entry = Qnil;
+  Lisp_Object pane_prefix;
   char *datap;
   int ulx, uly, width, height;
   int dispwidth, dispheight;
@@ -2091,6 +2049,7 @@ x_menu_show (struct frame *f, int x, int y, int menuflags,
       return Qnil;
     }
 
+  USE_SAFE_ALLOCA;
   block_input ();
 
   /* Figure out which root window F is on.  */
@@ -2103,8 +2062,7 @@ x_menu_show (struct frame *f, int x, int y, int menuflags,
   if (menu == NULL)
     {
       *error_name = "Can't create menu";
-      unblock_input ();
-      return Qnil;
+      goto return_entry;
     }
 
   /* Don't GC while we prepare and show the menu,
@@ -2147,8 +2105,7 @@ x_menu_show (struct frame *f, int x, int y, int menuflags,
            {
              XMenuDestroy (FRAME_X_DISPLAY (f), menu);
              *error_name = "Can't create pane";
-             unblock_input ();
-             return Qnil;
+             goto return_entry;
            }
          i += MENU_ITEMS_PANE_LENGTH;
 
@@ -2192,9 +2149,7 @@ x_menu_show (struct frame *f, int x, int y, int menuflags,
 
          if (!NILP (descrip))
            {
-             /* if alloca is fast, use that to make the space,
-                to reduce gc needs.  */
-             item_data = alloca (maxwidth + SBYTES (descrip) + 1);
+             item_data = SAFE_ALLOCA (maxwidth + SBYTES (descrip) + 1);
              memcpy (item_data, SSDATA (item_name), SBYTES (item_name));
              for (j = SCHARS (item_name); j < maxwidth; j++)
                item_data[j] = ' ';
@@ -2212,8 +2167,7 @@ x_menu_show (struct frame *f, int x, int y, int menuflags,
            {
              XMenuDestroy (FRAME_X_DISPLAY (f), menu);
              *error_name = "Can't add selection to menu";
-             unblock_input ();
-             return Qnil;
+             goto return_entry;
            }
          i += MENU_ITEMS_ITEM_LENGTH;
           lines++;
@@ -2287,7 +2241,7 @@ x_menu_show (struct frame *f, int x, int y, int menuflags,
   status = XMenuActivate (FRAME_X_DISPLAY (f), menu, &pane, &selidx,
                           x, y, ButtonReleaseMask, &datap,
                           menu_help_callback);
-  entry = pane_prefix = Qnil;
+  pane_prefix = Qnil;
 
   switch (status)
     {
@@ -2346,10 +2300,10 @@ x_menu_show (struct frame *f, int x, int y, int menuflags,
       break;
     }
 
+ return_entry:
   unblock_input ();
-  unbind_to (specpdl_count, Qnil);
-
-  return entry;
+  SAFE_FREE ();
+  return unbind_to (specpdl_count, entry);
 }
 
 #endif /* not USE_X_TOOLKIT */
@@ -2377,13 +2331,13 @@ DEFUN ("menu-or-popup-active-p", Fmenu_or_popup_active_p, Smenu_or_popup_active_
 void
 syms_of_xmenu (void)
 {
-  DEFSYM (Qdebug_on_next_call, "debug-on-next-call");
-
 #ifdef USE_X_TOOLKIT
-  widget_id_tick = (1<<16);
+  enum { WIDGET_ID_TICK_START = 1 << 16 };
+  widget_id_tick = WIDGET_ID_TICK_START;
   next_menubar_widget_id = 1;
 #endif
 
+  DEFSYM (Qdebug_on_next_call, "debug-on-next-call");
   defsubr (&Smenu_or_popup_active_p);
 
 #if defined (USE_GTK) || defined (USE_X_TOOLKIT)