Michael's Keyboard Laws for Developers, Part 3

by Michael S. Kaplan, published on 2007/11/20 10:16 -05:00, original URI: http://blogs.msdn.com/b/michkap/archive/2007/11/20/6420601.aspx

See also the first law (VK_A is not always 'A') and the second law (Not every keyboard contains every VK_* value).

Thought you had escaped the long arm of the law, didn't you? :-)

Sorry, there is no escaping it!

Like the first two laws, you might read it and assume it is completely obvious:

Not every keyboard contains every character

Given that there are over 100,000 characters in Unicode this one seems like it really does not need to be said.

But there are applications like Microsoft Telnet Client. You can run it and you will see something like the following:

In case that isn't seem cool enough, there is literally code in telnet.exe that figured out that keystroke for the escape character based on the current keyboard.

Let's look at MSKLC 1.4 to see what it is looking for:

S there you go, telnet.exe is assuming that U+001d is a part of every keyboard layout, in the control shift state.

Usually, it just so happens that it is.

Not on always on that key, mind you.

But on some key.

But you will notice that I have not quoted any law about that -- and I won't.

Because telnet.exe requiring every keyboard layout on Windows to support a specific Unicode code point is a major case of the tail wagging the dog. And as any dog owner will tell you, that isn't how tails work....

For specifc keyboards where this won't work, you can look at the keyboard for Belarusian, and others. And you will never see a ^], even if you wanted to.

And this principle can be extended to any character, any character at all.

If your application assumes that a particular character is there no matter what the keyboard, then it is broken.

And what is worse is that it is breaking the law....


This post brought to you by U+001d (a.k.a. INFORMATION SEPARATOR THREE)

# Name required on 20 Nov 2007 12:00 PM:

Well, telnet uses CTRL-] as its standard key for escaping into command mode. They were requiring it to be able to support the 7-bit ASCII range, so any special telnet keys had to be outside that. I can't find any RFC requirement that it be THAT key, I think it's just something the implementations settled on, so it's become something any user of telnet would expect.

If you look at the telnet RFCs, they specifically say the NVT (network virtual terminal) is to be using ASCII, and that the remote user be able to type any ASCII 7-bit character, specifically including ESC, which would be the usual suspect for this sort of function.

How else would you do it? What's the "right way"? IIRC, you can't really test to see if ^] is "available" and even if you could, how would you pick a fallback?

Built-in telnet only goes back to the Win 3.11 days, doesn't it?

(and yeah, I've been in situations not involving any MS software where I wasn't able to type that character, for one reason or another)

> If your application assumes that a particular character is there no matter
> what the keyboard, then it is broken.

This isn't much different than EMACS assuming "help" is ^H, which most UNIX boxes use for backspace. They even have a FAQ "Why does hitting backspace bring up help?" trying to defend why that isn't broken, and why "your system is set up improperly"

# Name required on 20 Nov 2007 12:07 PM:

Oh yeah, and speaking of keyboard mappings and EMACS, it was developed on the MIT LISP machines that were "equipped with no fewer than seven shift keys: four keys for bucky bits (‘control’, ‘meta’, ‘hyper’, and ‘super’) and three regular shift keys, called ‘shift’, ‘top’, and ‘front’."

See http://www.faqs.org/docs/jargon/S/space-cadet-keyboard.html

Fortunately EMACS didn't use hyper & super much, and meta is usually mapped to the left alt key, or to ctrl-esc.

# Michael S. Kaplan on 20 Nov 2007 12:44 PM:

The unfortunate side effect in the MS code here is the assumption of the character always being on whatever key held the ] (beyond the obvious flaw in assuming there always would be a ] since that is not a requirement, either).

# Dean Harding on 20 Nov 2007 4:26 PM:

Ah, but telnet.exe has the "-e" command-line option so that you can change the escape character. I'm assuming they chose "Ctrl+]" as the default because, "most" keyboards have it, and you gotta have SOMETHING as the default...

# Michael S. Kaplan on 20 Nov 2007 4:33 PM:

Ah, but that is [part of] my point -- the implementation is actually based on this random control character (which may not be there) and claims to be baded on this particular character (which may also not bethered, though that may be less likely to be true unless you are in places like Belarus!)....

# Kalle Olavi Niemitalo on 20 Nov 2007 6:48 PM:

I wonder why they didn't use e.g. F2 or Shift+Esc as the command key.  If I understand correctly, this would require using low-level console functions rather than high-level, and CSRSS built-in line editing might then be lost; but the command key isn't needed in command mode anyway.

Is there a specific reason why the Belarusian keyboard layout does not include all control characters 0-31?

# Michael S. Kaplan on 20 Nov 2007 6:53 PM:

Well, Belarusian doesn't happen to have a ], which makes the text that telnet.exe pops up kind of amusing, but there are some other keyboards that have a ] without the control character -- and it that case telnet.exe's text is incredibly amusing (and something of a support hit)....

# Rosyna on 20 Nov 2007 8:21 PM:

Apple, for it's part, has special rules for defining keyboard shortcuts. With a huge warning (http://developer.apple.com/documentation/UserExperience/Conceptual/OSXHIGuidelines/XHIGUserInput/chapter_11_section_3.html#//apple_ref/doc/uid/TP30000361-TPXREF54):

"Note: Not all the keys described here exist on all keyboards. Don’t depend on a key as the only way for users to accomplish a task. You cannot assume anything about which keyboard (if any) is connected to a computer."


"Remember that other languages may require modifier keys to generate certain characters. For example, on a French keyboard, Option-5 generates the “{“ character. You can safely use the Command key as a modifier, but avoid using Command and an additional modifier with characters not available on all keyboards. If you must use a modifier key in addition to the Command key, try to use it only with the alphabetic characters (a through z)."

Which I think is the more important notice. Basically, never, ever try to set Control Shift [ as a command sequence.  The [ key might be part of a shift modifier on some keyboards, making it impossible to "double shift" the keyboard on some layouts. If you wanted this, use Control {. Although [ and { are in weird locations on my Japanese Keyboard compared to my US keyboard.

It's odd that most keyboard commands were made based on their location on the ANSI keyboard layout. Well, not "odd" as in unexpected but "odd" as in "silly programmers, q isn't in that location for the french".

# Peter Karlsson on 21 Nov 2007 3:27 AM:

Intereting. With my heavily KLC-modified Swedish-Norwegian hybrid keyboard currently running on an English version of XP, I get:

  Welcome to Microsoft Telnet Client

  Escape Character is ']'

I doubt that is much better than Ctrl+] (which would be Ctrl+AltGr+9 for me).

# Centaur on 21 Nov 2007 3:28 AM:

The part about Belarusian (and other Cyrillic) keyboards is a red herring. On Cyrillic keyboards each key is labeled with a Latin character and a Cyrillic character. And a Cyrillic keyboard layout is almost always installed as secondary, with primary being US, if only for the sake of entering URLs and shell commands.

The Windows edit control uses Ctrl+X Ctrl+C Ctrl+V for clipboard operations. They all work regardless of which layout is active. They work in Russian, although, by your reasoning, the Russian layout does not have X, C or V. It just so happens that Ctrl+Ч, Ctrl+С and Ctrl+М generate the expected key codes.

Which begs a question. For some reason, in my homebrewn MSKLC layouts, the Ctrl+[ Ctrl+] Ctrl+\ combinations seem to not do the right thing in Telnet and PuTTY. (I have to resort to the -e switch for Telnet to reassign the escape code.) Ctrl+letter combinations work as expected, though. Why is that? Do I need to explicitly lay out all the non-letter Ctrl codes?

# Michael S. Kaplan on 21 Nov 2007 10:39 AM:

Hi Centaur,

Not all layouts have such control characters assigned -- so apps expecting them are disappointed....

MSKLC 1.3 will not only fail to load them from existing layouts but will warn you in the validation phase if you add them later (1.4 does not warn you and willl load them if they are there, but will not add them spontaneously).

John Cowan on 4 Nov 2008 6:27 PM:

As a historical note, Ctrl+] goes back to the Berkeley implementation of Telnet for Unix, from which the Microsoft implementation is cloned.   It was chosen precisely because it *was* a 7-bit ASCII value, U+001D.  It is not prescribed by the Telnet RFC.

referenced by

2012/05/02 Who owns keyboard testing?

2012/04/26 Michael's Keyboard Laws for Developers, Part 5

2008/11/04 Strange control over CTRL and control characters

2008/09/03 Need to know the VK for A, ay?

2007/11/21 Michael's Keyboard Laws for Developers, Part 4

go to newer or older post, or back to index or month or day