/[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.4.9 by miles, Fri Nov 12 04:21:15 2004 UTC revision 1.230.4.10 by miles, Wed Dec 8 23:31:37 2004 UTC
# Line 48  Boston, MA 02111-1307, USA.  */ Line 48  Boston, MA 02111-1307, USA.  */
48  #include "buffer.h"  #include "buffer.h"
49  #include "charset.h"  #include "charset.h"
50  #include "coding.h"  #include "coding.h"
51    #include "sysselect.h"
52    
53  #ifdef MSDOS  #ifdef MSDOS
54  #include "msdos.h"  #include "msdos.h"
# Line 157  static void single_keymap_panes P_ ((Lis Line 158  static void single_keymap_panes P_ ((Lis
158  static void list_of_panes P_ ((Lisp_Object));  static void list_of_panes P_ ((Lisp_Object));
159  static void list_of_items P_ ((Lisp_Object));  static void list_of_items P_ ((Lisp_Object));
160    
 extern EMACS_TIME timer_check P_ ((int));  
   
161    
162  /* This holds a Lisp vector that holds the results of decoding  /* This holds a Lisp vector that holds the results of decoding
163     the keymaps or alist-of-alists that specify a menu.     the keymaps or alist-of-alists that specify a menu.
# Line 289  finish_menu_items () Line 288  finish_menu_items ()
288    
289  static Lisp_Object  static Lisp_Object
290  unuse_menu_items (dummy)  unuse_menu_items (dummy)
291       int dummy;       Lisp_Object dummy;
292  {  {
293    return menu_items_inuse = Qnil;    return menu_items_inuse = Qnil;
294  }  }
# Line 525  single_menu_item (key, item, dummy, skp_ Line 524  single_menu_item (key, item, dummy, skp_
524      return;                     /* Not a menu item.  */      return;                     /* Not a menu item.  */
525    
526    map = XVECTOR (item_properties)->contents[ITEM_PROPERTY_MAP];    map = XVECTOR (item_properties)->contents[ITEM_PROPERTY_MAP];
527      
528    if (skp->notreal)    if (skp->notreal)
529      {      {
530        /* 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 1099  on the left of the dialog box and all fo Line 1098  on the left of the dialog box and all fo
1098           the dialog.  Also, the lesstif/motif version crashes if there are           the dialog.  Also, the lesstif/motif version crashes if there are
1099           no buttons.  */           no buttons.  */
1100        contents = Fcons (title, Fcons (Fcons (build_string ("Ok"), Qt), Qnil));        contents = Fcons (title, Fcons (Fcons (build_string ("Ok"), Qt), Qnil));
1101        
1102      list_of_panes (Fcons (contents, Qnil));      list_of_panes (Fcons (contents, Qnil));
1103    
1104      /* Display them in a dialog box.  */      /* Display them in a dialog box.  */
# Line 1115  on the left of the dialog box and all fo Line 1114  on the left of the dialog box and all fo
1114    }    }
1115  #endif  #endif
1116  }  }
1117    
1118    
1119    #ifndef MSDOS
1120    
1121    /* Set menu_items_inuse so no other popup menu or dialog is created.  */
1122    
1123    void
1124    x_menu_set_in_use (in_use)
1125         int in_use;
1126    {
1127      menu_items_inuse = in_use ? Qt : Qnil;
1128      popup_activated_flag = in_use;
1129    }
1130    
1131    /* Wait for an X event to arrive or for a timer to expire.  */
1132    
1133    void
1134    x_menu_wait_for_event (void *data)
1135    {
1136      extern EMACS_TIME timer_check P_ ((int));
1137    
1138      /* Another way to do this is to register a timer callback, that can be
1139         done in GTK and Xt.  But we have to do it like this when using only X
1140         anyway, and with callbacks we would have three variants for timer handling
1141         instead of the small ifdefs below.  */
1142    
1143      while (
1144    #ifdef USE_X_TOOLKIT
1145             ! XtAppPending (Xt_app_con)
1146    #elif defined USE_GTK
1147             ! gtk_events_pending ()
1148    #else
1149             ! XPending ((Display*) data)
1150    #endif
1151             )
1152        {
1153          EMACS_TIME next_time = timer_check (1);
1154          long secs = EMACS_SECS (next_time);
1155          long usecs = EMACS_USECS (next_time);
1156          SELECT_TYPE read_fds;
1157          struct x_display_info *dpyinfo;
1158          int n = 0;
1159    
1160          FD_ZERO (&read_fds);
1161          for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
1162            {
1163              int fd = ConnectionNumber (dpyinfo->display);
1164              FD_SET (fd, &read_fds);
1165              if (fd > n) n = fd;
1166            }
1167    
1168          if (secs < 0 || (secs == 0 && usecs == 0))
1169            {
1170              /* Sometimes timer_check returns -1 (no timers) even if there are
1171                 timers.  So do a timeout anyway.  */
1172              EMACS_SET_SECS (next_time, 1);
1173              EMACS_SET_USECS (next_time, 0);
1174            }
1175    
1176          select (n + 1, &read_fds, (SELECT_TYPE *)0, (SELECT_TYPE *)0, &next_time);
1177        }
1178    }
1179    #endif /* ! MSDOS */
1180    
1181    
1182  #if defined (USE_X_TOOLKIT) || defined (USE_GTK)  #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
1183    
1184    #ifdef USE_X_TOOLKIT
1185    
1186  /* Loop in Xt until the menu pulldown or dialog popup has been  /* Loop in Xt until the menu pulldown or dialog popup has been
1187     popped down (deactivated).  This is used for x-popup-menu     popped down (deactivated).  This is used for x-popup-menu
1188     and x-popup-dialog; it is not used for the menu bar.     and x-popup-dialog; it is not used for the menu bar.
# Line 1127  on the left of the dialog box and all fo Line 1192  on the left of the dialog box and all fo
1192     NOTE: All calls to popup_get_selection should be protected     NOTE: All calls to popup_get_selection should be protected
1193     with BLOCK_INPUT, UNBLOCK_INPUT wrappers.  */     with BLOCK_INPUT, UNBLOCK_INPUT wrappers.  */
1194    
 #ifdef USE_X_TOOLKIT  
1195  static void  static void
1196  popup_get_selection (initial_event, dpyinfo, id, do_timers, down_on_keypress)  popup_get_selection (initial_event, dpyinfo, id, do_timers, down_on_keypress)
1197       XEvent *initial_event;       XEvent *initial_event;
# Line 1140  popup_get_selection (initial_event, dpyi Line 1204  popup_get_selection (initial_event, dpyi
1204    
1205    while (popup_activated_flag)    while (popup_activated_flag)
1206      {      {
        /* If we have no events to run, consider timers.  */        
        if (do_timers && !XtAppPending (Xt_app_con))        
          timer_check (1);          
   
1207         if (initial_event)         if (initial_event)
1208          {          {
1209            event = *initial_event;            event = *initial_event;
1210            initial_event = 0;            initial_event = 0;
1211          }          }
1212        else        else
1213          XtAppNextEvent (Xt_app_con, &event);          {
1214              if (do_timers) x_menu_wait_for_event (0);
1215              XtAppNextEvent (Xt_app_con, &event);
1216            }
1217    
1218        /* Make sure we don't consider buttons grabbed after menu goes.        /* Make sure we don't consider buttons grabbed after menu goes.
1219           And make sure to deactivate for any ButtonRelease,           And make sure to deactivate for any ButtonRelease,
# Line 1195  popup_get_selection (initial_event, dpyi Line 1258  popup_get_selection (initial_event, dpyi
1258  #ifdef USE_GTK  #ifdef USE_GTK
1259  /* Loop util popup_activated_flag is set to zero in a callback.  /* Loop util popup_activated_flag is set to zero in a callback.
1260     Used for popup menus and dialogs. */     Used for popup menus and dialogs. */
1261    
1262  static void  static void
1263  popup_widget_loop ()  popup_widget_loop (do_timers, widget)
1264         int do_timers;
1265         GtkWidget *widget;
1266  {  {
1267    ++popup_activated_flag;    ++popup_activated_flag;
1268    
1269    /* Process events in the Gtk event loop until done.  */    /* Process events in the Gtk event loop until done.  */
1270    while (popup_activated_flag)    while (popup_activated_flag)
1271      {      {
1272          if (do_timers) x_menu_wait_for_event (0);
1273        gtk_main_iteration ();        gtk_main_iteration ();
1274      }      }
1275  }  }
# Line 2329  menu_position_func (menu, x, y, push_in, Line 2396  menu_position_func (menu, x, y, push_in,
2396    GtkRequisition req;    GtkRequisition req;
2397    int disp_width = FRAME_X_DISPLAY_INFO (data->f)->width;    int disp_width = FRAME_X_DISPLAY_INFO (data->f)->width;
2398    int disp_height = FRAME_X_DISPLAY_INFO (data->f)->height;    int disp_height = FRAME_X_DISPLAY_INFO (data->f)->height;
2399      
2400    *x = data->x;    *x = data->x;
2401    *y = data->y;    *y = data->y;
2402    
# Line 2353  popup_selection_callback (widget, client Line 2420  popup_selection_callback (widget, client
2420    if (cb_data) menu_item_selection = (Lisp_Object *) cb_data->call_data;    if (cb_data) menu_item_selection = (Lisp_Object *) cb_data->call_data;
2421  }  }
2422    
2423    static Lisp_Object
2424    pop_down_menu (arg)
2425         Lisp_Object arg;
2426    {
2427      struct Lisp_Save_Value *p = XSAVE_VALUE (arg);
2428    
2429      popup_activated_flag = 0;
2430      BLOCK_INPUT;
2431      gtk_widget_destroy (GTK_WIDGET (p->pointer));
2432      UNBLOCK_INPUT;
2433      return Qnil;
2434    }
2435    
2436  /* Pop up the menu for frame F defined by FIRST_WV at X/Y and loop until the  /* Pop up the menu for frame F defined by FIRST_WV at X/Y and loop until the
2437     menu pops down.     menu pops down.
2438     menu_item_selection will be set to the selection.  */     menu_item_selection will be set to the selection.  */
# Line 2368  create_and_show_popup_menu (f, first_wv, Line 2448  create_and_show_popup_menu (f, first_wv,
2448    GtkWidget *menu;    GtkWidget *menu;
2449    GtkMenuPositionFunc pos_func = 0;  /* Pop up at pointer.  */    GtkMenuPositionFunc pos_func = 0;  /* Pop up at pointer.  */
2450    struct next_popup_x_y popup_x_y;    struct next_popup_x_y popup_x_y;
2451      int specpdl_count = SPECPDL_INDEX ();
2452    
2453    xg_crazy_callback_abort = 1;    xg_crazy_callback_abort = 1;
2454    menu = xg_create_widget ("popup", first_wv->name, f, first_wv,    menu = xg_create_widget ("popup", first_wv->name, f, first_wv,
# Line 2398  create_and_show_popup_menu (f, first_wv, Line 2479  create_and_show_popup_menu (f, first_wv,
2479    gtk_widget_show_all (menu);    gtk_widget_show_all (menu);
2480    gtk_menu_popup (GTK_MENU (menu), 0, 0, pos_func, &popup_x_y, i, 0);    gtk_menu_popup (GTK_MENU (menu), 0, 0, pos_func, &popup_x_y, i, 0);
2481    
2482      record_unwind_protect (pop_down_menu, make_save_value (menu, 0));
2483    
2484    /* Set this to one.  popup_widget_loop increases it by one, so it becomes    /* Set this to one.  popup_widget_loop increases it by one, so it becomes
2485       two.  show_help_echo uses this to detect popup menus.  */       two.  show_help_echo uses this to detect popup menus.  */
2486    popup_activated_flag = 1;    popup_activated_flag = 1;
2487    /* Process events that apply to the menu.  */    /* Process events that apply to the menu.  */
2488    popup_widget_loop ();    popup_widget_loop (1, menu);
2489    
2490    gtk_widget_destroy (menu);    unbind_to (specpdl_count, Qnil);
2491    
2492    /* Must reset this manually because the button release event is not passed    /* Must reset this manually because the button release event is not passed
2493       to Emacs event loop. */       to Emacs event loop. */
# Line 2432  popup_selection_callback (widget, id, cl Line 2515  popup_selection_callback (widget, id, cl
2515    menu_item_selection = (Lisp_Object *) client_data;    menu_item_selection = (Lisp_Object *) client_data;
2516  }  }
2517    
2518    /* ARG is the LWLIB ID of the dialog box, represented
2519       as a Lisp object as (HIGHPART . LOWPART).  */
2520    
2521    static Lisp_Object
2522    pop_down_menu (arg)
2523         Lisp_Object arg;
2524    {
2525      LWLIB_ID id = (XINT (XCAR (arg)) << 4 * sizeof (LWLIB_ID)
2526                     | XINT (XCDR (arg)));
2527    
2528      BLOCK_INPUT;
2529      lw_destroy_all_widgets (id);
2530      UNBLOCK_INPUT;
2531      popup_activated_flag = 0;
2532    
2533      return Qnil;
2534    }
2535    
2536  /* Pop up the menu for frame F defined by FIRST_WV at X/Y and loop until the  /* Pop up the menu for frame F defined by FIRST_WV at X/Y and loop until the
2537     menu pops down.     menu pops down.
2538     menu_item_selection will be set to the selection.  */     menu_item_selection will be set to the selection.  */
# Line 2488  create_and_show_popup_menu (f, first_wv, Line 2589  create_and_show_popup_menu (f, first_wv,
2589    /* Display the menu.  */    /* Display the menu.  */
2590    lw_popup_menu (menu, (XEvent *) &dummy);    lw_popup_menu (menu, (XEvent *) &dummy);
2591    popup_activated_flag = 1;    popup_activated_flag = 1;
2592      
2593      {
2594        int fact = 4 * sizeof (LWLIB_ID);
2595        int specpdl_count = SPECPDL_INDEX ();
2596        record_unwind_protect (pop_down_menu,
2597                               Fcons (make_number (menu_id >> (fact)),
2598                                      make_number (menu_id & ~(-1 << (fact)))));
2599    
2600    /* Process events that apply to the menu.  */      /* Process events that apply to the menu.  */
2601    popup_get_selection ((XEvent *) 0, FRAME_X_DISPLAY_INFO (f), menu_id, 0, 0);      popup_get_selection ((XEvent *) 0, FRAME_X_DISPLAY_INFO (f), menu_id, 1, 0);
2602    
2603    /* fp turned off the following statement and wrote a comment      unbind_to (specpdl_count, Qnil);
2604       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);  
2605  }  }
2606    
2607  #endif /* not USE_GTK */  #endif /* not USE_GTK */
# Line 2807  create_and_show_dialog (f, first_wv) Line 2912  create_and_show_dialog (f, first_wv)
2912    
2913    if (menu)    if (menu)
2914      {      {
2915          int specpdl_count = SPECPDL_INDEX ();
2916          record_unwind_protect (pop_down_menu, make_save_value (menu, 0));
2917    
2918        /* Display the menu.  */        /* Display the menu.  */
2919        gtk_widget_show_all (menu);        gtk_widget_show_all (menu);
2920    
2921        /* Process events that apply to the menu.  */        /* Process events that apply to the menu.  */
2922        popup_widget_loop ();        popup_widget_loop (1, menu);
2923    
2924        gtk_widget_destroy (menu);        unbind_to (specpdl_count, Qnil);
2925      }      }
2926  }  }
2927    
# Line 2836  dialog_selection_callback (widget, id, c Line 2944  dialog_selection_callback (widget, id, c
2944  }  }
2945    
2946    
 /* ARG is the LWLIB ID of the dialog box, represented  
    as a Lisp object as (HIGHPART . LOWPART).  */  
   
 Lisp_Object  
 xdialog_show_unwind (arg)  
      Lisp_Object arg;  
 {  
   LWLIB_ID id = (XINT (XCAR (arg)) << 4 * sizeof (LWLIB_ID)  
                  | XINT (XCDR (arg)));  
   BLOCK_INPUT;  
   lw_destroy_all_widgets (id);  
   UNBLOCK_INPUT;  
   popup_activated_flag = 0;  
   return Qnil;  
 }  
   
   
2947  /* Pop up the dialog for frame F defined by FIRST_WV and loop until the  /* Pop up the dialog for frame F defined by FIRST_WV and loop until the
2948     dialog pops down.     dialog pops down.
2949     menu_item_selection will be set to the selection.  */     menu_item_selection will be set to the selection.  */
# Line 2880  create_and_show_dialog (f, first_wv) Line 2971  create_and_show_dialog (f, first_wv)
2971      int fact = 4 * sizeof (LWLIB_ID);      int fact = 4 * sizeof (LWLIB_ID);
2972    
2973      /* xdialog_show_unwind is responsible for popping the dialog box down.  */      /* xdialog_show_unwind is responsible for popping the dialog box down.  */
2974      record_unwind_protect (xdialog_show_unwind,      record_unwind_protect (pop_down_menu,
2975                             Fcons (make_number (dialog_id >> (fact)),                             Fcons (make_number (dialog_id >> (fact)),
2976                                    make_number (dialog_id & ~(-1 << (fact)))));                                    make_number (dialog_id & ~(-1 << (fact)))));
2977    
# Line 3113  menu_help_callback (help_string, pane, i Line 3204  menu_help_callback (help_string, pane, i
3204                    Qnil, menu_object, make_number (item), 1);                    Qnil, menu_object, make_number (item), 1);
3205  }  }
3206    
3207    static Lisp_Object
3208    pop_down_menu (arg)
3209         Lisp_Object arg;
3210    {
3211      struct Lisp_Save_Value *p1 = XSAVE_VALUE (Fcar (arg));
3212      struct Lisp_Save_Value *p2 = XSAVE_VALUE (Fcdr (arg));
3213      
3214      FRAME_PTR f = p1->pointer;
3215      XMenu *menu = p2->pointer;
3216    
3217      BLOCK_INPUT;
3218    #ifndef MSDOS
3219      XUngrabPointer (FRAME_X_DISPLAY (f), CurrentTime);
3220      XUngrabKeyboard (FRAME_X_DISPLAY (f), CurrentTime);
3221    #endif
3222      XMenuDestroy (FRAME_X_DISPLAY (f), menu);
3223    
3224    #ifdef HAVE_X_WINDOWS
3225      /* Assume the mouse has moved out of the X window.
3226         If it has actually moved in, we will get an EnterNotify.  */
3227      x_mouse_leave (FRAME_X_DISPLAY_INFO (f));
3228    
3229      /* State that no mouse buttons are now held.
3230         (The oldXMenu code doesn't track this info for us.)
3231         That is not necessarily true, but the fiction leads to reasonable
3232         results, and it is a pain to ask which are actually held now.  */
3233      FRAME_X_DISPLAY_INFO (f)->grabbed = 0;
3234    
3235    #endif /* HAVE_X_WINDOWS */
3236    
3237      UNBLOCK_INPUT;
3238    
3239      return Qnil;
3240    }
3241    
3242    
3243  static Lisp_Object  static Lisp_Object
3244  xmenu_show (f, x, y, for_click, keymaps, title, error)  xmenu_show (f, x, y, for_click, keymaps, title, error)
# Line 3134  xmenu_show (f, x, y, for_click, keymaps, Line 3260  xmenu_show (f, x, y, for_click, keymaps,
3260    int maxwidth;    int maxwidth;
3261    int dummy_int;    int dummy_int;
3262    unsigned int dummy_uint;    unsigned int dummy_uint;
3263      int specpdl_count = SPECPDL_INDEX ();
3264    
3265    *error = 0;    *error = 0;
3266    if (menu_items_n_panes == 0)    if (menu_items_n_panes == 0)
# Line 3323  xmenu_show (f, x, y, for_click, keymaps, Line 3450  xmenu_show (f, x, y, for_click, keymaps,
3450    XMenuSetFreeze (menu, TRUE);    XMenuSetFreeze (menu, TRUE);
3451    pane = selidx = 0;    pane = selidx = 0;
3452    
3453    #ifndef MSDOS
3454      XMenuActivateSetWaitFunction (x_menu_wait_for_event, FRAME_X_DISPLAY (f));
3455    #endif
3456      
3457      record_unwind_protect (pop_down_menu,
3458                             Fcons (make_save_value (f, 0),
3459                                    make_save_value (menu, 0)));
3460    
3461    /* Help display under X won't work because XMenuActivate contains    /* Help display under X won't work because XMenuActivate contains
3462       a loop that doesn't give Emacs a chance to process it.  */       a loop that doesn't give Emacs a chance to process it.  */
3463    menu_help_frame = f;    menu_help_frame = f;
3464    status = XMenuActivate (FRAME_X_DISPLAY (f), menu, &pane, &selidx,    status = XMenuActivate (FRAME_X_DISPLAY (f), menu, &pane, &selidx,
3465                            x, y, ButtonReleaseMask, &datap,                            x, y, ButtonReleaseMask, &datap,
3466                            menu_help_callback);                            menu_help_callback);
   
   
 #ifdef HAVE_X_WINDOWS  
   /* Assume the mouse has moved out of the X window.  
      If it has actually moved in, we will get an EnterNotify.  */  
   x_mouse_leave (FRAME_X_DISPLAY_INFO (f));  
 #endif  
3467    
3468    switch (status)    switch (status)
3469      {      {
# Line 3386  xmenu_show (f, x, y, for_click, keymaps, Line 3514  xmenu_show (f, x, y, for_click, keymaps,
3514        entry = Qnil;        entry = Qnil;
3515        break;        break;
3516      }      }
   XMenuDestroy (FRAME_X_DISPLAY (f), menu);  
3517    
3518  #ifdef HAVE_X_WINDOWS    unbind_to (specpdl_count, Qnil);
   /* State that no mouse buttons are now held.  
      (The oldXMenu code doesn't track this info for us.)  
      That is not necessarily true, but the fiction leads to reasonable  
      results, and it is a pain to ask which are actually held now.  */  
   FRAME_X_DISPLAY_INFO (f)->grabbed = 0;  
 #endif  
3519    
3520    return entry;    return entry;
3521  }  }

Legend:
Removed from v.1.230.4.9  
changed lines
  Added in v.1.230.4.10

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