ModMap.c revision f2d49d05
1/*
2
3Copyright 1986, 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 in
12all copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
21Except as contained in this notice, the name of The Open Group shall not be
22used in advertising or otherwise to promote the sale, use or other dealings
23in this Software without prior written authorization from The Open Group.
24
25*/
26
27#ifdef HAVE_CONFIG_H
28#include <config.h>
29#endif
30#include "Xlibint.h"
31#include "reallocarray.h"
32#include <limits.h>
33
34XModifierKeymap *
35XGetModifierMapping(register Display *dpy)
36{
37    xGetModifierMappingReply rep;
38    _X_UNUSED register xReq *req;
39    unsigned long nbytes;
40    XModifierKeymap *res;
41
42    LockDisplay(dpy);
43    GetEmptyReq(GetModifierMapping, req);
44    (void) _XReply (dpy, (xReply *)&rep, 0, xFalse);
45
46    if (rep.length < (INT_MAX >> 2) &&
47	(rep.length >> 1) == rep.numKeyPerModifier) {
48	nbytes = (unsigned long)rep.length << 2;
49	res = Xmalloc(sizeof (XModifierKeymap));
50	if (res)
51	    res->modifiermap = Xmalloc (nbytes);
52    } else
53	res = NULL;
54    if ((! res) || (! res->modifiermap)) {
55	Xfree(res);
56	res = (XModifierKeymap *) NULL;
57	_XEatDataWords(dpy, rep.length);
58    } else {
59	_XReadPad(dpy, (char *) res->modifiermap, (long) nbytes);
60	res->max_keypermod = rep.numKeyPerModifier;
61    }
62
63    UnlockDisplay(dpy);
64    SyncHandle();
65    return (res);
66}
67
68/*
69 *	Returns:
70 *	MappingSuccess (0)	Success
71 *	MappingBusy (1) 	Busy - one or more old or new modifiers are down
72 *	MappingFailed (2)	Failed - one or more new modifiers unacceptable
73 */
74int
75XSetModifierMapping(
76    register Display *dpy,
77    register XModifierKeymap *modifier_map)
78{
79    register xSetModifierMappingReq *req;
80    xSetModifierMappingReply rep;
81    int         mapSize = modifier_map->max_keypermod << 3;	/* 8 modifiers */
82
83    LockDisplay(dpy);
84    GetReq(SetModifierMapping, req);
85    req->length += mapSize >> 2;
86    req->numKeyPerModifier = modifier_map->max_keypermod;
87
88    Data(dpy, (const char *)modifier_map->modifiermap, mapSize);
89
90    (void) _XReply(dpy, (xReply *) & rep,
91	(SIZEOF(xSetModifierMappingReply) - SIZEOF(xReply)) >> 2, xTrue);
92    UnlockDisplay(dpy);
93    SyncHandle();
94    return (rep.success);
95}
96
97XModifierKeymap *
98XNewModifiermap(int keyspermodifier)
99{
100    XModifierKeymap *res = Xmalloc((sizeof (XModifierKeymap)));
101    if (res) {
102	res->max_keypermod = keyspermodifier;
103	res->modifiermap = (keyspermodifier > 0 ?
104			    Xmallocarray(keyspermodifier, 8)
105			    : (KeyCode *) NULL);
106	if (keyspermodifier && (res->modifiermap == NULL)) {
107	    Xfree(res);
108	    return (XModifierKeymap *) NULL;
109	}
110    }
111    return (res);
112}
113
114
115int
116XFreeModifiermap(XModifierKeymap *map)
117{
118    if (map) {
119        Xfree(map->modifiermap);
120	Xfree(map);
121    }
122    return 1;
123}
124
125XModifierKeymap *
126XInsertModifiermapEntry(XModifierKeymap *map,
127#if NeedWidePrototypes
128			unsigned int keycode,
129#else
130			KeyCode keycode,
131#endif
132			int modifier)
133{
134    XModifierKeymap *newmap;
135    int i,
136	row = modifier * map->max_keypermod,
137	newrow,
138	lastrow;
139
140    for (i=0; i<map->max_keypermod; i++) {
141        if (map->modifiermap[ row+i ] == keycode)
142	    return(map); /* already in the map */
143        if (map->modifiermap[ row+i ] == 0) {
144            map->modifiermap[ row+i ] = keycode;
145	    return(map); /* we added it without stretching the map */
146	}
147    }
148
149    /* stretch the map */
150    if ((newmap = XNewModifiermap(map->max_keypermod+1)) == NULL)
151	return (XModifierKeymap *) NULL;
152    newrow = row = 0;
153    lastrow = newmap->max_keypermod * 8;
154    while (newrow < lastrow) {
155	for (i=0; i<map->max_keypermod; i++)
156	    newmap->modifiermap[ newrow+i ] = map->modifiermap[ row+i ];
157	newmap->modifiermap[ newrow+i ] = 0;
158	row += map->max_keypermod;
159	newrow += newmap->max_keypermod;
160    }
161    (void) XFreeModifiermap(map);
162    newrow = newmap->max_keypermod * modifier + newmap->max_keypermod - 1;
163    newmap->modifiermap[ newrow ] = keycode;
164    return(newmap);
165}
166
167XModifierKeymap *
168XDeleteModifiermapEntry(XModifierKeymap *map,
169#if NeedWidePrototypes
170			unsigned int keycode,
171#else
172			KeyCode keycode,
173#endif
174			int modifier)
175{
176    int i,
177	row = modifier * map->max_keypermod;
178
179    for (i=0; i<map->max_keypermod; i++) {
180        if (map->modifiermap[ row+i ] == keycode)
181            map->modifiermap[ row+i ] = 0;
182    }
183    /* should we shrink the map?? */
184    return (map);
185}
186