PageRenderTime 77ms CodeModel.GetById 10ms app.highlight 60ms RepoModel.GetById 1ms app.codeStats 0ms

/libX11-1.5.0/src/xkb/XKBBind.c

#
C | 848 lines | 716 code | 81 blank | 51 comment | 161 complexity | cbfad56b75ab1a63640ca412b0063ed9 MD5 | raw file
  1/*
  2
  3Copyright 1985, 1987, 1994, 1998  The Open Group
  4
  5Permission to use, copy, modify, distribute, and sell this software and its
  6documentation for any purpose is hereby granted without fee, provided that
  7the above copyright notice appear in all copies and that both that
  8copyright notice and this permission notice appear in supporting
  9documentation.
 10
 11The above copyright notice and this permission notice shall be included
 12in all copies or substantial portions of the Software.
 13
 14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 15OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 16MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 17IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
 18OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 19ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 20OTHER DEALINGS IN THE SOFTWARE.
 21
 22Except as contained in this notice, the name of The Open Group shall
 23not be used in advertising or otherwise to promote the sale, use or
 24other dealings in this Software without prior written authorization
 25from The Open Group.
 26
 27*/
 28
 29	/* the new monsters ate the old ones */
 30
 31#ifdef HAVE_CONFIG_H
 32#include <config.h>
 33#endif
 34#include "XKBlib.h"
 35#include <X11/Xlibint.h>
 36#include <X11/Xutil.h>
 37#include <X11/keysym.h>
 38#include <stdio.h>
 39#include <ctype.h>
 40
 41#include <X11/extensions/XKBproto.h>
 42#include "XKBlibint.h"
 43
 44#ifdef USE_OWN_COMPOSE
 45#define	COMPOSE_NO_CONST_MEMBERS
 46#include "imComp.h"
 47#endif
 48
 49#define AllMods (ShiftMask|LockMask|ControlMask| \
 50		 Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)
 51
 52static int _XkbLoadDpy(
 53    Display *dpy
 54);
 55
 56struct _XKeytrans {
 57	struct _XKeytrans *next;/* next on list */
 58	char *string;		/* string to return when the time comes */
 59	int len;		/* length of string (since NULL is legit)*/
 60	KeySym key;		/* keysym rebound */
 61	unsigned int state;	/* modifier state */
 62	KeySym *modifiers;	/* modifier keysyms you want */
 63	int mlen;		/* length of modifier list */
 64};
 65
 66KeySym
 67XkbKeycodeToKeysym(Display *dpy,
 68#if NeedWidePrototypes
 69		 unsigned int kc,
 70#else
 71		 KeyCode kc,
 72#endif
 73		 int 	group,
 74		 int	level)
 75{
 76    XkbDescRec	*xkb;
 77
 78    if (_XkbUnavailable(dpy))
 79	return NoSymbol;
 80
 81    _XkbCheckPendingRefresh(dpy,dpy->xkb_info);
 82
 83    xkb = dpy->xkb_info->desc;
 84    if ((kc<xkb->min_key_code)||(kc>xkb->max_key_code))
 85	return NoSymbol;
 86
 87    if ((group<0)||(level<0)||(group>=XkbKeyNumGroups(xkb,kc)))
 88	return NoSymbol;
 89    if (level>=XkbKeyGroupWidth(xkb,kc,group)) {
 90	/* for compatibility with the core protocol, _always_ allow  */
 91	/* two symbols in the first two groups.   If either of the   */
 92	/* two is of type ONE_LEVEL, just replicate the first symbol */
 93	if ((group>XkbGroup2Index)||(XkbKeyGroupWidth(xkb,kc,group)!=1)||
 94								(level!=1)) {
 95	    return NoSymbol;
 96	}
 97	level= 0;
 98    }
 99    return XkbKeySymEntry(xkb,kc,level,group);
100}
101
102KeySym
103XKeycodeToKeysym(Display *dpy,
104#if NeedWidePrototypes
105		 unsigned int kc,
106#else
107		 KeyCode kc,
108#endif
109		 int col)
110{
111    XkbDescRec	*xkb;
112
113    if (_XkbUnavailable(dpy))
114	return _XKeycodeToKeysym(dpy, kc, col);
115
116    _XkbCheckPendingRefresh(dpy,dpy->xkb_info);
117
118    xkb = dpy->xkb_info->desc;
119    if ((kc<xkb->min_key_code)||(kc>xkb->max_key_code))
120	return NoSymbol;
121
122    if (col>3) {
123	int lastSym,tmp,nGrp;
124
125	lastSym= 3;
126	nGrp= XkbKeyNumGroups(xkb,kc);
127	if ((nGrp>0)&&((tmp=XkbKeyGroupWidth(xkb,kc,XkbGroup1Index))>2)) {
128	    if (col<=(lastSym+tmp-2))
129		return XkbKeycodeToKeysym(dpy,kc,XkbGroup1Index,col-lastSym+2);
130	    lastSym+= tmp-2;
131	}
132	if ((nGrp>1)&&((tmp=XkbKeyGroupWidth(xkb,kc,XkbGroup2Index))>2)) {
133	    if (col<=(lastSym+tmp-2))
134		return XkbKeycodeToKeysym(dpy,kc,XkbGroup2Index,col-lastSym+2);
135	    lastSym+= tmp-2;
136	}
137	if (nGrp>2) {
138	    tmp= XkbKeyGroupWidth(xkb,kc,XkbGroup3Index);
139	    if (col<=lastSym+tmp)
140		return XkbKeycodeToKeysym(dpy,kc,XkbGroup3Index,col-lastSym);
141	    lastSym+= tmp;
142	}
143	if (nGrp>3) {
144	    tmp= XkbKeyGroupWidth(xkb,kc,XkbGroup4Index);
145	    if (col<=lastSym+tmp)
146		return XkbKeycodeToKeysym(dpy,kc,XkbGroup4Index,col-lastSym);
147	}
148	return NoSymbol;
149    }
150    return XkbKeycodeToKeysym(dpy,kc,(col>>1),(col&1));
151}
152
153KeyCode
154XKeysymToKeycode(Display *dpy, KeySym ks)
155{
156    register int i, j, gotOne;
157
158    if (_XkbUnavailable(dpy))
159	return _XKeysymToKeycode(dpy,ks);
160    _XkbCheckPendingRefresh(dpy,dpy->xkb_info);
161
162    j= 0;
163    do {
164	register XkbDescRec *xkb = dpy->xkb_info->desc;
165	gotOne= 0;
166	for (i = dpy->min_keycode; i <= dpy->max_keycode; i++) {
167	    if ( j<(int)XkbKeyNumSyms(xkb,i) ) {
168		gotOne = 1;
169		if ((XkbKeySym(xkb,i,j)==ks))
170		    return i;
171	    }
172	}
173	j++;
174    } while (gotOne);
175    return 0;
176}
177
178static int
179_XkbComputeModmap(Display *dpy)
180{
181register XkbDescPtr xkb;
182
183    xkb= dpy->xkb_info->desc;
184    if (XkbGetUpdatedMap(dpy,XkbModifierMapMask,xkb)==Success)
185	return 1;
186    return 0;
187}
188
189unsigned
190XkbKeysymToModifiers(Display *dpy,KeySym ks)
191{
192    XkbDescRec *xkb;
193    register int i,j;
194    register KeySym *pSyms;
195    CARD8 mods;
196
197    if (_XkbUnavailable(dpy))
198	return _XKeysymToModifiers(dpy,ks);
199    _XkbCheckPendingRefresh(dpy,dpy->xkb_info);
200
201    if (_XkbNeedModmap(dpy->xkb_info)&&(!_XkbComputeModmap(dpy)))
202	return _XKeysymToModifiers(dpy,ks);
203
204    xkb= dpy->xkb_info->desc;
205    mods= 0;
206    for (i = xkb->min_key_code; i <= (int)xkb->max_key_code; i++) {
207	pSyms= XkbKeySymsPtr(xkb,i);
208	for (j=XkbKeyNumSyms(xkb,i)-1;j>=0;j--) {
209	    if (pSyms[j]==ks) {
210		mods|= xkb->map->modmap[i];
211		break;
212	    }
213	}
214    }
215    return mods;
216}
217
218KeySym
219XLookupKeysym(register XKeyEvent *event, int col)
220{
221    Display *dpy = event->display;
222    if (_XkbUnavailable(dpy))
223	return _XLookupKeysym(event, col);
224    _XkbCheckPendingRefresh(dpy,dpy->xkb_info);
225    return XKeycodeToKeysym(dpy, event->keycode, col);
226}
227
228   /*
229    * Not a public entry point -- XkbTranslateKey is an obsolete name
230    * that is preserved here so that functions linked against the old
231    * version will continue to work in a shared library environment.
232    */
233int
234XkbTranslateKey(	register Display *	dpy,
235			KeyCode 		key,
236			register unsigned int 	mods,
237			unsigned int *		mods_rtrn,
238			KeySym *		keysym_rtrn);
239int
240XkbTranslateKey(	register Display *	dpy,
241			KeyCode 		key,
242			register unsigned int 	mods,
243			unsigned int *		mods_rtrn,
244			KeySym *		keysym_rtrn)
245{
246    return XkbLookupKeySym(dpy,key,mods,mods_rtrn,keysym_rtrn);
247}
248
249Bool
250XkbLookupKeySym(	register Display *	dpy,
251			KeyCode 		key,
252			register unsigned int 	mods,
253			unsigned int *		mods_rtrn,
254			KeySym *		keysym_rtrn)
255{
256    if (_XkbUnavailable(dpy))
257	return _XTranslateKey(dpy, key, mods, mods_rtrn, keysym_rtrn);
258    _XkbCheckPendingRefresh(dpy,dpy->xkb_info);
259    return XkbTranslateKeyCode(dpy->xkb_info->desc,key,mods,mods_rtrn,
260								keysym_rtrn);
261}
262
263Bool
264XkbTranslateKeyCode(	register XkbDescPtr	xkb,
265			KeyCode 		key,
266			register unsigned int 	mods,
267			unsigned int *		mods_rtrn,
268			KeySym *		keysym_rtrn)
269{
270    XkbKeyTypeRec *type;
271    int col,nKeyGroups;
272    unsigned preserve,effectiveGroup;
273    KeySym *syms;
274
275    if (mods_rtrn!=NULL)
276	*mods_rtrn = 0;
277
278    nKeyGroups= XkbKeyNumGroups(xkb,key);
279    if ((!XkbKeycodeInRange(xkb,key))||(nKeyGroups==0)) {
280	if (keysym_rtrn!=NULL)
281	    *keysym_rtrn = NoSymbol;
282	return False;
283    }
284
285    syms = XkbKeySymsPtr(xkb,key);
286
287    /* find the offset of the effective group */
288    col = 0;
289    effectiveGroup= XkbGroupForCoreState(mods);
290    if ( effectiveGroup>=nKeyGroups ) {
291	unsigned groupInfo= XkbKeyGroupInfo(xkb,key);
292	switch (XkbOutOfRangeGroupAction(groupInfo)) {
293	    default:
294		effectiveGroup %= nKeyGroups;
295		break;
296	    case XkbClampIntoRange:
297		effectiveGroup = nKeyGroups-1;
298		break;
299	    case XkbRedirectIntoRange:
300		effectiveGroup = XkbOutOfRangeGroupNumber(groupInfo);
301		if (effectiveGroup>=nKeyGroups)
302		    effectiveGroup= 0;
303		break;
304	}
305    }
306    col= effectiveGroup*XkbKeyGroupsWidth(xkb,key);
307    type = XkbKeyKeyType(xkb,key,effectiveGroup);
308
309    preserve= 0;
310    if (type->map) { /* find the column (shift level) within the group */
311	register int i;
312	register XkbKTMapEntryPtr entry;
313	for (i=0,entry=type->map;i<type->map_count;i++,entry++) {
314	    if ((entry->active)&&((mods&type->mods.mask)==entry->mods.mask)) {
315		col+= entry->level;
316		if (type->preserve)
317		    preserve= type->preserve[i].mask;
318		break;
319	    }
320	}
321    }
322
323    if (keysym_rtrn!=NULL)
324	*keysym_rtrn= syms[col];
325    if (mods_rtrn) {
326	*mods_rtrn= type->mods.mask&(~preserve);
327	/* The Motif VTS doesn't get the help callback called if help
328	 * is bound to Shift+<whatever>, and it appears as though it
329	 * is XkbTranslateKeyCode that is causing the problem.  The
330	 * core X version of XTranslateKey always OR's in ShiftMask
331	 * and LockMask for mods_rtrn, so this "fix" keeps this behavior
332	 * and solves the VTS problem.
333	 */
334	if ((xkb->dpy)&&(xkb->dpy->xkb_info)&&
335	    (xkb->dpy->xkb_info->xlib_ctrls&XkbLC_AlwaysConsumeShiftAndLock)) {
336	    *mods_rtrn|= (ShiftMask|LockMask);
337	}
338    }
339    return (syms[col]!=NoSymbol);
340}
341
342Status
343XkbRefreshKeyboardMapping(register XkbMapNotifyEvent *event)
344{
345    Display *dpy = event->display;
346    XkbInfoPtr xkbi;
347
348    if (_XkbUnavailable(dpy)) {
349	_XRefreshKeyboardMapping((XMappingEvent *)event);
350	return Success;
351    }
352    xkbi= dpy->xkb_info;
353
354    if (((event->type&0x7f)-xkbi->codes->first_event)!=XkbEventCode)
355	return BadMatch;
356    if (event->xkb_type==XkbNewKeyboardNotify) {
357	_XkbReloadDpy(dpy);
358	return Success;
359    }
360    if (event->xkb_type==XkbMapNotify) {
361	XkbMapChangesRec	changes;
362	Status			rtrn;
363
364	if (xkbi->flags&XkbMapPending)
365	     changes= xkbi->changes;
366	else bzero(&changes,sizeof(changes));
367	XkbNoteMapChanges(&changes,event,XKB_XLIB_MAP_MASK);
368	if ((rtrn=XkbGetMapChanges(dpy,xkbi->desc,&changes))!=Success) {
369#ifdef DEBUG
370	    fprintf(stderr,"Internal Error! XkbGetMapChanges failed:\n");
371#endif
372	    xkbi->changes= changes;
373	}
374	else if (xkbi->flags&XkbMapPending) {
375	    xkbi->flags&= ~XkbMapPending;
376	    bzero(&xkbi->changes,sizeof(XkbMapChangesRec));
377	}
378	return rtrn;
379    }
380    return BadMatch;
381}
382
383int
384XRefreshKeyboardMapping(register XMappingEvent *event)
385{
386    XkbEvent	*xkbevent = (XkbEvent *)event;
387    Display *dpy = event->display;
388    XkbMapChangesRec changes;
389    XkbInfoPtr xkbi;
390
391    /* always do this for input methods, which still use the old keymap */
392    (void) _XRefreshKeyboardMapping(event);
393
394    if (_XkbUnavailable(dpy))
395	return 1;
396
397    xkbi = dpy->xkb_info;
398
399    if (((event->type&0x7f)-xkbi->codes->first_event)==XkbEventCode)
400	return XkbRefreshKeyboardMapping(&xkbevent->map);
401
402    if (xkbi->flags&XkbXlibNewKeyboard) {
403	_XkbReloadDpy(dpy);
404	return 1;
405    }
406
407    if ((xkbi->flags&XkbMapPending)||(event->request==MappingKeyboard)) {
408	if (xkbi->flags&XkbMapPending) {
409	    changes= xkbi->changes;
410	    _XkbNoteCoreMapChanges(&changes,event,XKB_XLIB_MAP_MASK);
411	}
412	else {
413	    bzero(&changes,sizeof(changes));
414	    changes.changed= XkbKeySymsMask;
415	    if (xkbi->desc->min_key_code<xkbi->desc->max_key_code) {
416		changes.first_key_sym= xkbi->desc->min_key_code;
417		changes.num_key_syms= xkbi->desc->max_key_code-
418						xkbi->desc->min_key_code+1;
419	    }
420	    else {
421		changes.first_key_sym= event->first_keycode;
422		changes.num_key_syms= event->count;
423	    }
424	}
425
426	if (XkbGetMapChanges(dpy,xkbi->desc, &changes)!=Success) {
427#ifdef DEBUG
428		fprintf(stderr,"Internal Error! XkbGetMapChanges failed:\n");
429		if (changes.changed&XkbKeyTypesMask) {
430		    int first= changes.first_type;
431		    int last= changes.first_type+changes.num_types-1;
432		    fprintf(stderr,"       types:  %d..%d\n",first,last);
433		}
434		if (changes.changed&XkbKeySymsMask) {
435		    int first= changes.first_key_sym;
436		    int last= changes.first_key_sym+changes.num_key_syms-1;
437		    fprintf(stderr,"     symbols:  %d..%d\n",first,last);
438		}
439		if (changes.changed&XkbKeyActionsMask) {
440		    int last,first= changes.first_key_act;
441		    last= changes.first_key_act+changes.num_key_acts-1;
442		    fprintf(stderr,"     acts:  %d..%d\n",first,last);
443		}
444		if (changes.changed&XkbKeyBehaviorsMask) {
445		    int last,first= changes.first_key_behavior;
446		    last= first+changes.num_key_behaviors-1;
447		    fprintf(stderr,"   behaviors:  %d..%d\n",first,last);
448		}
449		if (changes.changed&XkbVirtualModsMask) {
450		    fprintf(stderr,"virtual mods: 0x%04x\n",
451					changes.vmods);
452		}
453		if (changes.changed&XkbExplicitComponentsMask) {
454		    int last,first= changes.first_key_explicit;
455		    last= first+changes.num_key_explicit-1;
456		    fprintf(stderr,"    explicit:  %d..%d\n",first,last);
457		}
458#endif
459	}
460	LockDisplay(dpy);
461	if (xkbi->flags&XkbMapPending) {
462	    xkbi->flags&= ~XkbMapPending;
463	    bzero(&xkbi->changes,sizeof(XkbMapChangesRec));
464	}
465	UnlockDisplay(dpy);
466    }
467    if (event->request==MappingModifier) {
468	LockDisplay(dpy);
469	if (xkbi->desc->map->modmap) {
470	    _XkbFree(xkbi->desc->map->modmap);
471	    xkbi->desc->map->modmap= NULL;
472	}
473	if (dpy->key_bindings) {
474	    register struct _XKeytrans *p;
475	    for (p = dpy->key_bindings; p; p = p->next) {
476		register int i;
477		p->state= 0;
478	  	if (p->mlen>0) {
479		    for (i = 0; i < p->mlen; i++) {
480			p->state|= XkbKeysymToModifiers(dpy,p->modifiers[i]);
481		    }
482		    if (p->state)	p->state &= AllMods;
483		    else		p->state = AnyModifier;
484		}
485	    }
486	}
487	UnlockDisplay(dpy);
488    }
489    return 1;
490}
491
492static int
493_XkbLoadDpy(Display *dpy)
494{
495    XkbInfoPtr xkbi;
496    unsigned query,oldEvents;
497    XkbDescRec *desc;
498
499    if (!XkbUseExtension(dpy,NULL,NULL))
500	return 0;
501
502    xkbi = dpy->xkb_info;
503    query = XkbAllClientInfoMask;
504    desc = XkbGetMap(dpy,query,XkbUseCoreKbd);
505    if (!desc) {
506#ifdef DEBUG
507	fprintf(stderr,"Warning! XkbGetMap failed!\n");
508#endif
509	return 0;
510    }
511    LockDisplay(dpy);
512    xkbi->desc = desc;
513
514    UnlockDisplay(dpy);
515    oldEvents= xkbi->selected_events;
516    if (!(xkbi->xlib_ctrls&XkbLC_IgnoreNewKeyboards)) {
517	XkbSelectEventDetails(dpy,xkbi->desc->device_spec,XkbNewKeyboardNotify,
518				XkbNKN_KeycodesMask|XkbNKN_DeviceIDMask,
519				XkbNKN_KeycodesMask|XkbNKN_DeviceIDMask);
520    }
521    XkbSelectEventDetails(dpy,xkbi->desc->device_spec,XkbMapNotify,
522				XkbAllClientInfoMask,XkbAllClientInfoMask);
523    LockDisplay(dpy);
524    xkbi->selected_events= oldEvents;
525    UnlockDisplay(dpy);
526    return 1;
527}
528
529void
530_XkbReloadDpy(Display *dpy)
531{
532    XkbInfoPtr xkbi;
533    XkbDescRec *desc;
534    unsigned	oldDeviceID;
535
536    if (_XkbUnavailable(dpy))
537	return;
538
539    xkbi = dpy->xkb_info;
540    LockDisplay(dpy);
541    if (xkbi->desc) {
542	oldDeviceID= xkbi->desc->device_spec;
543	XkbFreeKeyboard(xkbi->desc,XkbAllComponentsMask,True);
544	xkbi->desc= NULL;
545	xkbi->flags&= ~(XkbMapPending|XkbXlibNewKeyboard);
546	xkbi->changes.changed= 0;
547    }
548    else oldDeviceID= XkbUseCoreKbd;
549    UnlockDisplay(dpy);
550    desc = XkbGetMap(dpy,XkbAllClientInfoMask,XkbUseCoreKbd);
551    if (!desc)
552	return;
553    LockDisplay(dpy);
554    xkbi->desc = desc;
555    UnlockDisplay(dpy);
556
557    if (desc->device_spec!=oldDeviceID) {
558	/* transfer(?) event masks here */
559#ifdef NOTYET
560	unsigned oldEvents;
561	oldEvents= xkbi->selected_events;
562	XkbSelectEventDetails(dpy,xkbi->desc->device_spec,XkbMapNotify,
563				XkbAllMapComponentsMask,XkbAllClientInfoMask);
564	LockDisplay(dpy);
565	xkbi->selected_events= oldEvents;
566	UnlockDisplay(dpy);
567#endif
568    }
569    return;
570}
571
572int
573XkbTranslateKeySym(	register Display *	dpy,
574			register KeySym *	sym_rtrn,
575			unsigned int 		mods,
576			char *			buffer,
577			int 			nbytes,
578			int *			extra_rtrn)
579{
580    register XkbInfoPtr	xkb;
581    XkbKSToMBFunc cvtr;
582    XPointer priv;
583    char tmp[4];
584    int n;
585
586    xkb= dpy->xkb_info;
587    if (!xkb->cvt.KSToMB) {
588        _XkbGetConverters(_XkbGetCharset(),&xkb->cvt);
589        _XkbGetConverters("ISO8859-1",&xkb->latin1cvt);
590    }
591
592    if (extra_rtrn)
593	*extra_rtrn= 0;
594
595    if ((buffer==NULL)||(nbytes==0)) {
596	buffer= tmp;
597	nbytes= 4;
598    }
599
600    /* see if symbol rebound, if so, return that string. */
601    n = XkbLookupKeyBinding(dpy,*sym_rtrn,mods,buffer,nbytes,extra_rtrn);
602    if (n)
603        return n;
604
605    if ( nbytes>0 )
606	buffer[0]= '\0';
607
608    if ( xkb->cvt.KSToUpper && (mods&LockMask) ) {
609	*sym_rtrn = (*xkb->cvt.KSToUpper)(*sym_rtrn);
610    }
611    if (xkb->xlib_ctrls & XkbLC_ForceLatin1Lookup) {
612	cvtr = xkb->latin1cvt.KSToMB;
613	priv = xkb->latin1cvt.KSToMBPriv;
614    } else {
615	cvtr = xkb->cvt.KSToMB;
616	priv = xkb->cvt.KSToMBPriv;
617    }
618
619    n = (*cvtr)(priv,*sym_rtrn,buffer,nbytes,extra_rtrn);
620
621    if ((!xkb->cvt.KSToUpper)&&( mods&LockMask )) {
622	register int i;
623	int change;
624	char ch;
625	for (i=change=0;i<n;i++) {
626	    ch= toupper(buffer[i]);
627	    change= (change||(buffer[i]!=ch));
628	    buffer[i] = ch;
629	}
630	if (change) {
631	    if (n==1)
632	        *sym_rtrn=(*xkb->cvt.MBToKS)(xkb->cvt.MBToKSPriv,buffer,n,NULL);
633	    else *sym_rtrn= NoSymbol;
634	}
635    }
636
637    if ( mods&ControlMask ) {
638	if ( n==1 ) {
639	    buffer[0]= XkbToControl(buffer[0]);
640	    if ( nbytes>1 )
641		buffer[1]= '\0';
642	    return 1;
643	}
644	if ( nbytes > 0 )
645	    buffer[0]= '\0';
646	return 0;
647    }
648    return n;
649}
650
651int
652XLookupString (	register XKeyEvent *	event,
653		char *			buffer,
654		int 			nbytes,
655		KeySym *		keysym,
656		XComposeStatus *	status)
657{
658    KeySym	dummy;
659    int rtrnLen;
660    unsigned int new_mods;
661    Display *dpy = event->display;
662
663    if (keysym==NULL)
664	keysym= &dummy;
665    if (!XkbLookupKeySym(dpy,event->keycode,event->state, &new_mods,keysym))
666	return 0;
667    new_mods= (event->state&(~new_mods));
668
669    /* find the group where a symbol can be converted to control one */
670    if (new_mods&ControlMask && *keysym > 0x7F &&
671	(dpy->xkb_info->xlib_ctrls & XkbLC_ControlFallback)) {
672	XKeyEvent tmp_ev = *event;
673	KeySym tmp_keysym;
674	unsigned int tmp_new_mods;
675	if (_XkbUnavailable(dpy)) {
676            tmp_ev.state= event->state ^ dpy->mode_switch;
677            if (XkbLookupKeySym(dpy, tmp_ev.keycode, tmp_ev.state,
678                                &tmp_new_mods, &tmp_keysym) &&
679                tmp_keysym != NoSymbol && tmp_keysym < 0x80 ) {
680                *keysym = tmp_keysym;
681            }
682        } else {
683            int n = XkbKeyNumGroups(dpy->xkb_info->desc, tmp_ev.keycode);
684            int i;
685            for (i = 0; i < n; i++) {
686                if (XkbGroupForCoreState(event->state) == i)
687                    continue;
688                tmp_ev.state= XkbBuildCoreState(tmp_ev.state, i);
689                if (XkbLookupKeySym(dpy, tmp_ev.keycode, tmp_ev.state,
690                                     &tmp_new_mods, &tmp_keysym) &&
691                    tmp_keysym != NoSymbol && tmp_keysym < 0x80 ) {
692                    *keysym = tmp_keysym;
693                    new_mods= (event->state&(~tmp_new_mods));
694                    break;
695                }
696            }
697        }
698    }
699
700#ifdef USE_OWN_COMPOSE
701    if ( status ) {
702	static int been_here= 0;
703	if ( !been_here ) {
704	    XimCompInitTables();
705	    been_here = 1;
706	}
707	if ( !XimCompLegalStatus(status) ) {
708	    status->compose_ptr = NULL;
709	    status->chars_matched = 0;
710	}
711	if ( ((status->chars_matched>0)&&(status->compose_ptr!=NULL)) ||
712		XimCompIsComposeKey(*keysym,event->keycode,status) ) {
713	    XimCompRtrn rtrn;
714
715	    switch (XimCompProcessSym(status,*keysym,&rtrn)) {
716		case XIM_COMP_IGNORE:
717		    break;
718		case XIM_COMP_IN_PROGRESS:
719		    if ( keysym!=NULL )
720			*keysym = NoSymbol;
721#ifndef NO_COMPOSE_LED
722		    if ( dpy->xkb_info->xlib_ctrls&XkbLC_ComposeLED ) {
723			XkbSetNamedIndicator(dpy,dpy->xkb_info->composeLED,
724						True,True,False,NULL);
725		    }
726#endif
727		    return 0;
728		case XIM_COMP_FAIL:
729		{
730		    static Atom _ComposeFail= None;
731		    int n = 0, len= 0;
732#ifndef NO_COMPOSE_LED
733		    if ( dpy->xkb_info->xlib_ctrls&XkbLC_ComposeLED ) {
734			XkbSetNamedIndicator(dpy,dpy->xkb_info->composeLED,
735						True,False,False,NULL);
736		    }
737#endif
738#ifndef NO_BELL_ON_COMPOSE_FAIL
739		    if (dpy->xkb_info->xlib_ctrls&XkbLC_BeepOnComposeFail) {
740			if (_ComposeFail==None)
741			    _ComposeFail= XInternAtom(dpy,"ComposeFail",0);
742			XkbBell(dpy,event->window,0,_ComposeFail);
743		    }
744#endif
745		    for (n=len=0;rtrn.sym[n]!=XK_VoidSymbol;n++) {
746			if ( nbytes-len > 0 ) {
747			    len+= XkbTranslateKeySym(dpy,&rtrn.sym[n],new_mods,
748							buffer+len,nbytes-len,
749							NULL);
750			}
751		    }
752		    if ( keysym!=NULL ) {
753			if ( n==1 )	*keysym = rtrn.sym[0];
754			else		*keysym = NoSymbol;
755		    }
756		    return len;
757		}
758		case XIM_COMP_SUCCEED:
759		{
760		    int len,n = 0;
761
762#ifndef NO_COMPOSE_LED
763		    if ( dpy->xkb_info->xlib_ctrls&XkbLC_ComposeLED ) {
764			XkbSetNamedIndicator(dpy,dpy->xkb_info->composeLED,
765						True,False,False,NULL);
766		    }
767#endif
768		    *keysym = rtrn.matchSym;
769		    if ( rtrn.str[0]!='\0' ) {
770			strncpy(buffer,rtrn.str,nbytes-1);
771			buffer[nbytes-1]= '\0';
772			len = (int)strlen(buffer);
773		    }
774		    else {
775			len = XkbTranslateKeySym(dpy,keysym,new_mods,
776							buffer,nbytes,
777							NULL);
778		    }
779		    for (n=0;rtrn.sym[n]!=XK_VoidSymbol;n++) {
780			if ( nbytes-len > 0 ) {
781			    len+= XkbTranslateKeySym(dpy,&rtrn.sym[n],
782							event->state,
783							buffer+len,nbytes-len,
784							NULL);
785			}
786		    }
787		    return len;
788		}
789	    }
790	}
791    }
792#endif
793
794    /* We *should* use the new_mods (which does not contain any modifiers */
795    /* that were used to compute the symbol here, but pre-XKB XLookupString */
796    /* did not and we have to remain compatible.  Sigh. */
797    if (_XkbUnavailable(dpy) ||
798	(dpy->xkb_info->xlib_ctrls&XkbLC_ConsumeLookupMods)==0)
799	new_mods= event->state;
800
801    rtrnLen= XkbLookupKeyBinding(dpy,*keysym,new_mods,buffer,nbytes,NULL);
802    if (rtrnLen>0)
803	return rtrnLen;
804
805    return XkbTranslateKeySym(dpy,keysym,new_mods,buffer,nbytes,NULL);
806}
807
808
809int
810XkbLookupKeyBinding(	Display *		dpy,
811			register KeySym 	sym,
812			unsigned int 		mods,
813			char *			buffer,
814			int 			nbytes,
815			int * 			extra_rtrn)
816{
817    register struct _XKeytrans *p;
818
819    if (extra_rtrn)
820	*extra_rtrn= 0;
821    for (p = dpy->key_bindings; p; p = p->next) {
822	if (((mods & AllMods) == p->state) && (sym == p->key)) {
823	    int tmp = p->len;
824	    if (tmp > nbytes) {
825		if (extra_rtrn)
826		    *extra_rtrn= (tmp-nbytes);
827		tmp = nbytes;
828	    }
829	    memcpy (buffer, p->string, tmp);
830	    if (tmp < nbytes)	buffer[tmp]= '\0';
831	    return tmp;
832	}
833    }
834    return 0;
835}
836
837char
838XkbToControl( char ch )
839{
840    register char c = ch;
841
842    if ((c >= '@' && c < '\177') || c == ' ') c &= 0x1F;
843    else if (c == '2') c = '\000';
844    else if (c >= '3' && c <= '7') c -= ('3' - '\033');
845    else if (c == '8') c = '\177';
846    else if (c == '/') c = '_' & 0x1F;
847    return c;
848}