home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
evbl0627.zip
/
everblue_20010627.zip
/
x11
/
XKBBind.c
< prev
next >
Wrap
C/C++ Source or Header
|
1999-11-02
|
27KB
|
1,024 lines
/* $TOG: XKBBind.c /main/27 1997/06/10 06:53:17 kaleb $ */
/*
Copyright (c) 1985, 1987, 1994 X Consortium
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of the X Consortium shall
not be used in advertising or otherwise to promote the sale, use or
other dealings in this Software without prior written authorization
from the X Consortium.
*/
/* the new monsters ate the old ones */
#define NEED_EVENTS
#include "Xlib_private.h"
#include <X11/Xutil.h>
#include <X11/keysym.h>
#include <stdio.h>
#include <ctype.h>
#include <X11/extensions/XKBproto.h>
#include "XKBlibint.h"
#ifdef USE_OWN_COMPOSE
#define COMPOSE_NO_CONST_MEMBERS
#include "imComp.h"
#endif
#define AllMods (ShiftMask|LockMask|ControlMask| \
Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)
static int _XkbLoadDpy(
#if NeedFunctionPrototypes
Display *dpy
#endif
);
struct _XKeytrans {
struct _XKeytrans *next;/* next on list */
char *string; /* string to return when the time comes */
int len; /* length of string (since NULL is legit)*/
KeySym key; /* keysym rebound */
unsigned int state; /* modifier state */
KeySym *modifiers; /* modifier keysyms you want */
int mlen; /* length of modifier list */
};
KeySym
#if NeedFunctionPrototypes
XkbKeycodeToKeysym(Display *dpy,
#if NeedWidePrototypes
unsigned int kc,
#else
KeyCode kc,
#endif
int group,
int level)
#else
XkbKeycodeToKeysym(dpy, kc, group, level)
Display *dpy;
KeyCode kc;
int group;
int level;
#endif
{
DBUG_ENTER("XkbKeycodeToKeysym")
XkbDescRec *xkb;
KeySym result;
if (_XkbUnavailable(dpy))
DBUG_RETURN(NoSymbol);
_XkbCheckPendingRefresh(dpy,dpy->xkb_info);
xkb = dpy->xkb_info->desc;
if ((kc<xkb->min_key_code)||(kc>xkb->max_key_code))
DBUG_RETURN(NoSymbol);
if ((group<0)||(level<0)||(group>=XkbKeyNumGroups(xkb,kc)))
DBUG_RETURN(NoSymbol);
if (level>=XkbKeyGroupWidth(xkb,kc,group)) {
/* for compatibility with the core protocol, _always_ allow */
/* two symbols in the first two groups. If either of the */
/* two is of type ONE_LEVEL, just replicate the first symbol */
if ((group>XkbGroup2Index)||(XkbKeyGroupWidth(xkb,kc,group)!=1)||
(level!=1)) {
DBUG_RETURN(NoSymbol);
}
level= 0;
}
result = XkbKeySymEntry(xkb,kc,level,group);
DBUG_RETURN(result);
}
KeySym
#if NeedFunctionPrototypes
XKeycodeToKeysym(Display *dpy,
#if NeedWidePrototypes
unsigned int kc,
#else
KeyCode kc,
#endif
int col)
#else
XKeycodeToKeysym(dpy, kc, col)
Display *dpy;
KeyCode kc;
int col;
#endif
{
DBUG_ENTER("XKeycodeToKeysym")
XkbDescRec *xkb;
if (_XkbUnavailable(dpy)) {
KeySym result = _XKeycodeToKeysym(dpy, kc, col);
DBUG_RETURN(result);
}
_XkbCheckPendingRefresh(dpy,dpy->xkb_info);
xkb = dpy->xkb_info->desc;
if ((kc<xkb->min_key_code)||(kc>xkb->max_key_code))
DBUG_RETURN(NoSymbol);
if (col>3) {
int lastSym,tmp,nGrp;
lastSym= 3;
nGrp= XkbKeyNumGroups(xkb,kc);
if ((nGrp>0)&&((tmp=XkbKeyGroupWidth(xkb,kc,XkbGroup1Index))>2)) {
if (col<=(lastSym+tmp-2)) {
KeySym result = XkbKeycodeToKeysym(dpy,kc,XkbGroup1Index,col-lastSym+2);
DBUG_RETURN(result);
}
lastSym+= tmp-2;
}
if ((nGrp>1)&&((tmp=XkbKeyGroupWidth(xkb,kc,XkbGroup2Index))>2)) {
if (col<=(lastSym+tmp-2)) {
KeySym result = XkbKeycodeToKeysym(dpy,kc,XkbGroup2Index,col-lastSym+2);
DBUG_RETURN(result);
}
lastSym+= tmp-2;
}
if (nGrp>2) {
tmp= XkbKeyGroupWidth(xkb,kc,XkbGroup3Index);
if (col<=lastSym+tmp) {
KeySym result = XkbKeycodeToKeysym(dpy,kc,XkbGroup3Index,col-lastSym);
DBUG_RETURN(result);
}
lastSym+= tmp;
}
if (nGrp>3) {
tmp= XkbKeyGroupWidth(xkb,kc,XkbGroup4Index);
if (col<=lastSym+tmp) {
KeySym result = XkbKeycodeToKeysym(dpy,kc,XkbGroup4Index,col-lastSym);
DBUG_RETURN(result);
}
}
DBUG_RETURN(NoSymbol);
}
{
KeySym result = XkbKeycodeToKeysym(dpy,kc,(col>>1),(col&1));
DBUG_RETURN(result);
}
}
KeyCode
#if NeedFunctionPrototypes
XKeysymToKeycode(Display *dpy, KeySym ks)
#else
XKeysymToKeycode(dpy, ks)
Display *dpy;
KeySym ks;
#endif
{
DBUG_ENTER("XKeysymToKeycode")
register int i, j, gotOne;
if (_XkbUnavailable(dpy)) {
KeyCode result = _XKeysymToKeycode(dpy,ks);
DBUG_RETURN(result);
}
_XkbCheckPendingRefresh(dpy,dpy->xkb_info);
j= 0;
do {
register XkbDescRec *xkb = dpy->xkb_info->desc;
gotOne= 0;
for (i = dpy->min_keycode; i <= dpy->max_keycode; i++) {
if ( j<(int)XkbKeyNumSyms(xkb,i) ) {
gotOne = 1;
if ((XkbKeySym(xkb,i,j)==ks))
DBUG_RETURN(i);
}
}
j++;
} while (gotOne);
DBUG_RETURN(0);
}
static int
#if NeedFunctionPrototypes
_XkbComputeModmap(Display *dpy)
#else
_XkbComputeModmap(dpy)
Display *dpy;
#endif
{
DBUG_ENTER("_XkbComputeModmap")
register XkbDescPtr xkb;
xkb= dpy->xkb_info->desc;
if (XkbGetUpdatedMap(dpy,XkbModifierMapMask,xkb)==Success)
DBUG_RETURN(1);
DBUG_RETURN(0);
}
unsigned
#if NeedFunctionPrototypes
XkbKeysymToModifiers(Display *dpy,KeySym ks)
#else
XkbKeysymToModifiers(dpy,ks)
Display *dpy;
KeySym ks;
#endif
{
DBUG_ENTER("XkbKeysymToModifiers")
XkbDescRec *xkb;
register int i,j;
register KeySym *pSyms;
CARD8 mods;
if (_XkbUnavailable(dpy)) {
unsigned result = _XKeysymToModifiers(dpy,ks);
DBUG_RETURN(result);
}
_XkbCheckPendingRefresh(dpy,dpy->xkb_info);
if (_XkbNeedModmap(dpy->xkb_info)&&(!_XkbComputeModmap(dpy))) {
unsigned result =_XKeysymToModifiers(dpy,ks);
DBUG_RETURN(result);
}
xkb= dpy->xkb_info->desc;
mods= 0;
for (i = xkb->min_key_code; i <= (int)xkb->max_key_code; i++) {
pSyms= XkbKeySymsPtr(xkb,i);
for (j=XkbKeyNumSyms(xkb,i)-1;j>=0;j--) {
if (pSyms[j]==ks) {
mods|= xkb->map->modmap[i];
break;
}
}
}
DBUG_RETURN(mods);
}
KeySym
#if NeedFunctionPrototypes
XLookupKeysym(register XKeyEvent *event, int col)
#else
XLookupKeysym(event, col)
register XKeyEvent *event;
int col;
#endif
{
DBUG_ENTER("XLookupKeysym")
Display *dpy = event->display;
if (_XkbUnavailable(dpy)) {
KeySym result = _XLookupKeysym(event, col);
DBUG_RETURN(result);
}
_XkbCheckPendingRefresh(dpy,dpy->xkb_info);
{
KeySym result = XKeycodeToKeysym(dpy, event->keycode, col);
DBUG_RETURN(result);
}
}
/*
* Not a public entry point -- XkbTranslateKey is an obsolete name
* that is preserved here so that functions linked against the old
* version will continue to work in a shared library environment.
*/
int
#if NeedFunctionPrototypes
XkbTranslateKey( register Display * dpy,
KeyCode key,
register unsigned int mods,
unsigned int * mods_rtrn,
KeySym * keysym_rtrn)
#else
XkbTranslateKey(dpy, key, mods, mods_rtrn, keysym_rtrn)
register Display *dpy;
KeyCode key;
register unsigned int mods;
unsigned int *mods_rtrn;
KeySym *keysym_rtrn;
#endif
{
DBUG_ENTER("XkbTranslateKey")
int result = XkbLookupKeySym(dpy,key,mods,mods_rtrn,keysym_rtrn);
DBUG_RETURN(result);
}
Bool
#if NeedFunctionPrototypes
XkbLookupKeySym( register Display * dpy,
KeyCode key,
register unsigned int mods,
unsigned int * mods_rtrn,
KeySym * keysym_rtrn)
#else
XkbLookupKeySym(dpy, key, mods, mods_rtrn, keysym_rtrn)
register Display *dpy;
KeyCode key;
register unsigned int mods;
unsigned int *mods_rtrn;
KeySym *keysym_rtrn;
#endif
{
DBUG_ENTER("XkbLookupKeySym")
Bool result;
if (_XkbUnavailable(dpy)) {
result =_XTranslateKey(dpy, key, mods, mods_rtrn, keysym_rtrn);
DBUG_RETURN(result);
}
_XkbCheckPendingRefresh(dpy,dpy->xkb_info);
result = XkbTranslateKeyCode(dpy->xkb_info->desc,key,mods,mods_rtrn,
keysym_rtrn);
DBUG_RETURN(result);
}
Bool
#if NeedFunctionPrototypes
XkbTranslateKeyCode( register XkbDescPtr xkb,
KeyCode key,
register unsigned int mods,
unsigned int * mods_rtrn,
KeySym * keysym_rtrn)
#else
XkbTranslateKeyCode(xkb, key, mods, mods_rtrn, keysym_rtrn)
register XkbDescPtr xkb;
KeyCode key;
register unsigned int mods;
unsigned int *mods_rtrn;
KeySym *keysym_rtrn;
#endif
{
DBUG_ENTER("XkbTranslateKeyCode")
XkbKeyTypeRec *type;
int col,nKeyGroups;
unsigned preserve,effectiveGroup;
KeySym *syms;
if (mods_rtrn!=NULL)
*mods_rtrn = 0;
nKeyGroups= XkbKeyNumGroups(xkb,key);
if ((!XkbKeycodeInRange(xkb,key))||(nKeyGroups==0)) {
if (keysym_rtrn!=NULL)
*keysym_rtrn = NoSymbol;
DBUG_RETURN(False);
}
syms = XkbKeySymsPtr(xkb,key);
/* find the offset of the effective group */
col = 0;
effectiveGroup= XkbGroupForCoreState(mods);
if ( effectiveGroup>=nKeyGroups ) {
unsigned groupInfo= XkbKeyGroupInfo(xkb,key);
switch (XkbOutOfRangeGroupAction(groupInfo)) {
default:
effectiveGroup %= nKeyGroups;
break;
case XkbClampIntoRange:
effectiveGroup = nKeyGroups-1;
break;
case XkbRedirectIntoRange:
effectiveGroup = XkbOutOfRangeGroupNumber(groupInfo);
if (effectiveGroup>=nKeyGroups)
effectiveGroup= 0;
break;
}
}
col= effectiveGroup*XkbKeyGroupsWidth(xkb,key);
type = XkbKeyKeyType(xkb,key,effectiveGroup);
preserve= 0;
if (type->map) { /* find the column (shift level) within the group */
register int i;
register XkbKTMapEntryPtr entry;
for (i=0,entry=type->map;i<type->map_count;i++,entry++) {
if ((entry->active)&&((mods&type->mods.mask)==entry->mods.mask)) {
col+= entry->level;
if (type->preserve)
preserve= type->preserve[i].mask;
break;
}
}
}
if (keysym_rtrn!=NULL)
*keysym_rtrn= syms[col];
if (mods_rtrn) {
*mods_rtrn= type->mods.mask&(~preserve);
/* The Motif VTS doesn't get the help callback called if help
* is bound to Shift+<whatever>, and it appears as though it
* is XkbTranslateKeyCode that is causing the problem. The
* core X version of XTranslateKey always OR's in ShiftMask
* and LockMask for mods_rtrn, so this "fix" keeps this behavior
* and solves the VTS problem.
*/
if ((xkb->dpy)&&(xkb->dpy->xkb_info)&&
(xkb->dpy->xkb_info->xlib_ctrls&XkbLC_AlwaysConsumeShiftAndLock)) {
*mods_rtrn|= (ShiftMask|LockMask);
}
}
DBUG_RETURN(syms[col]!=NoSymbol);
}
Status
#if NeedFunctionPrototypes
XkbRefreshKeyboardMapping(register XkbMapNotifyEvent *event)
#else
XkbRefreshKeyboardMapping(event)
register XkbMapNotifyEvent *event;
#endif
{
DBUG_ENTER("XkbRefreshKeyboardMapping")
Display *dpy = event->display;
XkbInfoPtr xkbi;
if (_XkbUnavailable(dpy)) {
_XRefreshKeyboardMapping((XMappingEvent *)event);
DBUG_RETURN(Success);
}
xkbi= dpy->xkb_info;
if (((event->type&0x7f)-xkbi->codes->first_event)!=XkbEventCode)
DBUG_RETURN(BadMatch);
if (event->xkb_type==XkbNewKeyboardNotify) {
_XkbReloadDpy(dpy);
DBUG_RETURN(Success);
}
if (event->xkb_type==XkbMapNotify) {
XkbMapChangesRec changes;
Status rtrn;
if (xkbi->flags&XkbMapPending)
changes= xkbi->changes;
else bzero(&changes,sizeof(XkbChangesRec));
XkbNoteMapChanges(&changes,event,XKB_XLIB_MAP_MASK);
LockDisplay(dpy);
if ((rtrn=XkbGetMapChanges(dpy,xkbi->desc,&changes))!=Success) {
#ifdef DEBUG
fprintf(stderr,"Internal Error! XkbGetMapChanges failed:\n");
#endif
xkbi->changes= changes;
}
else if (xkbi->flags&XkbMapPending) {
xkbi->flags&= ~XkbMapPending;
bzero(&xkbi->changes,sizeof(XkbMapChangesRec));
}
UnlockDisplay(dpy);
DBUG_RETURN(rtrn);
}
DBUG_RETURN(BadMatch);
}
int
#if NeedFunctionPrototypes
XRefreshKeyboardMapping(register XMappingEvent *event)
#else
XRefreshKeyboardMapping(event)
register XMappingEvent *event;
#endif
{
DBUG_ENTER("XRefreshKeyboardMapping")
XkbEvent *xkbevent = (XkbEvent *)event;
Display *dpy = event->display;
XkbMapChangesRec changes;
XkbInfoPtr xkbi;
int result;
/* always do this for input methods, which still use the old keymap */
(void) _XRefreshKeyboardMapping(event);
if (_XkbUnavailable(dpy))
DBUG_RETURN(1);
xkbi = dpy->xkb_info;
if (((event->type&0x7f)-xkbi->codes->first_event)==XkbEventCode) {
result = XkbRefreshKeyboardMapping(&xkbevent->map);
DBUG_RETURN(result);
}
if (xkbi->flags&XkbXlibNewKeyboard) {
_XkbReloadDpy(dpy);
DBUG_RETURN(1);
}
if ((xkbi->flags&XkbMapPending)||(event->request==MappingKeyboard)) {
if (xkbi->flags&XkbMapPending) {
changes= xkbi->changes;
_XkbNoteCoreMapChanges(&changes,event,XKB_XLIB_MAP_MASK);
}
else {
bzero(&changes,sizeof(changes));
changes.changed= XkbKeySymsMask;
if (xkbi->desc->min_key_code<xkbi->desc->max_key_code) {
changes.first_key_sym= xkbi->desc->min_key_code;
changes.num_key_syms= xkbi->desc->max_key_code-
xkbi->desc->min_key_code+1;
}
else {
changes.first_key_sym= event->first_keycode;
changes.num_key_syms= event->count;
}
}
if (XkbGetMapChanges(dpy,xkbi->desc, &changes)!=Success) {
#ifdef DEBUG
fprintf(stderr,"Internal Error! XkbGetMapChanges failed:\n");
if (changes.changed&XkbKeyTypesMask) {
int first= changes.first_type;
int last= changes.first_type+changes.num_types-1;
fprintf(stderr," types: %d..%d\n",first,last);
}
if (changes.changed&XkbKeySymsMask) {
int first= changes.first_key_sym;
int last= changes.first_key_sym+changes.num_key_syms-1;
fprintf(stderr," symbols: %d..%d\n",first,last);
}
if (changes.changed&XkbKeyActionsMask) {
int last,first= changes.first_key_act;
last= changes.first_key_act+changes.num_key_acts-1;
fprintf(stderr," acts: %d..%d\n",first,last);
}
if (changes.changed&XkbKeyBehaviorsMask) {
int last,first= changes.first_key_behavior;
last= first+changes.num_key_behaviors-1;
fprintf(stderr," behaviors: %d..%d\n",first,last);
}
if (changes.changed&XkbVirtualModsMask) {
fprintf(stderr,"virtual mods: 0x%04x\n",
changes.vmods);
}
if (changes.changed&XkbExplicitComponentsMask) {
int last,first= changes.first_key_explicit;
last= first+changes.num_key_explicit-1;
fprintf(stderr," explicit: %d..%d\n",first,last);
}
#endif
}
LockDisplay(dpy);
if (xkbi->flags&XkbMapPending) {
xkbi->flags&= ~XkbMapPending;
bzero(&xkbi->changes,sizeof(XkbMapChangesRec));
}
UnlockDisplay(dpy);
}
if (event->request==MappingModifier) {
if (xkbi->desc->map->modmap) {
_XkbFree(xkbi->desc->map->modmap);
xkbi->desc->map->modmap= NULL;
}
if (dpy->key_bindings) {
register struct _XKeytrans *p;
for (p = dpy->key_bindings; p; p = p->next) {
register int i;
p->state= 0;
if (p->mlen>0) {
for (i = 0; i < p->mlen; i++) {
p->state|= XkbKeysymToModifiers(dpy,p->modifiers[i]);
}
if (p->state) p->state &= AllMods;
else p->state = AnyModifier;
}
}
}
UnlockDisplay(dpy);
}
DBUG_RETURN(1);
}
static int
#if NeedFunctionPrototypes
_XkbLoadDpy(Display *dpy)
#else
_XkbLoadDpy(dpy)
Display *dpy;
#endif
{
DBUG_ENTER("_XkbLoadDpy")
XkbInfoPtr xkbi;
unsigned query,oldEvents;
XkbDescRec *desc;
if (!XkbUseExtension(dpy,NULL,NULL))
DBUG_RETURN(0);
xkbi = dpy->xkb_info;
query = XkbAllClientInfoMask;
desc = XkbGetMap(dpy,query,XkbUseCoreKbd);
if (!desc) {
#ifdef DEBUG
fprintf(stderr,"Warning! XkbGetMap failed!\n");
#endif
DBUG_RETURN(0);
}
LockDisplay(dpy);
xkbi->desc = desc;
_XkbGetConverters(_XkbGetCharset(),&xkbi->cvt);
_XkbGetConverters("ISO8859-1",&xkbi->latin1cvt);
UnlockDisplay(dpy);
oldEvents= xkbi->selected_events;
if (!(xkbi->xlib_ctrls&XkbLC_IgnoreNewKeyboards)) {
XkbSelectEventDetails(dpy,xkbi->desc->device_spec,XkbNewKeyboardNotify,
XkbNKN_KeycodesMask|XkbNKN_DeviceIDMask,
XkbNKN_KeycodesMask|XkbNKN_DeviceIDMask);
}
XkbSelectEventDetails(dpy,xkbi->desc->device_spec,XkbMapNotify,
XkbAllClientInfoMask,XkbAllClientInfoMask);
LockDisplay(dpy);
xkbi->selected_events= oldEvents;
UnlockDisplay(dpy);
DBUG_RETURN(1);
}
void
#if NeedFunctionPrototypes
_XkbReloadDpy(Display *dpy)
#else
_XkbReloadDpy(dpy)
Display *dpy;
#endif
{
DBUG_ENTER("_XkbReloadDpy")
XkbInfoPtr xkbi;
XkbDescRec *desc;
unsigned oldDeviceID;
if (_XkbUnavailable(dpy))
DBUG_VOID_RETURN;
xkbi = dpy->xkb_info;
LockDisplay(dpy);
if (xkbi->desc) {
oldDeviceID= xkbi->desc->device_spec;
XkbFreeKeyboard(xkbi->desc,XkbAllComponentsMask,True);
xkbi->desc= NULL;
xkbi->flags&= ~(XkbMapPending|XkbXlibNewKeyboard);
xkbi->changes.changed= 0;
}
else oldDeviceID= XkbUseCoreKbd;
UnlockDisplay(dpy);
desc = XkbGetMap(dpy,XkbAllClientInfoMask,XkbUseCoreKbd);
if (!desc)
DBUG_VOID_RETURN;
LockDisplay(dpy);
xkbi->desc = desc;
UnlockDisplay(dpy);
if (desc->device_spec!=oldDeviceID) {
/* transfer(?) event masks here */
#ifdef NOTYET
unsigned oldEvents;
oldEvents= xkbi->selected_events;
XkbSelectEventDetails(dpy,xkbi->desc->device_spec,XkbMapNotify,
XkbAllMapComponentsMask,XkbAllClientInfoMask);
LockDisplay(dpy);
xkbi->selected_events= oldEvents;
UnlockDisplay(dpy);
#endif
}
DBUG_VOID_RETURN;
}
int
#if NeedFunctionPrototypes
XkbTranslateKeySym( register Display * dpy,
register KeySym * sym_rtrn,
unsigned int mods,
char * buffer,
int nbytes,
int * extra_rtrn)
#else
XkbTranslateKeySym(dpy, sym_rtrn, mods, buffer, nbytes, extra_rtrn)
register Display *dpy;
register KeySym *sym_rtrn;
unsigned int mods;
char *buffer;
int nbytes;
int *extra_rtrn;
#endif
{
DBUG_ENTER("XkbTranslateKeySym")
register XkbInfoPtr xkb;
XkbKSToMBFunc cvtr;
XPointer priv;
char tmp[4];
register struct _XKeytrans *p;
int n;
if (extra_rtrn)
*extra_rtrn= 0;
if (_XkbUnavailable(dpy))
return _XTranslateKeySym(dpy, *sym_rtrn, mods, buffer, nbytes);
_XkbCheckPendingRefresh(dpy,dpy->xkb_info);
xkb= dpy->xkb_info;
if ((buffer==NULL)||(nbytes==0)) {
buffer= tmp;
nbytes= 4;
}
/* see if symbol rebound, if so, return that string. */
for (p = dpy->key_bindings; p; p = p->next) {
if (((mods & AllMods) == p->state) && (*sym_rtrn == p->key)) {
int tmp = p->len;
if (tmp > nbytes) {
if (extra_rtrn)
*extra_rtrn= tmp-nbytes;
tmp = nbytes;
}
memcpy (buffer, p->string, tmp);
DBUG_RETURN(tmp);
}
}
if ( nbytes>0 )
buffer[0]= '\0';
if ( xkb->cvt.KSToUpper && (mods&LockMask) ) {
*sym_rtrn = (*xkb->cvt.KSToUpper)(*sym_rtrn);
}
if (xkb->xlib_ctrls & XkbLC_ForceLatin1Lookup) {
cvtr = xkb->latin1cvt.KSToMB;
priv = xkb->latin1cvt.KSToMBPriv;
} else {
cvtr = xkb->cvt.KSToMB;
priv = xkb->cvt.KSToMBPriv;
}
n = (*cvtr)(priv,*sym_rtrn,buffer,nbytes,extra_rtrn);
if ((!xkb->cvt.KSToUpper)&&( mods&LockMask )) {
register int i;
if (!xkb->cvt.KSToUpper) {
int change;
char ch;
for (i=change=0;i<n;i++) {
ch= toupper(buffer[i]);
change= (change||(buffer[i]!=ch));
buffer[i] = ch;
}
if (change) {
if (n==1)
*sym_rtrn=(*xkb->cvt.MBToKS)(xkb->cvt.MBToKSPriv,
buffer,n,0);
else *sym_rtrn= NoSymbol;
}
}
}
if ( mods&ControlMask ) {
if ( n==1 ) {
register char c = buffer[0];
if ((c >= '@' && c < '\177') || c == ' ') c &= 0x1F;
else if (c == '2') c = '\000';
else if (c >= '3' && c <= '7') c -= ('3' - '\033');
else if (c == '8') c = '\177';
else if (c == '/') c = '_' & 0x1F;
buffer[0]= c;
if ( nbytes>1 )
buffer[1]= '\0';
DBUG_RETURN(1);
}
if ( nbytes > 0 )
buffer[0]= '\0';
DBUG_RETURN(0);
}
DBUG_RETURN(n);
}
int
#if NeedFunctionPrototypes
XLookupString ( register XKeyEvent * event,
char * buffer,
int nbytes,
KeySym * keysym,
XComposeStatus * status)
#else
XLookupString (event, buffer, nbytes, keysym, status)
register XKeyEvent *event;
char *buffer; /* buffer */
int nbytes; /* space in buffer for characters */
KeySym *keysym;
XComposeStatus *status;
#endif
{
DBUG_ENTER("XLookupString")
KeySym dummy;
int rtrnLen;
unsigned int new_mods;
Display *dpy = event->display;
XkbDescPtr xkb;
int result;
if (_XkbUnavailable(dpy)) {
result = _XLookupString(event, buffer, nbytes, keysym, status);
DBUG_RETURN(result);
}
_XkbCheckPendingRefresh(dpy,dpy->xkb_info);
if (keysym==NULL)
keysym= &dummy;
xkb= dpy->xkb_info->desc;
if (!XkbTranslateKeyCode(xkb,event->keycode,event->state, &new_mods,keysym))
DBUG_RETURN(0);
new_mods= (event->state&(~new_mods));
#ifdef USE_OWN_COMPOSE
if ( status ) {
static int been_here= 0;
if ( !been_here ) {
XimCompInitTables();
been_here = 1;
}
if ( !XimCompLegalStatus(status) ) {
status->compose_ptr = NULL;
status->chars_matched = 0;
}
if ( ((status->chars_matched>0)&&(status->compose_ptr!=NULL)) ||
XimCompIsComposeKey(*keysym,event->keycode,status) ) {
XimCompRtrn rtrn;
switch (XimCompProcessSym(status,*keysym,&rtrn)) {
case XIM_COMP_IGNORE:
break;
case XIM_COMP_IN_PROGRESS:
if ( keysym!=NULL )
*keysym = NoSymbol;
#ifndef NO_COMPOSE_LED
if ( dpy->xkb_info->xlib_ctrls&XkbLC_ComposeLED ) {
XkbSetNamedIndicator(dpy,dpy->xkb_info->composeLED,
True,True,False,NULL);
}
#endif
DBUG_RETURN(0);
case XIM_COMP_FAIL:
{
static Atom _ComposeFail= None;
int n = 0, len= 0;
#ifndef NO_COMPOSE_LED
if ( dpy->xkb_info->xlib_ctrls&XkbLC_ComposeLED ) {
XkbSetNamedIndicator(dpy,dpy->xkb_info->composeLED,
True,False,False,NULL);
}
#endif
#ifndef NO_BELL_ON_COMPOSE_FAIL
if (dpy->xkb_info->xlib_ctrls&XkbLC_BeepOnComposeFail) {
if (_ComposeFail==None)
_ComposeFail= XInternAtom(dpy,"ComposeFail",0);
XkbBell(dpy,event->window,0,_ComposeFail);
}
#endif
for (n=len=0;rtrn.sym[n]!=XK_VoidSymbol;n++) {
if ( nbytes-len > 0 ) {
len+= XkbTranslateKeySym(dpy,&rtrn.sym[n],new_mods,
buffer+len,nbytes-len,
NULL);
}
}
if ( keysym!=NULL ) {
if ( n==1 ) *keysym = rtrn.sym[0];
else *keysym = NoSymbol;
}
DBUG_RETURN(len);
}
case XIM_COMP_SUCCEED:
{
int len,n = 0;
#ifndef NO_COMPOSE_LED
if ( dpy->xkb_info->xlib_ctrls&XkbLC_ComposeLED ) {
XkbSetNamedIndicator(dpy,dpy->xkb_info->composeLED,
True,False,False,NULL);
}
#endif
*keysym = rtrn.matchSym;
if ( rtrn.str[0]!='\0' ) {
strncpy(buffer,rtrn.str,nbytes-1);
buffer[nbytes-1]= '\0';
len = (int)strlen(buffer);
}
else {
len = XkbTranslateKeySym(dpy,keysym,new_mods,
buffer,nbytes,
NULL);
}
for (n=0;rtrn.sym[n]!=XK_VoidSymbol;n++) {
if ( nbytes-len > 0 ) {
len+= XkbTranslateKeySym(dpy,&rtrn.sym[n],
event->state,
buffer+len,nbytes-len,
NULL);
}
}
DBUG_RETURN(len);
}
}
}
}
#endif
/* We *should* use the new_mods (which does not contain any modifiers */
/* that were used to compute the symbol here, but pre-XKB XLookupString */
/* did not and we have to remain compatible. Sigh. */
if ((dpy->xkb_info->flags&XkbLC_ConsumeLookupMods)==0)
new_mods= event->state;
rtrnLen= XkbLookupKeyBinding(dpy,*keysym,new_mods,buffer,nbytes,NULL);
if (rtrnLen>0)
DBUG_RETURN(rtrnLen);
rtrnLen = XkbTranslateKeySym(dpy,keysym,new_mods,buffer,nbytes,NULL);
if ((event->state&ControlMask)&&(nbytes>0)&&
((rtrnLen==0)||((rtrnLen==1)&&(buffer[0]>=' ')))&&
(XkbGroupForCoreState(event->state)!=XkbGroup1Index)&&
(dpy->xkb_info->xlib_ctrls&XkbLC_ControlFallback)) {
XKeyEvent tmp_ev;
tmp_ev= *event;
tmp_ev.state= XkbBuildCoreState(event->state,XkbGroup1Index);
result = XLookupString (&tmp_ev, buffer, nbytes, keysym, status);
DBUG_RETURN(result);
}
DBUG_RETURN(rtrnLen);
}
int
#if NeedFunctionPrototypes
XkbLookupKeyBinding( Display * dpy,
register KeySym sym,
unsigned int mods,
char * buffer,
int nbytes,
int * extra_rtrn)
#else
XkbLookupKeyBinding(dpy, sym, mods, buffer, nbytes, extra_rtrn)
Display *dpy;
register KeySym sym;
unsigned int mods;
char *buffer;
int nbytes;
int * extra_rtrn;
#endif
{
DBUG_ENTER("XkbLookupKeyBinding")
register struct _XKeytrans *p;
if (extra_rtrn)
*extra_rtrn= 0;
for (p = dpy->key_bindings; p; p = p->next) {
if (((mods & AllMods) == p->state) && (sym == p->key)) {
int tmp = p->len;
if (tmp > nbytes) {
if (extra_rtrn)
*extra_rtrn= (tmp-nbytes);
tmp = nbytes;
}
memcpy (buffer, p->string, tmp);
if (tmp < nbytes) buffer[tmp]= '\0';
DBUG_RETURN(tmp);
}
}
DBUG_RETURN(0);
}
char
#if NeedFunctionPrototypes
XkbToControl( char c )
#else
XkbToControl( c )
char c;
#endif
{
if ((c >= '@' && c < '\177') || c == ' ') c &= 0x1F;
else if (c == '2') c = '\000';
else if (c >= '3' && c <= '7') c -= ('3' - '\033');
else if (c == '8') c = '\177';
else if (c == '/') c = '_' & 0x1F;
return c;
}