A mini-howto on how to get your keys working under Linux v0.1 By Hans de Goede (j.w.r.degoede@et.tudelft.nl) Contents: 1 Introduction 2 Short description and history of the problem 3 Detailed description of the different sub-problems and fixes for it 3.1 The terminals 3.1.1 The console 3.1.2 Xterm 3.1.3 Other terminal emulators 3.2 The apps 3.2.1 Bash 3.2.2 Joe 3.2.3 Other apps 4 A quick fix 4.1 Fix the terminals 4.1.1 Get xterm to send the correct esc-sequences 4.1.2 Get terminfo / termcap to match these esc-sequences 4.2 Fix some apps 4.2.1 Fix bash 4.2.2 Fix joe 4.3 Some other goodies 1 Introduction. =============== Everybody probably know the frustrating experience of his keys not working as expected under linux, under console and especially under X-windows. This document doesn't only try to give a fix. But even more important tries to explain the origin of the problem hopefully making it easier to fix in the future. This is done in the following chapters: 1 Introduction 2 Short description and history of the problem 3 Detailed description of the different sub-problems and fixes for it 4 A quick fix For those only interested in a very quick fix skip to Chapter 4: A quick fix. 2 Short description and history of the problem ============================================== For historical reason's terminals under unices have always used 7-bit data representation. This 7-bit data representation doesn't have any representation however for special keys like home, end and delete. To avoid this problem so called esc-sequences are used. Basicly the terminal sends the character esc folowed by one or more special characters. This in it self is a good solution but not all terminals are created equal and don't send the same esc-sequences. For this reason every terminal has a terminal type which is set in the environment variable TERM, and every unice has a database containing which esc-sequences are send by a termtype for each key. This database is called termcap, on newer unices a new faster binary database called terminfo is also used. But for this document both are concidered the same. So the contents of both should always match for consistency! If keys don't work right people tend to point to termcap/terminfo, but most unice program's also have their own configuration for keymapping's, which can also be broken. Some programs even allow the entry of raw-esc sequences instead of termcap entry names. Others are even worse, only allowing raw esc-sequences. To make things even more complicated, most terminals also allow the esc-sequences which are send by a key to be modified. And not all termcaps expect the same sequence for a key. On some unices backspace is expected to send ^H (ctrl + H) for a xterm, on others however backspace is expected to send 177(octal) as value, which is the default for ansi-terminals and for linux-consoles. So all in all there isn't a straight forward fix. 3 Detailed description of the different sub-problems and fixes for it ===================================================================== First of all lets take a look at the console and termcap/terminfo side of things, then later we'll look at application specific problems. 3.1 The terminals ----------------- 3.1.1 The console ----------------- The console is configured quite well in the linux distributions I have used, and matches termcap/terminfo exactly. There is one small bug however, the termcap entry for the linux-console (TERM=linux) lacks the esc-sequence for: End all modes (termcap symbol me). One of the concequences of this is that inverted text doesn't work for apps which use termcap, terminfo apps however do work. To fix this I've appended the following to the linux entry in termcap: me=\E[m Which was all you need todo to get a perfect working console. I've got a package containing this and more fixes, see: Chapter 4: A quick fix. 3.1.2 Xterm ----------- Xterm is, well, basicly a big mess. Xterm initially started as a vt100 terminal emulator, but soon got it's own extension to allow more function keys etc. The big problem I'm having with fixing xterm is that I can't seem to find good docs on which esc-sequences xterm is supposed to send. The termcap/terminfo files differ in opinion on this from unice to unice. And even the termcap/terminfo files which come with XFree86 don't give the esc-sequences which their xterm uses by default. Keys which are known to be problematic are: home, end, delete, insert, page up, page down & backspace. The actual fix I have used for this is to use the same escape sequence's for home, end, delete, insert, pageup & page down with xterm as are used with linux-console. This also helps applications which only allow hardcoded esc-sequences since these now are the same for xterm and linux-console (and accidently also vt220). Another story alltogether is backspace some xterms send ^H others send 177. But we can't just make a choice here since some apps simple echo keys to the terminal. And some xterm's expect 177 to erase a char, while others expect ^H. The xterm with XFree86 is real messy on this point since it send ^H as backspace, but expects 177 to erase a char. This could be fixed by doing at a prompt: stty erase ^H (or stty erase ^? (=177)) But this would have to be hardcoded into /etc/profile, which could brake other terms. Since the default setting for xterm is to expect 177 for an erase and we don't want to do an stty, I use 177 for backspace. Which is the same as linux-console, thus making it easier for hardcoded apps. And which frees ^H as helpmapping in emacs ;) So basicly what you do is: map: to: home esc [ 1 ~ end esc [ 4 ~ delete esc [ 3 ~ insert esc [ 2 ~ page up esc [ 5 ~ page down esc [ 6 ~ backspace 177 (octal) Now this is neither the default for xterm, or termcap/terminfo, so all three need to be modified! To change the sequences for xterm add the following to your Xresources file: ! Fix xterm's keybindings *VT100*translations: #override \ BackSpace: string(0x7F) \n\ Insert: string(0x1b) string("[2~")\n\ Delete: string(0x1b) string("[3~")\n\ Home: string(0x1b) string("[1~")\n\ End: string(0x1b) string("[4~")\n\ Page_Up: string(0x1b) string("[5~")\n\ Page_Down: string(0x1b) string("[6~")\n\ ~@Num_LockKP_Insert: string(0x1b) string("[2~")\n\ ~@Num_LockKP_Delete: string(0x1b) string("[3~")\n\ ~@Num_LockKP_Home: string(0x1b) string("[1~")\n\ ~@Num_LockKP_End: string(0x1b) string("[4~")\n\ ~@Num_LockKP_Page_Up: string(0x1b) string("[5~")\n\ ~@Num_LockKP_Page_Down: string(0x1b) string("[6~") Note: As you can see we also map the numeric keypad if numlock is off. Besides this, xterm can't send alt+key, some apps also accept esc-key instead of alt+key, so I've also added the following lines to the above: aTab: string(0x1b) string(0x09) \n\ aReturn: string(0x1b) string(0x0d) \n\ aspace: string(0x1b) string(" ")\n\ aa: string(0x1b) string("a") \n\ ab: string(0x1b) string("b") \n\ ac: string(0x1b) string("c") \n\ etc. Another addition I've done is make xterm send the esc-sequences for F11-F20 when shift F1-F10 is pressed: sF1: string(0x1b) string("[23~") \n\ sF2: string(0x1b) string("[24~") \n\ sF3: string(0x1b) string("[25~") \n\ sF4: string(0x1b) string("[26~") \n\ sF5: string(0x1b) string("[28~") \n\ sF6: string(0x1b) string("[29~") \n\ sF7: string(0x1b) string("[31~") \n\ sF8: string(0x1b) string("[32~") \n\ sF9: string(0x1b) string("[33~") \n\ sF10: string(0x1b) string("[34~") \n\ And the last few fixes for xterm are: -make ctrl+enter send esc enter, since alt enter is often used by the wm -the same for ctrl-tab cTab: string(0x1b) string(0x09) \n\ cReturn: string(0x1b) string(0x0d) \n\ All these fixes are available in a package, see: Chapter 4: A quick fix. Now all that is left to do is to get termcap and terminfo to match the above esc-sequences. For those who wish to do this them selves, take a look at the man termcap entry and man terminfo entry. Again these fixes are available in a package see: Chapter 4: A quick fix. 3.1.3 Other terminal emulators ------------------------------ I haven't taken a look yet at fixing troublesome keys for other terminal emulators like: rxvt kde's terminal emulation gnome's terminal emualtion eterm All I do know is that I've tested all but eterm and all are broken much like xterm. Gnome's terminal emulation uses the same esc-sequences for home and end as used by the console (and the fixed xterm) which is good, but del and backspace ar still broken. If I get a lott of possitive feedback on this document, I might spend some time fixing them too (hint hint ;) 3.2 The Apps ------------ 3.2.1 Bash ---------- I've always wanted bash to understand home, end and delete on the cmd-line. Bash has two ways for changing and/or adding keybindings: Through a config file and through the bind command, see help bind. A problem with both is that bash only except's hardcoded esc-sequences, and not termcap/terminfo entry descriptions. When using the bind command there's a workaround for this however. Bash looks for a file called .inputrc in your homedir for its keybindings. By default bash doesn't look for a global file, this can be fixed by adding "export INPUTRC=/etc/inputrc" to /etc/profile. This would however disable the use of a personal inputrc. The hard-coding of esc-sequences is no problem since we use the same esc-sequences for home, end and delete for the console and the xterm. To get your keys working as expected put the following in inputrc: "\e[1~": beginning-of-line "\e[3~": delete-char "\e[4~": end-of-line The bind command uses the above line as an argument, and wants it as 1 argument so to get a working home-key, one could also type: bind '"\e[1~": beginning-of-line' However, more interesting is using tput to echo the esc-sequence for a key to the screen and feeding this to bind thus getting dynamic esc-sequences based on termtype: bind '"'`tput khome`'": beginning-of-line' 3.2.2 Joe --------- By default joe is configured to think that the termcap entry kH is the esc-sequence for end. This is incorrect however, the correct entry for end would be @7. But this poses a problem however, because joe only allows termcap entries starting with a 'k'. The solution is to hardcode the esc-sequence for home by changing the following in your joerc: eol .kH Go to end of line into: eol ^[ [ 4 ~ Go to end of line in joerc. 3.2.3 Other apps ---------------- I'm sure there are lots of other apps which also could use some tweaking, if you have any usefull info, feel free to email me at: j.w.r.degoede@et.tudelft.nl And I'll try to include these fixes in the next version of this howto. 4 A quick fix ============= As promised I've put together a quick and convienient package containing all modified files needed. You can get it from: http://electron.et.tudelft.nl/~jdegoede/fixkeys.html This tgz archive should contain the following files: Global terminal related: termcap xterm.ncurses3 xterm.ncurses4 Xdefaults.xterm-keys Xdefaults.xterm-other App related: inputrc joerc 4.1 Fix the terminals --------------------- 4.1.1 Get xterm to send the correct esc-sequences ------------------------------------------------- To get xterm to send the correct esc sequences add the contents of Xdefaults.xterm-keys to your global Xresources file. For most distributions the location of your global Xresources is: /usr/X11R6/lib/X11/xinit/.Xresources So to add the contents of Xdefaults.xterm-keys type: cat Xdefault.xterm-keys >> /usr/X11/xinit/.Xresources If you do this and you already had a .Xresources file you might get warnings when starting X like: xrdb: "*VT100*translations" on line 109 overrides entry on line 24 These can be safely ignored, or remove the block starting on the line which is overriden. If this doesn't work maybe your distribution has got a different location for its global Xresoures, take a look at /usr/X11R6/lib/X11/xinit/xinitrc its location should be specified in there. 4.1.2 Get terminfo / termcap to match these esc-sequences --------------------------------------------------------- To get termcap to match these esc-sequences simply copy the supplied termcap to /etc/termcap by typing: cp termcap /etc/termcap To get terminfo to match we just need to copy a new xterm entry to your terminfo dir. On redhat 5.1 your terminfo dir is /usr/share/terminfo and your ncurses version is 4 thus type: cp xterm.ncurses4 /usr/share/terminfo/x On redhat 5.0 and 4.x your ncurses dir is /usr/lib/terminfo and your ncurses version is 3 thus type: cp xterm.ncurses3 /usr/lib/terminfo/x On other dist's we first must know your ncurses version type: ldconfig -p|grep ncurses You will probably get multiple lines, some will contain a version no others won't. This version no is either 4.0 or 3.0 if you get both use 4.0. Now we need to find your terminfo dir, check wether one of /usr/lib/terminfo , /usr/share/terminfo or /etc/terminfo exist. If more exist they are probably (hopefully) links to eachother just choose one. Now copy xterm.ncurses4 or xterm.ncurses3 (depending on your version) to the x dir in your terminfo dir. 4.2 Fix some apps ----------------- 4.2.1 Fix bash -------------- To get bash to understand home, end and delete cp input rc to /etc/inputrc by typing: cp inputrc /etc/inputrc And now add the following line to /etc/profile: export INPUTRC=/etc/inputrc This can be done by typing: echo "export INPUTRC=/etc/inputrc" >> /etc/profile 4.2.2 Fix joe ------------- To fix the end key in joe cp joerc to /usr/lib/joe/joerc by typing: cp joerc /usr/lib/joe Note: If you've already customised your joe you will loose your custom settings so instead manually change joerc as described in 3.2.2: Joe. 4.3 Some other goodies ---------------------- Please note this has nothing todo with fixing your keys and is not nescesarry to use your keys. I've also included Xdefaults.xterm-other which can also be appended to your global Xresources as described in 4.1.1. This will give your normal xterm (not nxterm) the following nice extra's making it far better then nxterm: -Bold and underline colors instead of ugly overstriking / underlining -Nice console alike colors not ugly b/w -5000 lines scrollback buffer.