/[emacs]/emacs/src/xmenu.c
ViewVC logotype

Diff of /emacs/src/xmenu.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.230 by jasonr, Mon Jan 7 00:23:56 2002 UTC revision 1.230.4.1 by miles, Fri Apr 4 06:21:09 2003 UTC
# Line 81  Boston, MA 02111-1307, USA.  */ Line 81  Boston, MA 02111-1307, USA.  */
81  #endif /* USE_LUCID */  #endif /* USE_LUCID */
82  #include "../lwlib/lwlib.h"  #include "../lwlib/lwlib.h"
83  #else /* not USE_X_TOOLKIT */  #else /* not USE_X_TOOLKIT */
84    #ifndef USE_GTK
85  #include "../oldXMenu/XMenu.h"  #include "../oldXMenu/XMenu.h"
86    #endif
87  #endif /* not USE_X_TOOLKIT */  #endif /* not USE_X_TOOLKIT */
88  #endif /* HAVE_X_WINDOWS */  #endif /* HAVE_X_WINDOWS */
89    
# Line 108  extern Lisp_Object Qmenu_bar_update_hook Line 110  extern Lisp_Object Qmenu_bar_update_hook
110    
111  #ifdef USE_X_TOOLKIT  #ifdef USE_X_TOOLKIT
112  extern void set_frame_menubar ();  extern void set_frame_menubar ();
 extern void process_expose_from_menu ();  
113  extern XtAppContext Xt_app_con;  extern XtAppContext Xt_app_con;
114    
115  static Lisp_Object xdialog_show ();  static Lisp_Object xdialog_show ();
116  void popup_get_selection ();  static void popup_get_selection ();
117    
118  /* Define HAVE_BOXES if menus can handle radio and toggle buttons.  */  /* Define HAVE_BOXES if menus can handle radio and toggle buttons.  */
119    
120  #define HAVE_BOXES 1  #define HAVE_BOXES 1
121    #endif /* USE_X_TOOLKIT */
122    
123    #ifdef USE_GTK
124    #include "gtkutil.h"
125    #define HAVE_BOXES 1
126    extern void set_frame_menubar ();
127    static Lisp_Object xdialog_show ();
128  #endif  #endif
129    
130  static void push_menu_item P_ ((Lisp_Object, Lisp_Object, Lisp_Object,  static void push_menu_item P_ ((Lisp_Object, Lisp_Object, Lisp_Object,
# Line 132  static void single_menu_item P_ ((Lisp_O Line 140  static void single_menu_item P_ ((Lisp_O
140                                    int, int, int *));                                    int, int, int *));
141  static void list_of_panes P_ ((Lisp_Object));  static void list_of_panes P_ ((Lisp_Object));
142  static void list_of_items P_ ((Lisp_Object));  static void list_of_items P_ ((Lisp_Object));
143    
144    extern EMACS_TIME timer_check P_ ((int));
145    
146  /* This holds a Lisp vector that holds the results of decoding  /* This holds a Lisp vector that holds the results of decoding
147     the keymaps or alist-of-alists that specify a menu.     the keymaps or alist-of-alists that specify a menu.
# Line 174  enum menu_item_idx Line 184  enum menu_item_idx
184    
185  static Lisp_Object menu_items;  static Lisp_Object menu_items;
186    
187    /* If non-nil, means that the global vars defined here are already in use.
188       Used to detect cases where we try to re-enter this non-reentrant code.  */
189    static Lisp_Object menu_items_inuse;
190    
191  /* Number of slots currently allocated in menu_items.  */  /* Number of slots currently allocated in menu_items.  */
192  static int menu_items_allocated;  static int menu_items_allocated;
193    
# Line 189  static int menu_items_submenu_depth; Line 203  static int menu_items_submenu_depth;
203    
204  /* Flag which when set indicates a dialog or menu has been posted by  /* Flag which when set indicates a dialog or menu has been posted by
205     Xt on behalf of one of the widget sets.  */     Xt on behalf of one of the widget sets.  */
206  int popup_activated_flag;  static int popup_activated_flag;
207    
208  static int next_menubar_widget_id;  static int next_menubar_widget_id;
209    
# Line 241  init_menu_items () Line 255  init_menu_items ()
255        menu_items = Fmake_vector (make_number (menu_items_allocated), Qnil);        menu_items = Fmake_vector (make_number (menu_items_allocated), Qnil);
256      }      }
257    
258      if (!NILP (menu_items_inuse))
259        error ("Trying to use a menu from within a menu-entry");
260      menu_items_inuse = Qt;
261    menu_items_used = 0;    menu_items_used = 0;
262    menu_items_n_panes = 0;    menu_items_n_panes = 0;
263    menu_items_submenu_depth = 0;    menu_items_submenu_depth = 0;
# Line 253  finish_menu_items () Line 270  finish_menu_items ()
270  {  {
271  }  }
272    
273    static Lisp_Object
274    unuse_menu_items (dummy)
275         int dummy;
276    {
277      return menu_items_inuse = Qnil;
278    }
279    
280  /* Call when finished using the data for the current menu  /* Call when finished using the data for the current menu
281     in menu_items.  */     in menu_items.  */
282    
# Line 266  discard_menu_items () Line 290  discard_menu_items ()
290        menu_items = Qnil;        menu_items = Qnil;
291        menu_items_allocated = 0;        menu_items_allocated = 0;
292      }      }
293      xassert (NILP (menu_items_inuse));
294  }  }
295    
296  /* Make the menu_items vector twice as large.  */  /* Make the menu_items vector twice as large.  */
# Line 462  single_keymap_panes (keymap, pane_name, Line 487  single_keymap_panes (keymap, pane_name,
487    
488  /* This is a subroutine of single_keymap_panes that handles one  /* This is a subroutine of single_keymap_panes that handles one
489     keymap entry.     keymap entry.
490     KEY is a key in a keymap and ITEM is its binding.     KEY is a key in a keymap and ITEM is its binding.
491     PENDING_MAPS_PTR points to a list of keymaps waiting to be made into     PENDING_MAPS_PTR points to a list of keymaps waiting to be made into
492     separate panes.     separate panes.
493     If NOTREAL is nonzero, only check for equivalent key bindings, don't     If NOTREAL is nonzero, only check for equivalent key bindings, don't
# Line 483  single_menu_item (key, item, pending_map Line 508  single_menu_item (key, item, pending_map
508    Lisp_Object map, item_string, enabled;    Lisp_Object map, item_string, enabled;
509    struct gcpro gcpro1, gcpro2;    struct gcpro gcpro1, gcpro2;
510    int res;    int res;
511      
512    /* Parse the menu item and leave the result in item_properties.  */    /* Parse the menu item and leave the result in item_properties.  */
513    GCPRO2 (key, item);    GCPRO2 (key, item);
514    res = parse_menu_item (item, notreal, 0);    res = parse_menu_item (item, notreal, 0);
# Line 492  single_menu_item (key, item, pending_map Line 517  single_menu_item (key, item, pending_map
517      return;                     /* Not a menu item.  */      return;                     /* Not a menu item.  */
518    
519    map = XVECTOR (item_properties)->contents[ITEM_PROPERTY_MAP];    map = XVECTOR (item_properties)->contents[ITEM_PROPERTY_MAP];
520      
521    if (notreal)    if (notreal)
522      {      {
523        /* We don't want to make a menu, just traverse the keymaps to        /* We don't want to make a menu, just traverse the keymaps to
# Line 503  single_menu_item (key, item, pending_map Line 528  single_menu_item (key, item, pending_map
528      }      }
529    
530    enabled = XVECTOR (item_properties)->contents[ITEM_PROPERTY_ENABLE];    enabled = XVECTOR (item_properties)->contents[ITEM_PROPERTY_ENABLE];
531    item_string = XVECTOR (item_properties)->contents[ITEM_PROPERTY_NAME];    item_string = XVECTOR (item_properties)->contents[ITEM_PROPERTY_NAME];
532    
533    if (!NILP (map) && XSTRING (item_string)->data[0] == '@')    if (!NILP (map) && SREF (item_string, 0) == '@')
534      {      {
535        if (!NILP (enabled))        if (!NILP (enabled))
536          /* An enabled separate pane. Remember this to handle it later.  */          /* An enabled separate pane. Remember this to handle it later.  */
# Line 551  single_menu_item (key, item, pending_map Line 576  single_menu_item (key, item, pending_map
576                    index++;              /* Skip a left, right divider. */                    index++;              /* Skip a left, right divider. */
577                  else                  else
578                    {                    {
579                      if (!submenu && XSTRING (tem)->data[0] != '\0'                      if (!submenu && SREF (tem, 0) != '\0'
580                          && XSTRING (tem)->data[0] != '-')                          && SREF (tem, 0) != '-')
581                        XVECTOR (menu_items)->contents[index + MENU_ITEMS_ITEM_NAME]                        XVECTOR (menu_items)->contents[index + MENU_ITEMS_ITEM_NAME]
582                          = concat2 (build_string ("    "), tem);                          = concat2 (build_string ("    "), tem);
583                      index += MENU_ITEMS_ITEM_LENGTH;                      index += MENU_ITEMS_ITEM_LENGTH;
# Line 568  single_menu_item (key, item, pending_map Line 593  single_menu_item (key, item, pending_map
593            prefix = build_string (NILP (selected) ? "( ) " : "(*) ");            prefix = build_string (NILP (selected) ? "( ) " : "(*) ");
594        }        }
595      /* Not a button. If we have earlier buttons, then we need a prefix.  */      /* Not a button. If we have earlier buttons, then we need a prefix.  */
596      else if (!*notbuttons_ptr && XSTRING (item_string)->data[0] != '\0'      else if (!*notbuttons_ptr && SREF (item_string, 0) != '\0'
597               && XSTRING (item_string)->data[0] != '-')               && SREF (item_string, 0) != '-')
598        prefix = build_string ("    ");        prefix = build_string ("    ");
599    
600      if (!NILP (prefix))      if (!NILP (prefix))
601        item_string = concat2 (prefix, item_string);        item_string = concat2 (prefix, item_string);
602    }    }
603  #endif /* not HAVE_BOXES */  #endif /* not HAVE_BOXES */
604    
605  #ifndef USE_X_TOOLKIT  #if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
606    if (!NILP(map))    if (!NILP(map))
607      /* Indicate visually that this is a submenu.  */      /* Indicate visually that this is a submenu.  */
608      item_string = concat2 (item_string, build_string (" >"));      item_string = concat2 (item_string, build_string (" >"));
# Line 590  single_menu_item (key, item, pending_map Line 615  single_menu_item (key, item, pending_map
615                    XVECTOR (item_properties)->contents[ITEM_PROPERTY_SELECTED],                    XVECTOR (item_properties)->contents[ITEM_PROPERTY_SELECTED],
616                    XVECTOR (item_properties)->contents[ITEM_PROPERTY_HELP]);                    XVECTOR (item_properties)->contents[ITEM_PROPERTY_HELP]);
617    
618  #ifdef USE_X_TOOLKIT  #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
619    /* Display a submenu using the toolkit.  */    /* Display a submenu using the toolkit.  */
620    if (! (NILP (map) || NILP (enabled)))    if (! (NILP (map) || NILP (enabled)))
621      {      {
# Line 653  list_of_items (pane) Line 678  list_of_items (pane)
678      }      }
679  }  }
680    
681    #ifdef HAVE_X_WINDOWS
682    /* Return the mouse position in *X and *Y.  The coordinates are window
683       relative for the edit window in frame F.
684       This is for Fx_popup_menu.  The mouse_position_hook can not
685       be used for X, as it returns window relative coordinates
686       for the window where the mouse is in.  This could be the menu bar,
687       the scroll bar or the edit window.  Fx_popup_menu needs to be
688       sure it is the edit window.  */
689    static void
690    mouse_position_for_popup(f, x, y)
691         FRAME_PTR f;
692         int *x;
693         int *y;
694    {
695      Window root, dummy_window;
696      int dummy;
697    
698      BLOCK_INPUT;
699    
700      XQueryPointer (FRAME_X_DISPLAY (f),
701                     DefaultRootWindow (FRAME_X_DISPLAY (f)),
702    
703                     /* The root window which contains the pointer.  */
704                     &root,
705    
706                     /* Window pointer is on, not used  */
707                     &dummy_window,
708    
709                     /* The position on that root window.  */
710                     x, y,
711    
712                     /* x/y in dummy_window coordinates, not used.  */
713                     &dummy, &dummy,
714    
715                     /* Modifier keys and pointer buttons, about which
716                        we don't care.  */
717                     (unsigned int *) &dummy);
718    
719      UNBLOCK_INPUT;
720    
721      /* xmenu_show expects window coordinates, not root window
722         coordinates.  Translate.  */
723      *x -= f->output_data.x->left_pos
724        + FRAME_OUTER_TO_INNER_DIFF_X (f);
725      *y -= f->output_data.x->top_pos
726        + FRAME_OUTER_TO_INNER_DIFF_Y (f);
727    }
728    
729    #endif /* HAVE_X_WINDOWS */
730    
731  DEFUN ("x-popup-menu", Fx_popup_menu, Sx_popup_menu, 2, 2, 0,  DEFUN ("x-popup-menu", Fx_popup_menu, Sx_popup_menu, 2, 2, 0,
732         doc: /* Pop up a deck-of-cards menu and return user's selection.         doc: /* Pop up a deck-of-cards menu and return user's selection.
733  POSITION is a position specification.  This is either a mouse button event  POSITION is a position specification.  This is either a mouse button event
# Line 699  cached information about equivalent key Line 774  cached information about equivalent key
774    Lisp_Object x, y, window;    Lisp_Object x, y, window;
775    int keymaps = 0;    int keymaps = 0;
776    int for_click = 0;    int for_click = 0;
777      int specpdl_count = SPECPDL_INDEX ();
778    struct gcpro gcpro1;    struct gcpro gcpro1;
779    
780  #ifdef HAVE_MENUS  #ifdef HAVE_MENUS
781    if (! NILP (position))    if (! NILP (position))
782      {      {
783          int get_current_pos_p = 0;
784        check_x ();        check_x ();
785    
786        /* Decode the first argument: find the window and the coordinates.  */        /* Decode the first argument: find the window and the coordinates.  */
# Line 711  cached information about equivalent key Line 788  cached information about equivalent key
788            || (CONSP (position) && (EQ (XCAR (position), Qmenu_bar)            || (CONSP (position) && (EQ (XCAR (position), Qmenu_bar)
789                                     || EQ (XCAR (position), Qtool_bar))))                                     || EQ (XCAR (position), Qtool_bar))))
790          {          {
791            /* Use the mouse's current position.  */            get_current_pos_p = 1;
792            FRAME_PTR new_f = SELECTED_FRAME ();          }
           Lisp_Object bar_window;  
           enum scroll_bar_part part;  
           unsigned long time;  
   
           if (mouse_position_hook)  
             (*mouse_position_hook) (&new_f, 1, &bar_window,  
                                     &part, &x, &y, &time);  
           if (new_f != 0)  
             XSETFRAME (window, new_f);  
           else  
             {  
               window = selected_window;  
               XSETFASTINT (x, 0);  
               XSETFASTINT (y, 0);  
             }  
         }  
793        else        else
794          {          {
795            tem = Fcar (position);            tem = Fcar (position);
# Line 747  cached information about equivalent key Line 808  cached information about equivalent key
808                x = Fcar (tem);                x = Fcar (tem);
809                y = Fcdr (tem);                y = Fcdr (tem);
810              }              }
811    
812              /* If a click happens in an external tool bar or a detached
813                 tool bar, x and y is NIL.  In that case, use the current
814                 mouse position.  This happens for the help button in the
815                 tool bar.  Ideally popup-menu should pass NIL to
816                 this function, but it doesn't.  */
817              if (NILP (x) && NILP (y))
818                get_current_pos_p = 1;
819            }
820    
821          if (get_current_pos_p)
822            {
823              /* Use the mouse's current position.  */
824              FRAME_PTR new_f = SELECTED_FRAME ();
825    #ifdef HAVE_X_WINDOWS
826              /* Can't use mouse_position_hook for X since it returns
827                 coordinates relative to the window the mouse is in,
828                 we need coordinates relative to the edit widget always.  */
829              if (new_f != 0)
830                {
831                  int cur_x, cur_y;
832    
833                  mouse_position_for_popup (new_f, &cur_x, &cur_y);
834                  /* cur_x/y may be negative, so use make_number.  */
835                  x = make_number (cur_x);
836                  y = make_number (cur_y);
837                }
838    
839    #else /* not HAVE_X_WINDOWS */
840              Lisp_Object bar_window;
841              enum scroll_bar_part part;
842              unsigned long time;
843    
844              if (mouse_position_hook)
845                (*mouse_position_hook) (&new_f, 1, &bar_window,
846                                        &part, &x, &y, &time);
847    #endif /* not HAVE_X_WINDOWS */
848    
849              if (new_f != 0)
850                XSETFRAME (window, new_f);
851              else
852                {
853                  window = selected_window;
854                  XSETFASTINT (x, 0);
855                  XSETFASTINT (y, 0);
856                }
857          }          }
858    
859        CHECK_NUMBER (x);        CHECK_NUMBER (x);
# Line 777  cached information about equivalent key Line 884  cached information about equivalent key
884    
885        xpos += XINT (x);        xpos += XINT (x);
886        ypos += XINT (y);        ypos += XINT (y);
   
       XSETFRAME (Vmenu_updating_frame, f);  
887      }      }
888    Vmenu_updating_frame = Qnil;    Vmenu_updating_frame = Qnil;
889  #endif /* HAVE_MENUS */  #endif /* HAVE_MENUS */
890    
891      record_unwind_protect (unuse_menu_items, Qnil);
892    title = Qnil;    title = Qnil;
893    GCPRO1 (title);    GCPRO1 (title);
894    
# Line 851  cached information about equivalent key Line 957  cached information about equivalent key
957    
958        keymaps = 0;        keymaps = 0;
959      }      }
960      
961      unbind_to (specpdl_count, Qnil);
962    
963    if (NILP (position))    if (NILP (position))
964      {      {
965        discard_menu_items ();        discard_menu_items ();
# Line 955  on the left of the dialog box and all fo Line 1063  on the left of the dialog box and all fo
1063         but I don't want to make one now.  */         but I don't want to make one now.  */
1064      CHECK_WINDOW (window);      CHECK_WINDOW (window);
1065    
1066  #ifndef USE_X_TOOLKIT  #if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
1067    /* Display a menu with these alternatives    /* Display a menu with these alternatives
1068       in the middle of frame F.  */       in the middle of frame F.  */
1069    {    {
# Line 973  on the left of the dialog box and all fo Line 1081  on the left of the dialog box and all fo
1081      Lisp_Object title;      Lisp_Object title;
1082      char *error_name;      char *error_name;
1083      Lisp_Object selection;      Lisp_Object selection;
1084        int specpdl_count = SPECPDL_INDEX ();
1085    
1086      /* Decode the dialog items from what was specified.  */      /* Decode the dialog items from what was specified.  */
1087      title = Fcar (contents);      title = Fcar (contents);
1088      CHECK_STRING (title);      CHECK_STRING (title);
1089        record_unwind_protect (unuse_menu_items, Qnil);
1090    
1091      list_of_panes (Fcons (contents, Qnil));      list_of_panes (Fcons (contents, Qnil));
1092    
# Line 985  on the left of the dialog box and all fo Line 1095  on the left of the dialog box and all fo
1095      selection = xdialog_show (f, 0, title, &error_name);      selection = xdialog_show (f, 0, title, &error_name);
1096      UNBLOCK_INPUT;      UNBLOCK_INPUT;
1097    
1098        unbind_to (specpdl_count, Qnil);
1099      discard_menu_items ();      discard_menu_items ();
1100    
1101      if (error_name) error (error_name);      if (error_name) error (error_name);
# Line 993  on the left of the dialog box and all fo Line 1104  on the left of the dialog box and all fo
1104  #endif  #endif
1105  }  }
1106    
1107  #ifdef USE_X_TOOLKIT  #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
1108    
1109  /* Loop in Xt until the menu pulldown or dialog popup has been  /* Loop in Xt until the menu pulldown or dialog popup has been
1110     popped down (deactivated).  This is used for x-popup-menu     popped down (deactivated).  This is used for x-popup-menu
1111     and x-popup-dialog; it is not used for the menu bar any more.     and x-popup-dialog; it is not used for the menu bar.
1112    
1113       If DO_TIMERS is nonzero, run timers.
1114    
1115     NOTE: All calls to popup_get_selection should be protected     NOTE: All calls to popup_get_selection should be protected
1116     with BLOCK_INPUT, UNBLOCK_INPUT wrappers.  */     with BLOCK_INPUT, UNBLOCK_INPUT wrappers.  */
1117    
1118  void  #ifdef USE_X_TOOLKIT
1119  popup_get_selection (initial_event, dpyinfo, id)  static void
1120    popup_get_selection (initial_event, dpyinfo, id, do_timers)
1121       XEvent *initial_event;       XEvent *initial_event;
1122       struct x_display_info *dpyinfo;       struct x_display_info *dpyinfo;
1123       LWLIB_ID id;       LWLIB_ID id;
1124         int do_timers;
1125  {  {
1126    XEvent event;    XEvent event;
1127    
1128    /* Define a queue to save up for later unreading    while (popup_activated_flag)
1129       all X events that don't pertain to the menu.  */      {
1130    struct event_queue        /* If we have no events to run, consider timers.  */
1131      {        if (do_timers && !XtAppPending (Xt_app_con))
1132        XEvent event;          timer_check (1);
       struct event_queue *next;  
     };  
     
   struct event_queue *queue = NULL;  
   struct event_queue *queue_tmp;  
1133    
1134    if (initial_event)        if (initial_event)
1135      event = *initial_event;          {
1136    else            event = *initial_event;
1137      XtAppNextEvent (Xt_app_con, &event);            initial_event = 0;
1138            }
1139          else
1140            XtAppNextEvent (Xt_app_con, &event);
1141    
   while (1)  
     {  
       /* Handle expose events for editor frames right away.  */  
       if (event.type == Expose)  
         process_expose_from_menu (event);  
1142        /* Make sure we don't consider buttons grabbed after menu goes.        /* Make sure we don't consider buttons grabbed after menu goes.
1143           And make sure to deactivate for any ButtonRelease,           And make sure to deactivate for any ButtonRelease,
1144           even if XtDispatchEvent doesn't do that.  */           even if XtDispatchEvent doesn't do that.  */
1145        else if (event.type == ButtonRelease        if (event.type == ButtonRelease
1146                 && dpyinfo->display == event.xbutton.display)            && dpyinfo->display == event.xbutton.display)
1147          {          {
1148            dpyinfo->grabbed &= ~(1 << event.xbutton.button);            dpyinfo->grabbed &= ~(1 << event.xbutton.button);
1149            popup_activated_flag = 0;  #ifdef USE_MOTIF /* Pretending that the event came from a
1150  #ifdef USE_MOTIF /* Pretending that the event came from a                      Btn1Down seems the only way to convince Motif to
1151                      Btn1Down seems the only way to convince Motif to                      activate its callbacks; setting the XmNmenuPost
1152                      activate its callbacks; setting the XmNmenuPost                      isn't working. --marcus@sysc.pdx.edu.  */
1153                      isn't working. --marcus@sysc.pdx.edu.  */            event.xbutton.button = 1;
1154            event.xbutton.button = 1;            /*  Motif only pops down menus when no Ctrl, Alt or Mod
1155                  key is pressed and the button is released.  So reset key state
1156                  so Motif thinks this is the case.  */
1157              event.xbutton.state = 0;
1158  #endif  #endif
1159          }          }
1160        /* If the user presses a key, deactivate the menu.        /* If the user presses a key, deactivate the menu.
1161           The user is likely to do that if we get wedged.  */           The user is likely to do that if we get wedged.
1162             This is mostly for Lucid, Motif pops down the menu on ESC.  */
1163        else if (event.type == KeyPress        else if (event.type == KeyPress
                && dpyinfo->display == event.xbutton.display)  
         {  
           KeySym keysym = XLookupKeysym (&event.xkey, 0);  
           if (!IsModifierKey (keysym))  
             {  
               popup_activated_flag = 0;  
               break;  
             }  
         }  
       /* Button presses outside the menu also pop it down.  */  
       else if (event.type == ButtonPress  
                && event.xany.display == dpyinfo->display  
                && x_any_window_to_frame (dpyinfo, event.xany.window))  
         {  
           popup_activated_flag = 0;  
           break;  
         }  
   
       /* Queue all events not for this popup,  
          except for Expose, which we've already handled, and ButtonRelease.  
          Note that the X window is associated with the frame if this  
          is a menu bar popup, but not if it's a dialog box.  So we use  
          x_non_menubar_window_to_frame, not x_any_window_to_frame.  */  
       if (event.type != Expose  
           && !(event.type == ButtonRelease  
1164                 && dpyinfo->display == event.xbutton.display)                 && dpyinfo->display == event.xbutton.display)
1165            && (event.xany.display != dpyinfo->display          {
1166                || x_non_menubar_window_to_frame (dpyinfo, event.xany.window)))            KeySym keysym = XLookupKeysym (&event.xkey, 0);
1167          {            if (!IsModifierKey (keysym))
1168            queue_tmp = (struct event_queue *) xmalloc (sizeof *queue_tmp);              popup_activated_flag = 0;
1169            queue_tmp->event = event;          }
1170            queue_tmp->next = queue;  
1171            queue = queue_tmp;        x_dispatch_event (&event, event.xany.display);
1172          }      }
1173        else  }
1174          XtDispatchEvent (&event);  
1175    #endif /* USE_X_TOOLKIT */
1176    
1177    #ifdef USE_GTK
1178    /* Loop util popup_activated_flag is set to zero in a callback.
1179       Used for popup menus and dialogs. */
1180    static void
1181    popup_widget_loop ()
1182    {
1183      ++popup_activated_flag;
1184    
1185        if (!popup_activated ())    /* Process events in the Gtk event loop until done.  */
1186          break;    while (popup_activated_flag)
1187        XtAppNextEvent (Xt_app_con, &event);      {
1188      }        gtk_main_iteration ();
   
   /* Unread any events that we got but did not handle.  */  
   while (queue != NULL)  
     {  
       queue_tmp = queue;  
       XPutBackEvent (queue_tmp->event.xany.display, &queue_tmp->event);  
       queue = queue_tmp->next;  
       xfree ((char *)queue_tmp);  
       /* Cause these events to get read as soon as we UNBLOCK_INPUT.  */  
       interrupt_input_pending = 1;  
1189      }      }
1190  }  }
1191    #endif
1192    
1193  /* Activate the menu bar of frame F.  /* Activate the menu bar of frame F.
1194     This is called from keyboard.c when it gets the     This is called from keyboard.c when it gets the
1195     menu_bar_activate_event out of the Emacs event queue.     MENU_BAR_ACTIVATE_EVENT out of the Emacs event queue.
1196    
1197     To activate the menu bar, we use the X button-press event     To activate the menu bar, we use the X button-press event
1198     that was saved in saved_menu_event.     that was saved in saved_menu_event.
# Line 1116  popup_get_selection (initial_event, dpyi Line 1203  popup_get_selection (initial_event, dpyi
1203     The reason for saving the button event until here, instead of     The reason for saving the button event until here, instead of
1204     passing it to the toolkit right away, is that we can safely     passing it to the toolkit right away, is that we can safely
1205     execute Lisp code.  */     execute Lisp code.  */
1206      
1207  void  void
1208  x_activate_menubar (f)  x_activate_menubar (f)
1209       FRAME_PTR f;       FRAME_PTR f;
# Line 1124  x_activate_menubar (f) Line 1211  x_activate_menubar (f)
1211    if (!f->output_data.x->saved_menu_event->type)    if (!f->output_data.x->saved_menu_event->type)
1212      return;      return;
1213    
1214    #ifdef USE_GTK
1215      if (! xg_win_to_widget (f->output_data.x->saved_menu_event->xany.window))
1216        return;
1217    #endif
1218    
1219    set_frame_menubar (f, 0, 1);    set_frame_menubar (f, 0, 1);
1220    BLOCK_INPUT;    BLOCK_INPUT;
1221    XtDispatchEvent ((XEvent *) f->output_data.x->saved_menu_event);  #ifdef USE_GTK
1222      XPutBackEvent (f->output_data.x->display_info->display,
1223                     f->output_data.x->saved_menu_event);
1224      popup_activated_flag = 1;
1225    #else
1226      XtDispatchEvent (f->output_data.x->saved_menu_event);
1227    #endif
1228    UNBLOCK_INPUT;    UNBLOCK_INPUT;
1229  #ifdef USE_MOTIF  #ifdef USE_MOTIF
1230    if (f->output_data.x->saved_menu_event->type == ButtonRelease)    if (f->output_data.x->saved_menu_event->type == ButtonRelease)
1231      pending_menu_activation = 1;      pending_menu_activation = 1;
1232  #endif  #endif
1233      
1234    /* Ignore this if we get it a second time.  */    /* Ignore this if we get it a second time.  */
1235    f->output_data.x->saved_menu_event->type = 0;    f->output_data.x->saved_menu_event->type = 0;
1236  }  }
# Line 1148  popup_activated () Line 1246  popup_activated ()
1246  /* This callback is invoked when the user selects a menubar cascade  /* This callback is invoked when the user selects a menubar cascade
1247     pushbutton, but before the pulldown menu is posted.  */     pushbutton, but before the pulldown menu is posted.  */
1248    
1249    #ifndef USE_GTK
1250  static void  static void
1251  popup_activate_callback (widget, id, client_data)  popup_activate_callback (widget, id, client_data)
1252       Widget widget;       Widget widget;
# Line 1156  popup_activate_callback (widget, id, cli Line 1255  popup_activate_callback (widget, id, cli
1255  {  {
1256    popup_activated_flag = 1;    popup_activated_flag = 1;
1257  }  }
1258    #endif
1259    
1260  /* This callback is invoked when a dialog or menu is finished being  /* This callback is invoked when a dialog or menu is finished being
1261     used and has been unposted.  */     used and has been unposted.  */
1262    
1263    #ifdef USE_GTK
1264    static void
1265    popup_deactivate_callback (widget, client_data)
1266         GtkWidget *widget;
1267         gpointer client_data;
1268    {
1269      popup_activated_flag = 0;
1270    }
1271    #else
1272  static void  static void
1273  popup_deactivate_callback (widget, id, client_data)  popup_deactivate_callback (widget, id, client_data)
1274       Widget widget;       Widget widget;
# Line 1168  popup_deactivate_callback (widget, id, c Line 1277  popup_deactivate_callback (widget, id, c
1277  {  {
1278    popup_activated_flag = 0;    popup_activated_flag = 0;
1279  }  }
1280    #endif
1281    
 /* Lwlib callback called when menu items are highlighted/unhighlighted  
    while moving the mouse over them.  WIDGET is the menu bar or menu  
    popup widget.  ID is its LWLIB_ID.  CALL_DATA contains a pointer to  
    the widget_value structure for the menu item, or null in case of  
    unhighlighting.  */  
1282    
1283  void  /* Function that finds the frame for WIDGET and shows the HELP text
1284  menu_highlight_callback (widget, id, call_data)     for that widget.
1285       Widget widget;     F is the frame if known, or NULL if not known.  */
1286       LWLIB_ID id;  static void
1287       void *call_data;  show_help_event (f, widget, help)
1288         FRAME_PTR f;
1289         xt_or_gtk_widget widget;
1290         Lisp_Object help;
1291  {  {
1292    widget_value *wv = (widget_value *) call_data;    Lisp_Object frame;
   struct frame *f;  
   Lisp_Object frame, help;  
1293    
   help = wv ? wv->help : Qnil;  
     
   /* Determine the frame for the help event.  */  
   f = menubar_id_to_frame (id);  
1294    if (f)    if (f)
1295      {      {
1296        XSETFRAME (frame, f);        XSETFRAME (frame, f);
# Line 1196  menu_highlight_callback (widget, id, cal Line 1298  menu_highlight_callback (widget, id, cal
1298      }      }
1299    else    else
1300      {      {
1301        /* WIDGET is the popup menu.  It's parent is the frame's        /* WIDGET is the popup menu.  It's parent is the frame's
1302           widget.  See which frame that is.  */           widget.  See which frame that is.  */
1303        Widget frame_widget = XtParent (widget);        xt_or_gtk_widget frame_widget = XtParent (widget);
1304        Lisp_Object tail;        Lisp_Object tail;
1305    
1306        for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))        for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
# Line 1214  menu_highlight_callback (widget, id, cal Line 1316  menu_highlight_callback (widget, id, cal
1316      }      }
1317  }  }
1318    
1319  /* This callback is called from the menu bar pulldown menu  /* Callback called when menu items are highlighted/unhighlighted
1320     when the user makes a selection.     while moving the mouse over them.  WIDGET is the menu bar or menu
1321     Figure out what the user chose     popup widget.  ID is its LWLIB_ID.  CALL_DATA contains a pointer to
1322     and put the appropriate events into the keyboard buffer.  */     the data structure for the menu item, or null in case of
1323       unhighlighting.  */
1324    
1325  static void  #ifdef USE_GTK
1326  menubar_selection_callback (widget, id, client_data)  void
1327    menu_highlight_callback (widget, call_data)
1328         GtkWidget *widget;
1329         gpointer call_data;
1330    {
1331      xg_menu_item_cb_data *cb_data;
1332      Lisp_Object help;
1333    
1334      cb_data = (xg_menu_item_cb_data*) g_object_get_data (G_OBJECT (widget),
1335                                                           XG_ITEM_DATA);
1336      if (! cb_data) return;
1337    
1338      help = call_data ? cb_data->help : Qnil;
1339    
1340      /* If popup_activated_flag is greater than 1 we are in a popup menu.
1341         Don't show help for them, they won't appear before the
1342         popup is popped down.  */
1343      if (popup_activated_flag <= 1)
1344        show_help_event (cb_data->cl_data->f, widget, help);
1345    }
1346    #else
1347    void
1348    menu_highlight_callback (widget, id, call_data)
1349       Widget widget;       Widget widget;
1350       LWLIB_ID id;       LWLIB_ID id;
1351       XtPointer client_data;       void *call_data;
1352    {
1353      struct frame *f;
1354      Lisp_Object help;
1355    
1356      widget_value *wv = (widget_value *) call_data;
1357    
1358      help = wv ? wv->help : Qnil;
1359    
1360      /* Determine the frame for the help event.  */
1361      f = menubar_id_to_frame (id);
1362    
1363      show_help_event (f, widget, help);
1364    }
1365    #endif
1366    
1367    /* Find the menu selection and store it in the keyboard buffer.
1368       F is the frame the menu is on.
1369       MENU_BAR_ITEMS_USED is the length of VECTOR.
1370       VECTOR is an array of menu events for the whole menu.
1371     */
1372    void
1373    find_and_call_menu_selection (f, menu_bar_items_used, vector, client_data)
1374         FRAME_PTR f;
1375         int menu_bar_items_used;
1376         Lisp_Object vector;
1377         void *client_data;
1378  {  {
1379    Lisp_Object prefix, entry;    Lisp_Object prefix, entry;
   FRAME_PTR f = menubar_id_to_frame (id);  
   Lisp_Object vector;  
1380    Lisp_Object *subprefix_stack;    Lisp_Object *subprefix_stack;
1381    int submenu_depth = 0;    int submenu_depth = 0;
1382    int i;    int i;
1383    
   if (!f)  
     return;  
1384    entry = Qnil;    entry = Qnil;
1385    subprefix_stack = (Lisp_Object *) alloca (f->menu_bar_items_used * sizeof (Lisp_Object));    subprefix_stack = (Lisp_Object *) alloca (menu_bar_items_used * sizeof (Lisp_Object));
   vector = f->menu_bar_vector;  
1386    prefix = Qnil;    prefix = Qnil;
1387    i = 0;    i = 0;
1388    while (i < f->menu_bar_items_used)  
1389      while (i < menu_bar_items_used)
1390      {      {
1391        if (EQ (XVECTOR (vector)->contents[i], Qnil))        if (EQ (XVECTOR (vector)->contents[i], Qnil))
1392          {          {
# Line 1303  menubar_selection_callback (widget, id, Line 1450  menubar_selection_callback (widget, id,
1450      }      }
1451  }  }
1452    
1453    
1454    #ifdef USE_GTK
1455    /* Gtk calls callbacks just because we tell it what item should be
1456       selected in a radio group.  If this variable is set to a non-zero
1457       value, we are creating menus and don't want callbacks right now.
1458    */
1459    static int xg_crazy_callback_abort;
1460    
1461    /* This callback is called from the menu bar pulldown menu
1462       when the user makes a selection.
1463       Figure out what the user chose
1464       and put the appropriate events into the keyboard buffer.  */
1465    static void
1466    menubar_selection_callback (widget, client_data)
1467         GtkWidget *widget;
1468         gpointer client_data;
1469    {
1470      xg_menu_item_cb_data *cb_data = (xg_menu_item_cb_data*) client_data;
1471    
1472      if (xg_crazy_callback_abort)
1473        return;
1474    
1475      if (! cb_data || ! cb_data->cl_data || ! cb_data->cl_data->f)
1476        return;
1477    
1478      find_and_call_menu_selection (cb_data->cl_data->f,
1479                                    cb_data->cl_data->menu_bar_items_used,
1480                                    cb_data->cl_data->menu_bar_vector,
1481                                    cb_data->call_data);
1482    }
1483    
1484    #else /* not USE_GTK */
1485    
1486    /* This callback is called from the menu bar pulldown menu
1487       when the user makes a selection.
1488       Figure out what the user chose
1489       and put the appropriate events into the keyboard buffer.  */
1490    static void
1491    menubar_selection_callback (widget, id, client_data)
1492         Widget widget;
1493         LWLIB_ID id;
1494         XtPointer client_data;
1495    {
1496      FRAME_PTR f;
1497    
1498      f = menubar_id_to_frame (id);
1499      if (!f)
1500        return;
1501      find_and_call_menu_selection (f, f->menu_bar_items_used,
1502                                    f->menu_bar_vector, client_data);
1503    }
1504    #endif /* not USE_GTK */
1505    
1506  /* Allocate a widget_value, blocking input.  */  /* Allocate a widget_value, blocking input.  */
1507    
1508  widget_value *  widget_value *
# Line 1345  free_menubar_widget_value_tree (wv) Line 1545  free_menubar_widget_value_tree (wv)
1545    UNBLOCK_INPUT;    UNBLOCK_INPUT;
1546  }  }
1547    
1548  /* Return a tree of widget_value structures for a menu bar item  /* Set up data in menu_items for a menu bar item
1549     whose event type is ITEM_KEY (with string ITEM_NAME)     whose event type is ITEM_KEY (with string ITEM_NAME)
1550     and whose contents come from the list of keymaps MAPS.  */     and whose contents come from the list of keymaps MAPS.  */
1551    
1552  static widget_value *  static int
1553  single_submenu (item_key, item_name, maps)  parse_single_submenu (item_key, item_name, maps)
1554       Lisp_Object item_key, item_name, maps;       Lisp_Object item_key, item_name, maps;
1555  {  {
   widget_value *wv, *prev_wv, *save_wv, *first_wv;  
   int i;  
   int submenu_depth = 0;  
1556    Lisp_Object length;    Lisp_Object length;
1557    int len;    int len;
1558    Lisp_Object *mapvec;    Lisp_Object *mapvec;
1559    widget_value **submenu_stack;    int i;
   int previous_items = menu_items_used;  
1560    int top_level_items = 0;    int top_level_items = 0;
1561    
1562    length = Flength (maps);    length = Flength (maps);
# Line 1374  single_submenu (item_key, item_name, map Line 1570  single_submenu (item_key, item_name, map
1570        maps = Fcdr (maps);        maps = Fcdr (maps);
1571      }      }
1572    
   menu_items_n_panes = 0;  
   
1573    /* Loop over the given keymaps, making a pane for each map.    /* Loop over the given keymaps, making a pane for each map.
1574       But don't make a pane that is empty--ignore that map instead.  */       But don't make a pane that is empty--ignore that map instead.  */
1575    for (i = 0; i < len; i++)    for (i = 0; i < len; i++)
1576      {      {
1577        if (SYMBOLP (mapvec[i])        if (!KEYMAPP (mapvec[i]))
           || (CONSP (mapvec[i]) && !KEYMAPP (mapvec[i])))  
1578          {          {
1579            /* Here we have a command at top level in the menu bar            /* Here we have a command at top level in the menu bar
1580               as opposed to a submenu.  */               as opposed to a submenu.  */
# Line 1391  single_submenu (item_key, item_name, map Line 1584  single_submenu (item_key, item_name, map
1584                            Qnil, Qnil, Qnil, Qnil);                            Qnil, Qnil, Qnil, Qnil);
1585          }          }
1586        else        else
1587          single_keymap_panes (mapvec[i], item_name, item_key, 0, 10);          {
1588              Lisp_Object prompt;
1589              prompt = Fkeymap_prompt (mapvec[i]);
1590              single_keymap_panes (mapvec[i],
1591                                   !NILP (prompt) ? prompt : item_name,
1592                                   item_key, 0, 10);
1593            }
1594      }      }
1595    
1596    /* Create a tree of widget_value objects    return top_level_items;
1597       representing the panes and their items.  */  }
1598    
1599    /* Create a tree of widget_value objects
1600       representing the panes and items
1601       in menu_items starting at index START, up to index END.  */
1602    
1603    static widget_value *
1604    digest_single_submenu (start, end, top_level_items)
1605         int start, end, top_level_items;
1606    {
1607      widget_value *wv, *prev_wv, *save_wv, *first_wv;
1608      int i;
1609      int submenu_depth = 0;
1610      widget_value **submenu_stack;
1611    
1612    submenu_stack    submenu_stack
1613      = (widget_value **) alloca (menu_items_used * sizeof (widget_value *));      = (widget_value **) alloca (menu_items_used * sizeof (widget_value *));
# Line 1408  single_submenu (item_key, item_name, map Line 1620  single_submenu (item_key, item_name, map
1620    first_wv = wv;    first_wv = wv;
1621    save_wv = 0;    save_wv = 0;
1622    prev_wv = 0;    prev_wv = 0;
1623    
1624    /* Loop over all panes and items made during this call    /* Loop over all panes and items made by the preceding call
1625       and construct a tree of widget_value objects.       to parse_single_submenu and construct a tree of widget_value objects.
1626       Ignore the panes and items made by previous calls to       Ignore the panes and items used by previous calls to
1627       single_submenu, even though those are also in menu_items.  */       digest_single_submenu, even though those are also in menu_items.  */
1628    i = previous_items;    i = start;
1629    while (i < menu_items_used)    while (i < end)
1630      {      {
1631        if (EQ (XVECTOR (menu_items)->contents[i], Qnil))        if (EQ (XVECTOR (menu_items)->contents[i], Qnil))
1632          {          {
# Line 1441  single_submenu (item_key, item_name, map Line 1653  single_submenu (item_key, item_name, map
1653            /* Create a new pane.  */            /* Create a new pane.  */
1654            Lisp_Object pane_name, prefix;            Lisp_Object pane_name, prefix;
1655            char *pane_string;            char *pane_string;
1656              
1657            pane_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_NAME];            pane_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_NAME];
1658            prefix = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_PREFIX];            prefix = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_PREFIX];
1659              
1660  #ifndef HAVE_MULTILINGUAL_MENU  #ifndef HAVE_MULTILINGUAL_MENU
1661            if (STRINGP (pane_name) && STRING_MULTIBYTE (pane_name))            if (STRINGP (pane_name) && STRING_MULTIBYTE (pane_name))
1662              {              {
# Line 1453  single_submenu (item_key, item_name, map Line 1665  single_submenu (item_key, item_name, map
1665              }              }
1666  #endif  #endif
1667            pane_string = (NILP (pane_name)            pane_string = (NILP (pane_name)
1668                           ? "" : (char *) XSTRING (pane_name)->data);                           ? "" : (char *) SDATA (pane_name));
1669            /* If there is just one top-level pane, put all its items directly            /* If there is just one top-level pane, put all its items directly
1670               under the top-level menu.  */               under the top-level menu.  */
1671            if (menu_items_n_panes == 1)            if (menu_items_n_panes == 1)
# Line 1488  single_submenu (item_key, item_name, map Line 1700  single_submenu (item_key, item_name, map
1700            /* Create a new item within current pane.  */            /* Create a new item within current pane.  */
1701            Lisp_Object item_name, enable, descrip, def, type, selected;            Lisp_Object item_name, enable, descrip, def, type, selected;
1702            Lisp_Object help;            Lisp_Object help;
1703              
1704            item_name = AREF (menu_items, i + MENU_ITEMS_ITEM_NAME);            item_name = AREF (menu_items, i + MENU_ITEMS_ITEM_NAME);
1705            enable = AREF (menu_items, i + MENU_ITEMS_ITEM_ENABLE);            enable = AREF (menu_items, i + MENU_ITEMS_ITEM_ENABLE);
1706            descrip = AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY);            descrip = AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY);
# Line 1503  single_submenu (item_key, item_name, map Line 1715  single_submenu (item_key, item_name, map
1715                item_name = ENCODE_SYSTEM (item_name);                item_name = ENCODE_SYSTEM (item_name);
1716                AREF (menu_items, i + MENU_ITEMS_ITEM_NAME) = item_name;                AREF (menu_items, i + MENU_ITEMS_ITEM_NAME) = item_name;
1717              }              }
1718              
1719            if (STRINGP (descrip) && STRING_MULTIBYTE (descrip))            if (STRINGP (descrip) && STRING_MULTIBYTE (descrip))
1720              {              {
1721                descrip = ENCODE_SYSTEM (descrip);                descrip = ENCODE_SYSTEM (descrip);
# Line 1512  single_submenu (item_key, item_name, map Line 1724  single_submenu (item_key, item_name, map
1724  #endif /* not HAVE_MULTILINGUAL_MENU */  #endif /* not HAVE_MULTILINGUAL_MENU */
1725    
1726            wv = xmalloc_widget_value ();            wv = xmalloc_widget_value ();
1727            if (prev_wv)            if (prev_wv)
1728              prev_wv->next = wv;              prev_wv->next = wv;
1729            else            else
1730              save_wv->contents = wv;              save_wv->contents = wv;
1731    
1732            wv->name = (char *) XSTRING (item_name)->data;            wv->name = (char *) SDATA (item_name);
1733            if (!NILP (descrip))            if (!NILP (descrip))
1734              wv->key = (char *) XSTRING (descrip)->data;              wv->key = (char *) SDATA (descrip);
1735            wv->value = 0;            wv->value = 0;
1736            /* The EMACS_INT cast avoids a warning.  There's no problem            /* The EMACS_INT cast avoids a warning.  There's no problem
1737               as long as pointers have enough bits to hold small integers.  */               as long as pointers have enough bits to hold small integers.  */
1738            wv->call_data = (!NILP (def) ? (void *) (EMACS_INT) i : 0);            wv->call_data = (!NILP (def) ? (void *) (EMACS_INT) i : 0);
1739            wv->enabled = !NILP (enable);            wv->enabled = !NILP (enable);
1740              
1741            if (NILP (type))            if (NILP (type))
1742              wv->button_type = BUTTON_TYPE_NONE;              wv->button_type = BUTTON_TYPE_NONE;
1743            else if (EQ (type, QCradio))            else if (EQ (type, QCradio))
# Line 1558  single_submenu (item_key, item_name, map Line 1770  single_submenu (item_key, item_name, map
1770    
1771    return first_wv;    return first_wv;
1772  }  }
   
   
1773    
1774  /* Recompute all the widgets of frame F, when the menu bar has been  /* Recompute all the widgets of frame F, when the menu bar has been
1775     changed.  Value is non-zero if widgets were updated.  */     changed.  Value is non-zero if widgets were updated.  */
# Line 1568  static int Line 1778  static int
1778  update_frame_menubar (f)  update_frame_menubar (f)
1779       FRAME_PTR f;       FRAME_PTR f;
1780  {  {
1781    #ifdef USE_GTK
1782      return xg_update_frame_menubar (f);
1783    #else
1784    struct x_output *x = f->output_data.x;    struct x_output *x = f->output_data.x;
1785    int columns, rows;    int columns, rows;
1786      
1787    if (!x->menubar_widget || XtIsManaged (x->menubar_widget))    if (!x->menubar_widget || XtIsManaged (x->menubar_widget))
1788      return 0;      return 0;
1789    
# Line 1602  update_frame_menubar (f) Line 1815  update_frame_menubar (f)
1815    /* Force the pane widget to resize itself with the right values.  */    /* Force the pane widget to resize itself with the right values.  */
1816    EmacsFrameSetCharSize (x->edit_widget, columns, rows);    EmacsFrameSetCharSize (x->edit_widget, columns, rows);
1817    UNBLOCK_INPUT;    UNBLOCK_INPUT;
1818    #endif
1819    return 1;    return 1;
1820  }  }
1821    
# Line 1615  set_frame_menubar (f, first_time, deep_p Line 1829  set_frame_menubar (f, first_time, deep_p
1829       int first_time;       int first_time;
1830       int deep_p;       int deep_p;
1831  {  {
1832    Widget menubar_widget = f->output_data.x->menubar_widget;    xt_or_gtk_widget menubar_widget = f->output_data.x->menubar_widget;
1833    #ifdef USE_X_TOOLKIT
1834      LWLIB_ID id;
1835    #endif
1836    Lisp_Object items;    Lisp_Object items;
1837    widget_value *wv, *first_wv, *prev_wv = 0;    widget_value *wv, *first_wv, *prev_wv = 0;
1838    int i;    int i, last_i;
1839      int *submenu_start, *submenu_end;
1840      int *submenu_top_level_items, *submenu_n_panes;
1841    
   LWLIB_ID id;  
1842    
1843    XSETFRAME (Vmenu_updating_frame, f);    XSETFRAME (Vmenu_updating_frame, f);
1844    
1845    #ifdef USE_X_TOOLKIT
1846    if (f->output_data.x->id == 0)    if (f->output_data.x->id == 0)
1847      f->output_data.x->id = next_menubar_widget_id++;      f->output_data.x->id = next_menubar_widget_id++;
1848    id = f->output_data.x->id;    id = f->output_data.x->id;
1849    #endif
1850    
1851    if (! menubar_widget)    if (! menubar_widget)
1852      deep_p = 1;      deep_p = 1;
# Line 1640  set_frame_menubar (f, first_time, deep_p Line 1860  set_frame_menubar (f, first_time, deep_p
1860        f->output_data.x->saved_menu_event->type = 0;        f->output_data.x->saved_menu_event->type = 0;
1861      }      }
1862    
   wv = xmalloc_widget_value ();  
   wv->name = "menubar";  
   wv->value = 0;  
   wv->enabled = 1;  
   wv->button_type = BUTTON_TYPE_NONE;  
   wv->help = Qnil;  
   first_wv = wv;  
   
1863    if (deep_p)    if (deep_p)
1864      {      {
1865        /* Make a widget-value tree representing the entire menu trees.  */        /* Make a widget-value tree representing the entire menu trees.  */
1866    
1867        struct buffer *prev = current_buffer;        struct buffer *prev = current_buffer;
1868        Lisp_Object buffer;        Lisp_Object buffer;
1869        int specpdl_count = specpdl_ptr - specpdl;        int specpdl_count = SPECPDL_INDEX ();
1870        int previous_menu_items_used = f->menu_bar_items_used;        int previous_menu_items_used = f->menu_bar_items_used;
1871        Lisp_Object *previous_items        Lisp_Object *previous_items
1872          = (Lisp_Object *) alloca (previous_menu_items_used          = (Lisp_Object *) alloca (previous_menu_items_used
# Line 1672  set_frame_menubar (f, first_time, deep_p Line 1884  set_frame_menubar (f, first_time, deep_p
1884        specbind (Qdebug_on_next_call, Qnil);        specbind (Qdebug_on_next_call, Qnil);
1885    
1886        record_unwind_protect (Fset_match_data, Fmatch_data (Qnil, Qnil));        record_unwind_protect (Fset_match_data, Fmatch_data (Qnil, Qnil));
1887          record_unwind_protect (unuse_menu_items, Qnil);
1888        if (NILP (Voverriding_local_map_menu_flag))        if (NILP (Voverriding_local_map_menu_flag))
1889          {          {
1890            specbind (Qoverriding_terminal_local_map, Qnil);            specbind (Qoverriding_terminal_local_map, Qnil);
# Line 1682  set_frame_menubar (f, first_time, deep_p Line 1895  set_frame_menubar (f, first_time, deep_p
1895    
1896        /* Run the Lucid hook.  */        /* Run the Lucid hook.  */
1897        safe_run_hooks (Qactivate_menubar_hook);        safe_run_hooks (Qactivate_menubar_hook);
1898          
1899        /* If it has changed current-menubar from previous value,        /* If it has changed current-menubar from previous value,
1900           really recompute the menubar from the value.  */           really recompute the menubar from the value.  */
1901        if (! NILP (Vlucid_menu_bar_dirty_flag))        if (! NILP (Vlucid_menu_bar_dirty_flag))
# Line 1692  set_frame_menubar (f, first_time, deep_p Line 1905  set_frame_menubar (f, first_time, deep_p
1905    
1906        items = FRAME_MENU_BAR_ITEMS (f);        items = FRAME_MENU_BAR_ITEMS (f);
1907    
       inhibit_garbage_collection ();  
   
1908        /* Save the frame's previous menu bar contents data.  */        /* Save the frame's previous menu bar contents data.  */
1909        if (previous_menu_items_used)        if (previous_menu_items_used)
1910          bcopy (XVECTOR (f->menu_bar_vector)->contents, previous_items,          bcopy (XVECTOR (f->menu_bar_vector)->contents, previous_items,
1911                 previous_menu_items_used * sizeof (Lisp_Object));                 previous_menu_items_used * sizeof (Lisp_Object));
1912    
1913        /* Fill in the current menu bar contents.  */        /* Fill in menu_items with the current menu bar contents.
1914             This can evaluate Lisp code.  */
1915        menu_items = f->menu_bar_vector;        menu_items = f->menu_bar_vector;
1916        menu_items_allocated = VECTORP (menu_items) ? ASIZE (menu_items) : 0;        menu_items_allocated = VECTORP (menu_items) ? ASIZE (menu_items) : 0;
1917          submenu_start = (int *) alloca (XVECTOR (items)->size * sizeof (int *));
1918          submenu_end = (int *) alloca (XVECTOR (items)->size * sizeof (int *));
1919          submenu_n_panes = (int *) alloca (XVECTOR (items)->size * sizeof (int));
1920          submenu_top_level_items
1921            = (int *) alloca (XVECTOR (items)->size * sizeof (int *));
1922        init_menu_items ();        init_menu_items ();
1923        for (i = 0; i < XVECTOR (items)->size; i += 4)        for (i = 0; i < XVECTOR (items)->size; i += 4)
1924          {          {
1925            Lisp_Object key, string, maps;            Lisp_Object key, string, maps;
1926    
1927              last_i = i;
1928    
1929            key = XVECTOR (items)->contents[i];            key = XVECTOR (items)->contents[i];
1930            string = XVECTOR (items)->contents[i + 1];            string = XVECTOR (items)->contents[i + 1];
1931            maps = XVECTOR (items)->contents[i + 2];            maps = XVECTOR (items)->contents[i + 2];
1932            if (NILP (string))            if (NILP (string))
1933              break;              break;
1934    
1935            wv = single_submenu (key, string, maps);            submenu_start[i] = menu_items_used;
1936            if (prev_wv)  
1937              menu_items_n_panes = 0;
1938              submenu_top_level_items[i]
1939                = parse_single_submenu (key, string, maps);
1940              submenu_n_panes[i] = menu_items_n_panes;
1941    
1942              submenu_end[i] = menu_items_used;
1943            }
1944    
1945          finish_menu_items ();
1946    
1947          /* Convert menu_items into widget_value trees
1948             to display the menu.  This cannot evaluate Lisp code.  */
1949    
1950          wv = xmalloc_widget_value ();
1951          wv->name = "menubar";
1952          wv->value = 0;
1953          wv->enabled = 1;
1954          wv->button_type = BUTTON_TYPE_NONE;
1955          wv->help = Qnil;
1956          first_wv = wv;
1957    
1958          for (i = 0; i < last_i; i += 4)
1959            {
1960              menu_items_n_panes = submenu_n_panes[i];
1961              wv = digest_single_submenu (submenu_start[i], submenu_end[i],
1962                                          submenu_top_level_items[i]);
1963              if (prev_wv)
1964              prev_wv->next = wv;              prev_wv->next = wv;
1965            else            else
1966              first_wv->contents = wv;              first_wv->contents = wv;
# Line 1724  set_frame_menubar (f, first_time, deep_p Line 1970  set_frame_menubar (f, first_time, deep_p
1970            prev_wv = wv;            prev_wv = wv;
1971          }          }
1972    
       finish_menu_items ();  
   
1973        set_buffer_internal_1 (prev);        set_buffer_internal_1 (prev);
1974        unbind_to (specpdl_count, Qnil);        unbind_to (specpdl_count, Qnil);
1975    
# Line 1739  set_frame_menubar (f, first_time, deep_p Line 1983  set_frame_menubar (f, first_time, deep_p
1983        if (i == menu_items_used && i == previous_menu_items_used && i != 0)        if (i == menu_items_used && i == previous_menu_items_used && i != 0)
1984          {          {
1985            free_menubar_widget_value_tree (first_wv);            free_menubar_widget_value_tree (first_wv);
1986            menu_items = Qnil;            discard_menu_items ();
1987    
1988            return;            return;
1989          }          }
# Line 1753  set_frame_menubar (f, first_time, deep_p Line 1997  set_frame_menubar (f, first_time, deep_p
1997            string = XVECTOR (items)->contents[i + 1];            string = XVECTOR (items)->contents[i + 1];
1998            if (NILP (string))            if (NILP (string))
1999              break;              break;
2000            wv->name = (char *) XSTRING (string)->data;            wv->name = (char *) SDATA (string);
2001            wv = wv->next;            wv = wv->next;
2002          }          }
2003    
2004        f->menu_bar_vector = menu_items;        f->menu_bar_vector = menu_items;
2005        f->menu_bar_items_used = menu_items_used;        f->menu_bar_items_used = menu_items_used;
2006        menu_items = Qnil;        discard_menu_items ();
2007      }      }
2008    else    else
2009      {      {
2010        /* Make a widget-value tree containing        /* Make a widget-value tree containing
2011           just the top level menu bar strings.  */           just the top level menu bar strings.  */
2012    
2013          wv = xmalloc_widget_value ();
2014          wv->name = "menubar";
2015          wv->value = 0;
2016          wv->enabled = 1;
2017          wv->button_type = BUTTON_TYPE_NONE;
2018          wv->help = Qnil;
2019          first_wv = wv;
2020    
2021        items = FRAME_MENU_BAR_ITEMS (f);        items = FRAME_MENU_BAR_ITEMS (f);
2022        for (i = 0; i < XVECTOR (items)->size; i += 4)        for (i = 0; i < XVECTOR (items)->size; i += 4)
2023          {          {
# Line 1776  set_frame_menubar (f, first_time, deep_p Line 2028  set_frame_menubar (f, first_time, deep_p
2028              break;              break;
2029    
2030            wv = xmalloc_widget_value ();            wv = xmalloc_widget_value ();
2031            wv->name = (char *) XSTRING (string)->data;            wv->name = (char *) SDATA (string);
2032            wv->value = 0;            wv->value = 0;
2033            wv->enabled = 1;            wv->enabled = 1;
2034            wv->button_type = BUTTON_TYPE_NONE;            wv->button_type = BUTTON_TYPE_NONE;
# Line 1787  set_frame_menubar (f, first_time, deep_p Line 2039  set_frame_menubar (f, first_time, deep_p
2039               This value just has to be different from small integers.  */               This value just has to be different from small integers.  */
2040            wv->call_data = (void *) (EMACS_INT) (-1);            wv->call_data = (void *) (EMACS_INT) (-1);
2041    
2042            if (prev_wv)            if (prev_wv)
2043              prev_wv->next = wv;              prev_wv->next = wv;
2044            else            else
2045              first_wv->contents = wv;              first_wv->contents = wv;
# Line 1804  set_frame_menubar (f, first_time, deep_p Line 2056  set_frame_menubar (f, first_time, deep_p
2056    
2057    BLOCK_INPUT;    BLOCK_INPUT;
2058    
2059    #ifdef USE_GTK
2060      xg_crazy_callback_abort = 1;
2061      if (menubar_widget)
2062        {
2063          /* The third arg is DEEP_P, which says to consider the entire
2064             menu trees we supply, rather than just the menu bar item names.  */
2065          xg_modify_menubar_widgets (menubar_widget,
2066                                     f,
2067                                     first_wv,
2068                                     deep_p,
2069                                     G_CALLBACK (menubar_selection_callback),
2070                                     G_CALLBACK (popup_deactivate_callback),
2071                                     G_CALLBACK (menu_highlight_callback));
2072        }
2073      else
2074        {
2075          GtkWidget *wvbox = f->output_data.x->vbox_widget;
2076    
2077          menubar_widget
2078            = xg_create_widget ("menubar", "menubar", f, first_wv,
2079                                G_CALLBACK (menubar_selection_callback),
2080                                G_CALLBACK (popup_deactivate_callback),
2081                                G_CALLBACK (menu_highlight_callback));
2082    
2083          f->output_data.x->menubar_widget = menubar_widget;
2084        }
2085    
2086    
2087    #else /* not USE_GTK */
2088    if (menubar_widget)    if (menubar_widget)
2089      {      {
2090        /* Disable resizing (done for Motif!) */        /* Disable resizing (done for Motif!) */
# Line 1818  set_frame_menubar (f, first_time, deep_p Line 2099  set_frame_menubar (f, first_time, deep_p
2099      }      }
2100    else    else
2101      {      {
2102        menubar_widget = lw_create_widget ("menubar", "menubar", id, first_wv,        menubar_widget = lw_create_widget ("menubar", "menubar", id, first_wv,
2103                                           f->output_data.x->column_widget,                                           f->output_data.x->column_widget,
2104                                           0,                                           0,
2105                                           popup_activate_callback,                                           popup_activate_callback,
# Line 1829  set_frame_menubar (f, first_time, deep_p Line 2110  set_frame_menubar (f, first_time, deep_p
2110      }      }
2111    
2112    {    {
2113      int menubar_size      int menubar_size
2114        = (f->output_data.x->menubar_widget        = (f->output_data.x->menubar_widget
2115           ? (f->output_data.x->menubar_widget->core.height           ? (f->output_data.x->menubar_widget->core.height
2116              + f->output_data.x->menubar_widget->core.border_width)              + f->output_data.x->menubar_widget->core.border_width)
# Line 1850  set_frame_menubar (f, first_time, deep_p Line 2131  set_frame_menubar (f, first_time, deep_p
2131    
2132      f->output_data.x->menubar_height = menubar_size;      f->output_data.x->menubar_height = menubar_size;
2133    }    }
2134      #endif /* not USE_GTK */
2135    
2136    free_menubar_widget_value_tree (first_wv);    free_menubar_widget_value_tree (first_wv);
2137    update_frame_menubar (f);    update_frame_menubar (f);
2138    
2139    #ifdef USE_GTK
2140      xg_crazy_callback_abort = 0;
2141    #endif
2142    
2143    UNBLOCK_INPUT;    UNBLOCK_INPUT;
2144  }  }
2145    
# Line 1874  initialize_frame_menubar (f) Line 2160  initialize_frame_menubar (f)
2160    
2161    
2162  /* Get rid of the menu bar of frame F, and free its storage.  /* Get rid of the menu bar of frame F, and free its storage.
2163     This is used when deleting a frame, and when turning off the menu bar.  */     This is used when deleting a frame, and when turning off the menu bar.
2164       For GTK this function is in gtkutil.c.  */
2165    
2166    #ifndef USE_GTK
2167  void  void
2168  free_frame_menubar (f)  free_frame_menubar (f)
2169       FRAME_PTR f;       FRAME_PTR f;
# Line 1885  free_frame_menubar (f) Line 2173  free_frame_menubar (f)
2173    menubar_widget = f->output_data.x->menubar_widget;    menubar_widget = f->output_data.x->menubar_widget;
2174    
2175    f->output_data.x->menubar_height = 0;    f->output_data.x->menubar_height = 0;
2176      
2177    if (menubar_widget)    if (menubar_widget)
2178      {      {
2179  #ifdef USE_MOTIF  #ifdef USE_MOTIF
# Line 1899  free_frame_menubar (f) Line 2187  free_frame_menubar (f)
2187           is switched off, which fixes the shell position.  */           is switched off, which fixes the shell position.  */
2188        Position x0, y0, x1, y1;        Position x0, y0, x1, y1;
2189  #endif  #endif
2190          
2191        BLOCK_INPUT;        BLOCK_INPUT;
2192    
2193  #ifdef USE_MOTIF  #ifdef USE_MOTIF
2194        if (f->output_data.x->widget)        if (f->output_data.x->widget)
2195          XtVaGetValues (f->output_data.x->widget, XtNx, &x0, XtNy, &y0, NULL);          XtVaGetValues (f->output_data.x->widget, XtNx, &x0, XtNy, &y0, NULL);
2196  #endif  #endif
2197          
2198        lw_destroy_all_widgets ((LWLIB_ID) f->output_data.x->id);        lw_destroy_all_widgets ((LWLIB_ID) f->output_data.x->id);
2199        f->output_data.x->menubar_widget = NULL;        f->output_data.x->menubar_widget = NULL;
2200    
# Line 1918  free_frame_menubar (f) Line 2206  free_frame_menubar (f)
2206              XtVaSetValues (f->output_data.x->widget, XtNx, x0, XtNy, y0, NULL);              XtVaSetValues (f->output_data.x->widget, XtNx, x0, XtNy, y0, NULL);
2207          }          }
2208  #endif  #endif
2209          
2210        UNBLOCK_INPUT;        UNBLOCK_INPUT;
2211      }      }
2212  }  }
2213    #endif /* not USE_GTK */
2214    
2215  #endif /* USE_X_TOOLKIT */  #endif /* USE_X_TOOLKIT || USE_GTK */
2216    
2217  /* xmenu_show actually displays a menu using the panes and items in menu_items  /* xmenu_show actually displays a menu using the panes and items in menu_items
2218     and returns the value selected from it.     and returns the value selected from it.
# Line 1941  free_frame_menubar (f) Line 2230  free_frame_menubar (f)
2230     ERROR is a place to store an error message string in case of failure.     ERROR is a place to store an error message string in case of failure.
2231     (We return nil on failure, but the value doesn't actually matter.)  */     (We return nil on failure, but the value doesn't actually matter.)  */
2232    
2233  #ifdef USE_X_TOOLKIT  #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
2234    
2235    /* The item selected in the popup menu.  */
2236    static Lisp_Object *volatile menu_item_selection;
2237    
2238    #ifdef USE_GTK
2239    
2240    /* Used when position a popup menu.  See menu_position_func and
2241       create_and_show_popup_menu below.  */
2242    struct next_popup_x_y
2243    {
2244      FRAME_PTR f;
2245      int x;
2246      int y;
2247    };
2248    
2249    /* The menu position function to use if we are not putting a popup
2250       menu where the pointer is.
2251       MENU is the menu to pop up.
2252       X and Y shall on exit contain x/y where the menu shall pop up.
2253       PUSH_IN is not documented in the GTK manual.
2254       USER_DATA is any data passed in when calling gtk_menu_popup.
2255       Here it points to a struct next_popup_x_y where the coordinates
2256       to store in *X and *Y are as well as the frame for the popup.
2257    
2258       Here only X and Y are used.  */
2259    static void
2260    menu_position_func (menu, x, y, push_in, user_data)
2261         GtkMenu *menu;
2262         gint *x;
2263         gint *y;
2264         gboolean *push_in;
2265         gpointer user_data;
2266    {
2267      struct next_popup_x_y* data = (struct next_popup_x_y*)user_data;
2268      GtkRequisition req;
2269      int disp_width = FRAME_X_DISPLAY_INFO (data->f)->width;
2270      int disp_height = FRAME_X_DISPLAY_INFO (data->f)->height;
2271      
2272      *x = data->x;
2273      *y = data->y;
2274    
2275      /* Check if there is room for the menu.  If not, adjust x/y so that
2276         the menu is fully visible.  */
2277      gtk_widget_size_request (GTK_WIDGET (menu), &req);
2278      if (data->x + req.width > disp_width)
2279        *x -= data->x + req.width - disp_width;
2280      if (data->y + req.height > disp_height)
2281        *y -= data->y + req.height - disp_height;
2282    }
2283    
2284    static void
2285    popup_selection_callback (widget, client_data)
2286         GtkWidget *widget;
2287         gpointer client_data;
2288    {
2289      xg_menu_item_cb_data *cb_data = (xg_menu_item_cb_data*) client_data;
2290    
2291      if (xg_crazy_callback_abort) return;
2292      if (cb_data) menu_item_selection = (Lisp_Object *) cb_data->call_data;
2293    }
2294    
2295    /* Pop up the menu for frame F defined by FIRST_WV at X/Y and loop until the
2296       menu pops down.
2297       menu_item_selection will be set to the selection.  */
2298    static void
2299    create_and_show_popup_menu (f, first_wv, x, y, for_click)
2300         FRAME_PTR f;
2301         widget_value *first_wv;
2302         int x;
2303         int y;
2304         int for_click;
2305    {
2306      int i;
2307      GtkWidget *menu;
2308      GtkMenuPositionFunc pos_func = 0;  /* Pop up at pointer.  */
2309      struct next_popup_x_y popup_x_y;
2310    
2311      xg_crazy_callback_abort = 1;
2312      menu = xg_create_widget ("popup", first_wv->name, f, first_wv,
2313                               G_CALLBACK (popup_selection_callback),
2314                               G_CALLBACK (popup_deactivate_callback),
2315                               G_CALLBACK (menu_highlight_callback));
2316      xg_crazy_callback_abort = 0;
2317    
2318      for (i = 0; i < 5; i++)
2319        if (FRAME_X_DISPLAY_INFO (f)->grabbed & (1 << i))
2320          break;
2321    
2322      if (! for_click)
2323        {
2324          /* Not invoked by a click.  pop up at x/y.  */
2325          pos_func = menu_position_func;
2326    
2327          /* Adjust coordinates to be root-window-relative.  */
2328          x += f->output_data.x->left_pos + FRAME_OUTER_TO_INNER_DIFF_X (f);
2329          y += f->output_data.x->top_pos + FRAME_OUTER_TO_INNER_DIFF_Y (f);
2330    
2331          popup_x_y.x = x;
2332          popup_x_y.y = y;
2333          popup_x_y.f = f;
2334        }
2335    
2336      /* Display the menu.  */
2337      gtk_widget_show_all (menu);
2338      gtk_menu_popup (GTK_MENU (menu), 0, 0, pos_func, &popup_x_y, i, 0);
2339    
2340      xg_did_tearoff = 0;
2341      /* Set this to one.  popup_widget_loop increases it by one, so it becomes
2342         two.  show_help_echo uses this to detect popup menus.  */
2343      popup_activated_flag = 1;
2344      /* Process events that apply to the menu.  */
2345      popup_widget_loop ();
2346    
2347      if (xg_did_tearoff)
2348        xg_keep_popup (menu, xg_did_tearoff);
2349      else
2350        gtk_widget_destroy (menu);
2351    
2352      /* Must reset this manually because the button release event is not passed
2353         to Emacs event loop. */
2354      FRAME_X_DISPLAY_INFO (f)->grabbed = 0;
2355    }
2356    
2357    #else /* not USE_GTK */
2358    
2359  /* We need a unique id for each widget handled by the Lucid Widget  /* We need a unique id for each widget handled by the Lucid Widget
2360     library.     library.
# Line 1953  free_frame_menubar (f) Line 2366  free_frame_menubar (f)
2366     next_menubar_widget_id.  */     next_menubar_widget_id.  */
2367  LWLIB_ID widget_id_tick;  LWLIB_ID widget_id_tick;
2368    
 static Lisp_Object *volatile menu_item_selection;  
   
2369  static void  static void
2370  popup_selection_callback (widget, id, client_data)  popup_selection_callback (widget, id, client_data)
2371       Widget widget;       Widget widget;
# Line 1964  popup_selection_callback (widget, id, cl Line 2375  popup_selection_callback (widget, id, cl
2375    menu_item_selection = (Lisp_Object *) client_data;    menu_item_selection = (Lisp_Object *) client_data;
2376  }  }
2377    
2378    /* Pop up the menu for frame F defined by FIRST_WV at X/Y and loop until the
2379       menu pops down.
2380       menu_item_selection will be set to the selection.  */
2381    static void
2382    create_and_show_popup_menu (f, first_wv, x, y, for_click)
2383         FRAME_PTR f;
2384         widget_value *first_wv;
2385         int x;
2386         int y;
2387         int for_click;
2388    {
2389      int i;
2390      Arg av[2];
2391      int ac = 0;
2392      XButtonPressedEvent dummy;
2393      LWLIB_ID menu_id;
2394      Widget menu;
2395      Window child;
2396    
2397      menu_id = widget_id_tick++;
2398      menu = lw_create_widget ("popup", first_wv->name, menu_id, first_wv,
2399                               f->output_data.x->widget, 1, 0,
2400                               popup_selection_callback,
2401                               popup_deactivate_callback,
2402                               menu_highlight_callback);
2403    
2404      dummy.type = ButtonPress;
2405      dummy.serial = 0;
2406      dummy.send_event = 0;
2407      dummy.display = FRAME_X_DISPLAY (f);
2408      dummy.time = CurrentTime;
2409      dummy.root = FRAME_X_DISPLAY_INFO (f)->root_window;
2410      dummy.window = dummy.root;
2411      dummy.subwindow = dummy.root;
2412      dummy.x = x;
2413      dummy.y = y;
2414    
2415      /* Adjust coordinates to be root-window-relative.  */
2416      x += f->output_data.x->left_pos + FRAME_OUTER_TO_INNER_DIFF_X (f);
2417      y += f->output_data.x->top_pos + FRAME_OUTER_TO_INNER_DIFF_Y (f);
2418    
2419      dummy.x_root = x;
2420      dummy.y_root = y;
2421    
2422      dummy.state = 0;
2423      dummy.button = 0;
2424      for (i = 0; i < 5; i++)
2425        if (FRAME_X_DISPLAY_INFO (f)->grabbed & (1 << i))
2426          dummy.button = i;
2427    
2428      /* Don't allow any geometry request from the user.  */
2429      XtSetArg (av[ac], XtNgeometry, 0); ac++;
2430      XtSetValues (menu, av, ac);
2431    
2432      /* Display the menu.  */
2433      lw_popup_menu (menu, (XEvent *) &dummy);
2434      popup_activated_flag = 1;
2435    
2436      /* Process events that apply to the menu.  */
2437      popup_get_selection ((XEvent *) 0, FRAME_X_DISPLAY_INFO (f), menu_id, 0);
2438    
2439      /* fp turned off the following statement and wrote a comment
2440         that it is unnecessary--that the menu has already disappeared.
2441         Nowadays the menu disappears ok, all right, but
2442         we need to delete the widgets or multiple ones will pile up.  */
2443      lw_destroy_all_widgets (menu_id);
2444    }
2445    
2446    #endif /* not USE_GTK */
2447    
2448  static Lisp_Object  static Lisp_Object
2449  xmenu_show (f, x, y, for_click, keymaps, title, error)  xmenu_show (f, x, y, for_click, keymaps, title, error)
2450       FRAME_PTR f;       FRAME_PTR f;
# Line 1975  xmenu_show (f, x, y, for_click, keymaps, Line 2456  xmenu_show (f, x, y, for_click, keymaps,
2456       char **error;       char **error;
2457  {  {
2458    int i;    int i;
   LWLIB_ID menu_id;  
   Widget menu;  
   Arg av[2];  
   int ac = 0;  
2459    widget_value *wv, *save_wv = 0, *first_wv = 0, *prev_wv = 0;    widget_value *wv, *save_wv = 0, *first_wv = 0, *prev_wv = 0;
2460    widget_value **submenu_stack    widget_value **submenu_stack
2461      = (widget_value **) alloca (menu_items_used * sizeof (widget_value *));      = (widget_value **) alloca (menu_items_used * sizeof (widget_value *));
2462    Lisp_Object *subprefix_stack    Lisp_Object *subprefix_stack
2463      = (Lisp_Object *) alloca (menu_items_used * sizeof (Lisp_Object));      = (Lisp_Object *) alloca (menu_items_used * sizeof (Lisp_Object));
2464    int submenu_depth = 0;    int submenu_depth = 0;
   XButtonPressedEvent dummy;  
2465    
2466    int first_pane;    int first_pane;
2467    
# Line 2007  xmenu_show (f, x, y, for_click, keymaps, Line 2483  xmenu_show (f, x, y, for_click, keymaps,
2483    wv->help =Qnil;    wv->help =Qnil;
2484    first_wv = wv;    first_wv = wv;
2485    first_pane = 1;    first_pane = 1;
2486    
2487    /* Loop over all panes and items, filling in the tree.  */    /* Loop over all panes and items, filling in the tree.  */
2488    i = 0;    i = 0;
2489    while (i < menu_items_used)    while (i < menu_items_used)
# Line 2039  xmenu_show (f, x, y, for_click, keymaps, Line 2515  xmenu_show (f, x, y, for_click, keymaps,
2515            /* Create a new pane.  */            /* Create a new pane.  */
2516            Lisp_Object pane_name, prefix;            Lisp_Object pane_name, prefix;
2517            char *pane_string;            char *pane_string;
2518              
2519            pane_name = AREF (menu_items, i + MENU_ITEMS_PANE_NAME);            pane_name = AREF (menu_items, i + MENU_ITEMS_PANE_NAME);
2520            prefix = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX);            prefix = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX);
2521              
2522  #ifndef HAVE_MULTILINGUAL_MENU  #ifndef HAVE_MULTILINGUAL_MENU
2523            if (STRINGP (pane_name) && STRING_MULTIBYTE (pane_name))            if (STRINGP (pane_name) && STRING_MULTIBYTE (pane_name))
2524              {              {
# Line 2051  xmenu_show (f, x, y, for_click, keymaps, Line 2527  xmenu_show (f, x, y, for_click, keymaps,
2527              }              }
2528  #endif  #endif
2529            pane_string = (NILP (pane_name)            pane_string = (NILP (pane_name)
2530                           ? "" : (char *) XSTRING (pane_name)->data);                           ? "" : (char *) SDATA (pane_name));
2531            /* If there is just one top-level pane, put all its items directly            /* If there is just one top-level pane, put all its items directly
2532               under the top-level menu.  */               under the top-level menu.  */
2533            if (menu_items_n_panes == 1)            if (menu_items_n_panes == 1)
# Line 2103  xmenu_show (f, x, y, for_click, keymaps, Line 2579  xmenu_show (f, x, y, for_click, keymaps,
2579                item_name = ENCODE_SYSTEM (item_name);                item_name = ENCODE_SYSTEM (item_name);
2580                AREF (menu_items, i + MENU_ITEMS_ITEM_NAME) = item_name;                AREF (menu_items, i + MENU_ITEMS_ITEM_NAME) = item_name;
2581              }              }
2582              
2583            if (STRINGP (descrip) && STRING_MULTIBYTE (descrip))            if (STRINGP (descrip) && STRING_MULTIBYTE (descrip))
2584              {              {
2585                descrip = ENCODE_SYSTEM (descrip);                descrip = ENCODE_SYSTEM (descrip);
2586                AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY) = descrip;                AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY) = descrip;
2587              }              }
2588  #endif /* not HAVE_MULTILINGUAL_MENU */  #endif /* not HAVE_MULTILINGUAL_MENU */
2589    
2590            wv = xmalloc_widget_value ();            wv = xmalloc_widget_value ();
2591            if (prev_wv)            if (prev_wv)
2592              prev_wv->next = wv;              prev_wv->next = wv;
2593            else            else
2594              save_wv->contents = wv;              save_wv->contents = wv;
2595            wv->name = (char *) XSTRING (item_name)->data;            wv->name = (char *) SDATA (item_name);
2596            if (!NILP (descrip))            if (!NILP (descrip))
2597              wv->key = (char *) XSTRING (descrip)->data;              wv->key = (char *) SDATA (descrip);
2598            wv->value = 0;            wv->value = 0;
2599            /* If this item has a null value,            /* If this item has a null value,
2600               make the call_data null so that it won't display a box               make the call_data null so that it won't display a box
# Line 2168  xmenu_show (f, x, y, for_click, keymaps, Line 2644  xmenu_show (f, x, y, for_click, keymaps,
2644        if (STRING_MULTIBYTE (title))        if (STRING_MULTIBYTE (title))
2645          title = ENCODE_SYSTEM (title);          title = ENCODE_SYSTEM (title);
2646  #endif  #endif
2647          
2648        wv_title->name = (char *) XSTRING (title)->data;        wv_title->name = (char *) SDATA (title);
2649        wv_title->enabled = TRUE;        wv_title->enabled = TRUE;
2650        wv_title->button_type = BUTTON_TYPE_NONE;        wv_title->button_type = BUTTON_TYPE_NONE;
2651        wv_title->next = wv_sep1;        wv_title->next = wv_sep1;
# Line 2177  xmenu_show (f, x, y, for_click, keymaps, Line 2653  xmenu_show (f, x, y, for_click, keymaps,
2653        first_wv->contents = wv_title;        first_wv->contents = wv_title;
2654      }      }
2655    
   /* Actually create the menu.  */  
   menu_id = widget_id_tick++;  
   menu = lw_create_widget ("popup", first_wv->name, menu_id, first_wv,  
                            f->output_data.x->widget, 1, 0,  
                            popup_selection_callback,  
                            popup_deactivate_callback,  
                            menu_highlight_callback);  
   
   /* Adjust coordinates to relative to the outer (window manager) window.  */  
   {  
     Window child;  
     int win_x = 0, win_y = 0;  
   
     /* Find the position of the outside upper-left corner of  
        the inner window, with respect to the outer window.  */  
     if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)  
       {  
         BLOCK_INPUT;  
         XTranslateCoordinates (FRAME_X_DISPLAY (f),  
   
                                /* From-window, to-window.  */  
                                f->output_data.x->window_desc,  
                                f->output_data.x->parent_desc,  
   
                                /* From-position, to-position.  */  
                                0, 0, &win_x, &win_y,  
   
                                /* Child of window.  */  
                                &child);  
         UNBLOCK_INPUT;  
         x += win_x;  
         y += win_y;  
       }  
   }  
   
   /* Adjust coordinates to be root-window-relative.  */  
   x += f->output_data.x->left_pos;  
   y += f->output_data.x->top_pos;  
   
   dummy.type = ButtonPress;  
   dummy.serial = 0;  
   dummy.send_event = 0;  
   dummy.display = FRAME_X_DISPLAY (f);  
   dummy.time = CurrentTime;  
   dummy.root = FRAME_X_DISPLAY_INFO (f)->root_window;  
   dummy.window = dummy.root;  
   dummy.subwindow = dummy.root;  
   dummy.x_root = x;  
   dummy.y_root = y;  
   dummy.x = x;  
   dummy.y = y;  
   dummy.state = (FRAME_X_DISPLAY_INFO (f)->grabbed >> 1) * Button1Mask;  
   dummy.button = 0;  
   for (i = 0; i < 5; i++)  
     if (FRAME_X_DISPLAY_INFO (f)->grabbed & (1 << i))  
       dummy.button = i;  
   
   /* Don't allow any geometry request from the user.  */  
   XtSetArg (av[ac], XtNgeometry, 0); ac++;  
   XtSetValues (menu, av, ac);  
   
   /* Free the widget_value objects we used to specify the contents.  */  
   free_menubar_widget_value_tree (first_wv);  
   
2656    /* No selection has been chosen yet.  */    /* No selection has been chosen yet.  */
2657    menu_item_selection = 0;    menu_item_selection = 0;
2658    
2659    /* Display the menu.  */    /* Actually create and show the menu until popped down.  */
2660    lw_popup_menu (menu, (XEvent *) &dummy);    create_and_show_popup_menu (f, first_wv, x, y, for_click);
   popup_activated_flag = 1;  
2661    
2662    /* Process events that apply to the menu.  */    /* Free the widget_value objects we used to specify the contents.  */
2663    popup_get_selection ((XEvent *) 0, FRAME_X_DISPLAY_INFO (f), menu_id);    free_menubar_widget_value_tree (first_wv);
   
   /* fp turned off the following statement and wrote a comment  
      that it is unnecessary--that the menu has already disappeared.  
      Nowadays the menu disappears ok, all right, but  
      we need to delete the widgets or multiple ones will pile up.  */  
   lw_destroy_all_widgets (menu_id);  
2664    
2665    /* Find the selected item, and its pane, to return    /* Find the selected item, and its pane, to return
2666       the proper value.  */       the proper value.  */
# Line 2315  xmenu_show (f, x, y, for_click, keymaps, Line 2720  xmenu_show (f, x, y, for_click, keymaps,
2720    return Qnil;    return Qnil;
2721  }  }
2722    
2723    #ifdef USE_GTK
2724    static void
2725    dialog_selection_callback (widget, client_data)
2726         GtkWidget *widget;
2727         gpointer client_data;
2728    {
2729      /* The EMACS_INT cast avoids a warning.  There's no problem
2730         as long as pointers have enough bits to hold small integers.  */
2731      if ((int) (EMACS_INT) client_data != -1)
2732        menu_item_selection = (Lisp_Object *) client_data;
2733    
2734      popup_activated_flag = 0;
2735    }
2736    
2737    /* Pop up the dialog for frame F defined by FIRST_WV and loop until the
2738       dialog pops down.
2739       menu_item_selection will be set to the selection.  */
2740    static void
2741    create_and_show_dialog (f, first_wv)
2742         FRAME_PTR f;
2743         widget_value *first_wv;
2744    {
2745      GtkWidget *menu;
2746    
2747      menu = xg_create_widget ("dialog", first_wv->name, f, first_wv,
2748                               G_CALLBACK (dialog_selection_callback),
2749                               G_CALLBACK (popup_deactivate_callback),
2750                               0);
2751    
2752      if (menu)
2753        {
2754          /* Display the menu.  */
2755          gtk_widget_show_all (menu);
2756    
2757          /* Process events that apply to the menu.  */
2758          popup_widget_loop ();
2759    
2760          gtk_widget_destroy (menu);
2761        }
2762    }
2763    
2764    #else /* not USE_GTK */
2765  static void  static void
2766  dialog_selection_callback (widget, id, client_data)  dialog_selection_callback (widget, id, client_data)
2767       Widget widget;       Widget widget;
# Line 2325  dialog_selection_callback (widget, id, c Line 2772  dialog_selection_callback (widget, id, c
2772       as long as pointers have enough bits to hold small integers.  */       as long as pointers have enough bits to hold small integers.  */
2773    if ((int) (EMACS_INT) client_data != -1)    if ((int) (EMACS_INT) client_data != -1)
2774      menu_item_selection = (Lisp_Object *) client_data;      menu_item_selection = (Lisp_Object *) client_data;
2775    
2776    BLOCK_INPUT;    BLOCK_INPUT;
2777    lw_destroy_all_widgets (id);    lw_destroy_all_widgets (id);
2778    UNBLOCK_INPUT;    UNBLOCK_INPUT;
2779    popup_activated_flag = 0;    popup_activated_flag = 0;
2780  }  }
2781    
2782    
2783    /* ARG is the LWLIB ID of the dialog box, represented
2784       as a Lisp object as (HIGHPART . LOWPART).  */
2785    
2786    Lisp_Object
2787    xdialog_show_unwind (arg)
2788         Lisp_Object arg;
2789    {
2790      LWLIB_ID id = (XINT (XCAR (arg)) << 4 * sizeof (LWLIB_ID)
2791                     | XINT (XCDR (arg)));
2792      BLOCK_INPUT;
2793      lw_destroy_all_widgets (id);
2794      UNBLOCK_INPUT;
2795      popup_activated_flag = 0;
2796      return Qnil;
2797    }
2798    
2799    
2800    /* Pop up the dialog for frame F defined by FIRST_WV and loop until the
2801       dialog pops down.
2802       menu_item_selection will be set to the selection.  */
2803    static void
2804    create_and_show_dialog (f, first_wv)
2805         FRAME_PTR f;
2806         widget_value *first_wv;
2807    {
2808      LWLIB_ID dialog_id;
2809    
2810      dialog_id = widget_id_tick++;
2811      lw_create_widget (first_wv->name, "dialog", dialog_id, first_wv,
2812                        f->output_data.x->widget, 1, 0,
2813                        dialog_selection_callback, 0, 0);
2814      lw_modify_all_widgets (dialog_id, first_wv->contents, True);
2815    
2816      /* Display the dialog box.  */
2817      lw_pop_up_all_widgets (dialog_id);
2818      popup_activated_flag = 1;
2819    
2820      /* Process events that apply to the dialog box.
2821         Also handle timers.  */
2822      {
2823        int count = SPECPDL_INDEX ();
2824        int fact = 4 * sizeof (LWLIB_ID);
2825    
2826        /* xdialog_show_unwind is responsible for popping the dialog box down.  */
2827        record_unwind_protect (xdialog_show_unwind,
2828                               Fcons (make_number (dialog_id >> (fact)),
2829                                      make_number (dialog_id & ~(-1 << (fact)))));
2830    
2831        popup_get_selection ((XEvent *) 0, FRAME_X_DISPLAY_INFO (f), dialog_id, 1);
2832    
2833        unbind_to (count, Qnil);
2834      }
2835    }
2836    
2837    #endif /* not USE_GTK */
2838    
2839  static char * button_names [] = {  static char * button_names [] = {
2840    "button1", "button2", "button3", "button4", "button5",    "button1", "button2", "button3", "button4", "button5",
2841    "button6", "button7", "button8", "button9", "button10" };    "button6", "button7", "button8", "button9", "button10" };
# Line 2343  xdialog_show (f, keymaps, title, error) Line 2848  xdialog_show (f, keymaps, title, error)
2848       char **error;       char **error;
2849  {  {
2850    int i, nb_buttons=0;    int i, nb_buttons=0;
   LWLIB_ID dialog_id;  
   Widget menu;  
2851    char dialog_name[6];    char dialog_name[6];
2852    
2853    widget_value *wv, *first_wv = 0, *prev_wv = 0;    widget_value *wv, *first_wv = 0, *prev_wv = 0;
# Line 2370  xdialog_show (f, keymaps, title, error) Line 2873  xdialog_show (f, keymaps, title, error)
2873      pane_name = XVECTOR (menu_items)->contents[MENU_ITEMS_PANE_NAME];      pane_name = XVECTOR (menu_items)->contents[MENU_ITEMS_PANE_NAME];
2874      prefix = XVECTOR (menu_items)->contents[MENU_ITEMS_PANE_PREFIX];      prefix = XVECTOR (menu_items)->contents[MENU_ITEMS_PANE_PREFIX];
2875      pane_string = (NILP (pane_name)      pane_string = (NILP (pane_name)
2876                     ? "" : (char *) XSTRING (pane_name)->data);                       ? "" : (char *) SDATA (pane_name));
2877      prev_wv = xmalloc_widget_value ();      prev_wv = xmalloc_widget_value ();
2878      prev_wv->value = pane_string;      prev_wv->value = pane_string;
2879      if (keymaps && !NILP (prefix))      if (keymaps && !NILP (prefix))
# Line 2379  xdialog_show (f, keymaps, title, error) Line 2882  xdialog_show (f, keymaps, title, error)
2882      prev_wv->name = "message";      prev_wv->name = "message";
2883      prev_wv->help = Qnil;      prev_wv->help = Qnil;
2884      first_wv = prev_wv;      first_wv = prev_wv;
2885    
2886      /* Loop over all panes and items, filling in the tree.  */      /* Loop over all panes and items, filling in the tree.  */
2887      i = MENU_ITEMS_PANE_LENGTH;      i = MENU_ITEMS_PANE_LENGTH;
2888      while (i < menu_items_used)      while (i < menu_items_used)
2889        {        {
2890            
2891          /* Create a new item within current pane.  */          /* Create a new item within current pane.  */
2892          Lisp_Object item_name, enable, descrip;          Lisp_Object item_name, enable, descrip;
2893          item_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_NAME];          item_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_NAME];
2894          enable = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_ENABLE];          enable = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_ENABLE];
2895          descrip          descrip
2896            = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_EQUIV_KEY];            = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_EQUIV_KEY];
2897            
2898          if (NILP (item_name))          if (NILP (item_name))
2899            {            {
2900              free_menubar_widget_value_tree (first_wv);              free_menubar_widget_value_tree (first_wv);
# Line 2417  xdialog_show (f, keymaps, title, error) Line 2920  xdialog_show (f, keymaps, title, error)
2920          prev_wv->next = wv;          prev_wv->next = wv;
2921          wv->name = (char *) button_names[nb_buttons];          wv->name = (char *) button_names[nb_buttons];
2922          if (!NILP (descrip))          if (!NILP (descrip))
2923            wv->key = (char *) XSTRING (descrip)->data;            wv->key = (char *) SDATA (descrip);
2924          wv->value = (char *) XSTRING (item_name)->data;          wv->value = (char *) SDATA (item_name);
2925          wv->call_data = (void *) &XVECTOR (menu_items)->contents[i];          wv->call_data = (void *) &XVECTOR (menu_items)->contents[i];
2926          wv->enabled = !NILP (enable);          wv->enabled = !NILP (enable);
2927          wv->help = Qnil;          wv->help = Qnil;
# Line 2454  xdialog_show (f, keymaps, title, error) Line 2957  xdialog_show (f, keymaps, title, error)
2957      first_wv = wv;      first_wv = wv;
2958    }    }
2959    
   /* Actually create the dialog.  */  
   dialog_id = widget_id_tick++;  
   menu = lw_create_widget (first_wv->name, "dialog", dialog_id, first_wv,  
                            f->output_data.x->widget, 1, 0,  
                            dialog_selection_callback, 0, 0);  
   lw_modify_all_widgets (dialog_id, first_wv->contents, True);  
   /* Free the widget_value objects we used to specify the contents.  */  
   free_menubar_widget_value_tree (first_wv);  
   
2960    /* No selection has been chosen yet.  */    /* No selection has been chosen yet.  */
2961    menu_item_selection = 0;    menu_item_selection = 0;
2962    
2963    /* Display the menu.  */    /* Actually create and show the dialog.  */
2964    lw_pop_up_all_widgets (dialog_id);    create_and_show_dialog (f, first_wv);
   popup_activated_flag = 1;  
2965    
2966    /* Process events that apply to the menu.  */    /* Free the widget_value objects we used to specify the contents.  */
2967    popup_get_selection ((XEvent *) 0, FRAME_X_DISPLAY_INFO (f), dialog_id);    free_menubar_widget_value_tree (first_wv);
   
   lw_destroy_all_widgets (dialog_id);  
2968    
2969    /* Find the selected item, and its pane, to return    /* Find the selected item, and its pane, to return
2970       the proper value.  */       the proper value.  */
# Line 2521  xdialog_show (f, keymaps, title, error) Line 3012  xdialog_show (f, keymaps, title, error)
3012    return Qnil;    return Qnil;
3013  }  }
3014    
3015  #else /* not USE_X_TOOLKIT */  #else /* not USE_X_TOOLKIT && not USE_GTK */
3016    
3017  /* The frame of the last activated non-toolkit menu bar.  /* The frame of the last activated non-toolkit menu bar.
3018     Used to generate menu help events.  */     Used to generate menu help events.  */
# Line 2533  static struct frame *menu_help_frame; Line 3024  static struct frame *menu_help_frame;
3024    
3025     PANE is the pane number, and ITEM is the menu item number in     PANE is the pane number, and ITEM is the menu item number in
3026     the menu (currently not used).     the menu (currently not used).
3027      
3028     This cannot be done with generating a HELP_EVENT because     This cannot be done with generating a HELP_EVENT because
3029     XMenuActivate contains a loop that doesn't let Emacs process     XMenuActivate contains a loop that doesn't let Emacs process
3030     keyboard events.  */     keyboard events.  */
# Line 2547  menu_help_callback (help_string, pane, i Line 3038  menu_help_callback (help_string, pane, i
3038    Lisp_Object *first_item;    Lisp_Object *first_item;
3039    Lisp_Object pane_name;    Lisp_Object pane_name;
3040    Lisp_Object menu_object;    Lisp_Object menu_object;
3041    
3042    first_item = XVECTOR (menu_items)->contents;    first_item = XVECTOR (menu_items)->contents;
3043    if (EQ (first_item[0], Qt))    if (EQ (first_item[0], Qt))
3044      pane_name = first_item[MENU_ITEMS_PANE_NAME];      pane_name = first_item[MENU_ITEMS_PANE_NAME];
# Line 2556  menu_help_callback (help_string, pane, i Line 3047  menu_help_callback (help_string, pane, i
3047      pane_name = empty_string;      pane_name = empty_string;
3048    else    else
3049      pane_name = first_item[MENU_ITEMS_ITEM_NAME];      pane_name = first_item[MENU_ITEMS_ITEM_NAME];
3050    
3051    /* (menu-item MENU-NAME PANE-NUMBER)  */    /* (menu-item MENU-NAME PANE-NUMBER)  */
3052    menu_object = Fcons (Qmenu_item,    menu_object = Fcons (Qmenu_item,
3053                         Fcons (pane_name,                         Fcons (pane_name,
# Line 2564  menu_help_callback (help_string, pane, i Line 3055  menu_help_callback (help_string, pane, i
3055    show_help_echo (help_string ? build_string (help_string) : Qnil,    show_help_echo (help_string ? build_string (help_string) : Qnil,
3056                    Qnil, menu_object, make_number (item), 1);                    Qnil, menu_object, make_number (item), 1);
3057  }  }
3058      
3059    
3060  static Lisp_Object  static Lisp_Object
3061  xmenu_show (f, x, y, for_click, keymaps, title, error)  xmenu_show (f, x, y, for_click, keymaps, title, error)
# Line 2575  xmenu_show (f, x, y, for_click, keymaps, Line 3066  xmenu_show (f, x, y, for_click, keymaps,
3066       Lisp_Object title;       Lisp_Object title;
3067       char **error;       char **error;
3068  {  {
3069    Window root;              Window root;
3070    XMenu *menu;    XMenu *menu;
3071    int pane, selidx, lpane, status;    int pane, selidx, lpane, status;
3072    Lisp_Object entry, pane_prefix;    Lisp_Object entry, pane_prefix;
# Line 2642  xmenu_show (f, x, y, for_click, keymaps, Line 3133  xmenu_show (f, x, y, for_click, keymaps,
3133    /* Adjust coordinates to be root-window-relative.  */    /* Adjust coordinates to be root-window-relative.  */
3134    x += f->output_data.x->left_pos;    x += f->output_data.x->left_pos;
3135    y += f->output_data.x->top_pos;    y += f->output_data.x->top_pos;
3136    
3137    /* Create all the necessary panes and their items.  */    /* Create all the necessary panes and their items.  */
3138    i = 0;    i = 0;
3139    while (i < menu_items_used)    while (i < menu_items_used)
# Line 2656  xmenu_show (f, x, y, for_click, keymaps, Line 3147  xmenu_show (f, x, y, for_click, keymaps,
3147            pane_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_NAME];            pane_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_NAME];
3148            prefix = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_PREFIX];            prefix = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_PREFIX];
3149            pane_string = (NILP (pane_name)            pane_string = (NILP (pane_name)
3150                           ? "" : (char *) XSTRING (pane_name)->data);                           ? "" : (char *) SDATA (pane_name));
3151            if (keymaps && !NILP (prefix))            if (keymaps && !NILP (prefix))
3152              pane_string++;              pane_string++;
3153    
# Line 2683  xmenu_show (f, x, y, for_click, keymaps, Line 3174  xmenu_show (f, x, y, for_click, keymaps,
3174                    j++;                    j++;
3175                    continue;                    continue;
3176                  }                  }
3177                width = STRING_BYTES (XSTRING (item));                width = SBYTES (item);
3178                if (width > maxwidth)                if (width > maxwidth)
3179                  maxwidth = width;                  maxwidth = width;
3180    
# Line 2706  xmenu_show (f, x, y, for_click, keymaps, Line 3197  xmenu_show (f, x, y, for_click, keymaps,
3197            descrip            descrip
3198              = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_EQUIV_KEY];              = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_EQUIV_KEY];
3199            help = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_HELP];            help = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_HELP];
3200            help_string = STRINGP (help) ? XSTRING (help)->data : NULL;            help_string = STRINGP (help) ? SDATA (help) : NULL;
3201              
3202            if (!NILP (descrip))            if (!NILP (descrip))
3203              {              {
3204                int gap = maxwidth - STRING_BYTES (XSTRING (item_name));                int gap = maxwidth - SBYTES (item_name);
3205  #ifdef C_ALLOCA  #ifdef C_ALLOCA
3206                Lisp_Object spacer;                Lisp_Object spacer;
3207                spacer = Fmake_string (make_number (gap), make_number (' '));                spacer = Fmake_string (make_number (gap), make_number (' '));
3208                item_name = concat2 (item_name, spacer);                item_name = concat2 (item_name, spacer);
3209                item_name = concat2 (item_name, descrip);                item_name = concat2 (item_name, descrip);
3210                item_data = XSTRING (item_name)->data;                item_data = SDATA (item_name);
3211  #else  #else
3212                /* if alloca is fast, use that to make the space,                /* if alloca is fast, use that to make the space,
3213                   to reduce gc needs.  */                   to reduce gc needs.  */
3214                item_data                item_data
3215                  = (unsigned char *) alloca (maxwidth                  = (unsigned char *) alloca (maxwidth
3216                                              + STRING_BYTES (XSTRING (descrip)) + 1);                                              + SBYTES (descrip) + 1);
3217                bcopy (XSTRING (item_name)->data, item_data,                bcopy (SDATA (item_name), item_data,
3218                       STRING_BYTES (XSTRING (item_name)));                       SBYTES (item_name));
3219                for (j = XSTRING (item_name)->size; j < maxwidth; j++)                for (j = SCHARS (item_name); j < maxwidth; j++)
3220                  item_data[j] = ' ';                  item_data[j] = ' ';
3221                bcopy (XSTRING (descrip)->data, item_data + j,                bcopy (SDATA (descrip), item_data + j,
3222                       STRING_BYTES (XSTRING (descrip)));                       SBYTES (descrip));
3223                item_data[j + STRING_BYTES (XSTRING (descrip))] = 0;                item_data[j + SBYTES (descrip)] = 0;
3224  #endif  #endif
3225              }              }
3226            else            else
3227              item_data = XSTRING (item_name)->data;              item_data = SDATA (item_name);
3228    
3229            if (XMenuAddSelection (FRAME_X_DISPLAY (f),            if (XMenuAddSelection (FRAME_X_DISPLAY (f),
3230                                   menu, lpane, 0, item_data,                                   menu, lpane, 0, item_data,
# Line 2860  syms_of_xmenu () Line 3351  syms_of_xmenu ()
3351  {  {
3352    staticpro (&menu_items);    staticpro (&menu_items);
3353    menu_items = Qnil;    menu_items = Qnil;
3354      menu_items_inuse = Qnil;
3355    
3356    Qdebug_on_next_call = intern ("debug-on-next-call");    Qdebug_on_next_call = intern ("debug-on-next-call");
3357    staticpro (&Qdebug_on_next_call);    staticpro (&Qdebug_on_next_call);
# Line 2870  The enable predicate for a menu command Line 3362  The enable predicate for a menu command
3362    Vmenu_updating_frame = Qnil;    Vmenu_updating_frame = Qnil;
3363    
3364  #ifdef USE_X_TOOLKIT  #ifdef USE_X_TOOLKIT
3365    widget_id_tick = (1<<16);        widget_id_tick = (1<<16);
3366    next_menubar_widget_id = 1;    next_menubar_widget_id = 1;
3367  #endif  #endif
3368    

Legend:
Removed from v.1.230  
changed lines
  Added in v.1.230.4.1

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26