ModMap.c revision eb411b4b
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 <limits.h>
32
33XModifierKeymap *
34XGetModifierMapping(register Display *dpy)
35{
36    xGetModifierMappingReply rep;
37    register xReq *req;
38    unsigned long nbytes;
39    XModifierKeymap *res;
40
41    LockDisplay(dpy);
42    GetEmptyReq(GetModifierMapping, req);
43    (void) _XReply (dpy, (xReply *)&rep, 0, xFalse);
44
45    if (rep.length < (LONG_MAX >> 2)) {
46	nbytes = (unsigned long)rep.length << 2;
47	res = Xmalloc(sizeof (XModifierKeymap));
48	if (res)
49	    res->modifiermap = Xmalloc (nbytes);
50    } else
51	res = NULL;
52    if ((! res) || (! res->modifiermap)) {
53	if (res) Xfree((char *) res);
54	res = (XModifierKeymap *) NULL;
55	_XEatDataWords(dpy, rep.length);
56    } else {
57	_XReadPad(dpy, (char *) res->modifiermap, (long) nbytes);
58	res->max_keypermod = rep.numKeyPerModifier;
59    }
60
61    UnlockDisplay(dpy);
62    SyncHandle();
63    return (res);
64}
65
66/*
67 *	Returns:
68 *	0	Success
69 *	1	Busy - one or more old or new modifiers are down
70 *	2	Failed - one or more new modifiers unacceptable
71 */
72int
73XSetModifierMapping(
74    register Display *dpy,
75    register XModifierKeymap *modifier_map)
76{
77    register xSetModifierMappingReq *req;
78    xSetModifierMappingReply rep;
79    int         mapSize = modifier_map->max_keypermod << 3;	/* 8 modifiers */
80
81    LockDisplay(dpy);
82    GetReqExtra(SetModifierMapping, mapSize, req);
83
84    req->numKeyPerModifier = modifier_map->max_keypermod;
85
86    memcpy((char *) NEXTPTR(req,xSetModifierMappingReq),
87	   (char *) modifier_map->modifiermap,
88	   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			    Xmalloc(8 * keyspermodifier)
105			    : (KeyCode *) NULL);
106	if (keyspermodifier && (res->modifiermap == NULL)) {
107	    Xfree((char *) res);
108	    return (XModifierKeymap *) NULL;
109	}
110    }
111    return (res);
112}
113
114
115int
116XFreeModifiermap(XModifierKeymap *map)
117{
118    if (map) {
119	if (map->modifiermap)
120	    Xfree((char *) map->modifiermap);
121	Xfree((char *) map);
122    }
123    return 1;
124}
125
126XModifierKeymap *
127XInsertModifiermapEntry(XModifierKeymap *map,
128#if NeedWidePrototypes
129			unsigned int keycode,
130#else
131			KeyCode keycode,
132#endif
133			int modifier)
134{
135    XModifierKeymap *newmap;
136    int i,
137	row = modifier * map->max_keypermod,
138	newrow,
139	lastrow;
140
141    for (i=0; i<map->max_keypermod; i++) {
142        if (map->modifiermap[ row+i ] == keycode)
143	    return(map); /* already in the map */
144        if (map->modifiermap[ row+i ] == 0) {
145            map->modifiermap[ row+i ] = keycode;
146	    return(map); /* we added it without stretching the map */
147	}
148    }
149
150    /* stretch the map */
151    if ((newmap = XNewModifiermap(map->max_keypermod+1)) == NULL)
152	return (XModifierKeymap *) NULL;
153    newrow = row = 0;
154    lastrow = newmap->max_keypermod * 8;
155    while (newrow < lastrow) {
156	for (i=0; i<map->max_keypermod; i++)
157	    newmap->modifiermap[ newrow+i ] = map->modifiermap[ row+i ];
158	newmap->modifiermap[ newrow+i ] = 0;
159	row += map->max_keypermod;
160	newrow += newmap->max_keypermod;
161    }
162    (void) XFreeModifiermap(map);
163    newrow = newmap->max_keypermod * modifier + newmap->max_keypermod - 1;
164    newmap->modifiermap[ newrow ] = keycode;
165    return(newmap);
166}
167
168XModifierKeymap *
169XDeleteModifiermapEntry(XModifierKeymap *map,
170#if NeedWidePrototypes
171			unsigned int keycode,
172#else
173			KeyCode keycode,
174#endif
175			int modifier)
176{
177    int i,
178	row = modifier * map->max_keypermod;
179
180    for (i=0; i<map->max_keypermod; i++) {
181        if (map->modifiermap[ row+i ] == keycode)
182            map->modifiermap[ row+i ] = 0;
183    }
184    /* should we shrink the map?? */
185    return (map);
186}
187