|
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 |
}
|