exec.c revision ce62200c
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/*
32ce62200cSmrg * Copyright (c) 1987, Oracle and/or its affiliates. All rights reserved.
331a30de1fSmrg *
34ce62200cSmrg * Permission is hereby granted, free of charge, to any person obtaining a
35ce62200cSmrg * copy of this software and associated documentation files (the "Software"),
36ce62200cSmrg * to deal in the Software without restriction, including without limitation
37ce62200cSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
38ce62200cSmrg * and/or sell copies of the Software, and to permit persons to whom the
39ce62200cSmrg * Software is furnished to do so, subject to the following conditions:
401a30de1fSmrg *
41ce62200cSmrg * The above copyright notice and this permission notice (including the next
42ce62200cSmrg * paragraph) shall be included in all copies or substantial portions of the
43ce62200cSmrg * Software.
44ce62200cSmrg *
45ce62200cSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
46ce62200cSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
47ce62200cSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
48ce62200cSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
49ce62200cSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
50ce62200cSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
51ce62200cSmrg * DEALINGS IN THE SOFTWARE.
52ce62200cSmrg */
53ce62200cSmrg
54ce62200cSmrg/*
551a30de1fSmrg * Author:  Jim Fulton, MIT X Consortium; derived from parts of the
561a30de1fSmrg * original xmodmap, written by David Rosenthal, of Sun Microsystems.
571a30de1fSmrg */
581a30de1fSmrg/* $XFree86: xc/programs/xmodmap/exec.c,v 1.5 2001/12/14 20:02:13 dawes Exp $ */
591a30de1fSmrg
601a30de1fSmrg#include <X11/Xos.h>
611a30de1fSmrg#include <X11/Xlib.h>
621a30de1fSmrg#include <stdio.h>
631a30de1fSmrg#include "xmodmap.h"
641a30de1fSmrg#include "wq.h"
651a30de1fSmrg
661a30de1fSmrgstatic void
671a30de1fSmrgmapping_busy_key(int timeout)
681a30de1fSmrg{
691a30de1fSmrg    int i;
701a30de1fSmrg    unsigned char keymap[32];
711a30de1fSmrg    static unsigned int masktable[8] = {
721a30de1fSmrg	0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
731a30de1fSmrg
741a30de1fSmrg    XQueryKeymap (dpy, (char *) keymap);
751a30de1fSmrg
761a30de1fSmrg    fprintf (stderr,
771a30de1fSmrg	     "%s:  please release the following keys within %d seconds:\n",
781a30de1fSmrg	     ProgramName, timeout);
791a30de1fSmrg    for (i = 0; i < 256; i++) {
801a30de1fSmrg	if (keymap[i >> 3] & masktable[i & 7]) {
811a30de1fSmrg	    KeySym ks = XKeycodeToKeysym (dpy, (KeyCode) i, 0);
821a30de1fSmrg	    char *cp = XKeysymToString (ks);
831a30de1fSmrg	    fprintf (stderr, "    %s (keysym 0x%x, keycode %d)\n",
841a30de1fSmrg		     cp ? cp : "UNNAMED", (unsigned int)ks, i);
851a30de1fSmrg	}
861a30de1fSmrg    }
871a30de1fSmrg    sleep (timeout);
881a30de1fSmrg    return;
891a30de1fSmrg}
901a30de1fSmrg
911a30de1fSmrgstatic void
921a30de1fSmrgmapping_busy_pointer(int timeout)
931a30de1fSmrg{
941a30de1fSmrg    int i;
951a30de1fSmrg    Window root, child;			/* dummy variables */
961a30de1fSmrg    int rx, ry, wx, wy;			/* dummy variables */
971a30de1fSmrg    unsigned int mask;
981a30de1fSmrg    static unsigned int masks[5] = {
991a30de1fSmrg	Button1Mask, Button2Mask, Button3Mask, Button4Mask, Button5Mask };
1001a30de1fSmrg
1011a30de1fSmrg    if (!XQueryPointer (dpy, RootWindow(dpy,DefaultScreen(dpy)),
1021a30de1fSmrg			&root, &child, &rx, &ry, &wx, &wy, &mask))
1031a30de1fSmrg      mask = 0;
1041a30de1fSmrg
1051a30de1fSmrg    fprintf (stderr,
1061a30de1fSmrg	     "%s:  please release the following buttons within %d seconds:\n",
1071a30de1fSmrg	     ProgramName, timeout);
1081a30de1fSmrg    for (i = 0; i < 5; i++) {
1091a30de1fSmrg	if (mask & masks[i])
1101a30de1fSmrg	  fprintf (stderr, "    Button%d\n", i+1);
1111a30de1fSmrg    }
1121a30de1fSmrg    sleep (timeout);
1131a30de1fSmrg    return;
1141a30de1fSmrg}
1151a30de1fSmrg
1161a30de1fSmrg
1171a30de1fSmrg/*
1181a30de1fSmrg * UpdateModifierMapping - this sends the modifier map to the server
1191a30de1fSmrg * and deals with retransmissions due to the keyboard being busy.
1201a30de1fSmrg */
1211a30de1fSmrg
1221a30de1fSmrgint
1231a30de1fSmrgUpdateModifierMapping(XModifierKeymap *map)
1241a30de1fSmrg{
1251a30de1fSmrg    int retries, timeout;
1261a30de1fSmrg
1271a30de1fSmrg    for (retries = 5, timeout = 2; retries > 0; retries--, timeout *= 2) {
1281a30de1fSmrg	int result;
1291a30de1fSmrg
1301a30de1fSmrg	result = XSetModifierMapping (dpy, map);
1311a30de1fSmrg	switch (result) {
1321a30de1fSmrg	  case MappingSuccess:	/* Success */
1331a30de1fSmrg	    return (0);
1341a30de1fSmrg	  case MappingBusy:		/* Busy */
1351a30de1fSmrg	    mapping_busy_key (timeout);
1361a30de1fSmrg	    continue;
1371a30de1fSmrg	  case MappingFailed:
1381a30de1fSmrg	    fprintf (stderr, "%s: bad set modifier mapping.\n",
1391a30de1fSmrg		     ProgramName);
1401a30de1fSmrg	    return (-1);
1411a30de1fSmrg	  default:
1421a30de1fSmrg	    fprintf (stderr, "%s:  bad return %d from XSetModifierMapping\n",
1431a30de1fSmrg		     ProgramName, result);
1441a30de1fSmrg	    return (-1);
1451a30de1fSmrg	}
1461a30de1fSmrg    }
1471a30de1fSmrg    fprintf (stderr,
1481a30de1fSmrg	     "%s:  unable to set modifier mapping, keyboard problem\n",
1491a30de1fSmrg	     ProgramName);
1501a30de1fSmrg    return (-1);
1511a30de1fSmrg}
1521a30de1fSmrg
1531a30de1fSmrg
1541a30de1fSmrg/*
1551a30de1fSmrg * AddModifier - this adds a keycode to the modifier list
1561a30de1fSmrg */
1571a30de1fSmrg
1581a30de1fSmrgint
1591a30de1fSmrgAddModifier(XModifierKeymap **mapp, KeyCode keycode, int modifier)
1601a30de1fSmrg{
1611a30de1fSmrg    if (keycode) {
1621a30de1fSmrg	*mapp = XInsertModifiermapEntry (*mapp, keycode, modifier);
1631a30de1fSmrg	return (0);
1641a30de1fSmrg    } else {
1651a30de1fSmrg	return (-1);
1661a30de1fSmrg    }
1671a30de1fSmrg    /*NOTREACHED*/
1681a30de1fSmrg}
1691a30de1fSmrg
1701a30de1fSmrg
1711a30de1fSmrg/*
1721a30de1fSmrg * DeleteModifier - this removes a keycode from the modifier list
1731a30de1fSmrg */
1741a30de1fSmrg
1751a30de1fSmrgint
1761a30de1fSmrgRemoveModifier(XModifierKeymap **mapp, KeyCode keycode, int modifier)
1771a30de1fSmrg{
1781a30de1fSmrg    if (keycode) {
1791a30de1fSmrg	*mapp = XDeleteModifiermapEntry (*mapp, keycode, modifier);
1801a30de1fSmrg	return (0);
1811a30de1fSmrg    } else {
1821a30de1fSmrg	return (-1);
1831a30de1fSmrg    }
1841a30de1fSmrg    /*NOTREACHED*/
1851a30de1fSmrg}
1861a30de1fSmrg
1871a30de1fSmrg
1881a30de1fSmrg/*
1891a30de1fSmrg * ClearModifier - this removes all entries from the modifier list
1901a30de1fSmrg */
1911a30de1fSmrg
1921a30de1fSmrgint
1931a30de1fSmrgClearModifier(XModifierKeymap **mapp, int modifier)
1941a30de1fSmrg{
1951a30de1fSmrg    int i;
1961a30de1fSmrg    XModifierKeymap *map = *mapp;
1971a30de1fSmrg    KeyCode *kcp;
1981a30de1fSmrg
1991a30de1fSmrg    kcp = &map->modifiermap[modifier * map->max_keypermod];
2001a30de1fSmrg    for (i = 0; i < map->max_keypermod; i++) {
2011a30de1fSmrg	*kcp++ = (KeyCode) 0;
2021a30de1fSmrg    }
2031a30de1fSmrg    return (0);
2041a30de1fSmrg}
2051a30de1fSmrg
2061a30de1fSmrg
2071a30de1fSmrg/*
2081a30de1fSmrg * print the contents of the map
2091a30de1fSmrg */
2101a30de1fSmrgvoid
2111a30de1fSmrgPrintModifierMapping(XModifierKeymap *map, FILE *fp)
2121a30de1fSmrg{
2131a30de1fSmrg    int i, k = 0;
2141a30de1fSmrg    int min_keycode, max_keycode, keysyms_per_keycode = 0;
2151a30de1fSmrg
2161a30de1fSmrg    XDisplayKeycodes (dpy, &min_keycode, &max_keycode);
2171a30de1fSmrg    XGetKeyboardMapping (dpy, min_keycode, (max_keycode - min_keycode + 1),
2181a30de1fSmrg			 &keysyms_per_keycode);
2191a30de1fSmrg
2201a30de1fSmrg    fprintf (fp,
2211a30de1fSmrg    	     "%s:  up to %d keys per modifier, (keycodes in parentheses):\n\n",
2221a30de1fSmrg    	     ProgramName, map->max_keypermod);
2231a30de1fSmrg    for (i = 0; i < 8; i++) {
2241a30de1fSmrg	int j;
2251a30de1fSmrg
2261a30de1fSmrg	fprintf(fp, "%-10s", modifier_table[i].name);
2271a30de1fSmrg	for (j = 0; j < map->max_keypermod; j++) {
2281a30de1fSmrg	    if (map->modifiermap[k]) {
2291a30de1fSmrg		KeySym ks;
2301a30de1fSmrg		int index = 0;
2311a30de1fSmrg		char *nm;
2321a30de1fSmrg		do {
2331a30de1fSmrg		    ks = XKeycodeToKeysym(dpy, map->modifiermap[k], index);
2341a30de1fSmrg		    index++;
2351a30de1fSmrg		} while ( !ks && index < keysyms_per_keycode);
2361a30de1fSmrg		nm = XKeysymToString(ks);
2371a30de1fSmrg
2381a30de1fSmrg		fprintf (fp, "%s  %s (0x%0x)", (j > 0 ? "," : ""),
2391a30de1fSmrg			 (nm ? nm : "BadKey"), map->modifiermap[k]);
2401a30de1fSmrg	    }
2411a30de1fSmrg	    k++;
2421a30de1fSmrg	}
2431a30de1fSmrg	fprintf(fp, "\n");
2441a30de1fSmrg    }
2451a30de1fSmrg    fprintf (fp, "\n");
2461a30de1fSmrg    return;
2471a30de1fSmrg}
2481a30de1fSmrg
2491a30de1fSmrgvoid
2501a30de1fSmrgPrintKeyTable(Bool exprs, FILE *fp)
2511a30de1fSmrg{
2521a30de1fSmrg    int         i;
2531a30de1fSmrg    int min_keycode, max_keycode, keysyms_per_keycode;
2541a30de1fSmrg    KeySym *keymap, *origkeymap;
2551a30de1fSmrg
2561a30de1fSmrg    XDisplayKeycodes (dpy, &min_keycode, &max_keycode);
2571a30de1fSmrg    origkeymap = XGetKeyboardMapping (dpy, min_keycode,
2581a30de1fSmrg				      (max_keycode - min_keycode + 1),
2591a30de1fSmrg				      &keysyms_per_keycode);
2601a30de1fSmrg
2611a30de1fSmrg    if (!origkeymap) {
2621a30de1fSmrg	fprintf (stderr, "%s:  unable to get keyboard mapping table.\n",
2631a30de1fSmrg		 ProgramName);
2641a30de1fSmrg	return;
2651a30de1fSmrg    }
2661a30de1fSmrg    if (!exprs) {
2671a30de1fSmrg	fprintf (fp,
2681a30de1fSmrg		 "There are %d KeySyms per KeyCode; KeyCodes range from %d to %d.\n\n",
2691a30de1fSmrg		 keysyms_per_keycode, min_keycode, max_keycode);
2701a30de1fSmrg	fprintf (fp, "    KeyCode\tKeysym (Keysym)\t...\n");
2711a30de1fSmrg	fprintf (fp, "    Value  \tValue   (Name) \t...\n\n");
2721a30de1fSmrg    }
2731a30de1fSmrg    keymap = origkeymap;
2741a30de1fSmrg    for (i = min_keycode; i <= max_keycode; i++) {
2751a30de1fSmrg	int  j, max;
2761a30de1fSmrg
2771a30de1fSmrg	if (exprs)
2781a30de1fSmrg	    fprintf(fp, "keycode %3d =", i);
2791a30de1fSmrg	else
2801a30de1fSmrg	    fprintf(fp, "    %3d    \t", i);
2811a30de1fSmrg	max = keysyms_per_keycode - 1;
2821a30de1fSmrg	while ((max >= 0) && (keymap[max] == NoSymbol))
2831a30de1fSmrg	    max--;
2841a30de1fSmrg	for (j = 0; j <= max; j++) {
2851a30de1fSmrg	    register KeySym ks = keymap[j];
2861a30de1fSmrg	    char *s;
2871a30de1fSmrg	    if (ks != NoSymbol)
2881a30de1fSmrg		s = XKeysymToString (ks);
2891a30de1fSmrg	    else
2901a30de1fSmrg		s = "NoSymbol";
2911a30de1fSmrg	    if (!exprs)
2921a30de1fSmrg		fprintf (fp, "0x%04x (%s)\t",
2931a30de1fSmrg			 (unsigned int)ks, s ? s : "no name");
2941a30de1fSmrg	    else if (s)
2951a30de1fSmrg		fprintf (fp, " %s", s);
2961a30de1fSmrg	    else
2971a30de1fSmrg		fprintf (fp, " 0x%04x", (unsigned int)ks);
2981a30de1fSmrg	}
2991a30de1fSmrg	keymap += keysyms_per_keycode;
3001a30de1fSmrg	fprintf (fp, "\n");
3011a30de1fSmrg    }
3021a30de1fSmrg
3031a30de1fSmrg    XFree ((char *) origkeymap);
3041a30de1fSmrg    return;
3051a30de1fSmrg}
3061a30de1fSmrg
3071a30de1fSmrgvoid
3081a30de1fSmrgPrintPointerMap(FILE *fp)
3091a30de1fSmrg{
3101a30de1fSmrg    unsigned char pmap[256];		/* there are 8 bits of buttons */
3111a30de1fSmrg    int count, i;
3121a30de1fSmrg
3131a30de1fSmrg    count = XGetPointerMapping (dpy, pmap, 256);
3141a30de1fSmrg
3151a30de1fSmrg    fprintf (fp, "There are %d pointer buttons defined.\n\n", count);
3161a30de1fSmrg    fprintf (fp, "    Physical        Button\n");
3171a30de1fSmrg    fprintf (fp, "     Button          Code\n");
3181a30de1fSmrg/*               "      ###            ###\n"               */
3191a30de1fSmrg    for (i = 0; i < count; i++) {
3201a30de1fSmrg	fprintf (fp, "      %3u            %3u\n",
3211a30de1fSmrg		 i+1, (unsigned int) pmap[i]);
3221a30de1fSmrg    }
3231a30de1fSmrg    fprintf (fp, "\n");
3241a30de1fSmrg    return;
3251a30de1fSmrg}
3261a30de1fSmrg
3271a30de1fSmrg
3281a30de1fSmrg/*
3291a30de1fSmrg * SetPointerMap - set the pointer map
3301a30de1fSmrg */
3311a30de1fSmrg
3321a30de1fSmrgint
3331a30de1fSmrgSetPointerMap(unsigned char *map, int n)
3341a30de1fSmrg{
3351a30de1fSmrg    unsigned char defmap[MAXBUTTONCODES];
3361a30de1fSmrg    int j;
3371a30de1fSmrg    int retries, timeout;
3381a30de1fSmrg
3391a30de1fSmrg    if (n == 0) {				/* reset to default */
3401a30de1fSmrg	n = XGetPointerMapping (dpy, defmap, MAXBUTTONCODES);
3411a30de1fSmrg	for (j = 0; j < n; j++) defmap[j] = (unsigned char) (j + 1);
3421a30de1fSmrg	map = defmap;
3431a30de1fSmrg    }
3441a30de1fSmrg
3451a30de1fSmrg    for (retries = 5, timeout = 2; retries > 0; retries--, timeout *= 2) {
3461a30de1fSmrg	int result;
3471a30de1fSmrg
3481a30de1fSmrg	switch (result = XSetPointerMapping (dpy, map, n)) {
3491a30de1fSmrg	  case MappingSuccess:
3501a30de1fSmrg	    return 0;
3511a30de1fSmrg	  case MappingBusy:
3521a30de1fSmrg	    mapping_busy_pointer (timeout);
3531a30de1fSmrg	    continue;
3541a30de1fSmrg	  case MappingFailed:
3551a30de1fSmrg	    fprintf (stderr, "%s:  bad pointer mapping\n", ProgramName);
3561a30de1fSmrg	    return -1;
3571a30de1fSmrg	  default:
3581a30de1fSmrg	    fprintf (stderr, "%s:  bad return %d from XSetPointerMapping\n",
3591a30de1fSmrg		     ProgramName, result);
3601a30de1fSmrg	    return -1;
3611a30de1fSmrg	}
3621a30de1fSmrg    }
3631a30de1fSmrg    fprintf (stderr, "%s:  unable to set pointer mapping\n", ProgramName);
3641a30de1fSmrg    return -1;
3651a30de1fSmrg}
366