I need help from experts here on Emacs input in general and Emacs TTY input in particular. I'm working on adding support for menus on text-mode frames. The code which displays drop-down and pop-up menus, displays help-echo for the menu items (in the echo area), and returns the user selection is written, debugged, and works fairly well; as a teaser, I attach below a few snapshots from my development machine. The problem is how to drive the movement between, and selection of, the menu items with keyboard input (or with mouse a on TTYs that support mouse). What is needed, as a minimum, is to be able to read simple cursor motion commands (up/down/left/right) and RET, and convert them into appropriate movements/selection in the menu. We should support not only the C-f/C-b/C-n/C-p keys, but also the arrow keys which typically produce more-or-less arbitrary escape sequences. Which of the Emacs input routines should I use to get this to work? There's a gazillion of read_SOMETHING functions in keyboard.c. After some reading of the code and the commentary, I decided that read_char is the one I need, as it seems to be capable of both reading single-character keys and mouse events. Is there a better function? Anyway, an attempt to use read_char didn't succeed: when that function is called after dropping down the first menu, Emacs gets stuck inside 'select', which never returns, no matter how many keys I press. (Well, it will probably return after 100000 sec., but I didn't wait.) IOW, when called in this manner, read_char somehow doesn't sense that keyboard input arrived. Is this supposed to work? (I'm developing this on Windows, so what I see might be some Windows-specific issue; I could continue development on Unix, if read_char is supposed to work in this situation on Posix platforms.) Note that read_char is called recursively here, because x-popup-menu is itself called from read_char. Is it possible that read_char does not tolerate recursive calls? If using read_char for this is not a good idea, then what else should I use? Just in case it matters, here's the interesting part of the backtrace recorded when read_char was called from the menu code (some functions below Fx_popup_menu are new functions I wrote, so you will be unable to find them in the current trunk sources, but their names will hopefully tell what they do): #7 0x01227dc0 in sys_select (nfds=1, rfds=0x82f018, wfds=0x0, efds=0x0, timeout=0x82eff0, ignored=0x0) at w32proc.c:2096 #8 0x011c47cd in wait_reading_process_output (time_limit=0, nsecs=0, read_kbd=-1, do_display=true, wait_for_cell=55961626, wait_proc=0x0, just_wait_proc=0) at process.c:4552 #9 0x010e9ef1 in kbd_buffer_get_event (kbp=0x82f0cc, used_mouse_menu=0x0, end_time=0x0) at keyboard.c:3879 #10 0x010e6578 in read_event_from_main_queue (end_time=0x0, local_getcjmp=0x82f2c0, used_mouse_menu=0x0) at keyboard.c:2230 #11 0x010e67af in read_decoded_event_from_main_queue (end_time=0x0, local_getcjmp=0x82f2c0, prev_event=55961626, used_mouse_menu=0x0) at keyboard.c:2294 #12 0x010e7b62 in read_char (commandflag=-2, map=55961626, prev_event=55961626, used_mouse_menu=0x0, end_time=0x0) at keyboard.c:2881 #13 0x010d06bd in read_menu_input (sf=0x356f4d0, x=0x82f434, y=0x82f430, first_time=0x82f3e3) at term.c:3168 #14 0x010d0c76 in tty_menu_activate (menu=0x3a482a0, pane=0x82f7dc, selidx=0x82f7d8, x0=1, y0=1, txt=0x82f7c4, help_callback=0x10d1377 ) at term.c:3353 #15 0x010d1b7e in tty_menu_show (f=0x356f4d0, x=1, y=1, for_click=1, keymaps=1, title=19586025, error_name=0x82f8b8) at term.c:3751 #16 0x01074fad in Fx_popup_menu (position=60067158, menu=58308814) at menu.c:1358 #17 0x010f230c in read_char_x_menu_prompt (map=58308814, prev_event=60067158, used_mouse_menu=0x82fb6b) at keyboard.c:8381 #18 0x010e7587 in read_char (commandflag=1, map=58308814, prev_event=60067158, used_mouse_menu=0x82fb6b, end_time=0x0) at keyboard.c:2754 #19 0x010f3843 in read_key_sequence (keybuf=0x82fc60, bufsize=30, prompt=55961626, dont_downcase_last=false, can_return_switch_frame=true, fix_current_buffer=true) at keyboard.c:9069 #20 0x010e498c in command_loop_1 () at keyboard.c:1436 And here are the teaser images: