1 /* $XConsortium: exec.c,v 1.13 94/04/17 20:24:20 rws Exp $ */
2 /*
3 
4 Copyright (c) 1988  X Consortium
5 
6 Permission is hereby granted, free of charge, to any person obtaining
7 a copy of this software and associated documentation files (the
8 "Software"), to deal in the Software without restriction, including
9 without limitation the rights to use, copy, modify, merge, publish,
10 distribute, sublicense, and/or sell copies of the Software, and to
11 permit persons to whom the Software is furnished to do so, subject to
12 the following conditions:
13 
14 The above copyright notice and this permission notice shall be included
15 in all copies or substantial portions of the Software.
16 
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
21 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 OTHER DEALINGS IN THE SOFTWARE.
24 
25 Except as contained in this notice, the name of the X Consortium shall
26 not be used in advertising or otherwise to promote the sale, use or
27 other dealings in this Software without prior written authorization
28 from the X Consortium.
29 
30 */
31 
32 /*
33  * Copyright 1987 by Sun Microsystems, Inc. Mountain View, CA.
34  *
35  *                     All Rights Reserved
36  *
37  * Permission  to  use,  copy,  modify,  and  distribute   this
38  * software  and  its documentation for any purpose and without
39  * fee is hereby granted, provided that the above copyright no-
40  * tice  appear  in all copies and that both that copyright no-
41  * tice and this permission notice appear in  supporting  docu-
42  * mentation,  and  that the name of Sun not be used in
43  * advertising or publicity pertaining to distribution  of  the
44  * software  without specific prior written permission. Sun
45  * makes no representations about the suitability of this
46  * software for any purpose. It is provided "as is" without any
47  * express or implied warranty.
48  *
49  * SUN DISCLAIMS ALL WARRANTIES WITH REGARD TO  THIS  SOFTWARE,
50  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT-
51  * NESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SUN BE  LI-
52  * ABLE  FOR  ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
53  * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,  DATA  OR
54  * PROFITS,  WHETHER  IN  AN  ACTION OF CONTRACT, NEGLIGENCE OR
55  * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
56  * THE USE OR PERFORMANCE OF THIS SOFTWARE.
57  *
58  * Author:  Jim Fulton, MIT X Consortium; derived from parts of the
59  * original xmodmap, written by David Rosenthal, of Sun Microsystems.
60  */
61 
62 #include <X11/Xos.h>
63 #include <X11/Xlib.h>
64 #include <stdio.h>
65 #include "xmodmap.h"
66 #include "wq.h"
67 
mapping_busy_key(timeout)68 static void mapping_busy_key (timeout)
69     int timeout;
70 {
71     int i;
72     unsigned char keymap[32];
73     static unsigned int masktable[8] = {
74 	0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
75 
76     XQueryKeymap (dpy, (char *) keymap);
77 
78     fprintf (stderr,
79 	     "%s:  please release the following keys within %d seconds:\n",
80 	     ProgramName, timeout);
81     for (i = 0; i < 256; i++) {
82 	if (keymap[i >> 3] & masktable[i & 7]) {
83 	    KeySym ks = XKeycodeToKeysym (dpy, (KeyCode) i, 0);
84 	    char *cp = XKeysymToString (ks);
85 	    fprintf (stderr, "    %s (keysym 0x%x, keycode %d)\n",
86 		     cp ? cp : "UNNAMED", (unsigned)ks, i);
87 	}
88     }
89     sleep (timeout);
90     return;
91 }
92 
mapping_busy_pointer(timeout)93 static void mapping_busy_pointer (timeout)
94     int timeout;
95 {
96     int i;
97     Window root, child;			/* dummy variables */
98     int rx, ry, wx, wy;			/* dummy variables */
99     unsigned int mask;
100     static unsigned int masks[5] = {
101 	Button1Mask, Button2Mask, Button3Mask, Button4Mask, Button5Mask };
102 
103     if (!XQueryPointer (dpy, RootWindow(dpy,DefaultScreen(dpy)),
104 			&root, &child, &rx, &ry, &wx, &wy, &mask))
105       mask = 0;
106 
107     fprintf (stderr,
108 	     "%s:  please release the following buttons within %d seconds:\n",
109 	     ProgramName, timeout);
110     for (i = 0; i < 5; i++) {
111 	if (mask & masks[i])
112 	  fprintf (stderr, "    Button%d\n", i+1);
113     }
114     sleep (timeout);
115     return;
116 }
117 
118 
119 /*
120  * UpdateModifierMapping - this sends the modifier map to the server
121  * and deals with retransmissions due to the keyboard being busy.
122  */
123 
UpdateModifierMapping(map)124 int UpdateModifierMapping (map)
125     XModifierKeymap *map;
126 {
127     int retries, timeout;
128 
129     for (retries = 5, timeout = 2; retries > 0; retries--, timeout *= 2) {
130 	int result;
131 
132 	result = XSetModifierMapping (dpy, map);
133 	switch (result) {
134 	  case MappingSuccess:	/* Success */
135 	    return (0);
136 	  case MappingBusy:		/* Busy */
137 	    mapping_busy_key (timeout);
138 	    continue;
139 	  case MappingFailed:
140 	    fprintf (stderr, "%s: bad set modifier mapping.\n",
141 		     ProgramName);
142 	    return (-1);
143 	  default:
144 	    fprintf (stderr, "%s:  bad return %d from XSetModifierMapping\n",
145 		     ProgramName, result);
146 	    return (-1);
147 	}
148     }
149     fprintf (stderr,
150 	     "%s:  unable to set modifier mapping, keyboard problem\n",
151 	     ProgramName);
152     return (-1);
153 }
154 
155 
156 /*
157  * AddModifier - this adds a keycode to the modifier list
158  */
159 
AddModifier(mapp,keycode,modifier)160 int AddModifier (mapp, keycode, modifier)
161     XModifierKeymap **mapp;
162     KeyCode keycode;
163     int modifier;
164 {
165     if (keycode) {
166 	*mapp = XInsertModifiermapEntry (*mapp, keycode, modifier);
167 	return (0);
168     } else {
169 	return (-1);
170     }
171     /*NOTREACHED*/
172 }
173 
174 
175 /*
176  * DeleteModifier - this removes a keycode from the modifier list
177  */
178 
RemoveModifier(mapp,keycode,modifier)179 int RemoveModifier (mapp, keycode, modifier)
180     XModifierKeymap **mapp;
181     KeyCode keycode;
182     int modifier;
183 {
184     if (keycode) {
185 	*mapp = XDeleteModifiermapEntry (*mapp, keycode, modifier);
186 	return (0);
187     } else {
188 	return (-1);
189     }
190     /*NOTREACHED*/
191 }
192 
193 
194 /*
195  * ClearModifier - this removes all entries from the modifier list
196  */
197 
ClearModifier(mapp,modifier)198 int ClearModifier (mapp, modifier)
199     XModifierKeymap **mapp;
200     int modifier;
201 {
202     int i;
203     XModifierKeymap *map = *mapp;
204     KeyCode *kcp;
205 
206     kcp = &map->modifiermap[modifier * map->max_keypermod];
207     for (i = 0; i < map->max_keypermod; i++) {
208 	*kcp++ = (KeyCode) 0;
209     }
210     return (0);
211 }
212 
213 
214 /*
215  * print the contents of the map
216  */
217 
PrintModifierMapping(map,fp)218 void PrintModifierMapping (map, fp)
219     XModifierKeymap *map;
220     FILE *fp;
221 {
222     int i, k = 0;
223 
224     fprintf (fp,
225     	     "%s:  up to %d keys per modifier, (keycodes in parentheses):\n\n",
226     	     ProgramName, map->max_keypermod);
227     for (i = 0; i < 8; i++) {
228 	int j;
229 
230 	fprintf(fp, "%-10s", modifier_table[i].name);
231 	for (j = 0; j < map->max_keypermod; j++) {
232 	    if (map->modifiermap[k]) {
233 		KeySym ks = XKeycodeToKeysym(dpy, map->modifiermap[k], 0);
234 		char *nm = XKeysymToString(ks);
235 
236 		fprintf (fp, "%s  %s (0x%0x)", (j > 0 ? "," : ""),
237 			 (nm ? nm : "BadKey"), map->modifiermap[k]);
238 	    }
239 	    k++;
240 	}
241 	fprintf(fp, "\n");
242     }
243     fprintf (fp, "\n");
244     return;
245 }
246 
247 
PrintKeyTable(exprs,fp)248 void PrintKeyTable (exprs, fp)
249     Bool exprs;
250     FILE *fp;
251 {
252     int         i;
253     int min_keycode, max_keycode, keysyms_per_keycode;
254     KeySym *keymap, *origkeymap;
255 
256     XDisplayKeycodes (dpy, &min_keycode, &max_keycode);
257     origkeymap = XGetKeyboardMapping (dpy, min_keycode,
258 				      (max_keycode - min_keycode + 1),
259 				      &keysyms_per_keycode);
260 
261     if (!origkeymap) {
262 	fprintf (stderr, "%s:  unable to get keyboard mapping table.\n",
263 		 ProgramName);
264 	return;
265     }
266     if (!exprs) {
267 	fprintf (fp,
268 		 "There are %d KeySyms per KeyCode; KeyCodes range from %d to %d.\n\n",
269 		 keysyms_per_keycode, min_keycode, max_keycode);
270 	fprintf (fp, "    KeyCode\tKeysym (Keysym)\t...\n");
271 	fprintf (fp, "    Value  \tValue   (Name) \t...\n\n");
272     }
273     keymap = origkeymap;
274     for (i = min_keycode; i <= max_keycode; i++) {
275 	int  j, max;
276 
277 	if (exprs)
278 	    fprintf(fp, "keycode %3d =", i);
279 	else
280 	    fprintf(fp, "    %3d    \t", i);
281 	max = keysyms_per_keycode - 1;
282 	while ((max >= 0) && (keymap[max] == NoSymbol))
283 	    max--;
284 	for (j = 0; j <= max; j++) {
285 	    register KeySym ks = keymap[j];
286 	    char *s;
287 	    if (ks != NoSymbol)
288 		s = XKeysymToString (ks);
289 	    else
290 		s = "NoSymbol";
291 	    if (!exprs)
292 		fprintf (fp, "0x%04x (%s)\t", (unsigned)ks, s ? s : "no name");
293 	    else if (s)
294 		fprintf (fp, " %s", s);
295 	    else
296 		fprintf (fp, " 0x%04x", (unsigned)ks);
297 	}
298 	keymap += keysyms_per_keycode;
299 	fprintf (fp, "\n");
300     }
301 
302     XFree ((char *) origkeymap);
303     return;
304 }
305 
306 
PrintPointerMap(fp)307 void PrintPointerMap (fp)
308     FILE *fp;
309 {
310     unsigned char pmap[256];		/* there are 8 bits of buttons */
311     int count, i;
312 
313     count = XGetPointerMapping (dpy, pmap, 256);
314 
315     fprintf (fp, "There are %d pointer buttons defined.\n\n", count);
316     fprintf (fp, "    Physical        Button\n");
317     fprintf (fp, "     Button          Code\n");
318 /*               "      ###            ###\n"               */
319     for (i = 0; i < count; i++) {
320 	fprintf (fp, "      %3u            %3u\n",
321 		 i+1, (unsigned int) pmap[i]);
322     }
323     fprintf (fp, "\n");
324     return;
325 }
326 
327 
328 /*
329  * SetPointerMap - set the pointer map
330  */
331 
SetPointerMap(map,n)332 int SetPointerMap (map, n)
333     unsigned char *map;
334     int n;
335 {
336     unsigned char defmap[MAXBUTTONCODES];
337     int j;
338     int retries, timeout;
339 
340     if (n == 0) {				/* reset to default */
341 	n = XGetPointerMapping (dpy, defmap, MAXBUTTONCODES);
342 	for (j = 0; j < n; j++) defmap[j] = (unsigned char) (j + 1);
343 	map = defmap;
344     }
345 
346     for (retries = 5, timeout = 2; retries > 0; retries--, timeout *= 2) {
347 	int result;
348 
349 	switch (result = XSetPointerMapping (dpy, map, n)) {
350 	  case MappingSuccess:
351 	    return 0;
352 	  case MappingBusy:
353 	    mapping_busy_pointer (timeout);
354 	    continue;
355 	  case MappingFailed:
356 	    fprintf (stderr, "%s:  bad pointer mapping\n", ProgramName);
357 	    return -1;
358 	  default:
359 	    fprintf (stderr, "%s:  bad return %d from XSetPointerMapping\n",
360 		     ProgramName, result);
361 	    return -1;
362 	}
363     }
364     fprintf (stderr, "%s:  unable to set pointer mapping\n", ProgramName);
365     return -1;
366 }
367