Fixing Function Key Sequences

Function key sequences are the reason people often shun curses applications. Basically, since you often can't get the F8 key to work reliably, you don't really want to rely on it in your application -- and thus you get stuck forcing the user to use bizarre control key sequences -- ala emacs.

In general, this problem can't be solved but it can be reliably solved for most function keys in most normal situations. This means that you should design your application to have both -- and provide the bizarre control keys and also quicker function key bindings -- and provide a help system that can be invoked without function keys (but faster with it).

If your function keys aren't working it is likely one of the following:

Not all problems can be solved. Typically, if you are using rlogin from one machine to another this won't confuse things, but occaisionally it does. Suppose you rlogin from machine A to machine B. Assume A and B have different (and for these purposes) incompatible os types. You _might_ have key binding trouble and you might not.

The easiest solution might be simply to telnet from your home machine directly to the machine B, run xterm there. That is, ensure that the application gets started in an xterm created on the machine of interest rather than using rlogin. Hopefully, you won't have to do this, however. The xterm program has standard enough key bindings that you should be able run without doing this -- assuming that you aren't doing wierd things using X, Xterm resources, or your windows emulator. If you do, then all bets are off.

The 'putty' terminal emulator program works well and doesn't confuse the situation by allowing the XTerm resources file to confuse the issue.

If your XTerm resources file needs unusual key bindings, you will need to change the file in $HOME/.tools_home/MACHINE_NAME to match what the XTerm resource file specifies for keyboard overrides. Here is an example override in the XTerm file:

	  xterm.*.translations: #override \n\
	      Shift<Key>Tab: string(0x1b) string("[Z")\

This override specifies that the shift-Tab sequences generates the escape key sequence, "Escape [ Z". The curses info file needs to accept the kTAB resource as that escape sequence. See editing it below. Or, you can jam in this escape sequence into the keyboard input software by modifying the lib/unix_curses.h file and hardcoding the sequence -- or you can, at run time jam in this extra sequence during program startup. See the function, create_key_sequences_map() for an example of how to do this at runtime. If you are going to start down this path, you need a file defining the key sequences which will be read at startup and from their jam in the extra sequences.

If your curses info file simply has the wrong data in for the machine on which you are running, you might need to reprogram that file. Here's how:

example run through

If you do not find $HOME/.tools_dir/MACHINE_NAME/, this means that you have not run any of the tools programs that do windowing activity on this machine. The first time you run a text windowing 'tool', it will create this for you.

Here are names of the curses key bindings:

 kEND=\EOq, kHOM=\EOw, kIC=\EOp, kLFT=\EOt, kNXT=\EOr,
 kPRV=\EOx, kRIT=\EOv, ka1=\EOH, ka3=\E[5~, kb2=\EOE,
 kbeg=\EOE, kbs=\177, kc1=\EOF, kc3=\E[6~, kcub1=\EOD,
 kcud1=\EOB, kcuf1=\EOC, kcuu1=\EOA, kdch1=\E[3~, kend=\EOF,
 kent=\EOM, kf0=\E[21~, kf1=\E[11~, kf10=\E[21~,
 kf11=\E[23~, kf12=\E[24~, kf13=\E[25~, kf14=\E[26~,
 kf15=\E[28~, kf16=\E[29~, kf17=\E[31~, kf18=\E[32~,
 kf19=\E[33~, kf2=\E[12~, kf20=\E[34~, kf21=\E[35~,
 kf22=\E[36~, kf3=\E[13~, kf4=\E[14~, kf5=\E[15~, kf54=\EOo,
 kf55=\EOj, kf56=\EOm, kf57=\EOk, kf58=\EOl, kf6=\E[17~,
 kf7=\E[18~, kf8=\E[19~, kf9=\E[20~, kfnd=\E[1~, khome=\EOH,
 kich1=\E[2~, kind=\EOs, kmous=\E[M, knp=\E[6~, kpp=\E[5~,
 kri=\EOy, kslt=\E[4~,

As usual, nothing ever works perfectly well. The key sequence mapping provided by curses is augmented by additional mappings found in lib/unix_curses.h. Actually, it is completely superseeded but the curses key sequence database is used to set up the tables.

So once you determine by reading the curses man page which binding is not doing what you want, you can now figure out what the correct binding is. Here's how:

When you have done this, you will see output that looks something like this:

lboggs@linux:~/source/c++/tools/editor > od -x

0000000 5b1b 3531 0a7e 0a0a 0a0a 0a0a 0a0a 0a0a

I pressed the page up key, and got the escape sequence:
    Escape [ 1 5 ~

This example was created on linux in an xterm. I repeat, this code only supports Xterms. All other window types screw up the function keys at some point -- even ansi.

In the above example, I pressed the F5 key, then pressed Enter about 16 times, then pressed ^C. You can see that the F5 key produces

This then is the F5 escape sequence on my linux box at home. If F5 isn't working on your machine, it is because your sequence will not match the text found in your file. Change the file to match the sequence. Remember that in the file, an Esc character is represented as -- not ^[.

Once you have edited your copy of file and saved it. Use the /usr/bin/tic program to update the terminal info database to reflect your change. Here's how:

If things get worse instead of better, restore the saved file and rerun the tic command as above.

Warning, it is generally a bad idea to do this via rlogin. You should do this with an xterm launched from the machine directly.

XTerm resource file example

The following text may be needed (some or all of it) to match your TERMINFO files (found in $HOME/.tools_home/MACHINENAME/ If you don't want to use these escape sequences, change them to be what you want but also change your file and run the term info compiler by hand to verify it. See the paragraphs above.

!       This xterm resource file contains required keyboard mappings to
!       make curses work properly.  It corresponds to the
!       file found here.  Put this file in your $HOME directory and name
!       it 'Xterm' -- case is signficiant.  If you already have such a
!       file, make sure it include the XTerm.*.vt100.translations
!       below (you can keep your font, color, and title settings, etc).
XTerm.*font:         9x15
XTerm.*.foreground:  black
XTerm.*.background:  white
XTerm.*.cursorColor: blue
XTerm.*.title:  my little xterm
XTerm.*.ttyModes:  erase ^h
XTerm.*.saveLines: 2000
XTerm.*.eightBitInput: true
XTerm.*.loginShell: false
XTerm.*.visualBell: false
XTerm.*.Geometry:   90x25

XTerm.*.vt100.translations: #override <Key>F13: keymap(dbx)
XTerm.*.vt100.translations: #override \
	Ctrl<KeyPress>Prior: string(0x1b) string("[prior;") \n\
	Ctrl<KeyPress>Next:  string(0x1b) string("[next;") \n\
	Ctrl<Key>Home:   string(0x1b) string("[home;") \n\
	Ctrl<Key>End:    string(0x1b) string("[end;") \n\
	Ctrl<KeyPress>Left: string(0x1b) string("[LEFT;") \n\
	Ctrl<KeyPress>Right: string(0x1b) string("[RIGHT;") \n\
	Shift<KeyPress>Prior: string(0x1b) string("[prior;") \n\
	Shift<KeyPress>Next:  string(0x1b) string("[next;") \n\
	Shift<Key>Home:   string(0x1b) string("[home;") \n\
	Shift<Key>End:    string(0x1b) string("[end;") \n\
	Shift<KeyPress>Tab: string(0x1b) string("[TAB;") \n\
	Shift<KeyPress>Left: string(0x1b) string("[LEFT;") \n\
	Shift<KeyPress>Right: string(0x1b) string("[RIGHT;") \n\
	<Key>Prior:  insert-eight-bit() \n\
	<Key>Next:   insert-eight-bit() \n\
	<Key>Home:   string(0x1b) string("[1~") \n\
	<Key>End:    string(0x1b) string("[4~") \n\
	Alt<KeyPress>: insert-eight-bit() \n\
Generated on Wed Feb 29 22:51:48 2012 for CXXUtilities by  doxygen 1.6.3