foolproof yet correct handling of keyboard input
Some time ago I started a project to write a text editor. The specification I came up with ahead of time was that it would use a reduced subset of the keys of nano and that it would use ncurses.
Window resize events, tab handling, word wrap and all originally specified functions are complete. The editor works and I use it every day. I'm not asking how to write a text editor. Already did it. :) There is just one nagging problem that I've yet to fix. Keyboard handling is not always correct. Keys from the keypad are not always correct. Backspace is sometimes ignored, or is sometimes interpreted as if it were the delete key. Home and end keys are sometimes ignored. The delete key sometimes is ignored. In an attempt to find consistency, I've tried my editor in the console, in xterm and a few other terminals. I've run it in screen and not in screen. The only consistency I've noted is that my editor, if started in the Linux console or xterm will correctly handle input keys ... unless one is in screen in xterm, detaches, exits xorg and then reattaches in the console. How I originally wrote keyboard handling, and everything else, was to read the man pages of ncurses and its functions. I begin to realize that keyboard handling is a bit complex. The kernel has drivers to read the various keyboards (One could in a USB keyboard in addition to a laptop's built-in keyboard). Each terminal takes the key-presses, and then passes them to the editor. Wait, if one is in xorg (or other x-windowing system) then I guess xorg reads keys from the kernel, then passes them to the window manager which in tern passes them to the terminal and then eventually to my editor? I looked at the source code for nano, to see how it handles keyboard input, and then had to walk away and have a lie-down. :p Is there some sort of guide or tutorial to correctly, yet in a way that always works, handle key-presses? |
A lot of the ncurses info out there on the web is woefully out of date.
I can provide an example of a small demo program I wrote several years ago while trying to get to grips with the 'wide' ncurses library. Perhaps that will give you some ideas. keypress.h: Code:
#ifndef KEYPRESS_H Code:
/* keypress.c */ Code:
/* keypress-example.c */ Code:
# Makefile for keypress: An ncurses input demonstration My advice would be to always use the ncursesw "wide" library and get_wch(), and to use keypad(, TRUE) mode to make life easier. |
That was an interesting program. At first it refused to compile but adding
Code:
#ifndef keypad It's revealed what I already suspected: each term has different ideas as to what many keys are. Thank you. I will read up on the wide thing and see how that goes. |
I think that you asked for this problem by using ncurses when you didn't actually want a terminal emulator.
If you write a GUI program instead, you will receive input events exactly as X generated them. No terminals involved. I recommend GTK 3. It passes the keypress events as-is. Ed |
That's weird. It compiles fine as is on both my CRUX and Slackware boxes.
There's nothing curses specific in keypress.h that would need the include, so I'm not sure what that is all about. This is what the make output looks like on my system: Code:
$ make And, yes, most the terminals tend to do their own thing. That's where keypad mode helps a little, though it does rely on the $TERM and terminfo entries being correct, which isn't always the case. To be honest, it's probably best to forget that the function keys exist and just stick to the normal keys and cursor movement. P.S. I've not encountered an escape sequence longer than 7 yet, but there might be some out there, so perhaps giving KEYDATASIZE a little more headroom might not be a bad idea. |
Quote:
I had to use ncurses, since my editor runs in the console as well, when x-windows is not running. Quote:
An update. I've tested nano on more terminals and ... wow, things go wonky for nano as well. So for now I've been using Gazl's most excellent program to suss out the key codes for the terminals that I *do* use and, like nano apparently does, will ignore other terminals. I figure if my editor works in the console, xterm and (to be fixed still) the OpenBSD console I'll stop there. |
Quote:
Your text editor lives higher in the software stack than the terminal emulation being done by ncurses, VTE, and the console. Your program is seeing the result. There may being a way to read the keyboard directly, but I have not tried to do that. Ed |
Just being pedantic, but ncurses' goal is "terminal abstraction" not "terminal emulation".
|
I wonder if this is related to the need to patch kbd when building LFS to get consistent handling of backspace and delete.
Quote:
|
This BackSpace/Delete problem is only 50+ years old, so there is no point in being impatient.
My terminfo database says: Code:
infocmp linux | egrep 'kbs|kdch1' |
For backspace/delete to do the right thing, 4 things must agree.
Most other terminal emulators follow the linux console and use BS=DEL. I can't remember what the OpenBSD console uses. P.S. we can blame emacs for all this BS=DEL nonsense! |
Thank you all for the replies. So much information!
p.s. I still remember back in the day, using CP/M and memorizing that ^h (8) was backspace and 127 was delete. The keyboard had a backspace key and that generated a ^h. I'd probably memorized half the ascii table back then. :D Right, let me stop rambling. Thanks again. :) |
All times are GMT -5. The time now is 04:57 AM. |