Article 63144 of comp.os.vms:
Path: jac.zko.dec.com!alfabx.lkg.dec.com!pa.dec.com!netnews.alf.dec.com!decatl!kendrix
From: kendrix@decatl.enet.dec.com (John Kendrix)
Newsgroups: comp.os.vms
Subject: How to remap the DELETE key...
Date: 16 Jun 1995 16:30:05 GMT
Organization: Digital Equipment Corporation
Lines: 584
Sender: kendrix@ruby.alf.dec.com (John Kendrix)
Distribution: world
Message-ID: <3rsbid$5h4@netnews.alf.dec.com>
Reply-To: kendrix@decatl.enet.dec.com (John Kendrix)
NNTP-Posting-Host: ruby.alf.dec.com
Keywords: KEYCODE KEYSYM DELETE KEY BACKSPACE
X-Newsreader: mxrn 6.18-16


Someone asked that I post this to the net.  I hope that you will find it of 
use.  
 
Regards,
 
John Kendrix
Motif Support Team
Atlanta/CSC

Discussion On Keycodes, Keysyms, And OSF/MOTIF Virtual Bindings


COPYRIGHT (c) 1988, 1993 by Digital Equipment Corporation.
ALL RIGHTS RESERVED. No distribution except as provided under contract.

PRODUCT: OSF/MOTIF

SOURCE:     Digital Customer Support Center


TABLE OF CONTENTS:

I.   X WINDOWS: KEYCODE VS. KEYSYM
II.  INFORMATIVE MAN PAGES XMODMAP INFORMATION ON KEYCODES/KEYSYMS
III. OSF/MOTIF VIRTUAL BINDINGS
IV.  INFORMATIVE .MOTIFBIND INFORMATION FROM SUN MOTIF KIT
V.   LIFE OF AN OSF/MOTIF KEY (FROM KEYCODE TO VIRTUAL KEY)
VI.  PRINT_KEYSYM.C


--------------------------------
I. X WINDOWS: KEYCODE VS. KEYSYM
--------------------------------

The server sends only KEYCODES.  A keycode is an *arbitrary* number that gets
defined based on the keyboard you're using.  All VMS keyboards are defined
in the DECW$KEYMAP directory.  (There's over 70 of 'em.)  They all have
a file extension of .DECW$KEYMAP.  On U*NX these are defined in
/usr/lib/X11/keymaps and keyboard maps have a file extension of
decw_keymap.  You can change the default keymap file by selecting 'Options'
from the Session Manager and then 'Keyboard' from the resulting pulldown
menu.  A scrolled list labeled 'Keyboard Type' lists all available keymaps.
The default is 'System Default', which according to the documentation
(VMS DECwindows Motif User's Guide, pg. 7-5, "Changing Your Keyboard
Settings") is North American.  Note that there are two (2) North American
keymaps, LK201 and LK401.  To find out which keymap your workstation is
using you can enter the following command:

$ SHOW LOGICAL/TABLE=DECW$SERVER0_TABLE DECW$DEFAULT_KEYBOARD_MAP

This logical is defined in DECW$STARTSERVER.COM, taking its value from
a symbol created in DECW$DEVICE.COM.  The default value in DECW$DEVICE.COM
is for NORTH_AMERICAN_LK201LA to be used, unless a different default keyboard
map was specified in DECW$PRIVATE_SERVER_SETUP.COM.  If your workstation
has an LK401 keyboard you should add the following line to your
DECW$PRIVATE_SERVER_SETUP.COM file:

$  decw$default_keyboard_map == "US_LK401AA"

The LK201 and LK401 keymap files are identical in most instances.  One
difference is that the LK401 will send a different keysym for a SHIFT/L
than it will for a SHIFT/R.  An LK201 sends the same keysym for both
SHIFT keys.

This keymap file allows the server to take a KEYCODE and turn it into a
KEYSYM.  This provides X with device independence, because once the keycode
has been converted into a keysym (using the device-dependent mechanism of
a keymap file) applications don't need to be concerned with what keyboard
is being used.

For example, using the NORTH_AMERICAN_LK201LA.DECW$KEYMAP file if
you press the 'D' key you'll generate a %xCD (205), which is translated into
a KEYSYM value of %x0044 (68).  This just so happens to be the equivalent of
the ASCII 'D', but this is purely for convenience.

At this point the server uses the X11:KEYSYMDEF.H file to translate the
KEYSYM value into a KEYSYM symbol.  For example, the 'D' key has a
KEYSYM value of %x044, which, according to the KEYSYMDEF.H file, equates
to a symbol of XK_D.  Note that X11R4 Xlib gives the ability to add a file
that defines additional keysyms over those built into the server.  This
file is called DECW$INCLUDE:DECW$XKEYSYMDB.DAT on VMS; /usr/lib/X11/XKeysymDB
on U*NX.

It's possible to use the xmodmap utility to change the keyboard mapping.

For example, assume KEYCODE definitions as follows:

KEYCODE         KEYSYM VALUE            KEYSYM NAME
=======         ============            ===========
  7C            FF6A                    Help
  86            FFBE                    F1

If we then do a:

xmodmap -e "keysym F1 = Help"

we'll now see:

KEYCODE         KEYSYM VALUE            KEYSYM NAME
=======         ============            ===========
  7C            FF6A                    Help
  86            FF6A                    Help

The above xmodmap routine essentially says when the key that's pressed
that's associated to KEYCODE 86 (the F1 key), make the server send a keysym
value of FF6A (Help) instead of FFBE (F1).

A common problem when you telnet from a Digital VMS workstation to a
UN*X machine is that your delete key will no longer work.  This is because
the VMS server sets the delete key (keycode = 188) to be a keysym of
0xffff (symbol = Delete).  Unfortunately many UN*X machines will anticipate
the "Rubout" key as being a BackSpace key.  As a result the server will
send a Delete key to the client, which doesn't know what to do with it,
because it's expecting a BackSpace key.

A solution to this is to tell the VMS server to send a BackSpace keysym
(%xff08) instead of a Delete (%xffff).  This can be done using xmodmap
as follows:

% xmodmap -e "keysym Delete = BackSpace" -display your_vms_server:0.0

For this to work it's important that the terminal you're using on the UN*X
client is interpreting the BackSpace key as the erase character, or
^H.  To ensure this, you should be able to enter:

% setenv TERM vt100
% tset -e -k

The tset command will set the erase character to control-H and the kill
character (i.e. "kill" or "ignore the line typed so far") to control-X.
It's also possible to use stty to do this:

% stty erase ^H
% stty kill ^X

Simply typing tset will often set the erase key (and possible kill key)
automatically.  It's common to see .login files do something like:

% tset -I -Q

This sets erase/kill while suppressing terminal inititialization strings
and informational messages.

SUN workstations allow you to:

% stty dec

which automatically sets up your session in conformance to Digital behavior.

One (1) disadvantage of modifying your server's key mapping is that if you
have multiple DECterm's and some are on a VMS machine while others are on
a UN*X machine your Rubout key on VMS will now not work.


-----------------------------------------------------------------
II. INFORMATIVE MAN PAGES XMODMAP INFORMATION ON KEYCODES/KEYSYMS
-----------------------------------------------------------------

Here's some information on keycode/keysym extracted from the xmodmap
man pages:


      keycode NUMBER = KEYSYMNAME ...
              The list of keysyms is assigned to the indicated keycode
              (which may be specified in decimal, hex or octal).  This list
              determines the keysym assigned to the corresponding keypress
              event when no modified, shift, mod1 or shift+mod1 are used
              (the standard translation makes use of only the first four
              keysyms in the list).

      keysym KEYSYMNAME = KEYSYMNAME ...
              An alternate way of assigning keysyms to a key by identifying
              the key with a symbolic name rather than a numeric keycode.
              The KEYSYMNAME on the left hand side is translated into a
              keycode (using XStringToKeysym() and XKeysymToKeycode()) and
              used to perform the corresponding keycode expression.  The
              list of keysym names may be found in the header file
              <X11/keysymdef.h> (without the XK_ prefix) or the keysym
              database /usr/lib/X11/XKeysymDB.  Note that if the same keysym
              is bound to multiple keys, the results for this expression are
              not defined.

      One of the more simple, yet convenient, uses of xmodmap is to set the
      keyboard's "rubout" key to generate an alternate keysym.  This
      frequently involves exchanging Backspace with Delete to be more
      comfortable to the user.  If the ttyModes resource in xterm is set as
      well, all terminal emulator windows will use the same key for erasing
      characters:

           %  xmodmap -e "keysym BackSpace = Delete"
           %  echo "XTerm*ttyModes:  erase ^?" | xrdb -merge


-------------------------------
III. OSF/MOTIF VIRTUAL BINDINGS
-------------------------------

Virtual Bindings give OSF/Motif a method of associating a button or key
to an actual event *virtually*.  That is, the events as described do not
necessarily correspond to a fixed set of X Window System events.

An example may be helpful.  When using the XmText widget in Motif various
events (ex: KDelete) will translate into associated actions
(delete-next-character).  (For a list of XmText translations,
see pages 1-1009 thru 1-1012 of the OSF/Motif Programmer's Reference
Manual.)  The "KDelete" key is considered a "Virtual Key".  A table on
page 1-161 thru 1-163 of the OSF/Motif Programmer's Reference Manual
("Virtual Key Bindings") lists the bindings of virtual keys to actual
key event descriptions in OSF/Motif.  Using the KDelete example, the
actual key event that will generate a KDelete is <Key>osfDelete.
Note that there  may be more than one actual key event that will result in
the corresponding virtual key.  For example, a KCut can be generated by
either a <Key>osfCut or a Shift<Key>osfDelete actual key event.
The binding of a Virtual Key to an Actual Key Event is fixed in
Motif, and is represented by the Virtual Key Bindings table mentioned above.

In order to generate an "osf" key, Motif maintains a mapping between "osf"
keysyms and actual keysyms.  The table on page 1-165 of the OSF/Motif
Programmer's Reference Manual defines the "Fallback Default Bindings" for
"osf" Keysyms".  For example, the Delete key is the Fallback Default
Binding for the "osf" Keysym osfDelete.

Note that it *is* possible to override this, but it can be tricky and is
poorly documented.

The order of precedence that is followed when mapping "osf" keysyms to
actual keysyms, listed from *lowest* priority to highest is:

1. A fixed fallback default.  This is listed on page 1-165 of the OSF/Motif
   Reference Manual.  This is by far what is most often used.

2. A fixed default based on the vendor string returned by the X server during
   the call to XOpenDisplay.

3. An XmNdefaultVirtualBindings application resource in the resource database.
   This is possible to use and will work, however it's imperative that there
   be no typos in the file and that the all the virtual bindings are supplied,
   not just some of them.  The symptoms that something is wrong with your
   virtual bindings are typically that no osf keys are recognized in your
   Motif application.  For example, the arrow keys or delete key don't work
   within an XmText widget.

   A sample virtual bindings resource file follows:

*defaultVirtualBindings:\
 osfCancel      :               <Key>F11        \n\
 osfLeft        :               <Key>Left       \n\
 osfUp          :               <Key>Up         \n\
 osfRight       :               <Key>Right      \n\
 osfDown        :               <Key>Down       \n\
 osfEndLine     :Alt            <Key>Right      \n\
 osfBeginLine   :Alt            <Key>Left       \n\
 osfPageUp      :               <Key>Prior      \n\
 osfPageDown    :               <Key>Next       \n\
 osfDelete      :Shift          <Key>Delete     \n\
 osfUndo        :Alt            <Key>Delete     \n\
 osfBackSpace   :               <Key>Delete     \n\
 osfAddMode     :Shift          <Key>F8         \n\
 osfHelp        :               <Key>Help       \n\
 osfMenu        :               <Key>F4         \n\
 osfMenuBar     :               <Key>F10        \n\
 osfSelect      :               <Key>Select     \n\
 osfActivate    :               <Key>KP_Enter   \n\
 osfCopy        :Shift          <Key>DRemove    \n\
 osfCut         :               <Key>DRemove    \n\
 osfPaste       :               <Key>Insert

Note that the slightest typo can cause the virtual bindings to not work.
For example, inserting even a single extra <SPACE> character after the
osf keys.  (i.e. delete won't work, arrow keys won't work, etc.)

4. A _MOTIF_BINDINGS property on the root window of screen 0.  The Motif
   Window Manager sets this property when it starts up, taking the contents
   from the .motifbind file in the user's home directory.  On VMS, this
   file is called DECW$MOTIFBIND.DAT.

   A sample .motifbind file follows.  This file was taken from the SUN
   Motif kit (./examples/X11/motifbindings/dec and modified to try to
   correspond to the VMS default implementation.  Since VMS does not
   include its default .motifbind (DECW$MOTIFBIND.DAT) file the following
   file could be used as a template for a user who wants to create their
   own.

!"DECWINDOWS DigitalEquipmentCorp."
!
!

osfCancel       :               <Key>F11
osfLeft         :               <Key>Left
osfUp           :               <Key>Up
osfRight        :               <Key>Right
osfDown         :               <Key>Down
osfEndLine      :Alt            <Key>Right
osfBeginLine    :Alt            <Key>Left
osfPageDown     :               <Key>Prior
osfPageUp       :               <Key>Next
osfBackSpace    :               <Key>Delete
osfCut          :               <Key>DRemove
osfPaste        :               <Key>Insert
osfAddMode      :Shift          <Key>F8
osfHelp         :               <Key>Help
osfMenuBar      :               <Key>F10
osfMenu         :               <Key>F4
osfSelect       :               <Key>Select
osfActivate     :               <Key>KP_Enter
osfPrimaryPaste :               <Key>F14
osfQuickPaste   :               <Key>F17

Note that its format is similar to, but not identical to, the
XmNdefaultVirtualBindings resource.  Also note that if this file
exists, it will take precedence over any XmNdefaultVirtaulBindings
resource that may have been set up.


---------------------------------------------------------
IV. INFORMATIVE .MOTIFBIND INFORMATION FROM SUN MOTIF KIT
---------------------------------------------------------

The following is taken from the ./examples/X11/motifbindings/README file
and has good information on the purpose of this file, pointers to
motifbind files for other vendor keyboards, etc.

This directory contains a collection of sample ".motifbind" files:

acorn
apollo
dec
dg_AViiON
doubleclick
hitachi
hp
ibm
intergraph17
intergraph
megatek
motorola
ncr_at
ncr_vt
sgi
siemens_9733
siemens_wx200
sun_mit
sun_news
tek

These files were provided by various vendors, though not necessarily
the vendors whose hardware they apply to.  Each file contains a set of
keyboard bindings that is suggested for use on that particular
server/hardware combination.  These files should be used as examples
of ~/.motifbind files to work from.

By copying the appropriate file into the user's home directory and
renaming it to ".motifbind", the bindings will be recognized and used
when the Motif window manager is (re)started.
These bindings will override any other default bindings except those
initiated within a client application (using XtOverrideTranslations).

These examples are provided, as is, only as a service to the vendors
and users.


---------------------------------------------------------
V. LIFE OF AN OSF/MOTIF KEY (FROM KEYCODE TO VIRTUAL KEY)
---------------------------------------------------------

This diary traces the life of a key (the Right Arrow key) from its inception
as a simple X keycode to its fulfillment as an OSF/Motif "Virtual Key":

1. User presses the <RIGHT ARROW> key within a Motif application's XmText
   widget.

2. The X server uses the appropriate keymap file (the default is
   DECW$KEYMAP:NORTH_AMERICAN_LK201LA.DECW$KEYMAP) to convert the
   keycode into a keysym:

        KEYCODE (A8)  -->  KEYSYM = FF53

3. The X server then uses information from the X11:KEYSYMDEF.H file to
   convert the keysym into a keysym Name:

        KEYSYM (FF53) -->  KEYSYM NAME (Right)

   At this point if we were to run xmodmap (with the -pk switch) we'd
   see the Right Arrow Key defined as:


           KeyCode      Keysym (Keysym) ...
           Value        Value   (Name)  ...

            168         0xff53 (Right)

   Note that 168 is A8 (hex).

   At this point the client knows it has received a "Right" Keysym Name and,
   because this is an OSF/Motif application, must convert this into a
   Virtual Key.

4. Motif (client) now attempts to translate the "Right" Keysym Name into an
   "osf" Keysym.  It does this by using (in order of least to highest
   precedence):

        1. A fixed fallback default
        2. A fixed efault based on the vendor string returned by the X
           server during the call to XOpenDisplay.
        3. An XmNdefaultVirtualBindings application resource in the resource
           database.
        4. A _MOTIF_BINDINGS property on the roto window of screen 0, placed
           there by the Motif Window Manager reading the contents from the
           DECW$MOTIFBIND.DAT file in the user's home directory.

   By default, VMS will associate the "Right" Keysym Name into an "osf"
   Keysym of "osfRight".

5. OSF/Motif now will bind the "osfRight" actual key event to a virtual key.
   This is a fixed translation that's documented on page 1-161 of the
   OSF/Motif Programmer's Reference Manual.  OSF/Motif associates
   <Key>osfRight to be a virtual key of "KRight".

6. We're now at the end of the line.  Because we're using an XmText widget
   there is an action routine that's associated to the KRight key.  Looking
   at page 1-1010 of the OSF/Motif Programmer's Reference Manual we can
   observe that:

        KRight: forward-character()

   If we had chosen to capture the osfRight key ourselves using our own
   translation table we might have code that looks like:

        static char *my_translations = "<KeyPress>osfRight: RightKey()";


------------------
VI. PRINT_KEYSYM.C
------------------

The attached program will allow the user to enter any key into an OSF/Motif
XmText widget.  The program will then display the appropriate keysym for
the keypress that triggered the event.


/*                                                                           
*/
/*              COPYRIGHT 1992 DIGITAL EQUIPMENT CORPORATION                
*/
/*                                                                           
*/
/*   THIS SOFTWARE MAY BE COPIED WITHOUT FEE PROVIDED THAT THE COPIES ARE    
*/
/*   NOT MADE OR DISTRIBUTED FOR DIRECT COMMERCIAL ADVANTAGE, THAT CREDIT    
*/
/*   TO THE SOURCE IS GIVEN, AND THAT THIS ENTIRE COPYRIGHT NOTICE IS        
*/
/*   INCLUDED.                                                               
*/
/*                                                                           
*/
/*   THE INFORMATION IN THIS SOFTWARE SHOULD NOT BE CONSTRUED AS A           
*/
/*   COMMITMENT BY DIGITAL EQUIPMENT CORPORATION.                            
*/
/*                                                                           
*/
/*   DIGITAL EQUIPMENT CORPORATION ASSUMES NO RESPONSIBILITY FOR THE USE,    
*/
/*   SUPPORT, OR RELIABILITY OF THIS SOFTWARE.  THIS SOFTWARE IS             
*/
/*   DISTRIBUTED "AS IS."                                                    
*/
/*                                                                           
*/


#include <stdio.h>
#include <Xm/PushB.h>
#include <Xm/Text.h>
#include <Xm/DialogS.h>
#include <X11/Shell.h>
#include <X11/Vendor.h>
#include <Xm/Xm.h>
#include <X11/StringDefs.h>

#define CS(label)       XmStringLtoRCreate (label, XmSTRING_DEFAULT_CHARSET)

static void     exit_proc ();

static XtCallbackRec  exit_cb [] = { {exit_proc, NULL},
                                           {NULL,      NULL} };

static void     print_keysym ();

static char our_translation_table [] =
    "~Ctrl ~Shift ~Meta ~Alt<Btn1Down>:         grab-focus()\n\
     <Key>:                                     print_keysym()";

static XtTranslations our_translations_parsed;

static XtActionsRec our_action_table [] =
{
    {"print_keysym",    (XtActionProc) print_keysym},
};

static void
print_keysym (w, event, params, num_params)
    Widget   w;
    XKeyEvent  *event;
    char   **params;
    int      num_params;
{
    char * keysym_string;
    KeySym keysym;
    Modifiers modifiers;

    keysym = XtGetActionKeysym(event, &modifiers);
    keysym_string = XKeysymToString(keysym);
    if (keysym_string)
        printf ("%s\n", keysym_string);
    else
        printf ("%x\n", keysym);
}

int     init_it (argc, argv)
    unsigned int        argc;
    char                **argv;
{
    Widget tl, bb, pb, tw;
    Arg al[25];
    int ac = 0;

    tl = XtInitialize (argv[0], "print_keysyms", NULL, 0, &argc, &argv);

    XtAddActions (our_action_table, 1);

    XtSetArg (al[ac], XmNautoUnmanage, FALSE);                  ac++;
    bb = XmCreateBulletinBoardDialog (tl, "bb", al, ac);

    ac = 0;
    XtSetArg (al[ac], XmNx, 30);                                ac++;
    XtSetArg (al[ac], XmNy, 55);                                ac++;
    XtSetArg (al[ac], XmNlabelString, CS ("Exit"));     ac++;
    XtSetArg (al[ac], XmNactivateCallback, exit_cb);            ac++;
    pb = XmCreatePushButton (bb, "pb", al, ac);
    XtManageChild (pb);

    ac = 0;
    XtSetArg (al[ac], XmNx, 30);                                ac++;
    XtSetArg (al[ac], XmNy, 10);                                ac++;
    our_translations_parsed = XtParseTranslationTable(our_translation_table);
    XtSetArg (al[ac], XtNtranslations, our_translations_parsed);    ac++;
    tw = XmCreateText (bb, "tw", al, ac);
    XtManageChild (tw);

    XtManageChild (bb);
}

int main (argc, argv)
    int argc;
    char *argv[];
{
    init_it (argc, argv);

    XtMainLoop ();
}

static void exit_proc (w, tag, reason)
    Widget              w;
    caddr_t             *tag;
    unsigned int        *reason;
{
   exit (1);
}

        Compile/Link Information:

        1.  cc -c print_keysym.c

                   OR

        2.  cc -o print_keysym print_keysym.o -lXm -lXt -lXext -lX11

                   OR

        3.  cc -o print_keysym print_keysym.c -lXm -lXt -lXext -lX11 



