Fix infinite loop in menu input due to block_input.
authorEli Zaretskii <eliz@gnu.org>
Sat, 21 Sep 2013 14:53:04 +0000 (17:53 +0300)
committerEli Zaretskii <eliz@gnu.org>
Sat, 21 Sep 2013 14:53:04 +0000 (17:53 +0300)
src/keyboard.c
src/menu.c
src/nsmenu.m
src/term.c
src/w32fns.c
src/w32inevt.c
src/w32menu.c
src/xmenu.c

index 1150064..8318d4e 100644 (file)
@@ -1694,6 +1694,22 @@ command_loop_1 (void)
     }
 }
 
+Lisp_Object
+read_menu_command (void)
+{
+  Lisp_Object cmd;
+  Lisp_Object keybuf[30];
+  int i = read_key_sequence (keybuf, sizeof keybuf / sizeof keybuf[0],
+                            Qnil, 0, 1, 1);
+
+  if (! FRAME_LIVE_P (XFRAME (selected_frame)))
+    Fkill_emacs (Qnil);
+  if (i == 0 || i == -1)
+    return Qnil;
+
+  return read_key_sequence_cmd;
+}
+
 /* Adjust point to a boundary of a region that has such a property
    that should be treated intangible.  For the moment, we check
    `composition', `display' and `invisible' properties.
index cf6ceb5..bbd0e70 100644 (file)
@@ -1328,7 +1328,6 @@ no quit occurs and `x-popup-menu' returns nil.  */)
 #endif
 
   /* Display them in a menu.  */
-  block_input ();
 
   /* FIXME: Use a terminal hook!  */
 #if defined HAVE_NTGUI
@@ -1358,8 +1357,6 @@ no quit occurs and `x-popup-menu' returns nil.  */)
     selection = tty_menu_show (f, xpos, ypos, for_click,
                               keymaps, title, &error_name);
 
-  unblock_input ();
-
 #ifdef HAVE_NS
   unbind_to (specpdl_count, Qnil);
 #else
index f9cd511..697329d 100644 (file)
@@ -833,6 +833,8 @@ ns_menu_show (struct frame *f, int x, int y, bool for_click, bool keymaps,
   ptrdiff_t specpdl_count = SPECPDL_INDEX ();
   widget_value *wv, *first_wv = 0;
 
+  block_input ();
+
   p.x = x; p.y = y;
 
   /* now parse stage 2 as in ns_update_menubar */
@@ -1035,6 +1037,7 @@ ns_menu_show (struct frame *f, int x, int y, bool for_click, bool keymaps,
   popup_activated_flag = 0;
   [[FRAME_NS_VIEW (SELECTED_FRAME ()) window] makeKeyWindow];
 
+  unblock_input ();
   return tem;
 }
 
index 553cc1b..a600a3b 100644 (file)
@@ -2815,6 +2815,9 @@ static int menu_help_paneno, menu_help_itemno;
 
 static int menu_x, menu_y;
 
+static Lisp_Object Qright_char, Qleft_char, Qforward_char, Qbackward_char;
+static Lisp_Object Qnext_line, Qprevious_line, Qnewline;
+
 typedef struct tty_menu_struct
 {
   int count;
@@ -3171,51 +3174,31 @@ read_menu_input (struct frame *sf, int *x, int *y, bool *first_time)
 
   while (1)
     {
-#if 0
-      do {
-       c = read_char (-2, Qnil, Qnil, NULL, NULL);
-      } while (BUFFERP (c) || (INTEGERP (c) && XINT (c) == -2));
-
-      if (INTEGERP (c))
+#if 1
+      extern Lisp_Object read_menu_command (void);
+      Lisp_Object cmd = read_menu_command ();
+      int usable_input = 1;
+      int st = 0;
+
+      if (NILP (cmd))
+       return -1;
+      if (EQ (cmd, Qright_char) || EQ (cmd, Qforward_char))
+       *x += 1;
+      else if (EQ (cmd, Qleft_char) || EQ (cmd, Qbackward_char))
+       *x -= 1;
+      else if (EQ (cmd, Qnext_line))
+       *y += 1;
+      else if (EQ (cmd, Qprevious_line))
+       *y -= 1;
+      else if (EQ (cmd, Qnewline))
+       st = 1;
+      else
        {
-         int ch = XINT (c);
-         int usable_input = 1;
-
-         /* FIXME: Exceedingly primitive!  Can we support arrow keys?  */
-         switch (ch && ~CHAR_MODIFIER_MASK)
-           {
-           case 7:     /* ^G */
-             return -1;
-           case 6:     /* ^F */
-             *x += 1;
-             break;
-           case 2:     /* ^B */
-             *x -= 1;
-             break;
-           case 14:    /* ^N */
-             *y += 1;
-             break;
-           case 16:    /* ^P */
-             *y -= 1;
-             break;
-           default:
-             usable_input = 0;
-             break;
-           }
-         if (usable_input)
-           sf->mouse_moved = 1;
-         break;
-       }
-
-      else if (EVENT_HAS_PARAMETERS (c))
-       {
-         if (EQ (EVENT_HEAD (c), Qmouse_movement))
-           {
-           }
-         else if (EQ (EVENT_HEAD_KIND (EVENT_HEAD (c)), Qmouse_click))
-           {
-           }
+         usable_input = 0;
+         st = -1;
        }
+      if (usable_input)
+       sf->mouse_moved = 1;
 #else
       int volatile dx = 0;
       int volatile dy = 0;
@@ -3225,11 +3208,11 @@ read_menu_input (struct frame *sf, int *x, int *y, bool *first_time)
       *y += dy;
       if (dx != 0 || dy != 0)
        sf->mouse_moved = 1;
+      Sleep (300);
+#endif
       menu_x = *x;
       menu_y = *y;
-      Sleep (300);
       return st;
-#endif
     }
   return 0;
 }
@@ -3371,10 +3354,16 @@ tty_menu_activate (tty_menu *menu, int *pane, int *selidx,
   while (!leave)
     {
       int mouse_button_count = 3; /* FIXME */
+      int input_status;
 
       if (!mouse_visible) mouse_on ();
-      if (read_menu_input (sf, &x, &y, &first_time) == -1)
-       leave = 1;
+      input_status = read_menu_input (sf, &x, &y, &first_time);
+      if (input_status)
+       {
+         if (input_status == -1)
+           result = TTYM_NO_SELECT;
+         leave = 1;
+       }
       else if (sf->mouse_moved)
        {
          sf->mouse_moved = 0;
@@ -4607,4 +4596,12 @@ bigger, or it may make it blink, or it may do nothing at all.  */);
 
   encode_terminal_src = NULL;
   encode_terminal_dst = NULL;
+
+  DEFSYM (Qright_char, "right-char");
+  DEFSYM (Qleft_char, "left-char");
+  DEFSYM (Qforward_char, "forward-char");
+  DEFSYM (Qbackward_char, "backward-char");
+  DEFSYM (Qprevious_line, "previous-line");
+  DEFSYM (Qnext_line, "next-line");
+  DEFSYM (Qnewline, "newline");
 }
index b8c445a..8ec9112 100644 (file)
@@ -5486,7 +5486,10 @@ show_hourglass (struct atimer *timer)
     f = SELECTED_FRAME ();
 
   if (!FRAME_W32_P (f))
-    return;
+    {
+      unblock_input ();
+      return;
+    }
 
   w32_show_hourglass (f);
   unblock_input ();
index ce36f29..3c41bec 100644 (file)
@@ -712,12 +712,17 @@ w32_console_read_socket (struct terminal *terminal,
       while (nev > 0)
         {
          struct input_event inev;
+         /* Having a separate variable with this value makes
+            debugging easier, as otherwise the compiler might
+            rearrange the switch below in a way that makes it hard to
+            track the event type.  */
+         unsigned evtype = queue_ptr->EventType;
 
          EVENT_INIT (inev);
          inev.kind = NO_EVENT;
          inev.arg = Qnil;
 
-         switch (queue_ptr->EventType)
+         switch (evtype)
             {
             case KEY_EVENT:
              add = key_event (&queue_ptr->Event.KeyEvent, &inev, &isdead);
index 34020fa..f804e83 100644 (file)
@@ -682,6 +682,8 @@ w32_menu_show (struct frame *f, int x, int y, int for_click, int keymaps,
       return Qnil;
     }
 
+  block_input ();
+
   /* Create a tree of widget_value objects
      representing the panes and their items.  */
   wv = xmalloc_widget_value ();
@@ -940,6 +942,7 @@ w32_menu_show (struct frame *f, int x, int y, int for_click, int keymaps,
                        if (!NILP (subprefix_stack[j]))
                          entry = Fcons (subprefix_stack[j], entry);
                    }
+                 unblock_input ();
                  return entry;
                }
              i += MENU_ITEMS_ITEM_LENGTH;
@@ -947,9 +950,13 @@ w32_menu_show (struct frame *f, int x, int y, int for_click, int keymaps,
        }
     }
   else if (!for_click)
-    /* Make "Cancel" equivalent to C-g.  */
-    Fsignal (Qquit, Qnil);
+    {
+      unblock_input ();
+      /* Make "Cancel" equivalent to C-g.  */
+      Fsignal (Qquit, Qnil);
+    }
 
+  unblock_input ();
   return Qnil;
 }
 \f
index 823c63b..5d1f44e 100644 (file)
@@ -1618,6 +1618,8 @@ xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps,
       return Qnil;
     }
 
+  block_input ();
+
   /* Create a tree of widget_value objects
      representing the panes and their items.  */
   wv = xmalloc_widget_value ();
@@ -1857,6 +1859,7 @@ xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps,
                        if (!NILP (subprefix_stack[j]))
                          entry = Fcons (subprefix_stack[j], entry);
                    }
+                 unblock_input ();
                  return entry;
                }
              i += MENU_ITEMS_ITEM_LENGTH;
@@ -1864,9 +1867,13 @@ xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps,
        }
     }
   else if (!for_click)
-    /* Make "Cancel" equivalent to C-g.  */
-    Fsignal (Qquit, Qnil);
+    {
+      unblock_input ();
+      /* Make "Cancel" equivalent to C-g.  */
+      Fsignal (Qquit, Qnil);
+    }
 
+  unblock_input ();
   return Qnil;
 }
 \f
@@ -2261,6 +2268,8 @@ xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps,
       return Qnil;
     }
 
+  block_input ();
+
   /* Figure out which root window F is on.  */
   XGetGeometry (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &root,
                &dummy_int, &dummy_int, &dummy_uint, &dummy_uint,
@@ -2271,6 +2280,7 @@ xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps,
   if (menu == NULL)
     {
       *error_name = "Can't create menu";
+      unblock_input ();
       return Qnil;
     }
 
@@ -2314,6 +2324,7 @@ xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps,
            {
              XMenuDestroy (FRAME_X_DISPLAY (f), menu);
              *error_name = "Can't create pane";
+             unblock_input ();
              return Qnil;
            }
          i += MENU_ITEMS_PANE_LENGTH;
@@ -2378,6 +2389,7 @@ xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps,
            {
              XMenuDestroy (FRAME_X_DISPLAY (f), menu);
              *error_name = "Can't add selection to menu";
+             unblock_input ();
              return Qnil;
            }
          i += MENU_ITEMS_ITEM_LENGTH;
@@ -2504,10 +2516,14 @@ xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps,
       /* Make "Cancel" equivalent to C-g unless FOR_CLICK (which means
         the menu was invoked with a mouse event as POSITION).  */
       if (! for_click)
-        Fsignal (Qquit, Qnil);
+       {
+         unblock_input ();
+         Fsignal (Qquit, Qnil);
+       }
       break;
     }
 
+  unblock_input ();
   unbind_to (specpdl_count, Qnil);
 
   return entry;