Linux	Keyboard Setup Howto
  Stephen Lee, sl14@cornell.edu
  Version 1.1, 10 March	1995

  This HOWTO document describes	setting	up the kernel and applications
  to handle the	Cursor control keys.

  1.  Introduction


  It has been annoying to me that cursor keys had not work consistently
  across different programs (and on different machines), so I took some
  time and tried to fix	all that.  Here	I document my experience so
  others would not need	to go through the same tedious cycle I did.

  I'm using Slackware 2.0.1, so	pathnames to files might be different
  from yours if	you are	using a	different distribution.

  Some of the material here appeared in	an earlier ``BackSpace Mini-
  HOWTO''.  Although the method	described there	still works, I consider
  this a better	solution.


  1.1.	Typography



  o  This is a program name.

  o  This is a ``command'' you'd type on a keyboard.

  o  This is a <Key> on	the keyboard.  eg. <BackSpace>,	<Delete>,
     <Shift-l>,	<Ctrl-q> etc.

  o  This is an	[X11 Keysym] which you can use for mapping keys	under X.
     eg. [BackSpace], [Delete],	[Left],	[Home] etc.


  1.2.	Terminalogy



     ESC
	ASCII character	0x1B.


     BS	ASCII character	0x08, or control-h.


     DEL
	ASCII character	0x7F.


     ^D	ASCII character	0x04, or control-d.


     VC	A Linux	Virtual	Console.




  1.3.	Acknowledgements


  Thanks to the	following people who commented on my ``BackSpace Mini-
  HOWTO'':
  John Copella,	Andrew Rakowski, Dr. Jacques Gelinas, Michael Bischoff,
  Topher Hughes, Chuck Meyer and especially Ted	Stern and Steve	Dunham.


  2.  Non-X configuration


  I assume you came from the DOS world like I did, and is used to the
  mapping of function that <BackSpace> deletes character to the	left of
  the cursor and <Delete> deletes character on top of the cursor.

  Under	a shell, the most intuitive mapping is <BackSpace> -> BS and
  <Delete> -> DEL.  This is fine unless	you want to use	EMACS. EMACS map
  <Ctrl-h> to its help function, which,	under ASCII, is	unfortunately
  BS.  So each time you	want to	erase a	character backwards, you invoke
  the help system.  Also, DEL under Emacs deletes BACKWARDS, like what
  you'd	expect for BS.

  One choice is	to remap the keys under	Emacs.	Unfortunately you'll
  lose the ``<Ctrl-h> =	help'' mapping.	 So, I decided to map
  <BackSpace> -> DEL.  This leaves BS for use by <Ctrl-h> in Emacs.

  So, now what shall we	do for the <Delete> key?  In a previous	verion
  of this document I used ^D, which works under	both Emacs and csh/tcsh
  as a ``Delete	character on cursor'' function.	 But since then	I've
  found	a better solution.  The	kernel by default maps <Delete>	as the
  VT100	``Remove'' key sequence	(``ESC[3~'').  It is not hard to teach
  Emacs	and tcsh to recognize it.  The advantage is that you can bind it
  differently than <Ctrl-d> in programs.  Also,	it is more consistent if
  you also map other cursor control keys.  The disadvantage is that you
  might	not be able to use it in some application which	you can't bind
  key sequences	(but than apply	to the <Delete>	-> ^D binding as well).


  2.1.	Linux console


  Linux	console	key bindings are controlled by the kernel.  The	kernel
  by default generates the correct bindings for	<Backspace> and
  <Delete>, so you should not need to change that.

  However, if you do, the following programs (in the 'kbd' package,
  which	should come with Slackware already) affect the key bindings:



     showkeys
	``showkeys'' shows the Linux keycode generated by a key. The
	keycode	can then be used by loadkeys(1)	to change the keymap.


     dumpkeys
	Shows the current keybindings. See the manual page for more
	detail.


     loadkeys
	``loadkeys file'' loads	keybindings from file ``file''.	Note
	that this changes the key bindings for ALL virtual consoles.
	This is	usually	done at	boot time in /etc/rc.d/rc.local.

	You can	start with one of the keytable files in
	/usr/lib/kbd/keytables/*.map and edit that. The	one that is
	compiled into your kernel would	be
	/usr/src/linux/drivers/char/defkeymap.map if you have the kernel
	source.	The format of the file is described in the keytables(5)
	manual page.

	The keys of particular interest	are <BackSpace>	(keycode 14),
	<Delete> (111).


     setmetamode
	``setmetamode''	controls whether the keystroke <Alt-x>,	where x
	is some	key, would send	the keycode M-x	or the key sequence ESC
	followed by x. This is virtual-console-specific, you can have
	different setting in different virtual consoles.



  2.2.	tty (including the Linux console)


  ``stty erase <ch>'' tells the	terminal what character	your <BackSpace>
  key generates.  It does NOT change your key bindings.	 If you	map
  <BackSpace> to DEL then do a ``stty erase '^H''' it won't magically
  changes your <BackSpace> key to generate ^H; it would	only confuse
  your computer.

  To correctly set your	terminal ``erase'' character to	DEL, type ``stty
  erase	'^?''' (where ^? can be	'^' followed by	'?' or <Ctrl-v>
  <BackSpace>) at your shell prompt.  You might	want to	put this in your
  $(HOME)/.cshrc or $(HOME)/.profile.

  Note:	although csh/tcsh treats BS and	DEL the	same way, other	programs
  don't.  So your mapping might	seem to	work under csh/tcsh but	you get
  wierd	stuff like ^? under some programs.  Solution: remember the
  ``stty'' command above.


  2.3.	Shells



  2.3.1.  tcsh


  tcsh provides	the command ``bindkey''	for binding keys:


     bindkey
	lists all current bindings.


     bindkey ``str'' function
	binds input string ``str'' to ``function''.  A list of tcsh
	functions can be obtained by ``bindkey -l''.


     bindkey -k	<up | down | left | right> function
	binds an arrow key to ``function''.


  Example: To bind cursor control keys,	put this in $HOME/.cshrc:








  ______________________________________________________________________
      if ($term	== "xterm" || $term == "vt100" \
	    || $term ==	"vt102"	|| $term !~ "con*") then
	  # bind keypad	keys for console, vt100, vt102,	xterm
	  bindkey "\e[1~" beginning-of-line  # Home
	  bindkey "\e[2~" overwrite-mode     # Ins
	  bindkey "\e[3~" delete-char	     # Delete
	  bindkey "\e[4~" end-of-line	     # End
      endif
  ______________________________________________________________________



  See the man page for tcsh(1) for a complete description.

  Example: You can have	4DOS-style command history under tcsh with the
  tcsh function-pair history-search-backward (Meta-p) and history-
  search-forward (Meta-n).  Typing ``abc<Meta-p>'' will	only show lines
  in history that start	with ``abc''.  Also, function magic-space
  expands !  histories as you type, and	I prefer them over the default
  so I bound them to the up/down arrow keys and	space:


  ______________________________________________________________________
      bindkey -k up history-search-backward
      bindkey -k down history-search-forward
      bindkey "	" magic-space
  ______________________________________________________________________




  2.3.2.  bash


  The ``.inputrc'' file	contains the list of key bindings to functions.

  For example, if you put the following	line in	$HOME/.inputrc:


  ______________________________________________________________________
      "\e[1~": beginning-of-line
      "\e[3~": delete-char
      "\e[4~": end-of-line
  ______________________________________________________________________



  It will map the <Home>, <Delete>, and	<End> keys respectively	to the
  corresponding	functions.


  2.4.	Editors



  2.4.1.  Emacs	19


  Emacs	19 provides the	elisp function define-key for binding keys.  You
  can bind a key sequence to a function	key like this in $(HOME)/.emacs:





  ______________________________________________________________________
      ;; map function keys on PC keyboard
      (setq term (getenv "TERM"))
      (if (or
	   (string= "xterm" term)
	   (string= "con" (substring term 0 3))	; linux	consoles
	   (string= "vt100" term)
	   (string= "vt102" term))
	  (progn
	    (defun my-setkey-hook ()
	      (define-key function-key-map "\e[1~" [home])
	      (define-key function-key-map "\e[2~" [insert])
	      (define-key function-key-map "\e[3~" [delete])
	      (define-key function-key-map "\e[4~" [end])
	      ;; these are just	my own sequences
	      ;; so I can use the keys under Emacs
	      (define-key function-key-map "\e[40~" [C-prior])
	      (define-key function-key-map "\e[41~" [C-next])
	      ;; function keys:	use same mapping as xterm
	      (define-key function-key-map "\e[11~" [f1])
	      (define-key function-key-map "\e[12~" [f2])
      ;; ...
	      (define-key function-key-map "\e[24~" [f12])
	      (define-key function-key-map "\e[25~" [S-f1])
	      (define-key function-key-map "\e[26~" [S-f2])
      ;; ...
	      (define-key function-key-map "\e[39~" [S-f12])
	      )
	    (add-hook 'term-setup-hook 'my-setkey-hook)
	    )
	()
	)
  ______________________________________________________________________



  Note the function key	names are all in lowercase.

  You can also bind function keys (or key sequences, but we won't be
  using	that here) to a	emacs command with global-set-key like this:


  ______________________________________________________________________
      (global-set-key [delete] 'delete-char)
      (global-set-key [home] 'beginning-of-line)      ;	you might not want this
      (global-set-key [end] 'end-of-line)	      ;	nor this
      (global-set-key [C-prior]	'beginning-of-buffer)
      (global-set-key [C-next] 'end-of-buffer)

      (global-set-key [f1] 'help-for-help)
      ;; ...
      (global-set-key [S-f12] 'info)
  ______________________________________________________________________




  2.4.2.  vi


  Anybody want to write	this?





  2.5.	Other Programs



  2.5.1.  less


  lesskey(1) allows you	to map keys for	the less(1) pager.  Put	the
  following lines in your $HOME/.lessrc	(this is for VT100-like
  terminals):


  ______________________________________________________________________
      ^[[A   back-line
      ^[[B   forw-line
      ^[[C   next-file
      ^[[D   prev-file
      ^[OA   back-line
      ^[OB   forw-line
      ^[OC   next-file
      ^[OD   prev-file
      ^[[6~  forw-scroll
      ^[[5~  back-scroll
      ^[[1~  goto-line
      ^[[4~  goto-end
  ______________________________________________________________________



  replacing '^[' with the ESC character	(ASCII 0x1B), then run ``lesskey
  .lessrc'' in your home directory.  You can then use the cursor pad
  keys for scrolling text under	less(1).



  3.  X	configuration


  Under	the X windows system, every key	can have a different keysym
  assigned to it, instead of just an ASCII value of key	sequence.  Thus,
  X applications can distinguish easily	between, for example, <Tab>
  (which generates the [Tab] keysym) and <Ctrl-i> (which generates the
  [i] keysym with the "Ctrl" modifier).

  One consequence is that we want <BackSpace> to generate the
  [BackSpace] keysym.  However,	on most	systems	<BackSpace> as well as
  <Delete> generate the	[Delete] keysym	by default due to the way the
  XFree86 server is written (it	reads the settings from	Linux's	key
  map).	This makes the two keys	indistinguishable.  See	the entry for
  xmodmap(1) for a fix.

  A list of keysyms can	be found in <X11/keysymdef.h> (usually
  /usr/include/X11/keysymdef.h), without the XK_ prefix, and also
  /usr/lib/X11/XKeysymDB.  Note	X keysyms are case sensitive.

  There	are several modifiers (like ``Shift'' and ``Ctrl'') that can be
  generated under X: Shift, Ctrl, Meta,	Alt, Super and Hyper.  Note that
  although ``Alt'' is present, most of the time	the <Alt> key on the PC
  keyboard is bound to the ``Meta'' modifier; it works with more
  applications this way.


  3.1.	X server



     xev
	xev(1) allows you to see events	generated on a window, including
	<KeyPress> and <KeyRelease> events where you can find the
	keycode	for a particular key.  Once the	keycode	is found for a
	key it can be mapped into a X11	keysym with xmodmap.


     xmodmap
	One of the function of xmodmap(1) is to	map X keycodes to
	keysyms.

	``xmodmap <file>'' reads the keycode ->	keysym table from the
	file ``file'' (usually named .xmodmaprc	or .Xmodmap in the
	user's home directory).	 This is usually done in
	$(HOME)/.xinitrc when X	starts up.  (Warning: X	exits when the
	last line of .xinitrc finishes,	so if you don't	have a .xinitrc
	before,	you must put something that will continue to run (like
	the window manager or an xterm)	at the end of .xinitrc,	and
	don't put it in	the background!)

	Alternatively, you might generate a map	file from your
	loadkey(1) *.map file using ``/usr/lib/kbd/keytables/mk_modmap
	foo.map	> foo.xmap''; you need to remove all the ``compose''
	command	in the output.	Note that <BackSpace> would be mapped to
	the [Delete] keysym if you start with the keymap provided, so be
	sure to	edit foo.xmap for keycode 22 (BackSpace) and 107
	(Delete), or see below.

	``xmodmap -e "command"'' can be	used to	execute	a single xmodmap
	command, for simple changes.  For example, the following lines
	in $HOME/.xinitrc will correct the <BackSpace> and <Delete> key
	mappings:


	________________________________________________________________
	    # map the <BackSpace> key to the [BackSpace] keysym.
	    xmodmap -e "keycode	22 = BackSpace"
	    # map the <Delete> key to the [Delete] keysym.
	    xmodmap -e "keycode	107 = Delete"
	________________________________________________________________





  3.2.	X applications


  X applications are usually configurated via resources.  User
  customizations are usually put in $HOME/.Xdefaults and loaded	via
  "xrdb	-load $HOME/.Xdefaults"	in .xinitrc (again, see	the warning in
  the xmodmap entry).


  3.2.1.  Terminal Emulators



  3.2.1.1.  xterm family


  Key mappings can be changed like this	in $(HOME)/.Xresources:




  ______________________________________________________________________
      *VT100.Translations: #override <Key>BackSpace: string(0x7F)\n\
	      <Key>Delete:	  string(0x1b) string("[3~")\n\
	      <Key>Home:	  string(0x1b) string("[1~")\n\
	      <Key>End:		  string(0x1b) string("[4~")\n\
	      Ctrl<Key>Prior:	  string(0x1b) string("[40~")\n\
	      Ctrl<Key>Next:	  string(0x1b) string("[41~")
  ______________________________________________________________________



  This applies to most xterm-based emulators (xterm, color_xterm, kterm
  etc. but not rxvt).


  3.2.1.2.  rxvt


  There	is apparaently no way to remap keys in rxvt except by patching
  the source.  Any proof to the	contrary would be welcome.


  3.2.2.  Editors



  3.2.2.1.  Emacs 19


  global-set-key can be	used to	map keys to Emacs commands.  See the
  Emacs	19 entry in the	non-X section.	To find	out what emacs symbol a
  key sends, press the key in question (in a scratch buffer so it won't
  clobber up your files) and then use the Emacs	command	view-lossage
  (usually <Ctrl-h> <l>) to see	what the key generated.

  Usually the symbol is	the X11	keysym in lowercase; for example,
  <Insert> (which generates the	[Insert] keysym) would be [insert] in
  Emacs.

  <Shift-fkey>,	<Ctrl-fkey>, <Meta-fkey> generates [S-fkey], [C-fkey],
  and [M-fkey] respectively.  Combinations generate something like [C-M-
  fkey].  Other	modifiers are s- for "Super", H- for "Hyper" and A- for
  "Alt".


  3.2.3.  Other	Programs



  3.2.3.1.  Motif applications


  Some people have problem with	using the <Delete> key in Motif
  applications (most notably, Mosaic & Netscape). Ted Stern
  <stern@amath.washington.edu> sent me this, which should fix the
  problem when put in $HOME/.Xdefaults:










  ______________________________________________________________________
      !
      !	 To make Backspace delete-previous-character and Delete
      !	 delete-next-character in Motif	applications generally ...
      !
      *XmText.translations:	 #override \n\
	      ~a <Key>osfBackSpace: delete-previous-character()	\n\
	      ~a <Key>osfDelete: delete-next-character() \n\
	      a	<Key>osfDelete:	delete-previous-word() \n\
	      c	<Key>d:	delete-next-character()	\n\
	      a	<Key>d:	delete-next-word() \n\
	      c	<Key>a:	beginning-of-line() \n\
	      c	<Key>e:	end-of-line() \n\
	      c	<Key>k:	delete-to-end-of-line()	\n\
	      a	<Key>Left: backward-word() \n\
	      a	<Key>Right: forward-word()

      *XmTextField.translations:      #override	\n\
	      ~a <Key>osfBackSpace: delete-previous-character()	\n\
	      ~a <Key>osfDelete: delete-next-character() \n\
	      a	<Key>osfDelete:	delete-previous-word() \n\
	      c	<Key>d:	delete-next-character()	\n\
	      a	<Key>d:	delete-next-word() \n\
	      c	<Key>a:	beginning-of-line() \n\
	      c	<Key>e:	end-of-line() \n\
	      c	<Key>k:	delete-to-end-of-line()	\n\
	      a	<Key>Left: backward-word() \n\
	      a	<Key>Right: forward-word()
  ______________________________________________________________________



  Remember that	this still requires the	<BackSpace> and	<Delete> key to
  generate the correct keysyms ([BackSpace] and	[Delete] respectively).
  See the xmodmap(1) entry.


  4.  For more information


  ``kbd.FAQ'' in the kbd package
  (ftp://sunsite.unc.edu/pub/Linux/system/Keyboards/kbd-0.89.tar.gz)
  contains more	examples on remapping the keyboard.

  Man pages for	the programs mentioned above are good sources of
  information, especially xterm(1x), xmodmap and stty(1).

  Info pages for Emacs tells you how to	remap keys under it; use ``emacs
  -f info'' to read them.