exec.c revision 1a30de1f
11a30de1fSmrg/* $XdotOrg: exec.c,v 1.4 2001/02/09 02:05:56 xorgcvs Exp $ */
21a30de1fSmrg/* $Xorg: exec.c,v 1.4 2001/02/09 02:05:56 xorgcvs Exp $ */
31a30de1fSmrg/*
41a30de1fSmrg
51a30de1fSmrgCopyright 1988, 1998  The Open Group
61a30de1fSmrg
71a30de1fSmrgPermission to use, copy, modify, distribute, and sell this software and its
81a30de1fSmrgdocumentation for any purpose is hereby granted without fee, provided that
91a30de1fSmrgthe above copyright notice appear in all copies and that both that
101a30de1fSmrgcopyright notice and this permission notice appear in supporting
111a30de1fSmrgdocumentation.
121a30de1fSmrg
131a30de1fSmrgThe above copyright notice and this permission notice shall be included
141a30de1fSmrgin all copies or substantial portions of the Software.
151a30de1fSmrg
161a30de1fSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
171a30de1fSmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
181a30de1fSmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
191a30de1fSmrgIN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
201a30de1fSmrgOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
211a30de1fSmrgARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
221a30de1fSmrgOTHER DEALINGS IN THE SOFTWARE.
231a30de1fSmrg
241a30de1fSmrgExcept as contained in this notice, the name of The Open Group shall
251a30de1fSmrgnot be used in advertising or otherwise to promote the sale, use or
261a30de1fSmrgother dealings in this Software without prior written authorization
271a30de1fSmrgfrom The Open Group.
281a30de1fSmrg
291a30de1fSmrg*/
301a30de1fSmrg
311a30de1fSmrg/*
321a30de1fSmrg * Copyright 1987 by Sun Microsystems, Inc. Mountain View, CA.
331a30de1fSmrg *
341a30de1fSmrg *                     All Rights Reserved
351a30de1fSmrg *
361a30de1fSmrg * Permission  to  use,  copy,  modify,  and  distribute   this
371a30de1fSmrg * software  and  its documentation for any purpose and without
381a30de1fSmrg * fee is hereby granted, provided that the above copyright no-
391a30de1fSmrg * tice  appear  in all copies and that both that copyright no-
401a30de1fSmrg * tice and this permission notice appear in  supporting  docu-
411a30de1fSmrg * mentation,  and  that the name of Sun not be used in
421a30de1fSmrg * advertising or publicity pertaining to distribution  of  the
431a30de1fSmrg * software  without specific prior written permission. Sun
441a30de1fSmrg * makes no representations about the suitability of this
451a30de1fSmrg * software for any purpose. It is provided "as is" without any
461a30de1fSmrg * express or implied warranty.
471a30de1fSmrg *
481a30de1fSmrg * SUN DISCLAIMS ALL WARRANTIES WITH REGARD TO  THIS  SOFTWARE,
491a30de1fSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT-
501a30de1fSmrg * NESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SUN BE  LI-
511a30de1fSmrg * ABLE  FOR  ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
521a30de1fSmrg * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,  DATA  OR
531a30de1fSmrg * PROFITS,  WHETHER  IN  AN  ACTION OF CONTRACT, NEGLIGENCE OR
541a30de1fSmrg * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
551a30de1fSmrg * THE USE OR PERFORMANCE OF THIS SOFTWARE.
561a30de1fSmrg *
571a30de1fSmrg * Author:  Jim Fulton, MIT X Consortium; derived from parts of the
581a30de1fSmrg * original xmodmap, written by David Rosenthal, of Sun Microsystems.
591a30de1fSmrg */
601a30de1fSmrg/* $XFree86: xc/programs/xmodmap/exec.c,v 1.5 2001/12/14 20:02:13 dawes Exp $ */
611a30de1fSmrg
621a30de1fSmrg#include <X11/Xos.h>
631a30de1fSmrg#include <X11/Xlib.h>
641a30de1fSmrg#include <stdio.h>
651a30de1fSmrg#include "xmodmap.h"
661a30de1fSmrg#include "wq.h"
671a30de1fSmrg
681a30de1fSmrgstatic void
691a30de1fSmrgmapping_busy_key(int timeout)
701a30de1fSmrg{
711a30de1fSmrg    int i;
721a30de1fSmrg    unsigned char keymap[32];
731a30de1fSmrg    static unsigned int masktable[8] = {
741a30de1fSmrg	0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
751a30de1fSmrg
761a30de1fSmrg    XQueryKeymap (dpy, (char *) keymap);
771a30de1fSmrg
781a30de1fSmrg    fprintf (stderr,
791a30de1fSmrg	     "%s:  please release the following keys within %d seconds:\n",
801a30de1fSmrg	     ProgramName, timeout);
811a30de1fSmrg    for (i = 0; i < 256; i++) {
821a30de1fSmrg	if (keymap[i >> 3] & masktable[i & 7]) {
831a30de1fSmrg	    KeySym ks = XKeycodeToKeysym (dpy, (KeyCode) i, 0);
841a30de1fSmrg	    char *cp = XKeysymToString (ks);
851a30de1fSmrg	    fprintf (stderr, "    %s (keysym 0x%x, keycode %d)\n",
861a30de1fSmrg		     cp ? cp : "UNNAMED", (unsigned int)ks, i);
871a30de1fSmrg	}
881a30de1fSmrg    }
891a30de1fSmrg    sleep (timeout);
901a30de1fSmrg    return;
911a30de1fSmrg}
921a30de1fSmrg
931a30de1fSmrgstatic void
941a30de1fSmrgmapping_busy_pointer(int timeout)
951a30de1fSmrg{
961a30de1fSmrg    int i;
971a30de1fSmrg    Window root, child;			/* dummy variables */
981a30de1fSmrg    int rx, ry, wx, wy;			/* dummy variables */
991a30de1fSmrg    unsigned int mask;
1001a30de1fSmrg    static unsigned int masks[5] = {
1011a30de1fSmrg	Button1Mask, Button2Mask, Button3Mask, Button4Mask, Button5Mask };
1021a30de1fSmrg
1031a30de1fSmrg    if (!XQueryPointer (dpy, RootWindow(dpy,DefaultScreen(dpy)),
1041a30de1fSmrg			&root, &child, &rx, &ry, &wx, &wy, &mask))
1051a30de1fSmrg      mask = 0;
1061a30de1fSmrg
1071a30de1fSmrg    fprintf (stderr,
1081a30de1fSmrg	     "%s:  please release the following buttons within %d seconds:\n",
1091a30de1fSmrg	     ProgramName, timeout);
1101a30de1fSmrg    for (i = 0; i < 5; i++) {
1111a30de1fSmrg	if (mask & masks[i])
1121a30de1fSmrg	  fprintf (stderr, "    Button%d\n", i+1);
1131a30de1fSmrg    }
1141a30de1fSmrg    sleep (timeout);
1151a30de1fSmrg    return;
1161a30de1fSmrg}
1171a30de1fSmrg
1181a30de1fSmrg
1191a30de1fSmrg/*
1201a30de1fSmrg * UpdateModifierMapping - this sends the modifier map to the server
1211a30de1fSmrg * and deals with retransmissions due to the keyboard being busy.
1221a30de1fSmrg */
1231a30de1fSmrg
1241a30de1fSmrgint
1251a30de1fSmrgUpdateModifierMapping(XModifierKeymap *map)
1261a30de1fSmrg{
1271a30de1fSmrg    int retries, timeout;
1281a30de1fSmrg
1291a30de1fSmrg    for (retries = 5, timeout = 2; retries > 0; retries--, timeout *= 2) {
1301a30de1fSmrg	int result;
1311a30de1fSmrg
1321a30de1fSmrg	result = XSetModifierMapping (dpy, map);
1331a30de1fSmrg	switch (result) {
1341a30de1fSmrg	  case MappingSuccess:	/* Success */
1351a30de1fSmrg	    return (0);
1361a30de1fSmrg	  case MappingBusy:		/* Busy */
1371a30de1fSmrg	    mapping_busy_key (timeout);
1381a30de1fSmrg	    continue;
1391a30de1fSmrg	  case MappingFailed:
1401a30de1fSmrg	    fprintf (stderr, "%s: bad set modifier mapping.\n",
1411a30de1fSmrg		     ProgramName);
1421a30de1fSmrg	    return (-1);
1431a30de1fSmrg	  default:
1441a30de1fSmrg	    fprintf (stderr, "%s:  bad return %d from XSetModifierMapping\n",
1451a30de1fSmrg		     ProgramName, result);
1461a30de1fSmrg	    return (-1);
1471a30de1fSmrg	}
1481a30de1fSmrg    }
1491a30de1fSmrg    fprintf (stderr,
1501a30de1fSmrg	     "%s:  unable to set modifier mapping, keyboard problem\n",
1511a30de1fSmrg	     ProgramName);
1521a30de1fSmrg    return (-1);
1531a30de1fSmrg}
1541a30de1fSmrg
1551a30de1fSmrg
1561a30de1fSmrg/*
1571a30de1fSmrg * AddModifier - this adds a keycode to the modifier list
1581a30de1fSmrg */
1591a30de1fSmrg
1601a30de1fSmrgint
1611a30de1fSmrgAddModifier(XModifierKeymap **mapp, KeyCode keycode, int modifier)
1621a30de1fSmrg{
1631a30de1fSmrg    if (keycode) {
1641a30de1fSmrg	*mapp = XInsertModifiermapEntry (*mapp, keycode, modifier);
1651a30de1fSmrg	return (0);
1661a30de1fSmrg    } else {
1671a30de1fSmrg	return (-1);
1681a30de1fSmrg    }
1691a30de1fSmrg    /*NOTREACHED*/
1701a30de1fSmrg}
1711a30de1fSmrg
1721a30de1fSmrg
1731a30de1fSmrg/*
1741a30de1fSmrg * DeleteModifier - this removes a keycode from the modifier list
1751a30de1fSmrg */
1761a30de1fSmrg
1771a30de1fSmrgint
1781a30de1fSmrgRemoveModifier(XModifierKeymap **mapp, KeyCode keycode, int modifier)
1791a30de1fSmrg{
1801a30de1fSmrg    if (keycode) {
1811a30de1fSmrg	*mapp = XDeleteModifiermapEntry (*mapp, keycode, modifier);
1821a30de1fSmrg	return (0);
1831a30de1fSmrg    } else {
1841a30de1fSmrg	return (-1);
1851a30de1fSmrg    }
1861a30de1fSmrg    /*NOTREACHED*/
1871a30de1fSmrg}
1881a30de1fSmrg
1891a30de1fSmrg
1901a30de1fSmrg/*
1911a30de1fSmrg * ClearModifier - this removes all entries from the modifier list
1921a30de1fSmrg */
1931a30de1fSmrg
1941a30de1fSmrgint
1951a30de1fSmrgClearModifier(XModifierKeymap **mapp, int modifier)
1961a30de1fSmrg{
1971a30de1fSmrg    int i;
1981a30de1fSmrg    XModifierKeymap *map = *mapp;
1991a30de1fSmrg    KeyCode *kcp;
2001a30de1fSmrg
2011a30de1fSmrg    kcp = &map->modifiermap[modifier * map->max_keypermod];
2021a30de1fSmrg    for (i = 0; i < map->max_keypermod; i++) {
2031a30de1fSmrg	*kcp++ = (KeyCode) 0;
2041a30de1fSmrg    }
2051a30de1fSmrg    return (0);
2061a30de1fSmrg}
2071a30de1fSmrg
2081a30de1fSmrg
2091a30de1fSmrg/*
2101a30de1fSmrg * print the contents of the map
2111a30de1fSmrg */
2121a30de1fSmrgvoid
2131a30de1fSmrgPrintModifierMapping(XModifierKeymap *map, FILE *fp)
2141a30de1fSmrg{
2151a30de1fSmrg    int i, k = 0;
2161a30de1fSmrg    int min_keycode, max_keycode, keysyms_per_keycode = 0;
2171a30de1fSmrg
2181a30de1fSmrg    XDisplayKeycodes (dpy, &min_keycode, &max_keycode);
2191a30de1fSmrg    XGetKeyboardMapping (dpy, min_keycode, (max_keycode - min_keycode + 1),
2201a30de1fSmrg			 &keysyms_per_keycode);
2211a30de1fSmrg
2221a30de1fSmrg    fprintf (fp,
2231a30de1fSmrg    	     "%s:  up to %d keys per modifier, (keycodes in parentheses):\n\n",
2241a30de1fSmrg    	     ProgramName, map->max_keypermod);
2251a30de1fSmrg    for (i = 0; i < 8; i++) {
2261a30de1fSmrg	int j;
2271a30de1fSmrg
2281a30de1fSmrg	fprintf(fp, "%-10s", modifier_table[i].name);
2291a30de1fSmrg	for (j = 0; j < map->max_keypermod; j++) {
2301a30de1fSmrg	    if (map->modifiermap[k]) {
2311a30de1fSmrg		KeySym ks;
2321a30de1fSmrg		int index = 0;
2331a30de1fSmrg		char *nm;
2341a30de1fSmrg		do {
2351a30de1fSmrg		    ks = XKeycodeToKeysym(dpy, map->modifiermap[k], index);
2361a30de1fSmrg		    index++;
2371a30de1fSmrg		} while ( !ks && index < keysyms_per_keycode);
2381a30de1fSmrg		nm = XKeysymToString(ks);
2391a30de1fSmrg
2401a30de1fSmrg		fprintf (fp, "%s  %s (0x%0x)", (j > 0 ? "," : ""),
2411a30de1fSmrg			 (nm ? nm : "BadKey"), map->modifiermap[k]);
2421a30de1fSmrg	    }
2431a30de1fSmrg	    k++;
2441a30de1fSmrg	}
2451a30de1fSmrg	fprintf(fp, "\n");
2461a30de1fSmrg    }
2471a30de1fSmrg    fprintf (fp, "\n");
2481a30de1fSmrg    return;
2491a30de1fSmrg}
2501a30de1fSmrg
2511a30de1fSmrgvoid
2521a30de1fSmrgPrintKeyTable(Bool exprs, FILE *fp)
2531a30de1fSmrg{
2541a30de1fSmrg    int         i;
2551a30de1fSmrg    int min_keycode, max_keycode, keysyms_per_keycode;
2561a30de1fSmrg    KeySym *keymap, *origkeymap;
2571a30de1fSmrg
2581a30de1fSmrg    XDisplayKeycodes (dpy, &min_keycode, &max_keycode);
2591a30de1fSmrg    origkeymap = XGetKeyboardMapping (dpy, min_keycode,
2601a30de1fSmrg				      (max_keycode - min_keycode + 1),
2611a30de1fSmrg				      &keysyms_per_keycode);
2621a30de1fSmrg
2631a30de1fSmrg    if (!origkeymap) {
2641a30de1fSmrg	fprintf (stderr, "%s:  unable to get keyboard mapping table.\n",
2651a30de1fSmrg		 ProgramName);
2661a30de1fSmrg	return;
2671a30de1fSmrg    }
2681a30de1fSmrg    if (!exprs) {
2691a30de1fSmrg	fprintf (fp,
2701a30de1fSmrg		 "There are %d KeySyms per KeyCode; KeyCodes range from %d to %d.\n\n",
2711a30de1fSmrg		 keysyms_per_keycode, min_keycode, max_keycode);
2721a30de1fSmrg	fprintf (fp, "    KeyCode\tKeysym (Keysym)\t...\n");
2731a30de1fSmrg	fprintf (fp, "    Value  \tValue   (Name) \t...\n\n");
2741a30de1fSmrg    }
2751a30de1fSmrg    keymap = origkeymap;
2761a30de1fSmrg    for (i = min_keycode; i <= max_keycode; i++) {
2771a30de1fSmrg	int  j, max;
2781a30de1fSmrg
2791a30de1fSmrg	if (exprs)
2801a30de1fSmrg	    fprintf(fp, "keycode %3d =", i);
2811a30de1fSmrg	else
2821a30de1fSmrg	    fprintf(fp, "    %3d    \t", i);
2831a30de1fSmrg	max = keysyms_per_keycode - 1;
2841a30de1fSmrg	while ((max >= 0) && (keymap[max] == NoSymbol))
2851a30de1fSmrg	    max--;
2861a30de1fSmrg	for (j = 0; j <= max; j++) {
2871a30de1fSmrg	    register KeySym ks = keymap[j];
2881a30de1fSmrg	    char *s;
2891a30de1fSmrg	    if (ks != NoSymbol)
2901a30de1fSmrg		s = XKeysymToString (ks);
2911a30de1fSmrg	    else
2921a30de1fSmrg		s = "NoSymbol";
2931a30de1fSmrg	    if (!exprs)
2941a30de1fSmrg		fprintf (fp, "0x%04x (%s)\t",
2951a30de1fSmrg			 (unsigned int)ks, s ? s : "no name");
2961a30de1fSmrg	    else if (s)
2971a30de1fSmrg		fprintf (fp, " %s", s);
2981a30de1fSmrg	    else
2991a30de1fSmrg		fprintf (fp, " 0x%04x", (unsigned int)ks);
3001a30de1fSmrg	}
3011a30de1fSmrg	keymap += keysyms_per_keycode;
3021a30de1fSmrg	fprintf (fp, "\n");
3031a30de1fSmrg    }
3041a30de1fSmrg
3051a30de1fSmrg    XFree ((char *) origkeymap);
3061a30de1fSmrg    return;
3071a30de1fSmrg}
3081a30de1fSmrg
3091a30de1fSmrgvoid
3101a30de1fSmrgPrintPointerMap(FILE *fp)
3111a30de1fSmrg{
3121a30de1fSmrg    unsigned char pmap[256];		/* there are 8 bits of buttons */
3131a30de1fSmrg    int count, i;
3141a30de1fSmrg
3151a30de1fSmrg    count = XGetPointerMapping (dpy, pmap, 256);
3161a30de1fSmrg
3171a30de1fSmrg    fprintf (fp, "There are %d pointer buttons defined.\n\n", count);
3181a30de1fSmrg    fprintf (fp, "    Physical        Button\n");
3191a30de1fSmrg    fprintf (fp, "     Button          Code\n");
3201a30de1fSmrg/*               "      ###            ###\n"               */
3211a30de1fSmrg    for (i = 0; i < count; i++) {
3221a30de1fSmrg	fprintf (fp, "      %3u            %3u\n",
3231a30de1fSmrg		 i+1, (unsigned int) pmap[i]);
3241a30de1fSmrg    }
3251a30de1fSmrg    fprintf (fp, "\n");
3261a30de1fSmrg    return;
3271a30de1fSmrg}
3281a30de1fSmrg
3291a30de1fSmrg
3301a30de1fSmrg/*
3311a30de1fSmrg * SetPointerMap - set the pointer map
3321a30de1fSmrg */
3331a30de1fSmrg
3341a30de1fSmrgint
3351a30de1fSmrgSetPointerMap(unsigned char *map, int n)
3361a30de1fSmrg{
3371a30de1fSmrg    unsigned char defmap[MAXBUTTONCODES];
3381a30de1fSmrg    int j;
3391a30de1fSmrg    int retries, timeout;
3401a30de1fSmrg
3411a30de1fSmrg    if (n == 0) {				/* reset to default */
3421a30de1fSmrg	n = XGetPointerMapping (dpy, defmap, MAXBUTTONCODES);
3431a30de1fSmrg	for (j = 0; j < n; j++) defmap[j] = (unsigned char) (j + 1);
3441a30de1fSmrg	map = defmap;
3451a30de1fSmrg    }
3461a30de1fSmrg
3471a30de1fSmrg    for (retries = 5, timeout = 2; retries > 0; retries--, timeout *= 2) {
3481a30de1fSmrg	int result;
3491a30de1fSmrg
3501a30de1fSmrg	switch (result = XSetPointerMapping (dpy, map, n)) {
3511a30de1fSmrg	  case MappingSuccess:
3521a30de1fSmrg	    return 0;
3531a30de1fSmrg	  case MappingBusy:
3541a30de1fSmrg	    mapping_busy_pointer (timeout);
3551a30de1fSmrg	    continue;
3561a30de1fSmrg	  case MappingFailed:
3571a30de1fSmrg	    fprintf (stderr, "%s:  bad pointer mapping\n", ProgramName);
3581a30de1fSmrg	    return -1;
3591a30de1fSmrg	  default:
3601a30de1fSmrg	    fprintf (stderr, "%s:  bad return %d from XSetPointerMapping\n",
3611a30de1fSmrg		     ProgramName, result);
3621a30de1fSmrg	    return -1;
3631a30de1fSmrg	}
3641a30de1fSmrg    }
3651a30de1fSmrg    fprintf (stderr, "%s:  unable to set pointer mapping\n", ProgramName);
3661a30de1fSmrg    return -1;
3671a30de1fSmrg}
368