xmodmap.c revision 1a30de1f
11a30de1fSmrg/* $Xorg: xmodmap.c,v 1.4 2001/02/09 02:05:56 xorgcvs Exp $ */
21a30de1fSmrg/*
31a30de1fSmrg
41a30de1fSmrgCopyright 1988, 1998  The Open Group
51a30de1fSmrg
61a30de1fSmrgPermission to use, copy, modify, distribute, and sell this software and its
71a30de1fSmrgdocumentation for any purpose is hereby granted without fee, provided that
81a30de1fSmrgthe above copyright notice appear in all copies and that both that
91a30de1fSmrgcopyright notice and this permission notice appear in supporting
101a30de1fSmrgdocumentation.
111a30de1fSmrg
121a30de1fSmrgThe above copyright notice and this permission notice shall be included
131a30de1fSmrgin all copies or substantial portions of the Software.
141a30de1fSmrg
151a30de1fSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
161a30de1fSmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
171a30de1fSmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
181a30de1fSmrgIN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
191a30de1fSmrgOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
201a30de1fSmrgARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
211a30de1fSmrgOTHER DEALINGS IN THE SOFTWARE.
221a30de1fSmrg
231a30de1fSmrgExcept as contained in this notice, the name of The Open Group shall
241a30de1fSmrgnot be used in advertising or otherwise to promote the sale, use or
251a30de1fSmrgother dealings in this Software without prior written authorization
261a30de1fSmrgfrom The Open Group.
271a30de1fSmrg
281a30de1fSmrg*/
291a30de1fSmrg/* $XFree86: xc/programs/xmodmap/xmodmap.c,v 1.8tsi Exp $ */
301a30de1fSmrg
311a30de1fSmrg#include <X11/Xos.h>
321a30de1fSmrg#include <X11/Xlib.h>
331a30de1fSmrg#include <stdio.h>
341a30de1fSmrg#include <stdlib.h>
351a30de1fSmrg#include <ctype.h>
361a30de1fSmrg#include "xmodmap.h"
371a30de1fSmrg
381a30de1fSmrgconst char *ProgramName;
391a30de1fSmrgDisplay *dpy = NULL;
401a30de1fSmrgint min_keycode, max_keycode;
411a30de1fSmrgBool verbose = False;
421a30de1fSmrgBool dontExecute = False;
431a30de1fSmrg
441a30de1fSmrgstatic void
451a30de1fSmrgExit(int status)
461a30de1fSmrg{
471a30de1fSmrg    if (dpy) {
481a30de1fSmrg	XCloseDisplay (dpy);
491a30de1fSmrg	dpy = NULL;
501a30de1fSmrg    }
511a30de1fSmrg    exit (status);
521a30de1fSmrg}
531a30de1fSmrg
541a30de1fSmrgvoid *
551a30de1fSmrgchk_malloc(size_t n_bytes)
561a30de1fSmrg{
571a30de1fSmrg    void *buf = malloc(n_bytes);
581a30de1fSmrg    if (!buf) {
591a30de1fSmrg	fprintf(stderr, "%s: Could not allocate %d bytes\n", ProgramName, (int)n_bytes);
601a30de1fSmrg	Exit(-1);
611a30de1fSmrg    }
621a30de1fSmrg    return buf;
631a30de1fSmrg}
641a30de1fSmrg
651a30de1fSmrgstatic const char help_message[] =
661a30de1fSmrg"\nwhere options include:\n"
671a30de1fSmrg"    -display host:dpy            X server to use\n"
681a30de1fSmrg"    -verbose, -quiet             turn logging on or off\n"
691a30de1fSmrg"    -n                           don't execute changes, just show like make\n"
701a30de1fSmrg"    -e expression                execute string\n"
711a30de1fSmrg"    -pm                          print modifier map\n"
721a30de1fSmrg"    -pk                          print keymap table\n"
731a30de1fSmrg"    -pke                         print keymap table as expressions\n"
741a30de1fSmrg"    -pp                          print pointer map\n"
751a30de1fSmrg"    -grammar                     print out short help on allowable input\n"
761a30de1fSmrg"    -                            read standard input\n"
771a30de1fSmrg"\n";
781a30de1fSmrg
791a30de1fSmrg
801a30de1fSmrgstatic void
811a30de1fSmrgusage(void)
821a30de1fSmrg{
831a30de1fSmrg    fprintf (stderr, "usage:  %s [-options ...] [filename]\n", ProgramName);
841a30de1fSmrg    fprintf (stderr, "%s\n", help_message);
851a30de1fSmrg    Exit (1);
861a30de1fSmrg}
871a30de1fSmrg
881a30de1fSmrgstatic const char grammar_message[] =
891a30de1fSmrg"    pointer = default              reset pointer buttons to default\n"
901a30de1fSmrg"    pointer = NUMBER ...           set pointer button codes\n"
911a30de1fSmrg"    keycode NUMBER = [KEYSYM ...]  map keycode to given keysyms\n"
921a30de1fSmrg"    keysym KEYSYM = [KEYSYM ...]   look up keysym and do a keycode operation\n"
931a30de1fSmrg"    clear MODIFIER                 remove all keys for this modifier\n"
941a30de1fSmrg"    add MODIFIER = KEYSYM ...      add the keysyms to the modifier\n"
951a30de1fSmrg"    remove MODIFIER = KEYSYM ...   remove the keysyms from the modifier\n"
961a30de1fSmrg"\n"
971a30de1fSmrg"where NUMBER is a decimal, octal, or hex constant; KEYSYM is a valid\n"
981a30de1fSmrg"Key Symbol name; and MODIFIER is one of the eight modifier names:  Shift,\n"
991a30de1fSmrg"Lock, Control, Mod1, Mod2, Mod3, Mod4, or Mod5.  Lines beginning with\n"
1001a30de1fSmrg"an exclamation mark (!) are taken as comments.  Case is significant except\n"
1011a30de1fSmrg"for MODIFIER names.\n"
1021a30de1fSmrg"\n"
1031a30de1fSmrg"Keysyms on the left hand side of the = sign are looked up before any changes\n"
1041a30de1fSmrg"are made; keysyms on the right are looked up after all of those on the left\n"
1051a30de1fSmrg"have been resolved.  This makes it possible to swap modifier keys.\n"
1061a30de1fSmrg"\n";
1071a30de1fSmrg
1081a30de1fSmrg
1091a30de1fSmrgstatic void
1101a30de1fSmrggrammar_usage(void)
1111a30de1fSmrg{
1121a30de1fSmrg    fprintf (stderr, "%s accepts the following input expressions:\n\n",
1131a30de1fSmrg	     ProgramName);
1141a30de1fSmrg    fprintf (stderr, "%s\n", grammar_message);
1151a30de1fSmrg    Exit (0);
1161a30de1fSmrg}
1171a30de1fSmrg
1181a30de1fSmrgint parse_errors = 0;
1191a30de1fSmrg
1201a30de1fSmrgint
1211a30de1fSmrgmain(int argc, char *argv[])
1221a30de1fSmrg{
1231a30de1fSmrg    int i;
1241a30de1fSmrg    char *displayname = NULL;
1251a30de1fSmrg    int status;
1261a30de1fSmrg    Bool printMap = False;
1271a30de1fSmrg    Bool printKeyTable = False;
1281a30de1fSmrg    Bool printKeyTableExprs = False;
1291a30de1fSmrg    Bool printPointerMap = False;
1301a30de1fSmrg    Bool didAnything = False;
1311a30de1fSmrg
1321a30de1fSmrg    ProgramName = argv[0];
1331a30de1fSmrg
1341a30de1fSmrg    /*
1351a30de1fSmrg     * scan the arg list once to find out which display to use
1361a30de1fSmrg     */
1371a30de1fSmrg
1381a30de1fSmrg    for (i = 1; i < argc; i++) {
1391a30de1fSmrg	if (strncmp (argv[i], "-d", 2) == 0) {
1401a30de1fSmrg	    if (++i >= argc) usage ();
1411a30de1fSmrg	    displayname = argv[i];
1421a30de1fSmrg	}
1431a30de1fSmrg    }
1441a30de1fSmrg
1451a30de1fSmrg    dpy = XOpenDisplay (displayname);
1461a30de1fSmrg    if (!dpy) {
1471a30de1fSmrg	fprintf (stderr, "%s:  unable to open display '%s'\n",
1481a30de1fSmrg		 ProgramName, XDisplayName (displayname));
1491a30de1fSmrg	Exit (1);
1501a30de1fSmrg    }
1511a30de1fSmrg
1521a30de1fSmrg    XDisplayKeycodes (dpy, &min_keycode, &max_keycode);
1531a30de1fSmrg
1541a30de1fSmrg    initialize_map ();
1551a30de1fSmrg
1561a30de1fSmrg    /*
1571a30de1fSmrg     * scan the arg list again to do the actual work (since it requires
1581a30de1fSmrg     * the display being open.
1591a30de1fSmrg     */
1601a30de1fSmrg
1611a30de1fSmrg    status = 0;
1621a30de1fSmrg    for (i = 1; i < argc; i++) {
1631a30de1fSmrg	char *arg = argv[i];
1641a30de1fSmrg
1651a30de1fSmrg	if (arg[0] == '-') {
1661a30de1fSmrg	    switch (arg[1]) {
1671a30de1fSmrg	      case 'd':			/* -display host:dpy */
1681a30de1fSmrg		++i;			/* handled above */
1691a30de1fSmrg		continue;
1701a30de1fSmrg	      case 'v':			/* -verbose */
1711a30de1fSmrg		verbose = True;
1721a30de1fSmrg		continue;
1731a30de1fSmrg	      case 'q':			/* -quiet */
1741a30de1fSmrg		verbose = False;
1751a30de1fSmrg		continue;
1761a30de1fSmrg	      case 'n':			/* -n (like make) */
1771a30de1fSmrg		dontExecute = True;
1781a30de1fSmrg		continue;
1791a30de1fSmrg	      case 'e':			/* -e expression */
1801a30de1fSmrg		didAnything = True;
1811a30de1fSmrg		if (++i >= argc) usage ();
1821a30de1fSmrg		process_line (argv[i]);
1831a30de1fSmrg		continue;
1841a30de1fSmrg	      case 'p':			/* -p... */
1851a30de1fSmrg		switch (arg[2]) {
1861a30de1fSmrg		  case '\0':
1871a30de1fSmrg		  case 'm':		/* -pm */
1881a30de1fSmrg		    printMap = True;
1891a30de1fSmrg		    break;
1901a30de1fSmrg		  case 'k':		/* -pk, -pke */
1911a30de1fSmrg		    switch (arg[3]) {
1921a30de1fSmrg		    case '\0':
1931a30de1fSmrg			printKeyTable = True;
1941a30de1fSmrg			break;
1951a30de1fSmrg		    case 'e':
1961a30de1fSmrg			printKeyTableExprs = True;
1971a30de1fSmrg			break;
1981a30de1fSmrg		    default:
1991a30de1fSmrg			usage ();
2001a30de1fSmrg		    }
2011a30de1fSmrg		    break;
2021a30de1fSmrg		  case 'p':		/* -pp */
2031a30de1fSmrg		    printPointerMap = True;
2041a30de1fSmrg		    break;
2051a30de1fSmrg		  default:
2061a30de1fSmrg		    usage ();
2071a30de1fSmrg		    /* NOTREACHED */
2081a30de1fSmrg		}
2091a30de1fSmrg		didAnything = True;
2101a30de1fSmrg		continue;
2111a30de1fSmrg	      case 'g':			/* -grammar */
2121a30de1fSmrg		grammar_usage ();
2131a30de1fSmrg		/*NOTREACHED*/
2141a30de1fSmrg	      case '\0':		/* - (use standard input) */
2151a30de1fSmrg		didAnything = True;
2161a30de1fSmrg		process_file (NULL);
2171a30de1fSmrg		continue;
2181a30de1fSmrg
2191a30de1fSmrg	      /*
2201a30de1fSmrg	       * provide old xmodmap args
2211a30de1fSmrg	       */
2221a30de1fSmrg	      case 'S':
2231a30de1fSmrg		didAnything = True;
2241a30de1fSmrg		process_line ("clear shift");
2251a30de1fSmrg		continue;
2261a30de1fSmrg	      case 'L':
2271a30de1fSmrg		didAnything = True;
2281a30de1fSmrg		process_line ("clear lock");
2291a30de1fSmrg		continue;
2301a30de1fSmrg	      case 'C':
2311a30de1fSmrg		didAnything = True;
2321a30de1fSmrg		process_line ("clear control");
2331a30de1fSmrg		continue;
2341a30de1fSmrg	      case '1':
2351a30de1fSmrg	      case '2':
2361a30de1fSmrg	      case '3':
2371a30de1fSmrg	      case '4':
2381a30de1fSmrg	      case '5': {
2391a30de1fSmrg		  char cmd[11] = "clear modX";
2401a30de1fSmrg		  cmd[9] = arg[1];
2411a30de1fSmrg		  process_line (cmd);
2421a30de1fSmrg		  continue;
2431a30de1fSmrg	      }
2441a30de1fSmrg	      case 's':
2451a30de1fSmrg	      case 'l':
2461a30de1fSmrg	      case 'c': {
2471a30de1fSmrg		  char *cmd;
2481a30de1fSmrg		  didAnything = True;
2491a30de1fSmrg		  if (++i >= argc) usage ();
2501a30de1fSmrg		  cmd = chk_malloc (strlen ("remove control = ") + strlen (argv[i]) + 1);
2511a30de1fSmrg		  (void) sprintf (cmd, "remove %s = %s",
2521a30de1fSmrg				  ((arg[1] == 's') ? "shift" :
2531a30de1fSmrg				   ((arg[1] == 'l') ? "lock" :
2541a30de1fSmrg				    "control")), argv[i]);
2551a30de1fSmrg		  process_line (cmd);
2561a30de1fSmrg		  continue;
2571a30de1fSmrg	      }
2581a30de1fSmrg	      default:
2591a30de1fSmrg		usage ();
2601a30de1fSmrg		/*NOTREACHED*/
2611a30de1fSmrg	    }
2621a30de1fSmrg	} else if (arg[0] == '+') {	/* old xmodmap args */
2631a30de1fSmrg	    switch (arg[1]) {
2641a30de1fSmrg	      case '1':
2651a30de1fSmrg	      case '2':
2661a30de1fSmrg	      case '3':
2671a30de1fSmrg	      case '4':
2681a30de1fSmrg	      case '5': {
2691a30de1fSmrg		  char *cmd;
2701a30de1fSmrg		  didAnything = True;
2711a30de1fSmrg		  if (++i >= argc) usage ();
2721a30de1fSmrg		  cmd = chk_malloc (strlen ("add modX = ") + strlen (argv[i]) + 1);
2731a30de1fSmrg		  (void) sprintf (cmd, "add mod%c = %s", arg[1], argv[i]);
2741a30de1fSmrg		  process_line (cmd);
2751a30de1fSmrg		  continue;
2761a30de1fSmrg	      }
2771a30de1fSmrg	      case 'S':
2781a30de1fSmrg	      case 'L':
2791a30de1fSmrg	      case 'C':
2801a30de1fSmrg		arg[1] = tolower (arg[1]);
2811a30de1fSmrg		/* fall through to handler below */
2821a30de1fSmrg	      case 's':
2831a30de1fSmrg	      case 'l':
2841a30de1fSmrg	      case 'c': {
2851a30de1fSmrg		  char *cmd;
2861a30de1fSmrg		  didAnything = True;
2871a30de1fSmrg		  if (++i >= argc) usage ();
2881a30de1fSmrg		  cmd = chk_malloc (strlen ("add control = ") + strlen (argv[i]) + 1);
2891a30de1fSmrg		  (void) sprintf (cmd, "add %s = %s",
2901a30de1fSmrg				  ((arg[1] == 's') ? "shift" :
2911a30de1fSmrg				   ((arg[1] == 'l') ? "lock" :
2921a30de1fSmrg				    "control")), argv[i]);
2931a30de1fSmrg		  process_line (cmd);
2941a30de1fSmrg		  continue;
2951a30de1fSmrg	      }
2961a30de1fSmrg	      default:
2971a30de1fSmrg		usage ();
2981a30de1fSmrg	    }
2991a30de1fSmrg	} else {
3001a30de1fSmrg	    didAnything = True;
3011a30de1fSmrg	    process_file (arg);
3021a30de1fSmrg	    continue;
3031a30de1fSmrg	}
3041a30de1fSmrg    }					/* end for loop */
3051a30de1fSmrg
3061a30de1fSmrg    /* for compatibility */
3071a30de1fSmrg    if (!didAnything) printMap = True;
3081a30de1fSmrg
3091a30de1fSmrg    /*
3101a30de1fSmrg     * at this point, the work list has been built and we can view it or
3111a30de1fSmrg     * execute it
3121a30de1fSmrg     */
3131a30de1fSmrg
3141a30de1fSmrg    if (dontExecute) {
3151a30de1fSmrg	print_work_queue ();
3161a30de1fSmrg	Exit (0);
3171a30de1fSmrg    }
3181a30de1fSmrg
3191a30de1fSmrg    if (parse_errors != 0) {
3201a30de1fSmrg	fprintf (stderr, "%s:  %d error%s encountered, aborting.\n",
3211a30de1fSmrg		 ProgramName, parse_errors,
3221a30de1fSmrg		 (parse_errors == 1 ? "" : "s"));
3231a30de1fSmrg	status = -1;	/* return an error condition */
3241a30de1fSmrg    } else {
3251a30de1fSmrg	status = execute_work_queue ();
3261a30de1fSmrg    }
3271a30de1fSmrg
3281a30de1fSmrg    if (printMap) {
3291a30de1fSmrg	print_modifier_map ();
3301a30de1fSmrg    }
3311a30de1fSmrg
3321a30de1fSmrg    if (printKeyTable) {
3331a30de1fSmrg	print_key_table (False);
3341a30de1fSmrg    }
3351a30de1fSmrg
3361a30de1fSmrg    if (printKeyTableExprs) {
3371a30de1fSmrg	print_key_table (True);
3381a30de1fSmrg    }
3391a30de1fSmrg
3401a30de1fSmrg    if (printPointerMap) {
3411a30de1fSmrg	print_pointer_map ();
3421a30de1fSmrg    }
3431a30de1fSmrg
3441a30de1fSmrg    Exit (status < 0 ? 1 : 0);
3451a30de1fSmrg
3461a30de1fSmrg    /* Muffle gcc */
3471a30de1fSmrg    return 0;
3481a30de1fSmrg}
3491a30de1fSmrg
350