diff options
author | Eli Zaretskii <eliz@gnu.org> | 2013-09-21 17:53:04 +0300 |
---|---|---|
committer | Eli Zaretskii <eliz@gnu.org> | 2013-09-21 17:53:04 +0300 |
commit | f0177f86f745ef86357214b110f9d98e4ed63b7a (patch) | |
tree | 85f8cbb3a930a39ea84bb02637279b7a783d37eb /src | |
parent | e11a3bd1d1848d0a3a2ac21a48360eb628127ed9 (diff) | |
download | emacs-f0177f86f745ef86357214b110f9d98e4ed63b7a.tar.gz |
Fix infinite loop in menu input due to block_input.
Diffstat (limited to 'src')
-rw-r--r-- | src/keyboard.c | 16 | ||||
-rw-r--r-- | src/menu.c | 3 | ||||
-rw-r--r-- | src/nsmenu.m | 3 | ||||
-rw-r--r-- | src/term.c | 91 | ||||
-rw-r--r-- | src/w32fns.c | 5 | ||||
-rw-r--r-- | src/w32inevt.c | 7 | ||||
-rw-r--r-- | src/w32menu.c | 11 | ||||
-rw-r--r-- | src/xmenu.c | 22 |
8 files changed, 101 insertions, 57 deletions
diff --git a/src/keyboard.c b/src/keyboard.c index 1150064a10f..8318d4eb3b1 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -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. diff --git a/src/menu.c b/src/menu.c index cf6ceb58e7f..bbd0e70fe04 100644 --- a/src/menu.c +++ b/src/menu.c @@ -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 diff --git a/src/nsmenu.m b/src/nsmenu.m index f9cd511efe9..697329df675 100644 --- a/src/nsmenu.m +++ b/src/nsmenu.m @@ -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; } diff --git a/src/term.c b/src/term.c index 553cc1b6084..a600a3b33b4 100644 --- a/src/term.c +++ b/src/term.c @@ -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"); } diff --git a/src/w32fns.c b/src/w32fns.c index b8c445a3a36..8ec911280a0 100644 --- a/src/w32fns.c +++ b/src/w32fns.c @@ -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 (); diff --git a/src/w32inevt.c b/src/w32inevt.c index ce36f291b00..3c41bec6bb5 100644 --- a/src/w32inevt.c +++ b/src/w32inevt.c @@ -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); diff --git a/src/w32menu.c b/src/w32menu.c index 34020fa61d2..f804e830ac0 100644 --- a/src/w32menu.c +++ b/src/w32menu.c @@ -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; } diff --git a/src/xmenu.c b/src/xmenu.c index 823c63bfc6f..5d1f44e0f5a 100644 --- a/src/xmenu.c +++ b/src/xmenu.c @@ -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; } @@ -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; |