ModMap.c revision b4ee4795
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#define NEED_REPLIES
28#ifdef HAVE_CONFIG_H
29#include <config.h>
30#endif
31#include "Xlibint.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    nbytes = (unsigned long)rep.length << 2;
46    res = (XModifierKeymap *) Xmalloc(sizeof (XModifierKeymap));
47    if (res) res->modifiermap = (KeyCode *) Xmalloc ((unsigned) nbytes);
48    if ((! res) || (! res->modifiermap)) {
49	if (res) Xfree((char *) res);
50	res = (XModifierKeymap *) NULL;
51	_XEatData(dpy, nbytes);
52    } else {
53	_XReadPad(dpy, (char *) res->modifiermap, (long) nbytes);
54	res->max_keypermod = rep.numKeyPerModifier;
55    }
56
57    UnlockDisplay(dpy);
58    SyncHandle();
59    return (res);
60}
61
62/*
63 *	Returns:
64 *	0	Success
65 *	1	Busy - one or more old or new modifiers are down
66 *	2	Failed - one or more new modifiers unacceptable
67 */
68int
69XSetModifierMapping(
70    register Display *dpy,
71    register XModifierKeymap *modifier_map)
72{
73    register xSetModifierMappingReq *req;
74    xSetModifierMappingReply rep;
75    int         mapSize = modifier_map->max_keypermod << 3;	/* 8 modifiers */
76
77    LockDisplay(dpy);
78    GetReqExtra(SetModifierMapping, mapSize, req);
79
80    req->numKeyPerModifier = modifier_map->max_keypermod;
81
82    memcpy((char *) NEXTPTR(req,xSetModifierMappingReq),
83	   (char *) modifier_map->modifiermap,
84	   mapSize);
85
86    (void) _XReply(dpy, (xReply *) & rep,
87	(SIZEOF(xSetModifierMappingReply) - SIZEOF(xReply)) >> 2, xTrue);
88    UnlockDisplay(dpy);
89    SyncHandle();
90    return (rep.success);
91}
92
93XModifierKeymap *
94XNewModifiermap(int keyspermodifier)
95{
96    XModifierKeymap *res = (XModifierKeymap *) Xmalloc((sizeof (XModifierKeymap)));
97    if (res) {
98	res->max_keypermod = keyspermodifier;
99	res->modifiermap = (keyspermodifier > 0 ?
100			    (KeyCode *) Xmalloc((unsigned) (8 * keyspermodifier))
101			    : (KeyCode *) NULL);
102	if (keyspermodifier && (res->modifiermap == NULL)) {
103	    Xfree((char *) res);
104	    return (XModifierKeymap *) NULL;
105	}
106    }
107    return (res);
108}
109
110
111int
112XFreeModifiermap(XModifierKeymap *map)
113{
114    if (map) {
115	if (map->modifiermap)
116	    Xfree((char *) map->modifiermap);
117	Xfree((char *) map);
118    }
119    return 1;
120}
121
122XModifierKeymap *
123XInsertModifiermapEntry(XModifierKeymap *map,
124#if NeedWidePrototypes
125			unsigned int keycode,
126#else
127			KeyCode keycode,
128#endif
129			int modifier)
130{
131    XModifierKeymap *newmap;
132    int i,
133	row = modifier * map->max_keypermod,
134	newrow,
135	lastrow;
136
137    for (i=0; i<map->max_keypermod; i++) {
138        if (map->modifiermap[ row+i ] == keycode)
139	    return(map); /* already in the map */
140        if (map->modifiermap[ row+i ] == 0) {
141            map->modifiermap[ row+i ] = keycode;
142	    return(map); /* we added it without stretching the map */
143	}
144    }
145
146    /* stretch the map */
147    if ((newmap = XNewModifiermap(map->max_keypermod+1)) == NULL)
148	return (XModifierKeymap *) NULL;
149    newrow = row = 0;
150    lastrow = newmap->max_keypermod * 8;
151    while (newrow < lastrow) {
152	for (i=0; i<map->max_keypermod; i++)
153	    newmap->modifiermap[ newrow+i ] = map->modifiermap[ row+i ];
154	newmap->modifiermap[ newrow+i ] = 0;
155	row += map->max_keypermod;
156	newrow += newmap->max_keypermod;
157    }
158    (void) XFreeModifiermap(map);
159    newrow = newmap->max_keypermod * modifier + newmap->max_keypermod - 1;
160    newmap->modifiermap[ newrow ] = keycode;
161    return(newmap);
162}
163
164XModifierKeymap *
165XDeleteModifiermapEntry(XModifierKeymap *map,
166#if NeedWidePrototypes
167			unsigned int keycode,
168#else
169			KeyCode keycode,
170#endif
171			int modifier)
172{
173    int i,
174	row = modifier * map->max_keypermod;
175
176    for (i=0; i<map->max_keypermod; i++) {
177        if (map->modifiermap[ row+i ] == keycode)
178            map->modifiermap[ row+i ] = 0;
179    }
180    /* should we shrink the map?? */
181    return (map);
182}
183