From: greg@thirdi.uucp (Greg Holmberg)
Newsgroups: comp.windows.x.motif
Subject: Re: question about virtual keysyms in motif
Keywords: motif virtual keysyms
Date: 16 Dec 92 21:21:11 GMT
Reply-To: greg@thirdi.UUCP (Greg Holmberg)
Organization: Third Eye Software, Menlo Park, CA

In article <1992Dec7.090058.21866@88opensi.88open.ORG> tbr@88opensi.88open.ORG (Terry Rhodes) writes:
	I am not that familiar w/X and motif internals but am trying to 
	help someone porting a X11R5 motif application. When we run the
	application on older R4 and R5 platforms we get errors saying
	that keysyms like osfPageRight are undefined.
	
	Reading section 2.3.6 of the Motif Programming Manual, I have
	determined that these are bound by reading /usr/lib/X11/XKeysymDB.
	I would just copy XKeysymDB to these systems except that some
	already have this file and overwrites or concatenation are not
	options.

osfPageRight is not BOUND in XKeysymDB, it is simply DEFINED there.
It is bound in ~/.motifbind.

You can set the environment variable XKEYSYMDB to the path to your
file.  Each Motif user would of course have to do this.  Or you
could wrap your executable in a shell script that sets the variable.
All Motif applications will be looking for the OSF additions, though.
It may be easier to append the one in /usr/lib/X11.
	
	The manual (pg 36) states that virtual bindings can be specified
	by application but doesn't mention how to implement this. Does
	anyone know how to do this?
	
	The manual mentions that the user can specify these in a file
	called .motifbind in his home directory. I have tried creating this
	file, but it never seems to be read. Can anyone give me any
	pointers here?

You can do this.  Don't confuse the bindings with the keysyms though -
you need both.  Each server/keyboard combo could potentially need
a different set of bindings.  DEC needs this, Sun needs that, etc.

Motif applications do not read the .motifbind file directly.  They read
the "_MOTIF_BINDINGS" property from the server.  The Motif window
manager loads the file into the property when it starts.  If you don't
have mwm, here is a little program I wrote to load the property.

Your Motif library supplier should provide a new XKeysymDB file or some
lines to append, and a set of .motifbind files for various platforms.
You need to provide these to your end-users.  Remember, X is a
network-based window system, so even though you may know the binaries
are for a Sun SPARC, you don't what the server is, so you have to
provide .motifbind files for many machines.


Greg Holmberg
greg@thirdeye.com or ...!{apple,pyramid,cdp}!thirdi!greg
Third Eye Software, Inc., 750 Menlo Avenue, Suite 300, Menlo Park, CA 94025
415/321-0967 Voice, 415/321-2066 Fax


#ifdef __STDC__
# undef _NO_PROTO
# define PARMS(p) p
# include <stdarg.h>
# define Va_start(list, last) va_start(list, last)
# define VARFUNC1(n, t1, a1) n(t1 a1, ...)
#else
# define _NO_PROTO
# define PARMS(p) ()
# include <varargs.h>
# define Va_start(list, last) va_start(list)
# define VARFUNC1(n, t1, a1) n(a1, va_alist) t1 a1; va_dcl
#endif

#define isNil(p) (((void *) (p)) == ((void *) 0))
typedef char *string;
typedef int boolean;
#define true ((boolean) 1)
#define false ((boolean) 0)

#include <stdio.h>
extern string vsprintf PARMS((string, string, ...));
extern int fputs PARMS((string, FILE *));
extern int fread PARMS((string, int, int, FILE *));
extern int fclose PARMS((FILE *));
extern int fprintf PARMS((FILE *, string, ...));
extern string getenv PARMS((string));

#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <Xm/MwmUtil.h>

#include <errno.h>
extern int errno;
extern string sys_errlist[];
extern int sys_nerr;

/* Globals */
Display *display;
Atom MOTIF_BINDINGS;
string progname;


boolean SetBindings(fileName)
string fileName;

{
    FILE		*fileP;
    static unsigned char	buffer[4096];
    int			count;
    static int		mode = PropModeReplace;

    fileP = fopen(fileName, "r");
    if (isNil(fileP))
	return false;

    while ((count = fread((char *) buffer, 1, sizeof(buffer), fileP)) > 0) {
	XChangeProperty (display, RootWindow(display, 0),
	    MOTIF_BINDINGS, 
	    XA_STRING, 8, mode, 
	    buffer, count);

	mode = PropModeAppend;
    }

    fclose(fileP);
    return true;
}


void VARFUNC1(Usage,
string,	sbFormat)

{
    va_list	args;
    static char buffer[128];

    Va_start(args, sbFormat);
    (void) vsprintf(buffer, sbFormat, args);
    fputs(buffer, stderr);
    va_end(args);

    fprintf(stderr, "\
\n\
Usage: %s {-display <host>:<screen>} <file>\n\
\n\
Loads <file> (usually ~/.motifbind) into the _MOTIF_BINDINGS property of the\n\
root window.  Normally mwm does this for you, but if you want to reload\n\
the bindings without restarting the window manager, or you are not using\n\
mwm, then you should use this tool.\n\
\n\
The bindings determine how your keyboard is interpreted by Motif-based\n\
applications.  If, for example, you find that you can't erase characters\n\
in text widgets, you probably need to load the right set of bindings for\n\
your X server.  After you load the bindings, you must restart your\n\
Motif-based applications.  Your non-Motif applications, your window manager,\n\
and your X server do NOT need to be restarted.\n\
\n\
For more information, see VirtualBindings(3XM) and mwm(1X).\n\
",
	progname);
    
    exit(1);
}


int main(argc, argv)
    int argc;
    string argv[];

{
    string *arg;
    string dpyName = NULL;
    string file = NULL;

    progname = argv[0];

    for (arg = &argv[1]; !isNil(*arg); ++arg) {
	if (strcmp("-display", *arg) == 0 || strcmp("-d", *arg) == 0) {
	    ++arg;
	    if (!isNil(dpyName))
		Usage("You have specified two displays, %s and %s\n",
		    dpyName, *arg);
	    dpyName = *arg;
	}
	else
	if (*arg[0] != '-') {
	    if (!isNil(file))
		Usage("You have specified two binding files, %s and %s\n",
		    file, *arg);
	    file = *arg;
	}
	else
	    Usage("%s is not a recognized option.\n", *arg);
    }   /* for arg */

    if (isNil(file))
	Usage("You must specify a binding file.\n");

    /* dpyName is allowed to be unspecified (NULL): means use $DISPLAY. */

    display = XOpenDisplay(dpyName);
    if (isNil(display)) {
	fprintf(stderr, "%s: Can't open display %s.\n",
	    progname, isNil(dpyName) ? getenv("DISPLAY") : dpyName);
	return 1;
    }

    /* Get the atom for the property. */
    MOTIF_BINDINGS = XInternAtom(display, _XA_MOTIF_BINDINGS, False);

    if (!SetBindings(file))
	fprintf(stderr, "%s: Can't open file '%s': %s.\n",
	    progname, file, sys_errlist[errno]);

    XCloseDisplay(display);
    return 0;
}
-- 
Greg Holmberg
greg@thirdeye.com or ...!{apple,pyramid,cdp}!thirdi!greg
Third Eye Software, Inc., 750 Menlo Avenue, Suite 300, Menlo Park, CA 94025
415/321-0967 Voice, 415/321-2066 Fax
Newsgroups: comp.windows.x.motif