Changes in Keyboard Mapping

This area explains how to make changes in keyboard mappings for (some applications in) Windows NT and OS/2. It assumes you're willing to edit binaries. The primary target is nuking the shift lock. I like other changes, but generally prefer to do them in the application (most typically, emacs and winqvt). The caps lock key is handled by the driver, so applications usually can't do anything about it.

To use the explanations here, you need two things:

m-x find-file-binary. Once I've finished editing a file, I compare the sizes of the original and edited copy. They should be the same. If they are not, I somehow didn't get binary mode or I goofed.
 * an editor that can safely edit binary files. I use emacs, with

by the keyboard. They are needed because the tables you need to edit are all dispatch tables in order to scan code. E.g. to switch caps lock and control, you need to know that control is right before "A", and caps lock is right after space. (For many purposes that may be all you need to know, and you know it now...)
 * a list of "scan codes". These are the internal codes produced

I include files that turn caps lock into control for NT 4.0 FCS (with US keyboard, all except DOS applications) and OS/2 Merlin (native text mode applications and Windows applications only):

NT: kbdus.dll, which belongs in \winnt\system32 OS2: keyboard.dcp, which belongs in \os2 keyboard.drv, which belongs in \os2\mdos\winos2\system

If you retrieve them via FTP, make sure you use binary mode


 * NT

Except for DOS, everything seems to go through \winnt\system32\kbdus.dll. (This name may be different if you're not using a US keyboard, though presumably the procedures will be the same.)

You are looking for a table that has two bytes per key, with the ASCII value for normal characters, and special codes for other things. At last in 4.0 with the US keyboard, if you search for "Q", you'll find it. For normal characters an entry is the ASCII value and a null. Note that the entry for Control, which is before "A", is \242 (octal 242), and the entry for shift lock, which is after space, is control-T. I simply copied the \242 byte in place of the control-T. This technique has worked for 3.5, 3.51, and 4.0 (and various betas).

This seems to work for native NT applications (text and GUI) and Windows applications (I just checked it with the 16-bit version of WinQVT), but not DOS applications. Since I don't do editing with DOS applications, I hadn't noticed that until writing this. DOS is complex, because it makes raw scan codes available to the application, and some applications actually use this. When I used DOS, I had a TSR that trapped the keyboard interrupt and hacked on the actual scan codes for shift lock. To do a complete job with DOS under NT, something like that would probably be needed. At this point I'm not interested.


 * OS/2 Merlin

OS/2 is more complex, and I don't use it as much, so my information here isn't as complete. For Merlin, I use the 3.1 version of WinQVT, so I need to fix both native and Windows applications.

For native text based applications (but not PM), the keyboard seems to be handled by \os2\keyboard.dcp. This contains a very large number of dispatch tables, apparently for each language and keyboard type. You can find the US ones by looking for the string "US". There's about 5. I ended up making my change (which was to turn caps lock into control) in all keyboards, because that was easiest. To find the first table, look for "aA". To find the first US table, look for "US". The tables contain 7 bytes for each key, e.g. here's the entry for "a":

^A ^@ a A ^@ ^@ ^@, i.e. control-A null "a" "A" null null null

I suspect that control-A is actually a binary 1, and is some sort of indicator as to the type of entry this is. Note that the entry shows what the key produces both with and without the shift key. Since I'm just copying entries, I haven't tried to figure out anything more.

As with NT, to turn caps lock into control, you want to copy the entry before "a" on top of the entry after space. The original values are:

control (before a):       ^L ^@ ^D ^A ^D ^@ ^@ shift lock (after space): ^P ^@  @  @  @ ^@ ^@

Note that shift lock uses actual @ characters as well as nulls (which show as ^@), thus making for maximal confusion when reading this entry in emacs.

What I actually did was to do a replace operation throughout the file, replacing all occurences of the shift lock sequence with the control sequence. You could also look for the US keyboards and do just them (or even figure out the specific keyboard you're using). Typing this in emacs is sort of a chose, because you have to quote all the characters, but it does work.

There is one slight inelegancy: this change does make caps lock work like control for text based applications such as emacs running in an OS/2 window. But it doesn't affect whatever code manages the caps lock light. So that light still goes on and off as if control were caps lock.

I also wanted to handle WinQVT, which I use for telnet. It's a Windows 3.1 application. Keyboard mapping for that is in \os2\mdos\winos2\system\keyboard.drv. There seems to be only one keyboard map. Search for the second occurence of QWERTY. You'll see that there's a control-Q before the A. This is presumably the code for Control. There is a control-T after the space. This is presumably the code for shift lock. If you copy the control-Q on top of the control-T, the shift lock key will now function as a control (at least in WinQVT, and presumably other Windows applications). This one handles the caps lock key too.

Note that neither of these changes handles PM applications (i.e. native OS/2 GUI applications). I have not found the map for PM applications. Fortunately I don't do lots of editing in PM applications, so this isn't critical to me. But I would like to know an answer.