XKBMisc.c revision b4ee4795
1/************************************************************
2Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
3
4Permission to use, copy, modify, and distribute this
5software and its documentation for any purpose and without
6fee is hereby granted, provided that the above copyright
7notice appear in all copies and that both that copyright
8notice and this permission notice appear in supporting
9documentation, and that the name of Silicon Graphics not be
10used in advertising or publicity pertaining to distribution
11of the software without specific prior written permission.
12Silicon Graphics makes no representation about the suitability
13of this software for any purpose. It is provided "as is"
14without any express or implied warranty.
15
16SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
17SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
19GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
20DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
22OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
23THE USE OR PERFORMANCE OF THIS SOFTWARE.
24
25********************************************************/
26
27#ifdef HAVE_DIX_CONFIG_H
28#include <dix-config.h>
29#elif defined(HAVE_CONFIG_H)
30#include <config.h>
31#endif
32
33#ifndef XKB_IN_SERVER
34
35#include <stdio.h>
36#define NEED_REPLIES
37#define NEED_EVENTS
38#include "Xlibint.h"
39#include <X11/extensions/XKBproto.h>
40#include <X11/keysym.h>
41#include "XKBlibint.h"
42
43#else
44
45#include <stdio.h>
46#include <X11/X.h>
47#define	NEED_EVENTS
48#define	NEED_REPLIES
49#include <X11/Xproto.h>
50#include "misc.h"
51#include "inputstr.h"
52#include <X11/keysym.h>
53#define	XKBSRV_NEED_FILE_FUNCS
54#include <X11/extensions/XKBsrv.h>
55
56#endif /* XKB_IN_SERVER */
57
58/***====================================================================***/
59
60#define	mapSize(m)	(sizeof(m)/sizeof(XkbKTMapEntryRec))
61static  XkbKTMapEntryRec map2Level[]= {
62  { True, ShiftMask, {1, ShiftMask, 0} }
63};
64
65static  XkbKTMapEntryRec mapAlpha[]= {
66  { True, ShiftMask, { 1, ShiftMask, 0 } },
67  { True, LockMask,  { 0,  LockMask, 0 } }
68};
69
70static	XkbModsRec preAlpha[]= {
71	{        0,        0, 0 },
72	{ LockMask, LockMask, 0 }
73};
74
75#define	NL_VMOD_MASK	0
76static  XkbKTMapEntryRec mapKeypad[]= {
77	{ True,	ShiftMask, { 1, ShiftMask,            0 } },
78	{ False,        0, { 1,         0, NL_VMOD_MASK } }
79};
80
81static	XkbKeyTypeRec	canonicalTypes[XkbNumRequiredTypes] = {
82	{ { 0, 0, 0 },
83	  1,	/* num_levels */
84	  0,	/* map_count */
85	  NULL,		NULL,
86	  None,		NULL
87	},
88	{ { ShiftMask, ShiftMask, 0 },
89	  2,	/* num_levels */
90	  mapSize(map2Level),	/* map_count */
91	  map2Level,	NULL,
92	  None,		NULL
93	},
94	{ { ShiftMask|LockMask, ShiftMask|LockMask, 0 },
95	  2,				/* num_levels */
96	  mapSize(mapAlpha),		/* map_count */
97	  mapAlpha,	preAlpha,
98	  None,		NULL
99	},
100	{ { ShiftMask, ShiftMask, NL_VMOD_MASK },
101	  2,				/* num_levels */
102	  mapSize(mapKeypad),		/* map_count */
103	  mapKeypad,	NULL,
104	  None,		NULL
105	}
106};
107
108Status
109XkbInitCanonicalKeyTypes(XkbDescPtr xkb,unsigned which,int keypadVMod)
110{
111XkbClientMapPtr	map;
112XkbKeyTypePtr	from,to;
113Status		rtrn;
114
115    if (!xkb)
116	return BadMatch;
117    rtrn= XkbAllocClientMap(xkb,XkbKeyTypesMask,XkbNumRequiredTypes);
118    if (rtrn!=Success)
119	return rtrn;
120    map= xkb->map;
121    if ((which&XkbAllRequiredTypes)==0)
122	return Success;
123    rtrn= Success;
124    from= canonicalTypes;
125    to= map->types;
126    if (which&XkbOneLevelMask)
127	rtrn= XkbCopyKeyType(&from[XkbOneLevelIndex],&to[XkbOneLevelIndex]);
128    if ((which&XkbTwoLevelMask)&&(rtrn==Success))
129	rtrn= XkbCopyKeyType(&from[XkbTwoLevelIndex],&to[XkbTwoLevelIndex]);
130    if ((which&XkbAlphabeticMask)&&(rtrn==Success))
131	rtrn= XkbCopyKeyType(&from[XkbAlphabeticIndex],&to[XkbAlphabeticIndex]);
132    if ((which&XkbKeypadMask)&&(rtrn==Success)) {
133	XkbKeyTypePtr type;
134	rtrn= XkbCopyKeyType(&from[XkbKeypadIndex],&to[XkbKeypadIndex]);
135	type= &to[XkbKeypadIndex];
136	if ((keypadVMod>=0)&&(keypadVMod<XkbNumVirtualMods)&&(rtrn==Success)) {
137	    type->mods.vmods= (1<<keypadVMod);
138	    type->map[0].active= True;
139	    type->map[0].mods.mask= ShiftMask;
140	    type->map[0].mods.real_mods= ShiftMask;
141	    type->map[0].mods.vmods= 0;
142	    type->map[0].level= 1;
143	    type->map[1].active= False;
144	    type->map[1].mods.mask= 0;
145	    type->map[1].mods.real_mods= 0;
146	    type->map[1].mods.vmods= (1<<keypadVMod);
147	    type->map[1].level= 1;
148	}
149    }
150    return Success;
151}
152
153/***====================================================================***/
154
155#define	CORE_SYM(i)	(i<map_width?core_syms[i]:NoSymbol)
156#define	XKB_OFFSET(g,l)	(((g)*groupsWidth)+(l))
157
158int
159XkbKeyTypesForCoreSymbols(	XkbDescPtr	xkb,
160				int		map_width,
161				KeySym *	core_syms,
162				unsigned int 	protected,
163    				int *		types_inout,
164				KeySym *	xkb_syms_rtrn)
165{
166register int	i;
167unsigned int	empty;
168int		nSyms[XkbNumKbdGroups];
169int		nGroups,tmp,groupsWidth;
170
171    /* Section 12.2 of the protocol describes this process in more detail */
172    /* Step 1:  find the # of symbols in the core mapping per group */
173    groupsWidth= 2;
174    for (i=0;i<XkbNumKbdGroups;i++) {
175	if ((protected&(1<<i))&&(types_inout[i]<xkb->map->num_types)) {
176	    nSyms[i]= xkb->map->types[types_inout[i]].num_levels;
177	    if (nSyms[i]>groupsWidth)
178		groupsWidth= nSyms[i];
179	}
180	else {
181	    types_inout[i]= XkbTwoLevelIndex;	/* don't really know, yet */
182	    nSyms[i]= 2;
183	}
184    }
185    if (nSyms[XkbGroup1Index]<2)
186	nSyms[XkbGroup1Index]= 2;
187    if (nSyms[XkbGroup2Index]<2)
188	nSyms[XkbGroup2Index]= 2;
189    /* Step 2:	Copy the symbols from the core ordering to XKB ordering	*/
190    /*		symbols in the core are in the order:			*/
191    /*		G1L1 G1L2 G2L1 G2L2 [G1L[3-n]] [G2L[3-n]] [G3L*] [G3L*]	*/
192    xkb_syms_rtrn[XKB_OFFSET(XkbGroup1Index,0)]= CORE_SYM(0);
193    xkb_syms_rtrn[XKB_OFFSET(XkbGroup1Index,1)]= CORE_SYM(1);
194    for (i=2;i<nSyms[XkbGroup1Index];i++) {
195	xkb_syms_rtrn[XKB_OFFSET(XkbGroup1Index,i)]= CORE_SYM(2+i);
196    }
197    xkb_syms_rtrn[XKB_OFFSET(XkbGroup2Index,0)]= CORE_SYM(2);
198    xkb_syms_rtrn[XKB_OFFSET(XkbGroup2Index,1)]= CORE_SYM(3);
199    tmp= 2+(nSyms[XkbGroup1Index]-2); /* offset to extra group2 syms */
200    for (i=2;i<nSyms[XkbGroup2Index];i++) {
201	xkb_syms_rtrn[XKB_OFFSET(XkbGroup2Index,i)]= CORE_SYM(tmp+i);
202    }
203    tmp= nSyms[XkbGroup1Index]+nSyms[XkbGroup2Index];
204    if ((tmp>=map_width)&&
205	 ((protected&(XkbExplicitKeyType3Mask|XkbExplicitKeyType4Mask))==0)) {
206	nSyms[XkbGroup3Index]= 0;
207	nSyms[XkbGroup4Index]= 0;
208	nGroups= 2;
209    }
210    else {
211    	nGroups= 3;
212	for (i=0;i<nSyms[XkbGroup3Index];i++,tmp++) {
213	    xkb_syms_rtrn[XKB_OFFSET(XkbGroup3Index,i)]= CORE_SYM(tmp);
214	}
215	if ((tmp<map_width)||(protected&XkbExplicitKeyType4Mask)) {
216	    nGroups= 4;
217	    for (i=0;i<nSyms[XkbGroup4Index];i++,tmp++) {
218		xkb_syms_rtrn[XKB_OFFSET(XkbGroup4Index,i)]= CORE_SYM(tmp);
219	    }
220	}
221	else {
222	    nSyms[XkbGroup4Index]= 0;
223	}
224    }
225    /* steps 3&4: alphanumeric expansion,  assign canonical types */
226    empty= 0;
227    for (i=0;i<nGroups;i++) {
228	KeySym *syms;
229	syms= &xkb_syms_rtrn[XKB_OFFSET(i,0)];
230	if ((nSyms[i]>1)&&(syms[1]==NoSymbol)&&(syms[0]!=NoSymbol)) {
231	    KeySym upper,lower;
232	    XConvertCase(syms[0],&lower,&upper);
233	    if (upper!=lower) {
234		xkb_syms_rtrn[XKB_OFFSET(i,0)]= lower;
235		xkb_syms_rtrn[XKB_OFFSET(i,1)]= upper;
236		if ((protected&(1<<i))==0)
237		    types_inout[i]= XkbAlphabeticIndex;
238	    }
239	    else if ((protected&(1<<i))==0) {
240		types_inout[i]= XkbOneLevelIndex;
241	/*	nSyms[i]=	1;*/
242	    }
243	}
244	if (((protected&(1<<i))==0)&&(types_inout[i]==XkbTwoLevelIndex)) {
245	    if (IsKeypadKey(syms[0])||IsKeypadKey(syms[1]))
246		types_inout[i]= XkbKeypadIndex;
247	    else {
248		KeySym upper,lower;
249		XConvertCase(syms[0],&lower,&upper);
250		if ((syms[0]==lower)&&(syms[1]==upper))
251		    types_inout[i]= XkbAlphabeticIndex;
252	    }
253	}
254	if (syms[0]==NoSymbol) {
255	    register int n;
256	    Bool	found;
257	    for (n=1,found=False;(!found)&&(n<nSyms[i]);n++) {
258		found= (syms[n]!=NoSymbol);
259	    }
260	    if (!found)
261		empty|= (1<<i);
262	}
263    }
264    /* step 5: squoosh out empty groups */
265    if (empty) {
266	for (i=nGroups-1;i>=0;i--) {
267	    if (((empty&(1<<i))==0)||(protected&(1<<i)))
268		break;
269	    nGroups--;
270	}
271    }
272    if (nGroups<1)
273	return 0;
274
275    /* step 6: replicate group 1 into group two, if necessary */
276    if ((nGroups>1)&&((empty&(XkbGroup1Mask|XkbGroup2Mask))==XkbGroup2Mask)) {
277	if ((protected&(XkbExplicitKeyType1Mask|XkbExplicitKeyType2Mask))==0) {
278	    nSyms[XkbGroup2Index]= nSyms[XkbGroup1Index];
279	    types_inout[XkbGroup2Index]= types_inout[XkbGroup1Index];
280	    memcpy((char *)&xkb_syms_rtrn[2],(char *)xkb_syms_rtrn,
281							2*sizeof(KeySym));
282	}
283	else if (types_inout[XkbGroup1Index]==types_inout[XkbGroup2Index]) {
284	    memcpy((char *)&xkb_syms_rtrn[nSyms[XkbGroup1Index]],
285	    				(char *)xkb_syms_rtrn,
286					nSyms[XkbGroup1Index]*sizeof(KeySym));
287	}
288    }
289
290    /* step 7: check for all groups identical or all width 1 */
291    if (nGroups>1) {
292	Bool sameType,allOneLevel;
293	allOneLevel= (xkb->map->types[types_inout[0]].num_levels==1);
294	for (i=1,sameType=True;(allOneLevel||sameType)&&(i<nGroups);i++) {
295	    sameType=(sameType&&(types_inout[i]==types_inout[XkbGroup1Index]));
296	    if (allOneLevel)
297		allOneLevel= (xkb->map->types[types_inout[i]].num_levels==1);
298	}
299	if ((sameType)&&
300	    (!(protected&(XkbExplicitKeyTypesMask&~XkbExplicitKeyType1Mask)))){
301	    register int s;
302	    Bool	identical;
303	    for (i=1,identical=True;identical&&(i<nGroups);i++) {
304		KeySym *syms;
305		syms= &xkb_syms_rtrn[XKB_OFFSET(i,0)];
306		for (s=0;identical&&(s<nSyms[i]);s++) {
307		    if (syms[s]!=xkb_syms_rtrn[s])
308			identical= False;
309		}
310	    }
311	    if (identical)
312		nGroups= 1;
313	}
314	if (allOneLevel && (nGroups>1)) {
315	    KeySym *syms;
316	    syms= &xkb_syms_rtrn[nSyms[XkbGroup1Index]];
317	    nSyms[XkbGroup1Index]= 1;
318	    for (i=1;i<nGroups;i++) {
319		xkb_syms_rtrn[i]= syms[0];
320		syms+= nSyms[i];
321		nSyms[i]= 1;
322	    }
323	}
324    }
325    return nGroups;
326}
327
328static XkbSymInterpretPtr
329_XkbFindMatchingInterp(	XkbDescPtr	xkb,
330			KeySym 		sym,
331			unsigned int	real_mods,
332			unsigned int	level)
333{
334register unsigned	 i;
335XkbSymInterpretPtr	 interp,rtrn;
336CARD8			 mods;
337
338    rtrn= NULL;
339    interp= xkb->compat->sym_interpret;
340    for (i=0;i<xkb->compat->num_si;i++,interp++) {
341	if ((interp->sym==NoSymbol)||(sym==interp->sym)) {
342	    int match;
343	    if ((level==0)||((interp->match&XkbSI_LevelOneOnly)==0))
344		 mods= real_mods;
345	    else mods= 0;
346	    switch (interp->match&XkbSI_OpMask) {
347		case XkbSI_NoneOf:
348		    match= ((interp->mods&mods)==0);
349		    break;
350		case XkbSI_AnyOfOrNone:
351		    match= ((mods==0)||((interp->mods&mods)!=0));
352		    break;
353		case XkbSI_AnyOf:
354		    match= ((interp->mods&mods)!=0);
355		    break;
356		case XkbSI_AllOf:
357		    match= ((interp->mods&mods)==interp->mods);
358		    break;
359		case XkbSI_Exactly:
360		    match= (interp->mods==mods);
361		    break;
362		default:
363		    match= 0;
364		    break;
365	    }
366	    if (match) {
367		if (interp->sym!=NoSymbol) {
368		    return interp;
369		}
370		else if (rtrn==NULL) {
371		    rtrn= interp;
372		}
373	    }
374	}
375    }
376    return rtrn;
377}
378
379static void
380_XkbAddKeyChange(KeyCode *pFirst,unsigned char *pNum,KeyCode newKey)
381{
382KeyCode	last;
383
384    last= (*pFirst)+(*pNum);
385    if (newKey<*pFirst) {
386	*pFirst= newKey;
387	*pNum= (last-newKey)+1;
388    }
389    else if (newKey>last) {
390	*pNum= (last-*pFirst)+1;
391    }
392    return;
393}
394
395static void
396_XkbSetActionKeyMods(XkbDescPtr xkb,XkbAction *act,unsigned mods)
397{
398unsigned	tmp;
399
400    switch (act->type) {
401	case XkbSA_SetMods: case XkbSA_LatchMods: case XkbSA_LockMods:
402	    if (act->mods.flags&XkbSA_UseModMapMods)
403		act->mods.real_mods= act->mods.mask= mods;
404	    if ((tmp= XkbModActionVMods(&act->mods))!=0) {
405		XkbVirtualModsToReal(xkb,tmp,&tmp);
406		act->mods.mask|= tmp;
407	    }
408	    break;
409	case XkbSA_ISOLock:
410	    if (act->iso.flags&XkbSA_UseModMapMods)
411		act->iso.real_mods= act->iso.mask= mods;
412	    if ((tmp= XkbModActionVMods(&act->iso))!=0) {
413		XkbVirtualModsToReal(xkb,tmp,&tmp);
414		act->iso.mask|= tmp;
415	    }
416	    break;
417    }
418    return;
419}
420
421#define	IBUF_SIZE	8
422
423Bool
424XkbApplyCompatMapToKey(XkbDescPtr xkb,KeyCode key,XkbChangesPtr changes)
425{
426KeySym *		syms;
427unsigned char 		explicit,mods;
428XkbSymInterpretPtr	*interps,ibuf[IBUF_SIZE];
429int			n,nSyms,found;
430unsigned		changed,tmp;
431
432    if ((!xkb)||(!xkb->map)||(!xkb->map->key_sym_map)||
433    			(!xkb->compat)||(!xkb->compat->sym_interpret)||
434			(key<xkb->min_key_code)||(key>xkb->max_key_code)) {
435	return False;
436    }
437    if (((!xkb->server)||(!xkb->server->key_acts))&&
438		(XkbAllocServerMap(xkb,XkbAllServerInfoMask,0)!=Success)) {
439	return False;
440    }
441    changed= 0;	/* keeps track of what has changed in _this_ call */
442    explicit= xkb->server->explicit[key];
443    if (explicit&XkbExplicitInterpretMask) /* nothing to do */
444	return True;
445    mods= (xkb->map->modmap?xkb->map->modmap[key]:0);
446    nSyms= XkbKeyNumSyms(xkb,key);
447    syms= XkbKeySymsPtr(xkb,key);
448    if (nSyms>IBUF_SIZE) {
449	interps= _XkbTypedCalloc(nSyms,XkbSymInterpretPtr);
450	if (interps==NULL) {
451	    interps= ibuf;
452	    nSyms= IBUF_SIZE;
453	}
454    }
455    else {
456	interps= ibuf;
457    }
458    found= 0;
459    for (n=0;n<nSyms;n++) {
460	unsigned level= (n%XkbKeyGroupsWidth(xkb,key));
461	interps[n]= NULL;
462	if (syms[n]!=NoSymbol) {
463	    interps[n]= _XkbFindMatchingInterp(xkb,syms[n],mods,level);
464	    if (interps[n]&&interps[n]->act.type!=XkbSA_NoAction)
465		found++;
466	    else interps[n]= NULL;
467	}
468    }
469    /* 1/28/96 (ef) -- XXX! WORKING HERE */
470    if (!found) {
471	if (xkb->server->key_acts[key]!=0) {
472	    xkb->server->key_acts[key]= 0;
473	    changed|= XkbKeyActionsMask;
474	}
475    }
476    else {
477	XkbAction *pActs;
478	unsigned int	new_vmodmask;
479	changed|= XkbKeyActionsMask;
480	pActs= XkbResizeKeyActions(xkb,key,nSyms);
481	if (!pActs) {
482            if (nSyms > IBUF_SIZE)
483                Xfree(interps);
484	    return False;
485        }
486	new_vmodmask= 0;
487	for (n=0;n<nSyms;n++) {
488	    if (interps[n]) {
489		unsigned effMods;
490
491		pActs[n]= *((XkbAction *)&interps[n]->act);
492		if ((n==0)||((interps[n]->match&XkbSI_LevelOneOnly)==0)) {
493		     effMods= mods;
494		     if (interps[n]->virtual_mod!=XkbNoModifier)
495			new_vmodmask|= (1<<interps[n]->virtual_mod);
496		}
497		else effMods= 0;
498		_XkbSetActionKeyMods(xkb,&pActs[n],effMods);
499	    }
500	    else pActs[n].type= XkbSA_NoAction;
501	}
502	if (((explicit&XkbExplicitVModMapMask)==0)&&
503				(xkb->server->vmodmap[key]!=new_vmodmask)) {
504	    changed|= XkbVirtualModMapMask;
505	    xkb->server->vmodmap[key]= new_vmodmask;
506	}
507	if (interps[0]) {
508	    if ((interps[0]->flags&XkbSI_LockingKey)&&
509				((explicit&XkbExplicitBehaviorMask)==0)) {
510		xkb->server->behaviors[key].type= XkbKB_Lock;
511		changed|= XkbKeyBehaviorsMask;
512	    }
513	    if (((explicit&XkbExplicitAutoRepeatMask)==0)&&(xkb->ctrls)) {
514		CARD8 old;
515		old= xkb->ctrls->per_key_repeat[key/8];
516		if (interps[0]->flags&XkbSI_AutoRepeat)
517		     xkb->ctrls->per_key_repeat[key/8]|= (1<<(key%8));
518		else xkb->ctrls->per_key_repeat[key/8]&= ~(1<<(key%8));
519		if (changes && (old!=xkb->ctrls->per_key_repeat[key/8]))
520		    changes->ctrls.changed_ctrls|= XkbPerKeyRepeatMask;
521	    }
522	}
523    }
524    if ((!found)||(interps[0]==NULL)) {
525	if (((explicit&XkbExplicitAutoRepeatMask)==0)&&(xkb->ctrls)) {
526	    CARD8 old;
527	    old= xkb->ctrls->per_key_repeat[key/8];
528#ifdef RETURN_SHOULD_REPEAT
529	    if (*XkbKeySymsPtr(xkb,key) != XK_Return)
530#endif
531		xkb->ctrls->per_key_repeat[key/8]|= (1<<(key%8));
532	    if (changes && (old!=xkb->ctrls->per_key_repeat[key/8]))
533		changes->ctrls.changed_ctrls|= XkbPerKeyRepeatMask;
534	}
535	if (((explicit&XkbExplicitBehaviorMask)==0)&&
536		(xkb->server->behaviors[key].type==XkbKB_Lock)) {
537		xkb->server->behaviors[key].type= XkbKB_Default;
538		changed|= XkbKeyBehaviorsMask;
539	}
540    }
541    if (changes) {
542	XkbMapChangesPtr	mc;
543	mc= &changes->map;
544	tmp= (changed&mc->changed);
545	if (tmp&XkbKeyActionsMask)
546	    _XkbAddKeyChange(&mc->first_key_act,&mc->num_key_acts,key);
547	else if (changed&XkbKeyActionsMask) {
548	    mc->changed|= XkbKeyActionsMask;
549	    mc->first_key_act= key;
550	    mc->num_key_acts= 1;
551	}
552	if (tmp&XkbKeyBehaviorsMask) {
553	    _XkbAddKeyChange(&mc->first_key_behavior,&mc->num_key_behaviors,
554	    								key);
555	}
556	else if (changed&XkbKeyBehaviorsMask) {
557	    mc->changed|= XkbKeyBehaviorsMask;
558	    mc->first_key_behavior= key;
559	    mc->num_key_behaviors= 1;
560	}
561	if (tmp&XkbVirtualModMapMask)
562	    _XkbAddKeyChange(&mc->first_vmodmap_key,&mc->num_vmodmap_keys,key);
563	else if (changed&XkbVirtualModMapMask) {
564	    mc->changed|= XkbVirtualModMapMask;
565	    mc->first_vmodmap_key= key;
566	    mc->num_vmodmap_keys= 1;
567	}
568	mc->changed|= changed;
569    }
570    if (interps!=ibuf)
571	_XkbFree(interps);
572    return True;
573}
574
575Bool
576XkbUpdateMapFromCore(	XkbDescPtr	xkb,
577			KeyCode		first_key,
578			int		num_keys,
579			int		map_width,
580			KeySym *	core_keysyms,
581			XkbChangesPtr	changes)
582{
583register int	key,last_key;
584KeySym *	syms;
585
586    syms= &core_keysyms[(first_key-xkb->min_key_code)*map_width];
587    if (changes) {
588	if (changes->map.changed&XkbKeySymsMask) {
589	    _XkbAddKeyChange(&changes->map.first_key_sym,
590	    			&changes->map.num_key_syms,first_key);
591	    if (num_keys>1) {
592		_XkbAddKeyChange(&changes->map.first_key_sym,
593						&changes->map.num_key_syms,
594						first_key+num_keys-1);
595	    }
596	}
597	else {
598	    changes->map.changed|= XkbKeySymsMask;
599	    changes->map.first_key_sym= first_key;
600	    changes->map.num_key_syms= num_keys;
601	}
602    }
603    last_key= first_key+num_keys-1;
604    for (key=first_key;key<=last_key;key++,syms+= map_width) {
605	XkbMapChangesPtr	mc;
606	unsigned		explicit;
607	KeySym			tsyms[XkbMaxSymsPerKey];
608	int	 		types[XkbNumKbdGroups];
609	int			nG;
610
611	explicit= xkb->server->explicit[key]&XkbExplicitKeyTypesMask;
612	types[XkbGroup1Index]= XkbKeyKeyTypeIndex(xkb,key,XkbGroup1Index);
613	types[XkbGroup2Index]= XkbKeyKeyTypeIndex(xkb,key,XkbGroup2Index);
614	types[XkbGroup3Index]= XkbKeyKeyTypeIndex(xkb,key,XkbGroup3Index);
615	types[XkbGroup4Index]= XkbKeyKeyTypeIndex(xkb,key,XkbGroup4Index);
616	nG= XkbKeyTypesForCoreSymbols(xkb,map_width,syms,explicit,types,tsyms);
617	if (changes)
618	     mc= &changes->map;
619	else mc= NULL;
620	XkbChangeTypesOfKey(xkb,key,nG,XkbAllGroupsMask,types,mc);
621	memcpy((char *)XkbKeySymsPtr(xkb,key),(char *)tsyms,
622					XkbKeyNumSyms(xkb,key)*sizeof(KeySym));
623	XkbApplyCompatMapToKey(xkb,key,changes);
624    }
625
626    if ((xkb->server->vmods!=NULL)&&(xkb->map->modmap!=NULL)&&(changes)&&
627	(changes->map.changed&(XkbVirtualModMapMask|XkbModifierMapMask))) {
628	unsigned char		newVMods[XkbNumVirtualMods];
629	register  unsigned 	bit,i;
630	unsigned		present;
631
632	bzero(newVMods,XkbNumVirtualMods);
633	present= 0;
634	for (key=xkb->min_key_code;key<=xkb->max_key_code;key++) {
635	    if (xkb->server->vmodmap[key]==0)
636		continue;
637	    for (i=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) {
638		if (bit&xkb->server->vmodmap[key]) {
639		    present|= bit;
640		    newVMods[i]|= xkb->map->modmap[key];
641		}
642	    }
643	}
644	for (i=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) {
645	    if ((bit&present)&&(newVMods[i]!=xkb->server->vmods[i])) {
646		changes->map.changed|= XkbVirtualModsMask;
647		changes->map.vmods|= bit;
648		xkb->server->vmods[i]= newVMods[i];
649	    }
650	}
651    }
652    if (changes && (changes->map.changed&XkbVirtualModsMask))
653	XkbApplyVirtualModChanges(xkb,changes->map.vmods,changes);
654    return True;
655}
656
657Status
658XkbChangeTypesOfKey(	XkbDescPtr		 xkb,
659			int		 	 key,
660			int			 nGroups,
661			unsigned	 	 groups,
662			int	* 	 	 newTypesIn,
663			XkbMapChangesPtr	 changes)
664{
665XkbKeyTypePtr	pOldType,pNewType;
666register int	i;
667int		width,nOldGroups,oldWidth,newTypes[XkbNumKbdGroups];
668
669    if ((!xkb) || (!XkbKeycodeInRange(xkb,key)) || (!xkb->map) ||
670	(!xkb->map->types)||((groups&XkbAllGroupsMask)==0)||
671	(nGroups>XkbNumKbdGroups)) {
672	return BadMatch;
673    }
674    if (nGroups==0) {
675	for (i=0;i<XkbNumKbdGroups;i++) {
676	    xkb->map->key_sym_map[key].kt_index[i]= XkbOneLevelIndex;
677	}
678	i= xkb->map->key_sym_map[key].group_info;
679	i= XkbSetNumGroups(i,0);
680	xkb->map->key_sym_map[key].group_info= i;
681	XkbResizeKeySyms(xkb,key,0);
682	return Success;
683    }
684
685    nOldGroups= XkbKeyNumGroups(xkb,key);
686    oldWidth= XkbKeyGroupsWidth(xkb,key);
687    for (width=i=0;i<nGroups;i++) {
688	if (groups&(1<<i))
689	     newTypes[i]=  newTypesIn[i];
690	else if (i<nOldGroups)
691	     newTypes[i]= XkbKeyKeyTypeIndex(xkb,key,i);
692	else if (nOldGroups>0)
693	     newTypes[i]= XkbKeyKeyTypeIndex(xkb,key,XkbGroup1Index);
694	else newTypes[i]= XkbTwoLevelIndex;
695	if (newTypes[i]>xkb->map->num_types)
696	    return BadMatch;
697	pNewType= &xkb->map->types[newTypes[i]];
698	if (pNewType->num_levels>width)
699	    width= pNewType->num_levels;
700    }
701    if ((xkb->ctrls)&&(nGroups>xkb->ctrls->num_groups))
702	xkb->ctrls->num_groups= nGroups;
703    if ((width!=oldWidth)||(nGroups!=nOldGroups)) {
704	KeySym		oldSyms[XkbMaxSymsPerKey],*pSyms;
705	int		nCopy;
706
707	if (nOldGroups==0) {
708	    pSyms= XkbResizeKeySyms(xkb,key,width*nGroups);
709	    if (pSyms!=NULL) {
710		i= xkb->map->key_sym_map[key].group_info;
711		i= XkbSetNumGroups(i,nGroups);
712		xkb->map->key_sym_map[key].group_info= i;
713		xkb->map->key_sym_map[key].width= width;
714		for (i=0;i<nGroups;i++) {
715		    xkb->map->key_sym_map[key].kt_index[i]= newTypes[i];
716		}
717		return Success;
718	    }
719	    return BadAlloc;
720	}
721	pSyms= XkbKeySymsPtr(xkb,key);
722	memcpy(oldSyms,pSyms,XkbKeyNumSyms(xkb,key)*sizeof(KeySym));
723	pSyms= XkbResizeKeySyms(xkb,key,width*nGroups);
724	if (pSyms==NULL)
725	    return BadAlloc;
726	bzero(pSyms,width*nGroups*sizeof(KeySym));
727	for (i=0;(i<nGroups)&&(i<nOldGroups);i++) {
728	    pOldType= XkbKeyKeyType(xkb,key,i);
729	    pNewType= &xkb->map->types[newTypes[i]];
730	    if (pNewType->num_levels>pOldType->num_levels)
731		 nCopy= pOldType->num_levels;
732	    else nCopy= pNewType->num_levels;
733	    memcpy(&pSyms[i*width],&oldSyms[i*oldWidth],nCopy*sizeof(KeySym));
734	}
735	if (XkbKeyHasActions(xkb,key)) {
736	    XkbAction	oldActs[XkbMaxSymsPerKey],*pActs;
737	    pActs= XkbKeyActionsPtr(xkb,key);
738	    memcpy(oldActs,pActs,XkbKeyNumSyms(xkb,key)*sizeof(XkbAction));
739	    pActs= XkbResizeKeyActions(xkb,key,width*nGroups);
740	    if (pActs==NULL)
741		return BadAlloc;
742	    bzero(pActs,width*nGroups*sizeof(XkbAction));
743	    for (i=0;(i<nGroups)&&(i<nOldGroups);i++) {
744		pOldType= XkbKeyKeyType(xkb,key,i);
745		pNewType= &xkb->map->types[newTypes[i]];
746		if (pNewType->num_levels>pOldType->num_levels)
747		     nCopy= pOldType->num_levels;
748		else nCopy= pNewType->num_levels;
749		memcpy(&pActs[i*width],&oldActs[i*oldWidth],
750						nCopy*sizeof(XkbAction));
751	    }
752	}
753	i= xkb->map->key_sym_map[key].group_info;
754	i= XkbSetNumGroups(i,nGroups);
755	xkb->map->key_sym_map[key].group_info= i;
756	xkb->map->key_sym_map[key].width= width;
757    }
758    width= 0;
759    for (i=0;i<nGroups;i++) {
760	xkb->map->key_sym_map[key].kt_index[i]= newTypes[i];
761	if (xkb->map->types[newTypes[i]].num_levels>width)
762	    width= xkb->map->types[newTypes[i]].num_levels;
763    }
764    xkb->map->key_sym_map[key].width= width;
765    if (changes!=NULL) {
766	if (changes->changed&XkbKeySymsMask) {
767	    _XkbAddKeyChange(&changes->first_key_sym,&changes->num_key_syms,
768	    								key);
769	}
770	else {
771	    changes->changed|= XkbKeySymsMask;
772	    changes->first_key_sym= key;
773	    changes->num_key_syms= 1;
774	}
775    }
776    return Success;
777}
778
779/***====================================================================***/
780
781Bool
782XkbVirtualModsToReal(XkbDescPtr xkb,unsigned virtual_mask,unsigned *mask_rtrn)
783{
784register int i,bit;
785register unsigned mask;
786
787    if (xkb==NULL)
788	return False;
789    if (virtual_mask==0) {
790	*mask_rtrn= 0;
791	return True;
792    }
793    if (xkb->server==NULL)
794	return False;
795    for (i=mask=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) {
796	if (virtual_mask&bit)
797	    mask|= xkb->server->vmods[i];
798    }
799    *mask_rtrn= mask;
800    return True;
801}
802
803/***====================================================================***/
804
805Bool
806XkbUpdateActionVirtualMods(XkbDescPtr xkb,XkbAction *act,unsigned changed)
807{
808unsigned int	tmp;
809
810    switch (act->type) {
811	case XkbSA_SetMods: case XkbSA_LatchMods: case XkbSA_LockMods:
812	    if (((tmp= XkbModActionVMods(&act->mods))&changed)!=0) {
813		XkbVirtualModsToReal(xkb,tmp,&tmp);
814		act->mods.mask= act->mods.real_mods;
815		act->mods.mask|= tmp;
816		return True;
817	    }
818	    break;
819	case XkbSA_ISOLock:
820	    if ((((tmp= XkbModActionVMods(&act->iso))!=0)&changed)!=0) {
821		XkbVirtualModsToReal(xkb,tmp,&tmp);
822		act->iso.mask= act->iso.real_mods;
823		act->iso.mask|= tmp;
824		return True;
825	    }
826	    break;
827    }
828    return False;
829}
830
831void
832XkbUpdateKeyTypeVirtualMods(	XkbDescPtr	xkb,
833				XkbKeyTypePtr	type,
834				unsigned int	changed,
835				XkbChangesPtr 	changes)
836{
837register unsigned int	i;
838unsigned int		mask;
839
840    XkbVirtualModsToReal(xkb,type->mods.vmods,&mask);
841    type->mods.mask= type->mods.real_mods|mask;
842    if ((type->map_count>0)&&(type->mods.vmods!=0)) {
843	XkbKTMapEntryPtr entry;
844	for (i=0,entry=type->map;i<type->map_count;i++,entry++) {
845	    if (entry->mods.vmods!=0) {
846		XkbVirtualModsToReal(xkb,entry->mods.vmods,&mask);
847		entry->mods.mask=entry->mods.real_mods|mask;
848		/* entry is active if vmods are bound*/
849	    	entry->active= (mask!=0);
850	    }
851	    else entry->active= 1;
852	}
853    }
854    if (changes) {
855	int	type_ndx;
856	type_ndx= type-xkb->map->types;
857	if ((type_ndx<0)||(type_ndx>xkb->map->num_types))
858	    return;
859	if (changes->map.changed&XkbKeyTypesMask) {
860	    int last;
861	    last= changes->map.first_type+changes->map.num_types-1;
862	    if (type_ndx<changes->map.first_type) {
863		changes->map.first_type= type_ndx;
864		changes->map.num_types= (last-type_ndx)+1;
865	    }
866	    else if (type_ndx>last) {
867		changes->map.num_types= (type_ndx-changes->map.first_type)+1;
868	    }
869	}
870	else {
871	    changes->map.changed|= XkbKeyTypesMask;
872	    changes->map.first_type= type_ndx;
873	    changes->map.num_types= 1;
874	}
875    }
876    return;
877}
878
879Bool
880XkbApplyVirtualModChanges(XkbDescPtr xkb,unsigned changed,XkbChangesPtr changes)
881{
882register int	i;
883unsigned int	checkState = 0;
884
885    if ((!xkb) || (!xkb->map) || (changed==0))
886	return False;
887    for (i=0;i<xkb->map->num_types;i++) {
888	if (xkb->map->types[i].mods.vmods & changed)
889	XkbUpdateKeyTypeVirtualMods(xkb,&xkb->map->types[i],changed,changes);
890    }
891    if (changed&xkb->ctrls->internal.vmods) {
892	unsigned int	newMask;
893	XkbVirtualModsToReal(xkb,xkb->ctrls->internal.vmods,&newMask);
894	newMask|= xkb->ctrls->internal.real_mods;
895	if (xkb->ctrls->internal.mask!=newMask) {
896	    xkb->ctrls->internal.mask= newMask;
897	    if (changes) {
898		changes->ctrls.changed_ctrls|= XkbInternalModsMask;
899		checkState= True;
900	    }
901	}
902    }
903    if (changed&xkb->ctrls->ignore_lock.vmods) {
904	unsigned int	newMask;
905	XkbVirtualModsToReal(xkb,xkb->ctrls->ignore_lock.vmods,&newMask);
906	newMask|= xkb->ctrls->ignore_lock.real_mods;
907	if (xkb->ctrls->ignore_lock.mask!=newMask) {
908	    xkb->ctrls->ignore_lock.mask= newMask;
909	    if (changes) {
910		changes->ctrls.changed_ctrls|= XkbIgnoreLockModsMask;
911		checkState= True;
912	    }
913	}
914    }
915    if (xkb->indicators!=NULL) {
916	XkbIndicatorMapPtr map;
917	map= &xkb->indicators->maps[0];
918	for (i=0;i<XkbNumIndicators;i++,map++) {
919	    if (map->mods.vmods&changed) {
920		unsigned int newMask;
921		XkbVirtualModsToReal(xkb,map->mods.vmods,&newMask);
922		newMask|= map->mods.real_mods;
923		if (newMask!=map->mods.mask) {
924		    map->mods.mask= newMask;
925		    if (changes) {
926			changes->indicators.map_changes|= (1<<i);
927			checkState= True;
928		    }
929		}
930	    }
931	}
932    }
933    if (xkb->compat!=NULL) {
934	XkbCompatMapPtr	compat;
935	compat= xkb->compat;
936	for (i=0;i<XkbNumKbdGroups;i++) {
937	    unsigned int newMask;
938	    XkbVirtualModsToReal(xkb,compat->groups[i].vmods,&newMask);
939	    newMask|= compat->groups[i].real_mods;
940	    if (compat->groups[i].mask!=newMask) {
941		compat->groups[i].mask= newMask;
942		if (changes) {
943		    changes->compat.changed_groups|= (1<<i);
944		    checkState= True;
945		}
946	    }
947	}
948    }
949    if (xkb->map && xkb->server) {
950	int highChange = 0, lowChange = -1;
951	for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) {
952	    if (XkbKeyHasActions(xkb,i)) {
953		register XkbAction *pAct;
954		register int n;
955
956		pAct= XkbKeyActionsPtr(xkb,i);
957		for (n=XkbKeyNumActions(xkb,i);n>0;n--,pAct++) {
958		    if ((pAct->type!=XkbSA_NoAction)&&
959			XkbUpdateActionVirtualMods(xkb,pAct,changed)) {
960			if (lowChange<0)
961			    lowChange= i;
962			highChange= i;
963		    }
964		}
965	    }
966	}
967	if (changes && (lowChange>0)) { /* something changed */
968	    if (changes->map.changed&XkbKeyActionsMask) {
969		int last;
970		if (changes->map.first_key_act<lowChange)
971		    lowChange= changes->map.first_key_act;
972		last= changes->map.first_key_act+changes->map.num_key_acts-1;
973		if (last>highChange)
974		    highChange= last;
975	    }
976	    changes->map.changed|= 	XkbKeyActionsMask;
977	    changes->map.first_key_act=	lowChange;
978	    changes->map.num_key_acts=	(highChange-lowChange)+1;
979	}
980    }
981    return checkState;
982}
983