Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2036373
  • 博文数量: 610
  • 博客积分: 11499
  • 博客等级: 上将
  • 技术积分: 5511
  • 用 户 组: 普通用户
  • 注册时间: 2008-03-12 19:27
文章分类

全部博文(610)

文章存档

2016年(5)

2015年(18)

2014年(12)

2013年(16)

2012年(297)

2011年(45)

2010年(37)

2009年(79)

2008年(101)

分类: LINUX

2008-03-31 22:52:26

Consistent BackSpace and Delete Configuration
The Linux Hall of Shame


version 0.6
Last updated 11/24/2006 04:41:29

Main Page| |

Index

Configuration of environments...
... and applications

These pages were originally written to address a nagging problem which bothered many people using . It has to do with the default behaviour of the BackSpace and Delete keys, which did not behave as expected. The goal of this document was and still is to make [<---] (i.e. the backspace-key on your keyboard) to erase to the left, and make [Delete](i.e. the delete-key) erase under the cursor. It seems all Linux distributions I am aware of have effectively dealt with the issue by now. However still lots of people visit these pages, presumably because the information presented here is applicable to other UNIX flavors and cross-platform environments and applications.

The keymapping problem can be traced back to the time when computers used punched tapes. The only way to correct a wrongly punched character was to punch additional bits in the tape (or rather, punch additional bits _out_ of the tape). Characters with all the bits punched were treated as deleted characters. See 'man ascii' for a list of the ASCII characterset, you'll see that DEL, (octal 177, decimal 127 and hexadecimal 7F) is the one with all the bits punched in (the ASCII code with the highest value). To be able to overwrite a character it is necessary to undo the feed between the characters first. For this the ASCII BS (octal 010, decimal 8, hexadecimal 08) was used. So to erase the last-typed character, you would have to press first BS to move back one character, and then DEL to delete the character. In newer computers either BS or DEL was chosen to move back and delete in one press.

The question to use BS or DEL was (and is...) just a matter of choice, just as different operating systems chose different ways to represent newlines, which was done by first issuing a carriage return (CR) and then a line-feed (LF). UNIX chose ASCII LF (hexadecimal 0A) to do both at the same time, Macintosh chose CR and MS-DOS both. Unfortunately, in the BS-DEL case, Linux ended up with two possibilities.

The essential point in this issue is to go for one way consistently. This page describes a way to consistently use DEL to erase the previous character, the page called describes a way to consistently use BS. On the latter page there are some tips which may be useful regardless of what approach you take.

At this point the best way to fix the keys on your machine is to install from version 2 (Hamm) and up, or , or any later Redhat/Fedora distribution, and I would bet that the issue has been addressed in other recent distributions as well. In fact, I find it surprising that so many people still refer to this page after 9 years, especially since nothing new has been added to it for at least 6 years.

If you miss an application on this page, it's either because the keys are ok in the application ("If it ain't broken, don't fix it"), or because I don't know about it. In either case, don't hesitate to mail me about it.

Throughout this document, [<---] and [Delete] are used to denote the physical keys on the keyboard, the things you actually press to erase characters. There are a few things to keep in mind: ASCII values can be represented in several equivalent ways. This means that ASCII BS is equivalent to 010 in octal, 8 in decimal and 08 in hexadecimal notation. To show that a number is in hexadecimal notation '0x' is put in front of it. Finally it should be noted that BS and DEL are known to applications by their corresponding control sequences. To sum it up:
Note:
ASCII BS == 0x08 == ^H
ASCII DEL == 0x7f == 0177 == ^?

The reason the keys (generally) do not work out-of-the-box is partly lack of configuration (as you will see later, simply creating .inputrc/.cshrc already helps a lot) and a more difficult issue which I will try to describe below.

The linux console emulates a vt220 terminal which has the following key-mapping:


Key KeySymName Console characters
--------------------------------------------------
Ctrl+H ---> Control_H ---> ASCII BS (0x08)
[<---] ---> Backspace ---> ASCII DEL (0x7f)
[Delete] ---> Delete ---> "\e[3~"
Note 1: BS (0x08) is equivalent to ^H, which is left to be used by applications (e.g. for help menus in emacs, but it could be anything). DEL is equivalent to ^?, or 0177 (octal) and 0x7f (hex) and "\e[3~" will show up in your xterm (using the ) as ^[[3~. Xterms on the other hand, emulate the vt100 terminal, which didn't have a [Delete]. It did have a [<---] which generated ASCII BS (but it was in an awkward position and did not serve as rubout).
VT100
--
Key KeySymName Console characters
--------------------------------------------------
Ctrl+H ---> Control_H ---> ASCII BS (0x08)
[<---] ---> Backspace ---> ASCII DEL (0x7F)
Now here's how xterm emulates the VT100 terminal:

Key KeySymName Console characters
--------------------------------------------------
Ctrl+H ---> Control_H ---> ASCII BS (0x08)
[<---] ---> Backspace ---> ASCII BS (0x08)
[Delete] ---> Delete ---> ASCII DEL (0x7F)
It may be clear that by default the keys are mapped differently on the console and in xterm. This would be ok if it weren't for the fact that while on the console ^H is free to be used by applications, in an xterm it is not (instead it's mapped to the [<---] key). Differences between terminal types are generally dealt with by the terminfo database (see below), mapping terminal specific strings to the correct key. However, in this case, the ^H should not be mapped. Terminfo is not enough, the settings of the terminal (xterm) have to be modified such that ^H is not used.

In at working around the problem, I put most of my effort in trying to map all keys to suit xterm's vt100 emulation. However, I now propose another way to deal with the problem. This basically means getting xterm to work with the consoles' default settings: [<---] will do ASCII DEL (0x7F, or ^?), and [Delete] will do "\e[3~". This way ^H is not used for any terminal specific functions, it can be used by applications.

There is no clear solution, but there are some pretty good work-arounds. What is needed is to tell how to handle the keys, and then to tell other applications about it (i.e. how xterm handles the keys). The terminfo database contains descriptions of how all kinds of terminals handle (terminal specific) keys. Applications look at the TERM variable, and then search the corresponding database for the value of a certain key, e.g. the left-arrow key, and find the string that corresponds to it. This means that the strings in the database had better correspond to your current xterm settings. This involves modifying xterm's terminfo entry.

When you change the keymapping on your own system, you may have problems when accessing other systems. Luckily, this can be worked-around by a script which changes the input it receives to the output that is expected by the application (telnet, rlogin). See the section.

This table summarizes the modifications needed in the different environments, and the tools it is done with:
Environment    
      Configuration files           
Configuration 
user   
 systemwide        
          -          terminfo                  infocmp/tic   
  ~/.Xdefaults (*)  /etc/X11/Xresources  xrdb ~/.Xdefaults (*)
               -   /etc/X11/xinit/.Xmodmap (**)   xmodmap .Xmodmap  
      ~/.inputrc    /etc/inputrc    export INPUTRC=/etc/inputrc  
      ~/.cshrc      /etc/cshrc           bindkey (shellcommand)  
* or .Xresources
** /etc/X11/XF86Config also affects the keyboard settings under X

This is often a problem. When you find that the keys are fine in e.g. vi on the console, but not in an xterm (or vice versa, or both) it means that your xterm-settings do not correspond to the settings listed in the terminfo database. I am not really comfortable with telling you to fiddle with terminfo, please be careful, make backups! If you run the tic command on the modified de-compiled terminfo entry as root, your system's terminfo database will be modified automagically. Put the original file in a save place so you can run tic on it and restore the original state. Read the manpage. First try it as non-privileged user. You can start with testing a modified xterminfo file (see below) as explained, however, since these are likely to differ from your system's entry at other points, it's probably better to modify your own instead. At any rate, first find out whether the terminfo entry for xterm is in accordance with your xterm settings:
infocmp | grep kbs
should return a line which includes kbs=\177. This means DEL (or ^?) is mapped to the backspace key, which is what we want.
infocmp | grep kdch1
should return a line with kdch1=\E[3~. This means that \E[3~ is mapped to the delete key. Often you will find kbs=^H and/or kdch1=\177, or there will be no kdch1 at all. You can either edit the terminfo entry as described on the (simply setting or adding kdch1=\E[3~ and kbs=\177, but make a backup first!). Put the file in ~/.terminfo/x/xterm (for testing purposes) and do for bash:
export TERMINFO=~/.terminfo
and/or for tcsh:
setenv TERMINFO ~/.terminfo
Make sure that the TERM variable is set to xterm:
echo $TERM
should return "xterm". If it works as intended (do 'toe' to check whether the terminfo dir you specified is indeed used, toe will return a list of available terminfo types, only xterm in this case), you can run tic as root, which will copy the file to
/etc/terminfo/x/xterm
() or
/usr/lib/terminfo/x/xterm
(, ). Make backups first, and test it before you replace any files!

The xterm (and friends) only needs little configuration. In the /etc/X11/Xresources or ~/.Xdefaults (or wherever it's merged with the other xresources) add the line:
*VT100.Translations: #override \
BackSpace: string(0x7F)\n\
Delete: string("\033[3~")\n\
Home: string("\033[1~")\n\
End: string("\033[4~")
*ttyModes: erase ^?

Rxvt only uses Xresources if it is compiled with this option. Since rxvt uses readline, to get home and end to work you will have to edit .inputrc, see the section). users can pick up the SRPM (source) and compile rxvt themselves with this , ensuring the right keybindings.

Putting xterm or nxterm in front of *vt100.translations makes the settings specific for xterm or nxterm. Sometimes this does not seem to work properly, in that case try using both nxterm*VT100.Translations and xterm*VT100.Translations.

1. The syntax of the Xresources files is very strict, make sure you don't leave blank spaces after the backslash on each line. Also watch the newline (\n\) sequences, there shouldn't be one at the last line of an entry.
2. The sections are named, if you only use *VT100.Translations it will work for all xterm and friends.
3. For info about Xresources and other X related stuff refer to .


If you use , make sure you have enable the XKB extensions in /etc/X11/XF86Config. It is enable by default, so it should be okay. Note the different keyboard layout-options. Now XFree86 will translate the console mapping, and everything should work in X. If you have problems, or want to fiddle with additional characters and things, create an Xmodmap. Also if you want the keyboard to generate special characters in X, xmodmap can also be used to configure the function-keys. This is adequately described in the manual page ('man xmodmap'. Make sure that the following lines are included in your Xmodmap:

keycode 22 = BackSpace
keycode 107 = Delete

Note that the keycodes in X are not the same as in a VT. Use showkey to see the keycodes generated by the keyboard in a VT, and xev in X. There is an excellent graphical front end for X-keyboard configuration: xkeycaps. Refer to the .

Another way of generating special characters in X (without using xmodmap) is by defining a Compose-key (for use as a "dead key") in XF86Config in the Keyboard section:

  RightCtl        Compose
Now you have a compose-key with the same properties as the one described in the section. Remember to set the environment variable LC_CTYPE=iso-8859-1 (see ). Consult if you want to know more. Note: this doesn't seem work rxvt.
Alternatively, owners of a windows keyboard (one with extra buttons, it need not be a M$ natural keyboard) can enable the XKEYBOARD extension (enabled per default) in XF86Config and uncomment the line (follow the instructions in the file):
  XkbModel    "microsoft" 
Now you can use the button with the windows flag on it to produce a great number of exotic characters, just press it in combination with e.g. a, producing á (a clear disadvantage is that there is no logic in the location of the special characters at all...).

Yet another way to use "dead keys" in X is by installing a modified version of libX11 which includes support for dead keys (transparent for all apps). First, get the modified version of libX11 (make sure you get the right version, if you use glibc replace both libX11, ELF-libc5 and ELF-libc6). Now, deactivate the XKB extension of XFree86 (edit XF86Config and run xmodmap on a Xmodmap file with dead keys like dead_acute, dead_grave, dead_cedilla, dead_ogonek and a Multi_keys one too.

A special case is if you use xdm, you need to deactivate XKB from the /etc/X11/xdm/Xservers file, passing a -kb parameter to the server like this:

:0 local /usr/X11R6/bin/X -kb
then in /etc/X11/xdm/Xsetup_0 file add a line to load the Xmodmap, like this:
if [ -r /etc/X11/xinit/.Xmodmap ]; then
/usr/X11R6/bin/xmodmap /etc/X11/xinit/.Xmodmap
fi
Now chars accesible by AltGr, dead keys or compose are usable in xdm too.

More Composing Talk

A problem common to all compose schemes is that while some composing systems make more sense than others, none of them make all of the iso_8859_1 characters readily accessible, simply because it is impossible to remember the combinations for all characters. So instead of, or in addition to getting special libraries, it is often desirable to simply have a list of characters you can copy from, a poor man's iso_8859_1 table so to speak. Just grab you favorite editor, open a file called iso_8859_1 (or any other name, but check the name and path) and put in all iso_8859_1 characters. Wait, here they are (you may want to create a different order):
¡ ¢ £ ¤ ¥ ¦ § ¨ © ª « ¬ ­ ® ¯ ° ± ² ³ ´ µ ¶ · ¸ ¹ º » ¼ ½ ¾ ¿ À Á Â Ã Ä Å Æ Ç
È É Ê Ë Ì Í Î Ï Ð Ñ Ò Ó Ô Õ Ö × Ø Ù Ú Û Ü Ý Þ ß à á â ã ä å æ ç è é ê ë ì í î
ï ð ñ ò ó ô õ ö ÷ ø ù ú û ü ý þ ÿ
Now you need a way to display them (millions of options here, I bet you can do all kinds of crazy things with fonts, colors, pixmaps, borders...). The script assumes the file with the characters is in /usr/local/lib.
 

#!/bin/bash
export LESSCHARSET=latin1
exec xterm -T Iso_8859_1-TABLE -geometry 77x4 +sb -bg SteelBlue -fg white \
-fn lucidasanstypewriter-bold-12 -e less /usr/local/lib/iso_8859_1

Refer to the manual page of iso_8859_1. If you do 'man iso_8859_1' but you don't see any special characters, edit /etc/man.config, and change the following line:
NROFF         /usr/bin/groff -Tascii -mandoc
to:
NROFF         /usr/bin/groff -Tlatin1 -mandoc
Now try 'man -c iso_8859_1' (the -c option is to make sure man does not use an old cat file).

Create a file, /etc/inputrc for system wide use or ~/.inputrc for personal use. Actually, this is the readline initialization file, readline is a library that some programs (bash, kvt) use to read input (try bind -v to see a list of readline key and function bindings). Cut and paste the following in the file to make the Delete key delete characters under the cursor, and make Home and End work as well:

"\e[3~": delete-char
# this is actually equivalent to "\C-?": delete-char
# VT
"\e[1~": beginning-of-line
"\e[4~": end-of-line
# kvt
"\e[H":beginning-of-line
"\e[F":end-of-line
# rxvt and konsole (i.e. the KDE-app...)
"\e[7~":beginning-of-line
"\e[8~":end-of-line
If a system-wide /etc/inputrc was created, add the following line to /etc/profile:
export INPUTRC=/etc/inputrc

Make sure that the stty erase character is set to ^?. Type

stty -a | grep erase

and check if it says

erase = ^?;

If it is set to something else (e.g. ^H) then put the following line in both .bashrc and in either .bash_profile or /etc/profile:

  if tty --quiet ; then
stty erase '^?'
fi
and for xterm and rxvt add this to .Xdefaults:
*ttyModes: erase ^?

If you create /etc/inputrc, note that Bash will ignore ~/.inputrc (currently this happens in all distributions except Debian, however, this might change in the future). As an alternative, you can edit ~/.inputrc, and copy this to /etc/skel/, so it's in the home directories of all new users.
Push the key-combination 'Ctrl-x-r' (push the control-key, the x-key. release it, push the r-key, release it, and then release the control-key) to see if the changes in inputrc take effect. Or just login again, and it will work.

You can also change the keybindings on the fly with the bind command, e.g:

[localhost]> bind "\C-?": backward-delete-char
This is useful to test different keybindings, if they work you can put them in ~/.inputrc. Read all about it in the readline manpage.

People using keymaps with e.g. Scandinavian characters who would like bash to display these characters (øl;-) have to add the following lines in .inputrc:
set convert-meta off
set output-meta on
set input-meta on

For more info, check the .


If you use the tcsh shell, put the following lines in your /etc/cshrc or your personal ~/.cshrc file:
#.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[7~" beginning-of-line # Home rxvt
bindkey "\e[2~" overwrite-mode # Ins
bindkey "\e[3~" delete-char # Delete
bindkey "\e[4~" end-of-line # End
bindkey "\e[8~" end-of-line # End rxvt
endif
To see whether it works or not, type:

[localhost]> source .cshrc



For programs using the Athena widgets (xpaint, xbmbrowser, xman, xmh, xedit, pixmap, bitmap, editres...) put the following in .Xdefaults to get Delete to work:
*Text.translations:    #override \ 
~Shift ~Meta Delete: delete-next-character()

In emacs, [<---] and [Delete] are by default configured to both erase the character on the left of the cursor. To change this, you can either edit the file x-win.el in the emacs root directory, and find the following:

;; Map certain keypad keys into ASCII characters
;; that people usually expect.
(define-key function-key-map [backspace] [127])
(define-key function-key-map [delete] [127])

and change the last line to
(define-key function-key-map [delete] [deletechar])

Alternatively you can add
(define-key function-key-map [delete] [deletechar])

to your ~/.emacs file. On a related note, by default in emacs the HOME key brings you to the beginning of the buffer (i.e. top of the document). Likewise the END key brings you to the end of the buffer. Adding the lines

(define-key global-map [home] `beginning-of-line)
(define-key global-map [end] `end-of-line)
to your ~/.emacs make these keys move you to the beginning and end of the current line. Note that the M-< and M-> keybindings remain untouched and can still be used to go to the beginning and end of the buffer.

First find the file joerc. It is most likely /usr/lib/joe/joerc, but sometimes /etc/joerc, or maybe even /usr/local/lib/joerc. Try 'locate joerc' if you can't find the file. Make a backup for safety, or copy it to .joerc in your home directory, and change/add the following lines in the section "Standard JOE user interface" in joerc:
bol              ^[ [ H          # Standard xterm escape seq.
bol ^[ [ 1 ~ # Standard VT escape seq.
bol ^[ [ 7 ~ # rxvt
eol ^[ [ F # Standard xterm escape seq.
eol ^[ [ 4 ~ # Standard VT escape seq.
eol ^[ [ 8 ~ # rxvt
Note that you first have to make sure that Home and End work in an . Check out . BTW, these modifications apply to jpicorc, jstarrc and jmacsrc as well.

provides a new alternative to kvt called konsole. To get the home/end keys to work in konsole you have to put:
 
"\e[H":beginning-of-line
"\e[F":end-of-line
in .inputrc. Additionally, make sure that you have checked the 'BS sends DEL' checkbox (right mouse click, or through the 'Options' pulldown menu). In kvt, home and end can be configured by editing ~/.inputrc (tcsh users too, it uses readline):
 
"\e[H":beginning-of-line
"\e[F":end-of-line

Less is ok on some systems. If it is not on yours, try the following. Create a file, /etc/lesskey, for system-wide use. This will be a lesskey input file. Put the following lines in the file:
#line-edit
\e[3~ delete
\e[1~ home
\e[4~ end

Save the file, and compile it as follows:
[localhost]> lesskey -o /etc/less /etc/lesskey

Add the following line to /etc/profile:

export LESS="-MM -k/etc/less"

Now type:

[localhost]> . /etc/profile

By fiddling with these settings you should be able to get less to accept (all of) the holy keycodes, at least, it works on my computer. For some exciting reading, check .

Put the following in ~/.Xdefaults:
 nedit.remapDeleteKey: False

Save the file, and the next time you start the Delete key will do what we want it to: delete under the cursor. Note: you can also put the line in ~/.nedit, but every time you save the default settings, the .nedit file will be overwritten, and you'll have to (n)edit it again.

Note the nedit, as e.g. netscape, is a motif application. This means that it uses the XKeysymDB, see thet netscape section.

The keys should be ok, as long as the XKeysymDB is installed in one of the places where netscape looks (where netscape itself is installed, or /usr/X11R6/lib/X11/). XKeysymDB is similar to an xmodmap file, but with a very cryptic and poorly documented syntax. Luckily, it does do the delete/backspace thing right, so no sweat.

If you use xmodmap, you may want to check out the graphical front end for X-keyboard configuration: xkeycaps. Get the .rpm at , or get the (or plain tarball). It's a nice tool. You can also look for a default Xmodmap file on your system. At any rate, make sure that the following is in the file:

keycode 22 = BackSpace
keycode 107 = Delete

alternatively, you can put it in e.g. your .Xclients file, or in /etc/X11/xdm/Xsetup_0):

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

I found that while the keys worked in a VT, in xterms only backspace works. This was caused by the .Xdefaults modifications. If you use the ~/.inputrc to get Delete to work in xterms (and then pico and pine will be able to use Delete), however, this creates problems with other apps (e.g. joe) which cannot be easily solved because joe relies on the .Xdefaults modifications to get the keys right. Anyway, it turns out that and pico are simply broken, as the workaround will clearly demonstrate. Admittedly broken is a relative thing in all this keyboard-confusion: from the other method's perspective they are perfectly ok. One thing is for sure, these two apps are exceptions. Try the following: make an expect script (let's call it picofix):
#!/usr/bin/expect

eval spawn -noecho $argv

interact {
\177 {send "\010"}
"\033\[3~" {send "\004"}
}
Make picofix executable, and start the editor (or pine) with
picofix pico
and it will work (then you can make an alias or a wrapper). Thanks to Philip Hands for this ingenious (and powerful!) workaround. You can also use an alternate editor. Edit .pinerc and find the following lines:

# Specifies the program invoked by ^_ in the Composer,
# or the "enable-alternate-editor-implicitly" feature.
editor=

You can enter the command for any editor here, e.g. joe or vi.

If you want the editor to be started right away, start pine, enter SETUP and Config and select the enable-alternate-editor-implicitly option. Now the editor of choice will be started automagically when you start writing a message.

Pico fans may want to try jpico, which is basically joe with pico keybindings (and all the extra's joe offers). Others my be even smarter and switch to and . Note that the first can be taught to do the Ctrl-j-trick, the latter can use pine keybindings.

Vim uses , so the keys should be ok if your terminfo is. However, if it is not, you can still get the keys to work in vim. Type :help fixdel in vim and read all about it.

Put the following line in ~/.muttrc:
bind editor  delete-char
This will make [Delete] do its job in internal pager.

If you have modified and you are e.g. telnetting to a machine with a default terminfo (for xterm usually), you can use the following script (let's call it kbdfix) to change the keysequences you generate to the ones the program expects:
#!/usr/bin/expect

eval spawn -noecho $argv

interact {
\177 {send "\010"}
"\033\[3~" {send "\177"}
}
If you press [<---], expect will receive \177 (equivalent to 0x7F and ^?, see the ) and it will send \010 (equivalent to ^H) along to telnet, which will result in [<---] at the other end. Make it executable and use kbdfix telnet brokenhost. Thanks to Philip Hands for this clever workaround.

The logical next step is to automate the trick. Create a file, /etc/broken-backspace-hosts (or a shorter name...). In this file, list the hosts which expect ^H and ^? instead of ^? and ^[[3~. Now you can make a wrapper for telnet as shown below. This particular script assumes that the telnet binary has been renamed telnet.orig, and that the kbdfix script described in the previous section is somewhere in your path):

#!/bin/sh
if grep -wq "$@" /etc/broken-backspace-hosts ; then
exec kbdfix telnet.orig "$@"
else
exec telnet.orig "$@"
fi
From now on, when you use telnet, the script will check whether the host you are telnetting to is considered broken (listed in the /etc/broken-backspace-hosts file). If it is, the expect script (kbdfix) will be used, if not, telnet will be started directly. You can do the same for rlogin, although rlogin can't be moved (i.e. won't work when it isn't called rlogin).

  • The Linux Keyboard and Console HOWTO
  • Linux Keyboard Setup Mini-Howto
  • Consistent Keyboard Configuration' article ( issue #38, June 97)
  • Danish-HOWTO
  • Tcsh documentation
  • Fixkeys Mini Howto
  • Bash documentation
  • 'man showkey'
  • 'man X'
  • 'man XF86Config'
  • 'man lesskey'
  • 'man joe'
  • Dead keys under X11

This document was put together by (anne@ibb.net). Please mail me if you find mistakes, tY-pO's, alternative or plain better solutions. A few people have already pointed out many mistakes (there simply cannot be that many left...), which improved the document a lot. I would like to thank all the people who contributed to the page, and Thomas Telkamp for hosting the site.

).
Last updated 11/24/2006 04:41:29
阅读(3248) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~