Blame lib/Xm/VirtKeys.c

Packit b099d7
/* 
Packit b099d7
 * Motif
Packit b099d7
 *
Packit b099d7
 * Copyright (c) 1987-2012, The Open Group. All rights reserved.
Packit b099d7
 *
Packit b099d7
 * These libraries and programs are free software; you can
Packit b099d7
 * redistribute them and/or modify them under the terms of the GNU
Packit b099d7
 * Lesser General Public License as published by the Free Software
Packit b099d7
 * Foundation; either version 2 of the License, or (at your option)
Packit b099d7
 * any later version.
Packit b099d7
 *
Packit b099d7
 * These libraries and programs are distributed in the hope that
Packit b099d7
 * they will be useful, but WITHOUT ANY WARRANTY; without even the
Packit b099d7
 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
Packit b099d7
 * PURPOSE. See the GNU Lesser General Public License for more
Packit b099d7
 * details.
Packit b099d7
 *
Packit b099d7
 * You should have received a copy of the GNU Lesser General Public
Packit b099d7
 * License along with these librararies and programs; if not, write
Packit b099d7
 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
Packit b099d7
 * Floor, Boston, MA 02110-1301 USA
Packit b099d7
*/ 
Packit b099d7
/* 
Packit b099d7
 * HISTORY
Packit b099d7
*/ 
Packit b099d7
#ifdef HAVE_CONFIG_H
Packit b099d7
#include <config.h>
Packit b099d7
#endif
Packit b099d7
Packit b099d7
Packit b099d7
#ifdef REV_INFO
Packit b099d7
#ifndef lint
Packit b099d7
static char rcsid[] = "$TOG: VirtKeys.c /main/22 1999/06/02 14:45:52 samborn $"
Packit b099d7
#endif
Packit b099d7
#endif
Packit b099d7
/* (c) Copyright 1990, 1991, 1992 HEWLETT-PACKARD COMPANY */
Packit b099d7
/* (c) Copyright 1990 MOTOROLA, INC. */
Packit b099d7
Packit b099d7
#ifndef X_NOT_STDC_ENV
Packit b099d7
#include <stdlib.h>
Packit b099d7
#endif
Packit b099d7
Packit b099d7
#include <stdio.h>
Packit b099d7
#include <ctype.h>
Packit b099d7
#include <string.h>
Packit b099d7
#include <X11/keysym.h>
Packit b099d7
#include <Xm/DisplayP.h>
Packit b099d7
#include <Xm/TransltnsP.h>
Packit b099d7
#include <Xm/AtomMgr.h>
Packit b099d7
#include <Xm/XmosP.h>
Packit b099d7
#include "MapEventsI.h"
Packit b099d7
#include "VirtKeysI.h"
Packit b099d7
#include "XmosI.h"
Packit b099d7
#include "XmI.h"
Packit b099d7
Packit b099d7
Packit b099d7
#define defaultFallbackBindings _XmVirtKeys_fallbackBindingString
Packit b099d7
Packit b099d7
#define BUFFERSIZE	2048
Packit b099d7
#define MAXLINE		256
Packit b099d7
Packit b099d7
/********    Static Function Declarations    ********/
Packit b099d7
Packit b099d7
static Boolean CvtStringToVirtualBinding(Display *dpy,
Packit b099d7
					 XrmValuePtr args,
Packit b099d7
					 Cardinal *num_args,
Packit b099d7
					 XrmValuePtr fromVal,
Packit b099d7
					 XrmValuePtr toVal,
Packit b099d7
					 XtPointer *closure_ret);
Packit b099d7
static void FillBindingsFromDB(Display *dpy,
Packit b099d7
			       XrmDatabase rdb,
Packit b099d7
			       XmVKeyBinding *keys,
Packit b099d7
			       Cardinal *num_keys);
Packit b099d7
static Boolean GetBindingsProperty(Display *display,
Packit b099d7
				   String property,
Packit b099d7
				   String *binding);
Packit b099d7
static void FindVirtKey(Display *dpy,
Packit b099d7
                        KeyCode keycode,
Packit b099d7
                        Modifiers modifiers,
Packit b099d7
                        Modifiers *modifiers_return,
Packit b099d7
                        KeySym *keysym_return);
Packit b099d7
static Modifiers EffectiveStdModMask(Display *dpy,
Packit b099d7
				     KeySym *kc_map,
Packit b099d7
				     int ks_per_kc);
Packit b099d7
static void LoadVendorBindings(Display *display,
Packit b099d7
			       char *path,
Packit b099d7
			       FILE *fp,
Packit b099d7
			       String *binding);
Packit b099d7
Packit b099d7
/********    End Static Function Declarations    ********/
Packit b099d7
Packit b099d7
static XmConst XmVirtualKeysymRec virtualKeysyms[] =
Packit b099d7
{
Packit b099d7
  { XmVosfActivate,		osfXK_Activate	      },
Packit b099d7
  { XmVosfAddMode,		osfXK_AddMode	      },
Packit b099d7
  { XmVosfBackSpace,		osfXK_BackSpace	      },
Packit b099d7
  { XmVosfBackTab,		osfXK_BackTab	      }, /* Defunct */
Packit b099d7
  { XmVosfBeginData,		osfXK_BeginData	      }, /* Defunct */
Packit b099d7
  { XmVosfBeginLine,		osfXK_BeginLine	      },
Packit b099d7
  { XmVosfCancel,		osfXK_Cancel	      },
Packit b099d7
  { XmVosfClear,		osfXK_Clear	      },
Packit b099d7
  { XmVosfCopy,			osfXK_Copy	      },
Packit b099d7
  { XmVosfCut,			osfXK_Cut	      },
Packit b099d7
  { XmVosfDelete,		osfXK_Delete	      },
Packit b099d7
  { XmVosfDeselectAll,		osfXK_DeselectAll     },
Packit b099d7
  { XmVosfDown,			osfXK_Down	      },
Packit b099d7
  { XmVosfEndData,		osfXK_EndData	      }, /* Defunct */
Packit b099d7
  { XmVosfEndLine,		osfXK_EndLine	      },
Packit b099d7
  { XmVosfEscape,		osfXK_Escape	      }, /* Defunct */
Packit b099d7
  { XmVosfExtend,		osfXK_Extend	      }, /* Defunct */
Packit b099d7
  { XmVosfHelp,			osfXK_Help	      },
Packit b099d7
  { XmVosfInsert,		osfXK_Insert	      },
Packit b099d7
  { XmVosfLeft,			osfXK_Left	      },
Packit b099d7
  { XmVosfLeftLine,		osfXK_LeftLine	      }, /* X11R6 */
Packit b099d7
  { XmVosfMenu,			osfXK_Menu	      },
Packit b099d7
  { XmVosfMenuBar,		osfXK_MenuBar	      },
Packit b099d7
  { XmVosfNext,			osfXK_Next	      }, /* X11R6 */
Packit b099d7
  { XmVosfNextField,		osfXK_NextField	      }, /* Defunct */
Packit b099d7
  { XmVosfNextMenu,		osfXK_NextMenu	      }, /* Defunct */
Packit b099d7
  { XmVosfNextMinor,		osfXK_NextMinor	      }, /* X11R6 */
Packit b099d7
  { XmVosfPageDown,		osfXK_PageDown	      },
Packit b099d7
  { XmVosfPageLeft,		osfXK_PageLeft	      },
Packit b099d7
  { XmVosfPageRight,		osfXK_PageRight	      },
Packit b099d7
  { XmVosfPageUp,		osfXK_PageUp	      },
Packit b099d7
  { XmVosfPaste,		osfXK_Paste	      },
Packit b099d7
  { XmVosfPrevField,		osfXK_PrevField	      }, /* Defunct */
Packit b099d7
  { XmVosfPrevMenu,		osfXK_PrevMenu	      }, /* Defunct */
Packit b099d7
  { XmVosfPrimaryPaste,		osfXK_PrimaryPaste    },
Packit b099d7
  { XmVosfPrior,		osfXK_Prior	      }, /* X11R6 */
Packit b099d7
  { XmVosfPriorMinor,		osfXK_PriorMinor      }, /* X11R6 */
Packit b099d7
  { XmVosfQuickPaste,		osfXK_QuickPaste      },
Packit b099d7
  { XmVosfReselect,		osfXK_Reselect	      },
Packit b099d7
  { XmVosfRestore,		osfXK_Restore	      },
Packit b099d7
  { XmVosfRight,		osfXK_Right	      },
Packit b099d7
  { XmVosfRightLine,		osfXK_RightLine	      }, /* X11R6 */
Packit b099d7
  { XmVosfSelect,		osfXK_Select	      },
Packit b099d7
  { XmVosfSelectAll,		osfXK_SelectAll	      },
Packit b099d7
  { XmVosfSwitchDirection,	osfXK_SwitchDirection }, /* X11R6 */
Packit b099d7
  { XmVosfUndo,			osfXK_Undo	      },
Packit b099d7
  { XmVosfUp,			osfXK_Up	      }
Packit b099d7
};
Packit b099d7
Packit b099d7
static XmConst XmDefaultBindingStringRec fallbackBindingStrings[] =
Packit b099d7
{
Packit b099d7
  { "Acorn Computers Ltd", 
Packit b099d7
      _XmVirtKeys_acornFallbackBindingString },
Packit b099d7
  { "Apollo Computer Inc.",
Packit b099d7
      _XmVirtKeys_apolloFallbackBindingString },
Packit b099d7
  { "DECWINDOWS DigitalEquipmentCorp.",
Packit b099d7
      _XmVirtKeys_decFallbackBindingString },
Packit b099d7
  { "Data General Corporation  Rev 04",
Packit b099d7
      _XmVirtKeys_dgFallbackBindingString },
Packit b099d7
  { "Double Click Imaging, Inc. KeyX",
Packit b099d7
      _XmVirtKeys_dblclkFallbackBindingString },
Packit b099d7
  { "Hewlett-Packard Company",
Packit b099d7
      _XmVirtKeys_hpFallbackBindingString },
Packit b099d7
  { "International Business Machines",
Packit b099d7
      _XmVirtKeys_ibmFallbackBindingString },
Packit b099d7
  { "Intergraph Corporation",
Packit b099d7
      _XmVirtKeys_ingrFallbackBindingString },
Packit b099d7
  { "Megatek Corporation",
Packit b099d7
      _XmVirtKeys_megatekFallbackBindingString },
Packit b099d7
  { "Motorola Inc. (Microcomputer Division) ",
Packit b099d7
      _XmVirtKeys_motorolaFallbackBindingString },
Packit b099d7
  { "Silicon Graphics Inc.",
Packit b099d7
      _XmVirtKeys_sgiFallbackBindingString },
Packit b099d7
  { "Silicon Graphics",
Packit b099d7
      _XmVirtKeys_sgiFallbackBindingString },
Packit b099d7
  { "Siemens Munich by SP-4's Hacker Crew",
Packit b099d7
      _XmVirtKeys_siemensWx200FallbackBindingString },
Packit b099d7
  { "Siemens Munich (SP-4's hacker-clan)",
Packit b099d7
      _XmVirtKeys_siemens9733FallbackBindingString },
Packit b099d7
  { "Sun Microsystems, Inc.",
Packit b099d7
      _XmVirtKeys_sunFallbackBindingString },
Packit b099d7
  { "X11/NeWS - Sun Microsystems Inc.",
Packit b099d7
      _XmVirtKeys_sunFallbackBindingString },
Packit b099d7
  { "Tektronix, Inc.",
Packit b099d7
      _XmVirtKeys_tekFallbackBindingString }
Packit b099d7
};
Packit b099d7

Packit b099d7
/*ARGSUSED*/
Packit b099d7
static Boolean 
Packit b099d7
CvtStringToVirtualBinding(Display    *dpy,
Packit b099d7
			  XrmValuePtr args,
Packit b099d7
			  Cardinal   *num_args,
Packit b099d7
			  XrmValuePtr fromVal,
Packit b099d7
			  XrmValuePtr toVal,
Packit b099d7
			  XtPointer  *closure_ret )
Packit b099d7
{
Packit b099d7
    char 	 *str = (char *)fromVal->addr;
Packit b099d7
    XKeyEvent	  event;
Packit b099d7
    int		  count, tmp;
Packit b099d7
    int		 *eventTypes;
Packit b099d7
    KeySym       *keysyms;
Packit b099d7
    unsigned int *modifiers;
Packit b099d7
    int		  j;
Packit b099d7
    int		  codes_per_sym;
Packit b099d7
    KeyCode	  minK;
Packit b099d7
    Modifiers	  used_mods;
Packit b099d7
Packit b099d7
    /* Lookup codes_per_sym, and let Xt cache the result instead of */
Packit b099d7
    /* always downloading a new copy with XGetKeyboardMapping(). */
Packit b099d7
    /* This also initializes Xt's per-display data structures, so */
Packit b099d7
    /* we can use XtTranslateKey() instead of XLookupString(). */
Packit b099d7
    (void) XtGetKeysymTable(dpy, &minK, &codes_per_sym);
Packit b099d7
Packit b099d7
    count = _XmMapKeyEvents(str, &eventTypes, &keysyms, &modifiers);
Packit b099d7
    if (count > 0)
Packit b099d7
      {
Packit b099d7
	Boolean fini;
Packit b099d7
Packit b099d7
	for (tmp = 0; tmp < count; tmp++)
Packit b099d7
	  {
Packit b099d7
	    fini = False;  
Packit b099d7
Packit b099d7
	    /*
Packit b099d7
	     * Here's a nasty bit of code. If some vendor defines one of
Packit b099d7
	     * the standard modifiers to be the mode switch mod, the
Packit b099d7
	     * keysym returned by XtTranslateKey is the mode-shifted 
Packit b099d7
	     * one. This may or may not be bogus, but we have to live
Packit b099d7
	     * with it :-(. Soo, we need to translate the keysym to a
Packit b099d7
	     * keycode, then ask someone to translate the combo for us.
Packit b099d7
	     */
Packit b099d7
	    event.display = dpy;
Packit b099d7
	    event.keycode = XKeysymToKeycode(dpy, keysyms[tmp]);
Packit b099d7
	    
Packit b099d7
	    /*
Packit b099d7
	     * In case the guy specifies a symbol that is modified (like
Packit b099d7
	     * HP's Del which is <shift><escape>), we'll find the implied
Packit b099d7
	     * modifers and 'OR' it together with the explicitly stated
Packit b099d7
	     * modifers.
Packit b099d7
	     */
Packit b099d7
	    event.state = 0;
Packit b099d7
	    if (XKeycodeToKeysym(dpy, event.keycode, 0) != keysyms[tmp])
Packit b099d7
	      for (j = 1; j < codes_per_sym; j++)
Packit b099d7
		if (XKeycodeToKeysym(dpy, event.keycode, j) == keysyms[tmp])
Packit b099d7
		  {
Packit b099d7
Packit b099d7
                  /* 
Packit b099d7
		   * Gross Hack for Hobo keyboard .. 
Packit b099d7
		   * Assumptions: 
Packit b099d7
		   * 	1. Hobo keyboard has XK_Return  as the first entry
Packit b099d7
		   *		and XK_KP_Enter as the 4th entry in its
Packit b099d7
		   *            keycode to keysym key map.
Packit b099d7
		   *	2. This fix is only designed to work for the precise 
Packit b099d7
		   *            combination of the Sun server with vendor 
Packit b099d7
		   *            string "Sun Microsystems, Inc." and the Hobo 
Packit b099d7
		   *            keyboard, as the fix assumes knowledge of the 
Packit b099d7
		   *            server keycode to keysym key map.
Packit b099d7
		   */
Packit b099d7
Packit b099d7
		    if ((keysyms[tmp] == XK_KP_Enter) &&
Packit b099d7
                        (j == 4) &&
Packit b099d7
                        (XKeycodeToKeysym(dpy, event.keycode, 0) 
Packit b099d7
			    == XK_Return) &&
Packit b099d7
			(strcmp("Sun Microsystems, Inc.", ServerVendor(dpy)) 
Packit b099d7
			 == 0)) 
Packit b099d7
		    {
Packit b099d7
			fini = True;
Packit b099d7
		    } else
Packit b099d7
			event.state = 1 << (j-1);
Packit b099d7
Packit b099d7
		    break;
Packit b099d7
		  }
Packit b099d7
Packit b099d7
	    if (!fini) {
Packit b099d7
		event.state |= modifiers[tmp];
Packit b099d7
		XtTranslateKey(dpy, event.keycode, event.state, &used_mods,
Packit b099d7
			       keysyms + tmp);
Packit b099d7
	    }
Packit b099d7
	  }
Packit b099d7
	
Packit b099d7
	/* Fail if insufficient storage was provided. */
Packit b099d7
	if ((toVal->addr != NULL) &&
Packit b099d7
	    (toVal->size < sizeof(XmKeyBindingRec) * count))
Packit b099d7
	  {
Packit b099d7
	    toVal->size = sizeof(XmKeyBindingRec) * count;
Packit b099d7
Packit b099d7
	    XtFree((char*) eventTypes);
Packit b099d7
	    XtFree((char*) keysyms);
Packit b099d7
	    XtFree((char*) modifiers);
Packit b099d7
	    return False;
Packit b099d7
	  }
Packit b099d7
Packit b099d7
	/* Allocate storage if none was provided. */
Packit b099d7
	toVal->size = sizeof(XmKeyBindingRec) * count;
Packit b099d7
	if (toVal->addr == NULL)
Packit b099d7
	  toVal->addr = XtMalloc(toVal->size);
Packit b099d7
Packit b099d7
	/* Copy the data. */
Packit b099d7
	for (tmp = 0; tmp < count; tmp++)
Packit b099d7
	  {
Packit b099d7
	    ((XmKeyBinding) toVal->addr)[tmp].keysym = keysyms[tmp];
Packit b099d7
	    ((XmKeyBinding) toVal->addr)[tmp].modifiers = modifiers[tmp];
Packit b099d7
	  }
Packit b099d7
Packit b099d7
	XtFree((char*) eventTypes);
Packit b099d7
	XtFree((char*) keysyms);
Packit b099d7
	XtFree((char*) modifiers);
Packit b099d7
	return True;
Packit b099d7
      }
Packit b099d7
Packit b099d7
    /* The value supplied could not be converted. */
Packit b099d7
    XtDisplayStringConversionWarning(dpy, str, XmRVirtualBinding);
Packit b099d7
    return False;
Packit b099d7
}
Packit b099d7

Packit b099d7
static void
Packit b099d7
FillBindingsFromDB(Display       *dpy,
Packit b099d7
		   XrmDatabase    rdb,
Packit b099d7
		   XmVKeyBinding *keys,
Packit b099d7
		   Cardinal      *num_keys)
Packit b099d7
{
Packit b099d7
  XrmName 	    xrm_name[2];
Packit b099d7
  XrmClass 	    xrm_class[2];
Packit b099d7
  XrmRepresentation rep_type;
Packit b099d7
  XrmValue 	    value;
Packit b099d7
  Cardinal	    vk_num;
Packit b099d7
  XrmQuark	    XmQVirtualBinding = XrmPermStringToQuark(XmRVirtualBinding);
Packit b099d7
  XrmQuark	    XmQString         = XrmPermStringToQuark(XmRString);
Packit b099d7
Packit b099d7
  xrm_class[0] = XmQVirtualBinding;
Packit b099d7
  xrm_class[1] = 0;
Packit b099d7
  
Packit b099d7
  /* Previously entries in display.bindings corresponded exactly to */
Packit b099d7
  /* entries in virtualKeysyms.  Since multiple keysyms can be bound */
Packit b099d7
  /* to a single virtual key, display.num_bindings and the virtkey */
Packit b099d7
  /* field in XmVKeyBindingRec were added.  This also allows us to */
Packit b099d7
  /* remove null bindings from the table, improving search times. */
Packit b099d7
Packit b099d7
  /* Allocate the initial arrays. */
Packit b099d7
  *num_keys = 0;
Packit b099d7
  *keys = NULL;
Packit b099d7
  
Packit b099d7
  /* Process each known virtual key. */
Packit b099d7
  for (vk_num = 0; vk_num < XtNumber(virtualKeysyms); vk_num++)
Packit b099d7
    {
Packit b099d7
      Boolean	   free_keys = False;
Packit b099d7
      XmKeyBinding new_keys = NULL;
Packit b099d7
      Cardinal	   new_num = 0;
Packit b099d7
Packit b099d7
      xrm_name[0] = XrmPermStringToQuark(virtualKeysyms[vk_num].name);
Packit b099d7
      xrm_name[1] = 0;
Packit b099d7
      if (XrmQGetResource(rdb, xrm_name, xrm_class, &rep_type, &value))
Packit b099d7
	{
Packit b099d7
	  if (rep_type == XmQVirtualBinding)
Packit b099d7
	    {
Packit b099d7
	      /* Resource already exists in the desired format? */
Packit b099d7
	      new_keys = (XmKeyBinding) value.addr;
Packit b099d7
	      new_num = value.size / sizeof(XmKeyBindingRec);
Packit b099d7
	    }
Packit b099d7
Packit b099d7
	  else if (rep_type == XmQString) 
Packit b099d7
	    {
Packit b099d7
	      /* Convert String resource to key bindings. */
Packit b099d7
	      XrmValue toVal;
Packit b099d7
	      toVal.addr = NULL;
Packit b099d7
	      toVal.size = 0;
Packit b099d7
	      if (XtCallConverter(dpy, CvtStringToVirtualBinding,
Packit b099d7
				  NULL, 0, &value, &toVal, NULL))
Packit b099d7
		{
Packit b099d7
		  new_keys = (XmKeyBinding) toVal.addr;
Packit b099d7
		  new_num = toVal.size / sizeof(XmKeyBindingRec);
Packit b099d7
		  free_keys = True;
Packit b099d7
		}
Packit b099d7
	    }
Packit b099d7
Packit b099d7
	  /* Append the new bindings to the end of the table. */
Packit b099d7
	  if (new_num > 0)
Packit b099d7
	    {
Packit b099d7
	      int tmp;
Packit b099d7
Packit b099d7
	      *keys = (XmVKeyBinding) 
Packit b099d7
		XtRealloc((char*) *keys, 
Packit b099d7
			  (*num_keys + new_num) * sizeof(XmVKeyBindingRec)); 
Packit b099d7
Packit b099d7
	      for (tmp = 0; tmp < new_num; tmp++)
Packit b099d7
		{
Packit b099d7
		  (*keys)[*num_keys + tmp].keysym = new_keys[tmp].keysym;
Packit b099d7
		  (*keys)[*num_keys + tmp].modifiers = new_keys[tmp].modifiers;
Packit b099d7
		  (*keys)[*num_keys + tmp].virtkey =
Packit b099d7
		    virtualKeysyms[vk_num].keysym; 
Packit b099d7
		}
Packit b099d7
Packit b099d7
	      *num_keys += new_num;
Packit b099d7
	    }
Packit b099d7
Packit b099d7
	  if (free_keys)
Packit b099d7
	    XtFree((char *)new_keys);
Packit b099d7
	}
Packit b099d7
    }
Packit b099d7
}
Packit b099d7

Packit b099d7
static Boolean 
Packit b099d7
GetBindingsProperty(Display *display,
Packit b099d7
		    String   property,
Packit b099d7
		    String  *binding)
Packit b099d7
{
Packit b099d7
  char		*prop = NULL;
Packit b099d7
  Atom		actual_type;
Packit b099d7
  int		actual_format;
Packit b099d7
  unsigned long	num_items;
Packit b099d7
  unsigned long	bytes_after;
Packit b099d7
Packit b099d7
Packit b099d7
  if ( binding == NULL ) 
Packit b099d7
    return False;
Packit b099d7
Packit b099d7
  XGetWindowProperty (display, 
Packit b099d7
		      RootWindow(display, 0),
Packit b099d7
		      XInternAtom(display, property, FALSE),
Packit b099d7
		      0, (long)1000000,
Packit b099d7
		      FALSE, XA_STRING,
Packit b099d7
		      &actual_type, &actual_format,
Packit b099d7
		      &num_items, &bytes_after,
Packit b099d7
		      (unsigned char **) &prop);
Packit b099d7
Packit b099d7
  if ((actual_type != XA_STRING) ||
Packit b099d7
      (actual_format != 8) || 
Packit b099d7
      (num_items == 0))
Packit b099d7
    {
Packit b099d7
      if (prop != NULL) 
Packit b099d7
	XFree(prop);
Packit b099d7
      return False;
Packit b099d7
    }
Packit b099d7
  else
Packit b099d7
    {
Packit b099d7
      *binding = prop;
Packit b099d7
      return True;
Packit b099d7
    }
Packit b099d7
}
Packit b099d7
	   
Packit b099d7
/*
Packit b099d7
 * This routine is called by the XmDisplay Initialize method to set
Packit b099d7
 * up the virtual bindings table, XtKeyProc, and event handler.
Packit b099d7
 */
Packit b099d7
void 
Packit b099d7
_XmVirtKeysInitialize(Widget widget)
Packit b099d7
{
Packit b099d7
  XmDisplay xmDisplay = (XmDisplay) widget;
Packit b099d7
  Display *dpy = XtDisplay(xmDisplay);
Packit b099d7
  XrmDatabase keyDB;
Packit b099d7
  String bindingsString;
Packit b099d7
  String fallbackString = NULL;
Packit b099d7
  Boolean needXFree = False;
Packit b099d7
  
Packit b099d7
  if (!XmIsDisplay(widget))
Packit b099d7
    return;
Packit b099d7
  
Packit b099d7
  bindingsString = xmDisplay->display.bindingsString;
Packit b099d7
  xmDisplay->display.lastKeyEvent = NULL;
Packit b099d7
  
Packit b099d7
  if (bindingsString == NULL) 
Packit b099d7
    {
Packit b099d7
      /* XmNdefaultVirtualBindings not set, try _MOTIF_BINDINGS */
Packit b099d7
      if (GetBindingsProperty(XtDisplay(xmDisplay),
Packit b099d7
			      XmS_MOTIF_BINDINGS,
Packit b099d7
			      &bindingsString) == True) 
Packit b099d7
	{
Packit b099d7
	  needXFree = True;
Packit b099d7
	}
Packit b099d7
      else if (GetBindingsProperty(XtDisplay(xmDisplay),
Packit b099d7
				   XmS_MOTIF_DEFAULT_BINDINGS,
Packit b099d7
				   &bindingsString) == True) 
Packit b099d7
	{
Packit b099d7
	  needXFree = True;
Packit b099d7
	}
Packit b099d7
      else 
Packit b099d7
	{
Packit b099d7
	  /* property not set, find a useful fallback */
Packit b099d7
	  _XmVirtKeysLoadFallbackBindings(XtDisplay(xmDisplay),
Packit b099d7
					  &fallbackString);
Packit b099d7
	  bindingsString = fallbackString;
Packit b099d7
	}
Packit b099d7
    }
Packit b099d7
  
Packit b099d7
  XtSetTypeConverter(XmRString, XmRVirtualBinding, CvtStringToVirtualBinding, 
Packit b099d7
		     NULL, 0, XtCacheNone, (XtDestructor)NULL);
Packit b099d7
  keyDB = XrmGetStringDatabase( bindingsString );
Packit b099d7
  FillBindingsFromDB (XtDisplay(xmDisplay), keyDB,
Packit b099d7
		      &xmDisplay->display.bindings,
Packit b099d7
		      &xmDisplay->display.num_bindings);
Packit b099d7
Packit b099d7
  XrmDestroyDatabase(keyDB);
Packit b099d7
  if (needXFree) 
Packit b099d7
    XFree (bindingsString);
Packit b099d7
  if (fallbackString) 
Packit b099d7
    XtFree (fallbackString);
Packit b099d7
  
Packit b099d7
  XtSetKeyTranslator(dpy, (XtKeyProc)XmTranslateKey);
Packit b099d7
}
Packit b099d7

Packit b099d7
/*
Packit b099d7
 * This routine is called by the XmDisplay Destroy method to free
Packit b099d7
 * up the virtual bindings table.
Packit b099d7
 */
Packit b099d7
void 
Packit b099d7
_XmVirtKeysDestroy(Widget widget)
Packit b099d7
{
Packit b099d7
  XmDisplay xmDisplay = (XmDisplay) widget;
Packit b099d7
Packit b099d7
  XtFree((char*)xmDisplay->display.lastKeyEvent);
Packit b099d7
  XtFree((char*)xmDisplay->display.bindings);
Packit b099d7
}
Packit b099d7

Packit b099d7
static void 
Packit b099d7
FindVirtKey(Display *dpy,
Packit b099d7
	    KeyCode keycode,
Packit b099d7
	    Modifiers modifiers,
Packit b099d7
	    Modifiers *modifiers_return,
Packit b099d7
	    KeySym *keysym_return )
Packit b099d7
{
Packit b099d7
  Cardinal      i;
Packit b099d7
  XmDisplay     xmDisplay = (XmDisplay) XmGetXmDisplay( dpy);
Packit b099d7
  XmVKeyBinding keyBindings = xmDisplay->display.bindings;
Packit b099d7
  KeyCode       min_kcode;
Packit b099d7
  int           ks_per_kc;
Packit b099d7
  KeySym       *ks_table = XtGetKeysymTable( dpy, &min_kcode, &ks_per_kc);
Packit b099d7
  KeySym       *kc_map = &ks_table[(keycode - min_kcode) * ks_per_kc];
Packit b099d7
  Modifiers     EffectiveSMMask = EffectiveStdModMask( dpy, kc_map, ks_per_kc);
Packit b099d7
  
Packit b099d7
  /* Get the modifiers from the actual event */
Packit b099d7
  Modifiers VirtualStdMods = 0;
Packit b099d7
  Modifiers StdModMask;
Packit b099d7
Packit b099d7
  for (i = 0; i < xmDisplay->display.num_bindings; i++)
Packit b099d7
    {
Packit b099d7
      unsigned j = ks_per_kc;
Packit b099d7
      KeySym vks = keyBindings[i].keysym;
Packit b099d7
      
Packit b099d7
      if (vks)
Packit b099d7
	{
Packit b099d7
	  while (j--)
Packit b099d7
	    {
Packit b099d7
	      /* Want to walk through keymap (containing all possible
Packit b099d7
	       * keysyms generated by this keycode) to compare against
Packit b099d7
	       * virtual key keysyms.  Any keycode that can possibly
Packit b099d7
	       * generate a virtual keysym must be sure to return all
Packit b099d7
	       * modifiers that are in the virtual key binding, since
Packit b099d7
	       * this means that those modifiers are now part of the
Packit b099d7
	       * "standard modifiers" for this keycode.  (A "standard
Packit b099d7
	       * modifier" is a modifier that can affect which keysym
Packit b099d7
	       * is generated from a particular keycode.)
Packit b099d7
	       */
Packit b099d7
	      if ((j == 1)  &&  (kc_map[j] == NoSymbol))
Packit b099d7
		{   
Packit b099d7
		  KeySym uc, lc;
Packit b099d7
		  
Packit b099d7
		  XtConvertCase( dpy, kc_map[0], &lc, &uc);
Packit b099d7
		  if ((vks == lc)  ||  (vks == uc))
Packit b099d7
		    VirtualStdMods |= keyBindings[i].modifiers;
Packit b099d7
		  break;
Packit b099d7
		} 
Packit b099d7
	      else if (vks == kc_map[j])
Packit b099d7
		{
Packit b099d7
		  /* The keysym generated by this keycode can possibly
Packit b099d7
		   * be influenced by the virtual key modifier(s), so must
Packit b099d7
		   * add the modifier(s) associated with this virtual
Packit b099d7
		   * key to the returned list of "standard modifiers".
Packit b099d7
		   * The Intrinsics requires that the set of modifiers
Packit b099d7
		   * returned by the keyproc is constant for a given
Packit b099d7
		   * keycode.
Packit b099d7
		   */
Packit b099d7
		  VirtualStdMods |= keyBindings[i].modifiers;
Packit b099d7
		  break;
Packit b099d7
		}
Packit b099d7
	    } 
Packit b099d7
	}
Packit b099d7
    }
Packit b099d7
  
Packit b099d7
  /* Don't want to return standard modifiers that do not
Packit b099d7
   * impact the keysym selected for a particular keycode,
Packit b099d7
   * since this blocks matching of translation productions
Packit b099d7
   * which use ":" style translations with the returned
Packit b099d7
   * standard modifier in the production.  The ":" style
Packit b099d7
   * of production is essential for proper matching of
Packit b099d7
   * Motif translations (PC numeric pad, for instance).
Packit b099d7
   *
Packit b099d7
   * Recent fixes to the Intrinsics should have included this
Packit b099d7
   * change to the set of standard modifiers returned from
Packit b099d7
   * the default key translation routine, but could not be
Packit b099d7
   * done for reasons of backwards compatibility (which is
Packit b099d7
   * not an issue for Xm, since we do not export this facility).
Packit b099d7
   * So, we do the extra masking here after the return from
Packit b099d7
   * the call to XtTranslateKey.
Packit b099d7
   */
Packit b099d7
  *modifiers_return &= EffectiveSMMask;
Packit b099d7
  
Packit b099d7
  /* Modifiers present in the virtual binding table for the
Packit b099d7
   * keysyms associated with this keycode, which are or might
Packit b099d7
   * have been used to change the keysym generated by this
Packit b099d7
   * keycode (to a virtual keysym), must be included in the
Packit b099d7
   * returned set of standard modifiers.  Remember that "standard
Packit b099d7
   * modifiers" for a keycode are those modifiers that can affect
Packit b099d7
   * which keysym is generated by that keycode.
Packit b099d7
   */
Packit b099d7
  *modifiers_return |= VirtualStdMods;
Packit b099d7
  
Packit b099d7
  /* Effective standard modifiers that are set in the event
Packit b099d7
   * will be 0 in the following bit mask, which will be used
Packit b099d7
   * to collapse conflicting modifiers in the virtual
Packit b099d7
   * key binding table, as described below.
Packit b099d7
   */
Packit b099d7
  StdModMask = ~(modifiers & EffectiveSMMask);
Packit b099d7
  
Packit b099d7
  for (i = 0; i < xmDisplay->display.num_bindings; i++)
Packit b099d7
    {
Packit b099d7
      XmVKeyBinding currBinding = &keyBindings[i];
Packit b099d7
      KeySym vks = currBinding->keysym;
Packit b099d7
      
Packit b099d7
      /* The null binding should not be interpreted as a match
Packit b099d7
       * keysym is zero (e.g. pre-edit terminator)
Packit b099d7
       */
Packit b099d7
      /* Those modifiers that are effective standard modifiers and
Packit b099d7
       * that are set in the event will be ignored in the following
Packit b099d7
       * conditional (i.e., the state designated in the virtual key
Packit b099d7
       * binding will not be considered), since these modifiers have
Packit b099d7
       * already had their affect in the determination of the value
Packit b099d7
       * of *keysym_return.  This allows matching that is consistent
Packit b099d7
       * with industry-standard interpretation for keys such as
Packit b099d7
       * those of the PC-style numeric pad.  This apparent loss of
Packit b099d7
       * binding semantics is an unavoidable consequence of specifying
Packit b099d7
       * a modifier in the virtual binding table that is already being
Packit b099d7
       * used to select one of several keysyms associated with a
Packit b099d7
       * particular keycode (usually as printed on the keycap).
Packit b099d7
       * The disambiguation of the collapsing of key bindings
Packit b099d7
       * is based on "first match" in the virtual key binding table.
Packit b099d7
       */
Packit b099d7
      if (vks && (vks == *keysym_return) &&
Packit b099d7
	  ((currBinding->modifiers & StdModMask) ==
Packit b099d7
	   (modifiers & VirtualStdMods & StdModMask)))
Packit b099d7
	{
Packit b099d7
	  *keysym_return = currBinding->virtkey;
Packit b099d7
	  break;
Packit b099d7
	}
Packit b099d7
    }
Packit b099d7
}
Packit b099d7

Packit b099d7
static Modifiers
Packit b099d7
EffectiveStdModMask(Display *dpy,
Packit b099d7
		    KeySym *kc_map,
Packit b099d7
		    int ks_per_kc)
Packit b099d7
{
Packit b099d7
  /* This routine determines which set of modifiers can possibly
Packit b099d7
   * impact the keysym that is generated by the keycode associated
Packit b099d7
   * with the keymap passed in.  The basis of the algorithm used
Packit b099d7
   * here is described in section 12.7 "Keyboard Encoding" of the
Packit b099d7
   * R5 "Xlib - C Language X Interface" specification.
Packit b099d7
   */
Packit b099d7
  KeySym uc;
Packit b099d7
  KeySym lc;
Packit b099d7
  
Packit b099d7
  /* Since the group modifier can be any of Mod1-Mod5 or Control, we will
Packit b099d7
   * return all of these bits if the group modifier is found to be effective.
Packit b099d7
   * Lock will always be returned (for backwards compatibility with
Packit b099d7
   * productions assuming that Lock is always a "don't care" modifier
Packit b099d7
   * for non-alphabetic keys).  Shift will be returned unless it has
Packit b099d7
   * no effect on the selection of keysyms within either group.
Packit b099d7
   */
Packit b099d7
  Modifiers esm_mask = (Mod5Mask | Mod4Mask | Mod3Mask | Mod2Mask | Mod1Mask |
Packit b099d7
			ControlMask | LockMask | ShiftMask);
Packit b099d7
  switch (ks_per_kc)
Packit b099d7
    {
Packit b099d7
    default:	/* CR 8799: Ignore non-standard modifier groups. */
Packit b099d7
    case 4:
Packit b099d7
      if (kc_map[3] != NoSymbol)
Packit b099d7
	{
Packit b099d7
	  /* The keysym in position 4 is selected when the group
Packit b099d7
	   * modifier is set and the Shift (or Lock) modifier is
Packit b099d7
	   * set, so both Shift/Lock and the group modifiers are
Packit b099d7
	   * all "effective" standard modifiers.
Packit b099d7
	   */
Packit b099d7
	  break;
Packit b099d7
	} 
Packit b099d7
    case 3:
Packit b099d7
      if (kc_map[2] == NoSymbol)
Packit b099d7
	{
Packit b099d7
	  /* Both Group 2 keysyms are NoSymbol, so the group
Packit b099d7
	   * modifier has no effect; only Shift and Lock remain
Packit b099d7
	   * as possible effective modifiers.
Packit b099d7
	   */
Packit b099d7
	  esm_mask = ShiftMask | LockMask;
Packit b099d7
	}
Packit b099d7
      else
Packit b099d7
	{
Packit b099d7
	  XtConvertCase( dpy, kc_map[2], &lc, &uc);
Packit b099d7
	  if (lc != uc)
Packit b099d7
	    {   
Packit b099d7
	      /* The Group 2 keysym is case-sensitive, so group
Packit b099d7
	       * modifiers and Shift/Lock modifiers are effective.
Packit b099d7
	       */
Packit b099d7
	      break;
Packit b099d7
	    }
Packit b099d7
	} 
Packit b099d7
      /* At this fall-through, the group modifier bits have been
Packit b099d7
       * decided, while the case is still out on Shift/Lock.
Packit b099d7
       */
Packit b099d7
    case 2:
Packit b099d7
      if (kc_map[1] != NoSymbol)
Packit b099d7
	{
Packit b099d7
	  /* Shift/Lock modifier selects keysym from Group 1,
Packit b099d7
	   * so leave those bits in the mask.  The group modifier
Packit b099d7
	   * was determined above, so leave those bits in the mask.
Packit b099d7
	   */
Packit b099d7
	  break;
Packit b099d7
	} 
Packit b099d7
    case 1:
Packit b099d7
      if (kc_map[0] != NoSymbol)
Packit b099d7
	{
Packit b099d7
	  XtConvertCase( dpy, kc_map[0], &lc, &uc);
Packit b099d7
	  if (lc != uc)
Packit b099d7
	    {
Packit b099d7
	      /* The Group 1 keysym is case-sensitive, so Shift/Lock
Packit b099d7
	       * modifiers are effective.
Packit b099d7
	       */
Packit b099d7
	      break;
Packit b099d7
	    }
Packit b099d7
	} 
Packit b099d7
      /* If we did not break out of the switch before this, then
Packit b099d7
       * the Shift modifier is not effective; mask it out.
Packit b099d7
       */
Packit b099d7
      esm_mask &= ~ShiftMask;
Packit b099d7
    case 0:
Packit b099d7
      break;
Packit b099d7
    } 
Packit b099d7
Packit b099d7
  return esm_mask;
Packit b099d7
}
Packit b099d7

Packit b099d7
void
Packit b099d7
XmTranslateKey(Display     *dpy,
Packit b099d7
#if NeedWidePrototypes
Packit b099d7
	       unsigned int keycode,
Packit b099d7
#else
Packit b099d7
	       KeyCode      keycode,
Packit b099d7
#endif /* NeedWidePrototypes */
Packit b099d7
	       Modifiers    modifiers,
Packit b099d7
	       Modifiers   *modifiers_return,
Packit b099d7
	       KeySym      *keysym_return )
Packit b099d7
{
Packit b099d7
  _XmDisplayToAppContext(dpy);
Packit b099d7
  _XmAppLock(app);
Packit b099d7
  XtTranslateKey(dpy, keycode, modifiers, modifiers_return, keysym_return);
Packit b099d7
Packit b099d7
  FindVirtKey(dpy, keycode, modifiers, modifiers_return, keysym_return);
Packit b099d7
  _XmAppUnlock(app);
Packit b099d7
}
Packit b099d7

Packit b099d7
int
Packit b099d7
XmeVirtualToActualKeysyms(Display      *dpy,
Packit b099d7
			  KeySym        virtKeysym,
Packit b099d7
			  XmKeyBinding *actualKeyData)
Packit b099d7
{
Packit b099d7
  int           matches;
Packit b099d7
  Cardinal      index;
Packit b099d7
  XmDisplay     xmDisplay = (XmDisplay)XmGetXmDisplay (dpy);
Packit b099d7
  XmVKeyBinding keyBindings = xmDisplay->display.bindings;
Packit b099d7
  _XmDisplayToAppContext(dpy);
Packit b099d7
  
Packit b099d7
  _XmAppLock(app);
Packit b099d7
  /* Initialize the return parameters. */
Packit b099d7
  *actualKeyData = NULL;
Packit b099d7
Packit b099d7
  /* Count the number of matches. */
Packit b099d7
  matches = 0;
Packit b099d7
  for (index = 0; index < xmDisplay->display.num_bindings; index++)
Packit b099d7
    if (keyBindings[index].virtkey == virtKeysym)
Packit b099d7
      matches++;
Packit b099d7
Packit b099d7
  /* Allocate the return array. */
Packit b099d7
  if (matches > 0)
Packit b099d7
    {
Packit b099d7
      *actualKeyData = (XmKeyBinding) 
Packit b099d7
	XtMalloc(matches * sizeof(XmKeyBindingRec));
Packit b099d7
Packit b099d7
      matches = 0;
Packit b099d7
      for (index = 0; index < xmDisplay->display.num_bindings; index++)
Packit b099d7
	if (keyBindings[index].virtkey == virtKeysym)
Packit b099d7
	  {
Packit b099d7
	    (*actualKeyData)[matches].keysym = keyBindings[index].keysym;
Packit b099d7
	    (*actualKeyData)[matches].modifiers = keyBindings[index].modifiers;
Packit b099d7
	    matches++;
Packit b099d7
	  }
Packit b099d7
    }
Packit b099d7
Packit b099d7
  _XmAppUnlock(app);
Packit b099d7
  return matches;
Packit b099d7
}
Packit b099d7

Packit b099d7
Boolean 
Packit b099d7
_XmVirtKeysLoadFileBindings(char   *fileName,
Packit b099d7
			    String *binding )
Packit b099d7
{
Packit b099d7
  FILE *fileP;
Packit b099d7
  int buffersize;
Packit b099d7
  int count;
Packit b099d7
  int firsttime;
Packit b099d7
  char line[256];
Packit b099d7
  Boolean skip;
Packit b099d7
  
Packit b099d7
  if ((fileP = fopen (fileName, "r")) != NULL) 
Packit b099d7
    {
Packit b099d7
      skip = False;
Packit b099d7
      count = 0;
Packit b099d7
      buffersize = 1;
Packit b099d7
      firsttime = 1;
Packit b099d7
Packit b099d7
      while (fgets(line, sizeof(line), fileP) != NULL) {
Packit b099d7
Packit b099d7
	/* handle '!' comments; they can extend across mutliple reads */
Packit b099d7
	if (skip) {
Packit b099d7
	  if (line[strlen(line) - 1] == '\n') skip = False;
Packit b099d7
	  continue;
Packit b099d7
	}
Packit b099d7
	if (line[0] == '!') {
Packit b099d7
	  if (line[strlen(line) - 1] == '\n') continue;
Packit b099d7
	  else {
Packit b099d7
	    skip = True;
Packit b099d7
	    continue;
Packit b099d7
	  }	    
Packit b099d7
	}
Packit b099d7
Packit b099d7
	/* must be >=, because buffersize is always 1 bigger for '\0' */
Packit b099d7
	if (count + strlen(line) >= buffersize) {
Packit b099d7
	  buffersize += BUFFERSIZE;
Packit b099d7
	  *binding = XtRealloc(*binding, buffersize);
Packit b099d7
Packit b099d7
	  /* always make sure that the end of *binding is null terminated */
Packit b099d7
	  if (firsttime) { 
Packit b099d7
	    *binding[0] = '\0';
Packit b099d7
	    firsttime = 0;
Packit b099d7
	  }
Packit b099d7
	}
Packit b099d7
Packit b099d7
	count += strlen(line);
Packit b099d7
Packit b099d7
	strcat(*binding, line);
Packit b099d7
      }
Packit b099d7
     
Packit b099d7
      /* trim unused buffer space */
Packit b099d7
      *binding = XtRealloc (*binding, count + 1);
Packit b099d7
Packit b099d7
      fclose (fileP);
Packit b099d7
      return True;
Packit b099d7
    }
Packit b099d7
Packit b099d7
  return False;
Packit b099d7
}
Packit b099d7

Packit b099d7
static void 
Packit b099d7
LoadVendorBindings(Display *display,
Packit b099d7
		   char    *path,
Packit b099d7
		   FILE    *fp,
Packit b099d7
		   String  *binding )
Packit b099d7
{
Packit b099d7
  char buffer[MAXLINE];
Packit b099d7
  char *bindFile;
Packit b099d7
  char *vendor;
Packit b099d7
  char *vendorV;
Packit b099d7
  char *ptr;
Packit b099d7
  char *start;
Packit b099d7
  
Packit b099d7
  vendor = ServerVendor(display);
Packit b099d7
  vendorV = XtMalloc (strlen(vendor) + 20); /* assume rel.# is < 19 digits */
Packit b099d7
  sprintf (vendorV, "%s %d", vendor, VendorRelease(display));
Packit b099d7
  
Packit b099d7
  while (fgets (buffer, MAXLINE, fp) != NULL) 
Packit b099d7
    {
Packit b099d7
      ptr = buffer;
Packit b099d7
      while (*ptr != '"' && *ptr != '!' && *ptr != '\0') 
Packit b099d7
	ptr++;
Packit b099d7
      if (*ptr != '"') 
Packit b099d7
	continue;
Packit b099d7
Packit b099d7
      start = ++ptr;
Packit b099d7
      while (*ptr != '"' && *ptr != '\0') 
Packit b099d7
	ptr++;
Packit b099d7
      if (*ptr != '"') 
Packit b099d7
	continue;
Packit b099d7
Packit b099d7
      *ptr = '\0';
Packit b099d7
      if ((strcmp (start, vendor) == 0) || (strcmp (start, vendorV) == 0)) 
Packit b099d7
	{
Packit b099d7
	  ptr++;
Packit b099d7
	  while (isspace((unsigned char)*ptr) && *ptr) 
Packit b099d7
	    ptr++;
Packit b099d7
	  if (*ptr == '\0') 
Packit b099d7
	    continue;
Packit b099d7
Packit b099d7
	  start = ptr;
Packit b099d7
	  while (!isspace((unsigned char)*ptr) && *ptr != '\n' && *ptr)
Packit b099d7
	    ptr++;
Packit b099d7
	  *ptr = '\0';
Packit b099d7
Packit b099d7
	  bindFile = _XmOSBuildFileName (path, start);
Packit b099d7
	  if (_XmVirtKeysLoadFileBindings (bindFile, binding)) 
Packit b099d7
	    {
Packit b099d7
	      XtFree (bindFile);
Packit b099d7
	      break;
Packit b099d7
	    }
Packit b099d7
	  XtFree (bindFile);
Packit b099d7
	}
Packit b099d7
    }
Packit b099d7
Packit b099d7
  XtFree (vendorV);
Packit b099d7
}
Packit b099d7

Packit b099d7
int 
Packit b099d7
_XmVirtKeysLoadFallbackBindings(Display	*display,
Packit b099d7
				String	*binding )
Packit b099d7
{
Packit b099d7
  enum { XmA_MOTIF_BINDINGS, XmA_MOTIF_DEFAULT_BINDINGS, NUM_ATOMS };
Packit b099d7
  static char *atom_names[] = {XmS_MOTIF_BINDINGS, XmS_MOTIF_DEFAULT_BINDINGS};
Packit b099d7
Packit b099d7
  XmConst XmDefaultBindingStringRec *currDefault;
Packit b099d7
  int i;
Packit b099d7
  FILE *fp;
Packit b099d7
  char *homeDir;
Packit b099d7
  char *fileName;
Packit b099d7
  char *bindDir;
Packit b099d7
  static XmConst char xmbinddir_fallback[] = XMBINDDIR_FALLBACK;
Packit b099d7
  Atom atoms[XtNumber(atom_names)];
Packit b099d7
  
Packit b099d7
  *binding = NULL;
Packit b099d7
  
Packit b099d7
  assert(XtNumber(atom_names) == NUM_ATOMS);
Packit b099d7
  XInternAtoms(display, atom_names, XtNumber(atom_names), False, atoms);
Packit b099d7
Packit b099d7
  /* Load .motifbind - necessary, if mwm and xmbind are not used */
Packit b099d7
  homeDir = XmeGetHomeDirName();
Packit b099d7
  fileName = _XmOSBuildFileName(homeDir, MOTIFBIND);
Packit b099d7
  _XmVirtKeysLoadFileBindings(fileName, binding);
Packit b099d7
  XtFree(fileName);
Packit b099d7
  
Packit b099d7
  /* Look for a match in the user's xmbind.alias */
Packit b099d7
  if (*binding == NULL) 
Packit b099d7
    {
Packit b099d7
      fileName = _XmOSBuildFileName (homeDir, XMBINDFILE);
Packit b099d7
      if ((fp = fopen (fileName, "r")) != NULL) 
Packit b099d7
	{
Packit b099d7
	  LoadVendorBindings (display, homeDir, fp, binding);
Packit b099d7
	  fclose (fp);
Packit b099d7
	}
Packit b099d7
      XtFree (fileName);
Packit b099d7
    }
Packit b099d7
  
Packit b099d7
  if (*binding != NULL) 
Packit b099d7
    {
Packit b099d7
      /* Set the user property for future Xm applications. */
Packit b099d7
      XChangeProperty (display, RootWindow(display, 0),
Packit b099d7
		       atoms[XmA_MOTIF_BINDINGS],
Packit b099d7
		       XA_STRING, 8, PropModeReplace,
Packit b099d7
		       (unsigned char *)*binding, strlen(*binding));
Packit b099d7
      return 0;
Packit b099d7
    }
Packit b099d7
  
Packit b099d7
  /* Look for a match in the system xmbind.alias */
Packit b099d7
  if (*binding == NULL) 
Packit b099d7
    {
Packit b099d7
      if ((bindDir = getenv(XMBINDDIR)) == NULL)
Packit b099d7
	bindDir = (char*) xmbinddir_fallback;
Packit b099d7
      fileName = _XmOSBuildFileName (bindDir, XMBINDFILE);
Packit b099d7
      if ((fp = fopen (fileName, "r")) != NULL) 
Packit b099d7
	{
Packit b099d7
	  LoadVendorBindings (display, bindDir, fp, binding);
Packit b099d7
	  fclose (fp);
Packit b099d7
	}
Packit b099d7
      XtFree (fileName);
Packit b099d7
    }
Packit b099d7
  
Packit b099d7
  /* Check hardcoded fallbacks (for 1.1 bc) */
Packit b099d7
  if (*binding == NULL) 
Packit b099d7
    {
Packit b099d7
      for (i = 0, currDefault = fallbackBindingStrings;
Packit b099d7
	   i < XtNumber(fallbackBindingStrings);
Packit b099d7
	   i++, currDefault++) 
Packit b099d7
	{
Packit b099d7
	  if (strcmp(currDefault->vendorName, ServerVendor(display)) == 0) 
Packit b099d7
	    {
Packit b099d7
	      *binding = XtMalloc (strlen (currDefault->defaults) + 1);
Packit b099d7
	      strcpy (*binding, currDefault->defaults);
Packit b099d7
	      break;
Packit b099d7
	    }
Packit b099d7
	}
Packit b099d7
    }
Packit b099d7
  
Packit b099d7
  /* Use generic fallback bindings */
Packit b099d7
  if (*binding == NULL) 
Packit b099d7
    {
Packit b099d7
      *binding = XtMalloc (strlen (defaultFallbackBindings) + 1);
Packit b099d7
      strcpy (*binding, defaultFallbackBindings);
Packit b099d7
    }
Packit b099d7
  
Packit b099d7
  /* Set the fallback property for future Xm applications */
Packit b099d7
  XChangeProperty (display, RootWindow(display, 0),
Packit b099d7
		   atoms[XmA_MOTIF_DEFAULT_BINDINGS],
Packit b099d7
		   XA_STRING, 8, PropModeReplace,
Packit b099d7
		   (unsigned char *)*binding, strlen(*binding));
Packit b099d7
  
Packit b099d7
  return 0;
Packit b099d7
}