#include <X11/Xos.h>
#include <X11/Xlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include "xmodmap.h"
char *ProgramName;
Display *dpy = NULL;
int min_keycode, max_keycode;
Bool verbose = False;
Bool dontExecute = False;
static void
Exit(int status)
{
if (dpy) {
XCloseDisplay (dpy);
dpy = NULL;
}
exit (status);
}
static char *help_message[] = {
"\nwhere options include:",
" -display host:dpy X server to use",
" -verbose, -quiet turn logging on or off",
" -n don't execute changes, just show like make",
" -e expression execute string",
" -pm print modifier map",
" -pk print keymap table",
" -pke print keymap table as expressions",
" -pp print pointer map",
" -grammar print out short help on allowable input",
" - read standard input",
"",
NULL};
static void
usage(void)
{
char **cpp;
fprintf (stderr, "usage: %s [-options ...] [filename]\n", ProgramName);
for (cpp = help_message; *cpp; cpp++) {
fprintf (stderr, "%s\n", *cpp);
}
Exit (1);
}
static char *grammar_message[] = {
" pointer = default reset pointer buttons to default",
" pointer = NUMBER ... set pointer button codes",
" keycode NUMBER = [KEYSYM ...] map keycode to given keysyms",
" keysym KEYSYM = [KEYSYM ...] look up keysym and do a keycode operation",
" clear MODIFIER remove all keys for this modifier",
" add MODIFIER = KEYSYM ... add the keysyms to the modifier",
" remove MODIFIER = KEYSYM ... remove the keysyms from the modifier",
"",
"where NUMBER is a decimal, octal, or hex constant; KEYSYM is a valid",
"Key Symbol name; and MODIFIER is one of the eight modifier names: Shift,",
"Lock, Control, Mod1, Mod2, Mod3, Mod4, or Mod5. Lines beginning with",
"an exclamation mark (!) are taken as comments. Case is significant except",
"for MODIFIER names.",
"",
"Keysyms on the left hand side of the = sign are looked up before any changes",
"are made; keysyms on the right are looked up after all of those on the left",
"have been resolved. This makes it possible to swap modifier keys.",
"",
NULL };
static void
grammar_usage(void)
{
char **cpp;
fprintf (stderr, "%s accepts the following input expressions:\n\n",
ProgramName);
for (cpp = grammar_message; *cpp; cpp++) {
fprintf (stderr, "%s\n", *cpp);
}
Exit (0);
}
int parse_errors = 0;
int
main(int argc, char *argv[])
{
int i;
char *displayname = NULL;
int status;
Bool printMap = False;
Bool printKeyTable = False;
Bool printKeyTableExprs = False;
Bool printPointerMap = False;
Bool didAnything = False;
ProgramName = argv[0];
for (i = 1; i < argc; i++) {
if (strncmp (argv[i], "-d", 2) == 0) {
if (++i >= argc) usage ();
displayname = argv[i];
}
}
dpy = XOpenDisplay (displayname);
if (!dpy) {
fprintf (stderr, "%s: unable to open display '%s'\n",
ProgramName, XDisplayName (displayname));
Exit (1);
}
XDisplayKeycodes (dpy, &min_keycode, &max_keycode);
initialize_map ();
status = 0;
for (i = 1; i < argc; i++) {
char *arg = argv[i];
if (arg[0] == '-') {
switch (arg[1]) {
case 'd':
++i;
continue;
case 'v':
verbose = True;
continue;
case 'q':
verbose = False;
continue;
case 'n':
dontExecute = True;
continue;
case 'e':
didAnything = True;
if (++i >= argc) usage ();
process_line (argv[i]);
continue;
case 'p':
switch (arg[2]) {
case '\0':
case 'm':
printMap = True;
break;
case 'k':
switch (arg[3]) {
case '\0':
printKeyTable = True;
break;
case 'e':
printKeyTableExprs = True;
break;
default:
usage ();
}
break;
case 'p':
printPointerMap = True;
break;
default:
usage ();
}
didAnything = True;
continue;
case 'g':
grammar_usage ();
case '\0':
didAnything = True;
process_file (NULL);
continue;
case 'S':
didAnything = True;
process_line ("clear shift");
continue;
case 'L':
didAnything = True;
process_line ("clear lock");
continue;
case 'C':
didAnything = True;
process_line ("clear control");
continue;
case '1':
case '2':
case '3':
case '4':
case '5': {
char cmd[11] = "clear modX";
cmd[9] = arg[1];
process_line (cmd);
continue;
}
case 's':
case 'l':
case 'c': {
char cmd[80];
didAnything = True;
if (++i >= argc) usage ();
(void) sprintf (cmd, "remove %s = %s",
((arg[1] == 's') ? "shift" :
((arg[1] == 'l') ? "lock" :
"control")), argv[i]);
process_line (cmd);
continue;
}
default:
usage ();
}
} else if (arg[0] == '+') {
switch (arg[1]) {
case '1':
case '2':
case '3':
case '4':
case '5': {
char cmd[80];
didAnything = True;
if (++i >= argc) usage ();
(void) sprintf (cmd, "add mod%c = %s", arg[1], argv[i]);
process_line (cmd);
continue;
}
case 'S':
case 'L':
case 'C':
arg[1] = tolower (arg[1]);
case 's':
case 'l':
case 'c': {
char cmd[80];
didAnything = True;
if (++i >= argc) usage ();
(void) sprintf (cmd, "add %s = %s",
((arg[1] == 's') ? "shift" :
((arg[1] == 'l') ? "lock" :
"control")), argv[i]);
process_line (cmd);
continue;
}
default:
usage ();
}
} else {
didAnything = True;
process_file (arg);
continue;
}
}
if (!didAnything) printMap = True;
if (dontExecute) {
print_work_queue ();
Exit (0);
}
if (parse_errors != 0) {
fprintf (stderr, "%s: %d error%s encountered, aborting.\n",
ProgramName, parse_errors,
(parse_errors == 1 ? "" : "s"));
status = -1;
} else {
status = execute_work_queue ();
}
if (printMap) {
print_modifier_map ();
}
if (printKeyTable) {
print_key_table (False);
}
if (printKeyTableExprs) {
print_key_table (True);
}
if (printPointerMap) {
print_pointer_map ();
}
Exit (status < 0 ? 1 : 0);
return 0;
}